00001 #include "config.h"
00002
00003 #include <ibrcommon/data/BLOB.h>
00004 #include <ibrcommon/data/File.h>
00005 #include <ibrcommon/AutoDelete.h>
00006 #include <ibrcommon/net/NetInterface.h>
00007 #include "ibrcommon/Logger.h"
00008 #include <ibrdtn/utils/Clock.h>
00009 #include <list>
00010
00011 #include "core/BundleCore.h"
00012 #include "core/EventSwitch.h"
00013 #include "core/BundleStorage.h"
00014 #include "core/SimpleBundleStorage.h"
00015
00016 #include "core/Node.h"
00017 #include "core/EventSwitch.h"
00018 #include "core/GlobalEvent.h"
00019 #include "core/NodeEvent.h"
00020
00021 #include "routing/BaseRouter.h"
00022 #include "routing/StaticRoutingExtension.h"
00023 #include "routing/NeighborRoutingExtension.h"
00024 #include "routing/EpidemicRoutingExtension.h"
00025 #include "routing/RetransmissionExtension.h"
00026
00027 #include "net/UDPConvergenceLayer.h"
00028 #include "net/TCPConvergenceLayer.h"
00029
00030 #ifdef HAVE_SQLITE
00031 #include "core/SQLiteBundleStorage.h"
00032 #endif
00033
00034 #ifdef HAVE_LIBCURL
00035 #include "net/HTTPConvergenceLayer.h"
00036 #endif
00037
00038 #ifdef HAVE_LOWPAN_SUPPORT
00039 #include "net/LOWPANConvergenceLayer.h"
00040 #endif
00041
00042 #include "net/IPNDAgent.h"
00043
00044 #include "ApiServer.h"
00045 #include "Configuration.h"
00046 #include "EchoWorker.h"
00047 #include "Notifier.h"
00048 #include "DevNull.h"
00049 #include "StatisticLogger.h"
00050 #include "Component.h"
00051
00052 #include <csignal>
00053 #include <sys/types.h>
00054 #include <syslog.h>
00055 #include <set>
00056
00057 using namespace dtn::core;
00058 using namespace dtn::daemon;
00059 using namespace dtn::utils;
00060 using namespace dtn::net;
00061
00062 #include "Debugger.h"
00063
00064 #define UNIT_MB * 1048576
00065
00066
00067 void term(int signal)
00068 {
00069 if (signal >= 1)
00070 {
00071 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00072 }
00073 }
00074
00075 void reload(int)
00076 {
00077
00078 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_RELOAD);
00079 }
00080
00081 void switchUser(Configuration &config)
00082 {
00083 try {
00084 setuid( config.getUID() );
00085 IBRCOMMON_LOGGER(info) << "Switching UID to " << config.getUID() << IBRCOMMON_LOGGER_ENDL;
00086 } catch (Configuration::ParameterNotSetException ex) {
00087
00088 }
00089
00090 try {
00091 setuid( config.getGID() );
00092 IBRCOMMON_LOGGER(info) << "Switching GID to " << config.getGID() << IBRCOMMON_LOGGER_ENDL;
00093 } catch (Configuration::ParameterNotSetException ex) {
00094
00095 }
00096 }
00097
00098 void setGlobalVars(Configuration &config)
00099 {
00100
00101
00102
00103 dtn::utils::Clock::timezone = config.getTimezone();
00104
00105
00106 dtn::core::BundleCore::local = config.getNodename();
00107 IBRCOMMON_LOGGER(info) << "Local node name: " << config.getNodename() << IBRCOMMON_LOGGER_ENDL;
00108
00109 try {
00110
00111 ibrcommon::BLOB::tmppath = config.getPath("blob");
00112 } catch (Configuration::ParameterNotSetException ex) {
00113
00114 }
00115
00116
00117 dtn::core::BundleCore::blocksizelimit = config.getLimit("blocksize");
00118 if (dtn::core::BundleCore::blocksizelimit > 0)
00119 {
00120 IBRCOMMON_LOGGER(info) << "Block size limited to " << dtn::core::BundleCore::blocksizelimit << " bytes" << IBRCOMMON_LOGGER_ENDL;
00121 }
00122 }
00123
00124 void createBundleStorage(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components)
00125 {
00126 dtn::core::BundleStorage *storage = NULL;
00127
00128 try {
00129
00130 ibrcommon::File path = conf.getPath("storage");
00131
00132 #ifdef HAVE_SQLITE
00133 dtn::core::SQLiteBundleStorage *sbs = new dtn::core::SQLiteBundleStorage(path, "sqlite.db", conf.getLimit("storage") );
00134 #else
00135
00136 if (!path.exists())
00137 {
00138 ibrcommon::File::createDirectory(path);
00139 }
00140
00141 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(path, conf.getLimit("storage"));
00142 #endif
00143 components.push_back(sbs);
00144 storage = sbs;
00145 } catch (Configuration::ParameterNotSetException ex) {
00146 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(conf.getLimit("storage"));
00147 components.push_back(sbs);
00148 storage = sbs;
00149 }
00150
00151
00152 core.setStorage(storage);
00153 }
00154
00155 void createConvergenceLayers(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components, dtn::net::IPNDAgent *ipnd)
00156 {
00157
00158 std::list<Configuration::NetConfig> nets = conf.getInterfaces();
00159
00160
00161 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00162 {
00163 const Configuration::NetConfig &net = (*iter);
00164
00165 try {
00166 switch (net.type)
00167 {
00168 case Configuration::NetConfig::NETWORK_UDP:
00169 {
00170 UDPConvergenceLayer *udpcl = new UDPConvergenceLayer( net.interface, net.port );
00171 core.addConvergenceLayer(udpcl);
00172 components.push_back(udpcl);
00173 if (ipnd != NULL) ipnd->addService(udpcl);
00174
00175 IBRCOMMON_LOGGER(info) << "UDP ConvergenceLayer added on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00176
00177 break;
00178 }
00179
00180 case Configuration::NetConfig::NETWORK_TCP:
00181 {
00182 TCPConvergenceLayer *tcpcl = new TCPConvergenceLayer( net.interface, net.port );
00183 core.addConvergenceLayer(tcpcl);
00184 components.push_back(tcpcl);
00185 if (ipnd != NULL) ipnd->addService(tcpcl);
00186
00187 IBRCOMMON_LOGGER(info) << "TCP ConvergenceLayer added on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00188
00189 break;
00190 }
00191
00192 #ifdef HAVE_LIBCURL
00193 case Configuration::NetConfig::NETWORK_HTTP:
00194 {
00195 HTTPConvergenceLayer *httpcl = new HTTPConvergenceLayer( net.address );
00196 core.addConvergenceLayer(httpcl);
00197 components.push_back(httpcl);
00198
00199 IBRCOMMON_LOGGER(info) << "HTTP ConvergenceLayer added, Server: " << net.address << IBRCOMMON_LOGGER_ENDL;
00200 break;
00201 }
00202 #endif
00203
00204 #ifdef HAVE_LOWPAN_SUPPORT
00205 case Configuration::NetConfig::NETWORK_LOWPAN:
00206 {
00207 LOWPANConvergenceLayer *lowpancl = new LOWPANConvergenceLayer( net.interface, net.port );
00208 core.addConvergenceLayer(lowpancl);
00209 components.push_back(lowpancl);
00210 if (ipnd != NULL) ipnd->addService(lowpancl);
00211
00212 IBRCOMMON_LOGGER(info) << "LOWPAN ConvergenceLayer added on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00213
00214 break;
00215 }
00216 #endif
00217
00218 default:
00219 break;
00220 }
00221 } catch (ibrcommon::SocketException ex) {
00222 IBRCOMMON_LOGGER(error) << "Failed to add TCP ConvergenceLayer on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00223 IBRCOMMON_LOGGER(error) << " Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00224 throw ex;
00225 }
00226 }
00227 }
00228
00229 int main(int argc, char *argv[])
00230 {
00231
00232 signal(SIGINT, term);
00233 signal(SIGTERM, term);
00234 signal(SIGHUP, reload);
00235
00236
00237 Configuration &conf = Configuration::getInstance();
00238
00239
00240 conf.params(argc, argv);
00241
00242
00243 {
00244
00245 unsigned char logopts = ibrcommon::Logger::LOG_TIMESTAMP | ibrcommon::Logger::LOG_LEVEL;
00246
00247
00248 unsigned int logerr = ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT;
00249
00250
00251 unsigned int logstd = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT);
00252
00253
00254 ibrcommon::Logger::enableSyslog("ibrdtn-daemon", LOG_PID, LOG_DAEMON, ibrcommon::Logger::LOGGER_INFO | ibrcommon::Logger::LOGGER_NOTICE);
00255
00256 if (!conf.beQuiet())
00257 {
00258
00259 ibrcommon::Logger::addStream(std::cout, logstd, logopts);
00260
00261
00262 ibrcommon::Logger::addStream(std::cerr, logerr, logopts);
00263 }
00264
00265
00266 IBRCOMMON_LOGGER(info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL;
00267
00268
00269 if (conf.doDebug() && !conf.beQuiet())
00270 {
00271
00272 ibrcommon::Logger::setVerbosity(conf.getDebugLevel());
00273
00274 IBRCOMMON_LOGGER(info) << "debug level set to " << conf.getDebugLevel() << IBRCOMMON_LOGGER_ENDL;
00275
00276 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);
00277 }
00278 }
00279
00280
00281 conf.load();
00282
00283
00284 switchUser(conf);
00285
00286
00287 setGlobalVars(conf);
00288
00289
00290 std::list< dtn::daemon::Component* > components;
00291
00292
00293 try {
00294 components.push_back( new dtn::daemon::Notifier( conf.getNotifyCommand() ) );
00295 } catch (Configuration::ParameterNotSetException ex) {
00296
00297 }
00298
00299
00300 BundleCore &core = BundleCore::getInstance();
00301
00302
00303 dtn::core::EventSwitch &esw = dtn::core::EventSwitch::getInstance();
00304
00305
00306 createBundleStorage(core, conf, components);
00307
00308
00309 dtn::net::IPNDAgent *ipnd = NULL;
00310
00311 if (conf.doDiscovery())
00312 {
00313
00314 int disco_port = conf.getDiscoveryPort();
00315
00316 try {
00317 ipnd = new dtn::net::IPNDAgent( disco_port, conf.getDiscoveryAddress() );
00318 } catch (Configuration::ParameterNotFoundException ex) {
00319 ipnd = new dtn::net::IPNDAgent( disco_port, "255.255.255.255" );
00320 }
00321
00322
00323 std::set<ibrcommon::NetInterface> interfaces;
00324
00325 std::list<Configuration::NetConfig> nets = conf.getInterfaces();
00326 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00327 {
00328 const Configuration::NetConfig &net = (*iter);
00329 interfaces.insert(net.interface);
00330 }
00331
00332 for (std::set<ibrcommon::NetInterface>::const_iterator iter = interfaces.begin(); iter != interfaces.end(); iter++)
00333 {
00334
00335 ipnd->bind(*iter);
00336 }
00337
00338 components.push_back(ipnd);
00339 }
00340 else
00341 {
00342 IBRCOMMON_LOGGER(info) << "Discovery disabled" << IBRCOMMON_LOGGER_ENDL;
00343 }
00344
00345
00346 dtn::routing::BaseRouter *router = new dtn::routing::BaseRouter(core.getStorage());
00347
00348
00349 switch (conf.getRoutingExtension())
00350 {
00351 case Configuration::EPIDEMIC_ROUTING:
00352 {
00353 IBRCOMMON_LOGGER(info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL;
00354 dtn::routing::EpidemicRoutingExtension *epidemic = new dtn::routing::EpidemicRoutingExtension();
00355 router->addExtension( epidemic );
00356 router->addExtension( new dtn::routing::RetransmissionExtension() );
00357 if (ipnd != NULL) ipnd->addService(epidemic);
00358 break;
00359 }
00360
00361 default:
00362 IBRCOMMON_LOGGER(info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL;
00363 router->addExtension( new dtn::routing::StaticRoutingExtension( conf.getStaticRoutes() ) );
00364 router->addExtension( new dtn::routing::NeighborRoutingExtension() );
00365 break;
00366 }
00367
00368 components.push_back(router);
00369
00370
00371 if (conf.doForwarding())
00372 {
00373 IBRCOMMON_LOGGER(info) << "Forwarding of bundles enabled." << IBRCOMMON_LOGGER_ENDL;
00374 BundleCore::forwarding = true;
00375 }
00376 else
00377 {
00378 IBRCOMMON_LOGGER(info) << "Forwarding of bundles disabled." << IBRCOMMON_LOGGER_ENDL;
00379 BundleCore::forwarding = false;
00380 }
00381
00382
00383 createConvergenceLayers(core, conf, components, ipnd);
00384
00385 if (conf.doAPI())
00386 {
00387 Configuration::NetConfig lo = conf.getAPIInterface();
00388
00389 try {
00390
00391 components.push_back( new ApiServer(lo.interface, lo.port) );
00392 } catch (ibrcommon::SocketException ex) {
00393 IBRCOMMON_LOGGER(error) << "Unable to bind to " << lo.interface.getAddress() << ":" << lo.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
00394 exit(-1);
00395 }
00396 }
00397 else
00398 {
00399 IBRCOMMON_LOGGER(info) << "API disabled" << IBRCOMMON_LOGGER_ENDL;
00400 }
00401
00402
00403 if (conf.useStatLogger())
00404 {
00405 try {
00406 if (conf.getStatLogType() == "stdout")
00407 {
00408 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatLogInterval() ) );
00409 }
00410 else if (conf.getStatLogType() == "syslog")
00411 {
00412 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_SYSLOG, conf.getStatLogInterval() ) );
00413 }
00414 else if (conf.getStatLogType() == "plain")
00415 {
00416 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_PLAIN, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00417 }
00418 else if (conf.getStatLogType() == "csv")
00419 {
00420 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_CSV, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00421 }
00422 else if (conf.getStatLogType() == "stat")
00423 {
00424 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_STAT, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00425 }
00426 else if (conf.getStatLogType() == "udp")
00427 {
00428 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_UDP, conf.getStatLogInterval(), conf.getStatAddress(), conf.getStatPort() ) );
00429 }
00430 } catch (Configuration::ParameterNotSetException ex) {
00431 IBRCOMMON_LOGGER(error) << "StatisticLogger: Parameter statistic_file is not set! Fallback to stdout logging." << IBRCOMMON_LOGGER_ENDL;
00432 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatLogInterval() ) );
00433 }
00434 }
00435
00436
00437 core.initialize();
00438
00439
00440 esw.initialize();
00441
00445 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00446 {
00447 (*iter)->initialize();
00448 }
00449
00450
00451 core.startup();
00452
00456 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00457 {
00458 (*iter)->startup();
00459 }
00460
00461
00462 Debugger debugger;
00463
00464
00465 EchoWorker echo;
00466
00467
00468 DevNull devnull;
00469
00470
00471 list<Node> static_nodes = conf.getStaticNodes();
00472
00473 for (list<Node>::iterator iter = static_nodes.begin(); iter != static_nodes.end(); iter++)
00474 {
00475 core.addConnection(*iter);
00476 }
00477
00478
00479 esw.loop();
00480
00481 IBRCOMMON_LOGGER(info) << "shutdown dtn node" << IBRCOMMON_LOGGER_ENDL;
00482
00483
00484 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00485
00489 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00490 {
00491 (*iter)->terminate();
00492 }
00493
00494
00495 esw.terminate();
00496
00497
00498 core.terminate();
00499
00500
00501 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00502 {
00503 delete (*iter);
00504 }
00505
00506 return 0;
00507 };