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/vinterface.h>
00007 #include <ibrcommon/Logger.h>
00008 #include <ibrcommon/net/LinkManager.h>
00009 #include <ibrdtn/utils/Clock.h>
00010 #include <list>
00011
00012 #include "core/BundleCore.h"
00013 #include "core/EventSwitch.h"
00014 #include "core/BundleStorage.h"
00015 #include "core/MemoryBundleStorage.h"
00016 #include "core/SimpleBundleStorage.h"
00017
00018 #include "core/Node.h"
00019 #include "core/EventSwitch.h"
00020 #include "core/GlobalEvent.h"
00021 #include "core/NodeEvent.h"
00022
00023 #include "routing/BaseRouter.h"
00024 #include "routing/StaticRoutingExtension.h"
00025 #include "routing/NeighborRoutingExtension.h"
00026 #include "routing/epidemic/EpidemicRoutingExtension.h"
00027 #include "routing/flooding/FloodRoutingExtension.h"
00028 #include "routing/RetransmissionExtension.h"
00029
00030 #include "net/UDPConvergenceLayer.h"
00031 #include "net/TCPConvergenceLayer.h"
00032
00033 #ifdef HAVE_SQLITE
00034 #include "core/SQLiteBundleStorage.h"
00035 #endif
00036
00037 #ifdef HAVE_LIBCURL
00038 #include "net/HTTPConvergenceLayer.h"
00039 #endif
00040
00041 #ifdef HAVE_LOWPAN_SUPPORT
00042 #include "net/LOWPANConvergenceLayer.h"
00043 #endif
00044
00045 #include "net/IPNDAgent.h"
00046
00047 #include "ApiServer.h"
00048 #include "Configuration.h"
00049 #include "EchoWorker.h"
00050 #include "Notifier.h"
00051 #include "DevNull.h"
00052 #include "StatisticLogger.h"
00053 #include "Component.h"
00054
00055 #ifdef WITH_BUNDLE_SECURITY
00056 #include "security/SecurityManager.h"
00057 #include "security/SecurityKeyManager.h"
00058 #endif
00059
00060 #ifdef HAVE_LIBDAEMON
00061 #include <libdaemon/daemon.h>
00062 #include <string.h>
00063 #endif
00064
00065 #include <csignal>
00066 #include <sys/types.h>
00067 #include <syslog.h>
00068 #include <set>
00069
00070 using namespace dtn::core;
00071 using namespace dtn::daemon;
00072 using namespace dtn::utils;
00073 using namespace dtn::net;
00074
00075 #include "Debugger.h"
00076
00077 #define UNIT_MB * 1048576
00078
00083
00084 unsigned char logopts = ibrcommon::Logger::LOG_DATETIME | ibrcommon::Logger::LOG_LEVEL;
00085
00086
00087 const unsigned char logerr = ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT;
00088
00089
00090 const unsigned char logstd = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT);
00091
00092
00093 const unsigned char logsys = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_NOTICE);
00094
00095
00096 bool _debug = false;
00097
00098
00099 void sighandler(int signal)
00100 {
00101 switch (signal)
00102 {
00103 case SIGTERM:
00104 case SIGINT:
00105 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00106 break;
00107 case SIGUSR1:
00108
00109
00110 ibrcommon::Logger::setVerbosity(99);
00111 IBRCOMMON_LOGGER(info) << "debug level set to 99" << IBRCOMMON_LOGGER_ENDL;
00112
00113 if (!_debug)
00114 {
00115 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);
00116 _debug = true;
00117 }
00118 break;
00119 case SIGUSR2:
00120
00121
00122 ibrcommon::Logger::setVerbosity(0);
00123 IBRCOMMON_LOGGER(info) << "debug level set to 0" << IBRCOMMON_LOGGER_ENDL;
00124 break;
00125 case SIGHUP:
00126
00127 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_RELOAD);
00128 break;
00129 }
00130 }
00131
00132 void switchUser(Configuration &config)
00133 {
00134 try {
00135 setuid( config.getUID() );
00136 IBRCOMMON_LOGGER(info) << "Switching UID to " << config.getUID() << IBRCOMMON_LOGGER_ENDL;
00137 } catch (const Configuration::ParameterNotSetException&) {
00138
00139 }
00140
00141 try {
00142 setuid( config.getGID() );
00143 IBRCOMMON_LOGGER(info) << "Switching GID to " << config.getGID() << IBRCOMMON_LOGGER_ENDL;
00144 } catch (const Configuration::ParameterNotSetException&) {
00145
00146 }
00147 }
00148
00149 void setGlobalVars(Configuration &config)
00150 {
00151
00152 dtn::utils::Clock::timezone = config.getTimezone();
00153
00154
00155 dtn::core::BundleCore::local = config.getNodename();
00156 IBRCOMMON_LOGGER(info) << "Local node name: " << config.getNodename() << IBRCOMMON_LOGGER_ENDL;
00157
00158 try {
00159
00160 ibrcommon::BLOB::tmppath = config.getPath("blob");
00161
00162
00163 if (ibrcommon::BLOB::tmppath.exists())
00164 {
00165 if (ibrcommon::BLOB::tmppath.isDirectory())
00166 {
00167 IBRCOMMON_LOGGER(info) << "using BLOB path: " << ibrcommon::BLOB::tmppath.getPath() << IBRCOMMON_LOGGER_ENDL;
00168 }
00169 else
00170 {
00171 IBRCOMMON_LOGGER(warning) << "BLOB path exists, but is not a directory! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL;
00172 ibrcommon::BLOB::tmppath = ibrcommon::File();
00173 }
00174 }
00175 else
00176 {
00177
00178 ibrcommon::File::createDirectory(ibrcommon::BLOB::tmppath);
00179
00180 if (ibrcommon::BLOB::tmppath.exists())
00181 {
00182 IBRCOMMON_LOGGER(info) << "using BLOB path: " << ibrcommon::BLOB::tmppath.getPath() << IBRCOMMON_LOGGER_ENDL;
00183 }
00184 else
00185 {
00186 IBRCOMMON_LOGGER(warning) << "Could not create BLOB path! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL;
00187 ibrcommon::BLOB::tmppath = ibrcommon::File();
00188 }
00189 }
00190 } catch (const Configuration::ParameterNotSetException&) {
00191 }
00192
00193
00194 dtn::core::BundleCore::blocksizelimit = config.getLimit("blocksize");
00195 if (dtn::core::BundleCore::blocksizelimit > 0)
00196 {
00197 IBRCOMMON_LOGGER(info) << "Block size limited to " << dtn::core::BundleCore::blocksizelimit << " bytes" << IBRCOMMON_LOGGER_ENDL;
00198 }
00199 }
00200
00201 void createBundleStorage(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components)
00202 {
00203 dtn::core::BundleStorage *storage = NULL;
00204
00205 #ifdef HAVE_SQLITE
00206 if (conf.getStorage() == "sqlite")
00207 {
00208 try {
00209
00210 ibrcommon::File path = conf.getPath("storage");
00211
00212
00213 if (!path.exists())
00214 {
00215 ibrcommon::File::createDirectory(path);
00216 }
00217
00218 IBRCOMMON_LOGGER(info) << "using sqlite bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
00219
00220 dtn::core::SQLiteBundleStorage *sbs = new dtn::core::SQLiteBundleStorage(path, conf.getLimit("storage") );
00221
00222 components.push_back(sbs);
00223 storage = sbs;
00224 } catch (const Configuration::ParameterNotSetException&) {
00225 IBRCOMMON_LOGGER(error) << "storage for bundles" << IBRCOMMON_LOGGER_ENDL;
00226 exit(-1);
00227 }
00228 }
00229 #endif
00230
00231 if ((conf.getStorage() == "simple") || (conf.getStorage() == "default"))
00232 {
00233
00234 try {
00235
00236 ibrcommon::File path = conf.getPath("storage");
00237
00238
00239 if (!path.exists())
00240 {
00241 ibrcommon::File::createDirectory(path);
00242 }
00243
00244 IBRCOMMON_LOGGER(info) << "using simple bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
00245
00246 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(path, conf.getLimit("storage"), conf.getLimit("storage_buffer"));
00247
00248 components.push_back(sbs);
00249 storage = sbs;
00250 } catch (const Configuration::ParameterNotSetException&) {
00251 IBRCOMMON_LOGGER(info) << "using bundle storage in memory-only mode" << IBRCOMMON_LOGGER_ENDL;
00252
00253 dtn::core::MemoryBundleStorage *sbs = new dtn::core::MemoryBundleStorage(conf.getLimit("storage"));
00254 components.push_back(sbs);
00255 storage = sbs;
00256 }
00257 }
00258
00259 if (storage == NULL)
00260 {
00261 IBRCOMMON_LOGGER(error) << "bundle storage module \"" << conf.getStorage() << "\" do not exists!" << IBRCOMMON_LOGGER_ENDL;
00262 exit(-1);
00263 }
00264
00265
00266 core.setStorage(storage);
00267 }
00268
00269 void createConvergenceLayers(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components, dtn::net::IPNDAgent *ipnd)
00270 {
00271
00272 const std::list<Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces();
00273
00274
00275 std::map<Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*> _cl_map;
00276
00277
00278 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00279 {
00280 const Configuration::NetConfig &net = (*iter);
00281
00282 try {
00283 switch (net.type)
00284 {
00285 case Configuration::NetConfig::NETWORK_UDP:
00286 {
00287 try {
00288 UDPConvergenceLayer *udpcl = new UDPConvergenceLayer( net.interface, net.port );
00289 core.addConvergenceLayer(udpcl);
00290 components.push_back(udpcl);
00291 if (ipnd != NULL) ipnd->addService(udpcl);
00292
00293 IBRCOMMON_LOGGER(info) << "UDP ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00294 } catch (const ibrcommon::Exception &ex) {
00295 IBRCOMMON_LOGGER(error) << "Failed to add UDP ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00296 }
00297
00298 break;
00299 }
00300
00301 case Configuration::NetConfig::NETWORK_TCP:
00302 {
00303
00304 std::map<Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*>::iterator it = _cl_map.find(net.type);
00305
00306 if (it == _cl_map.end())
00307 {
00308 try {
00309 TCPConvergenceLayer *tcpcl = new TCPConvergenceLayer();
00310 tcpcl->bind(net.interface, net.port);
00311
00312 core.addConvergenceLayer(tcpcl);
00313 components.push_back(tcpcl);
00314 if (ipnd != NULL) ipnd->addService(tcpcl);
00315 _cl_map[net.type] = tcpcl;
00316 IBRCOMMON_LOGGER(info) << "TCP ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00317 } catch (const ibrcommon::Exception &ex) {
00318 IBRCOMMON_LOGGER(error) << "Failed to add TCP ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00319 }
00320 }
00321 else
00322 {
00323 ConvergenceLayer *cl = it->second;
00324 TCPConvergenceLayer &tcpcl = dynamic_cast<TCPConvergenceLayer&>(*(cl));
00325 tcpcl.bind(net.interface, net.port);
00326 }
00327
00328 break;
00329 }
00330
00331 #ifdef HAVE_LIBCURL
00332 case Configuration::NetConfig::NETWORK_HTTP:
00333 {
00334 try {
00335 HTTPConvergenceLayer *httpcl = new HTTPConvergenceLayer( net.url );
00336 core.addConvergenceLayer(httpcl);
00337 components.push_back(httpcl);
00338
00339 IBRCOMMON_LOGGER(info) << "HTTP ConvergenceLayer added, Server: " << net.url << IBRCOMMON_LOGGER_ENDL;
00340 } catch (const ibrcommon::Exception &ex) {
00341 IBRCOMMON_LOGGER(error) << "Failed to add HTTP ConvergenceLayer, Server: " << net.url << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00342 }
00343 break;
00344 }
00345 #endif
00346
00347 #ifdef HAVE_LOWPAN_SUPPORT
00348 case Configuration::NetConfig::NETWORK_LOWPAN:
00349 {
00350 try {
00351 LOWPANConvergenceLayer *lowpancl = new LOWPANConvergenceLayer( net.interface, net.port );
00352 core.addConvergenceLayer(lowpancl);
00353 components.push_back(lowpancl);
00354 if (ipnd != NULL) ipnd->addService(lowpancl);
00355
00356 IBRCOMMON_LOGGER(info) << "LOWPAN ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00357 } catch (const ibrcommon::Exception &ex) {
00358 IBRCOMMON_LOGGER(error) << "Failed to add LOWPAN ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00359 }
00360
00361 break;
00362 }
00363 #endif
00364
00365 default:
00366 break;
00367 }
00368 } catch (const std::exception &ex) {
00369 IBRCOMMON_LOGGER(error) << "Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00370 }
00371 }
00372 }
00373
00374 int __daemon_run(Configuration &conf)
00375 {
00376
00377 signal(SIGINT, sighandler);
00378 signal(SIGTERM, sighandler);
00379 signal(SIGHUP, sighandler);
00380 signal(SIGQUIT, sighandler);
00381 signal(SIGUSR1, sighandler);
00382 signal(SIGUSR2, sighandler);
00383
00384
00385 if (conf.getLogger().display_timestamps())
00386 {
00387 logopts = (~(ibrcommon::Logger::LOG_DATETIME) & logopts) | ibrcommon::Logger::LOG_TIMESTAMP;
00388 }
00389
00390
00391 ibrcommon::Logger::enableAsync();
00392 ibrcommon::Logger::enableSyslog("ibrdtn-daemon", LOG_PID, LOG_DAEMON, logsys);
00393
00394 if (!conf.getDebug().quiet())
00395 {
00396
00397 ibrcommon::Logger::addStream(std::cout, logstd, logopts);
00398
00399
00400 ibrcommon::Logger::addStream(std::cerr, logerr, logopts);
00401 }
00402
00403
00404 IBRCOMMON_LOGGER(info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL;
00405
00406
00407 if (conf.getDebug().enabled() && !conf.getDebug().quiet())
00408 {
00409
00410 ibrcommon::Logger::setVerbosity(conf.getDebug().level());
00411
00412 IBRCOMMON_LOGGER(info) << "debug level set to " << conf.getDebug().level() << IBRCOMMON_LOGGER_ENDL;
00413
00414 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);
00415
00416 _debug = true;
00417 }
00418
00419
00420 conf.load();
00421
00422
00423 switchUser(conf);
00424
00425
00426 setGlobalVars(conf);
00427
00428 #ifdef WITH_BUNDLE_SECURITY
00429 const dtn::daemon::Configuration::Security &sec = conf.getSecurity();
00430
00431 if (sec.enabled())
00432 {
00433
00434 dtn::security::SecurityKeyManager::getInstance().initialize( sec.getPath(), sec.getCA(), sec.getKey() );
00435 }
00436 #endif
00437
00438
00439 std::list< dtn::daemon::Component* > components;
00440
00441
00442 try {
00443 components.push_back( new dtn::daemon::Notifier( conf.getNotifyCommand() ) );
00444 } catch (const Configuration::ParameterNotSetException&) {
00445
00446 }
00447
00448
00449 BundleCore &core = BundleCore::getInstance();
00450
00451
00452 dtn::core::EventSwitch &esw = dtn::core::EventSwitch::getInstance();
00453
00454
00455 createBundleStorage(core, conf, components);
00456
00457
00458 dtn::net::IPNDAgent *ipnd = NULL;
00459
00460 if (conf.getDiscovery().enabled())
00461 {
00462
00463 int disco_port = conf.getDiscovery().port();
00464
00465 try {
00466 ipnd = new dtn::net::IPNDAgent( disco_port, conf.getDiscovery().address() );
00467 } catch (const Configuration::ParameterNotFoundException&) {
00468 ipnd = new dtn::net::IPNDAgent( disco_port, ibrcommon::vaddress(ibrcommon::vaddress::VADDRESS_INET, "255.255.255.255") );
00469 }
00470
00471
00472 std::set<ibrcommon::vinterface> interfaces;
00473
00474 const std::list<Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces();
00475 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00476 {
00477 const Configuration::NetConfig &net = (*iter);
00478 interfaces.insert(net.interface);
00479 }
00480
00481 for (std::set<ibrcommon::vinterface>::const_iterator iter = interfaces.begin(); iter != interfaces.end(); iter++)
00482 {
00483
00484 ipnd->bind(*iter);
00485 }
00486
00487 components.push_back(ipnd);
00488 }
00489 else
00490 {
00491 IBRCOMMON_LOGGER(info) << "Discovery disabled" << IBRCOMMON_LOGGER_ENDL;
00492 }
00493
00494
00495 dtn::routing::BaseRouter *router = new dtn::routing::BaseRouter(core.getStorage());
00496
00497
00498 switch (conf.getNetwork().getRoutingExtension())
00499 {
00500 case Configuration::FLOOD_ROUTING:
00501 {
00502 IBRCOMMON_LOGGER(info) << "Using flooding routing extensions" << IBRCOMMON_LOGGER_ENDL;
00503 dtn::routing::FloodRoutingExtension *flooding = new dtn::routing::FloodRoutingExtension();
00504 router->addExtension( flooding );
00505 break;
00506 }
00507
00508 case Configuration::EPIDEMIC_ROUTING:
00509 {
00510 IBRCOMMON_LOGGER(info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL;
00511 router->addExtension( new dtn::routing::EpidemicRoutingExtension() );
00512 break;
00513 }
00514
00515 default:
00516 IBRCOMMON_LOGGER(info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL;
00517 break;
00518 }
00519
00520
00521 router->addExtension( new dtn::routing::StaticRoutingExtension( conf.getNetwork().getStaticRoutes() ) );
00522 router->addExtension( new dtn::routing::NeighborRoutingExtension() );
00523 router->addExtension( new dtn::routing::RetransmissionExtension() );
00524
00525 components.push_back(router);
00526
00527
00528 if (conf.getNetwork().doForwarding())
00529 {
00530 IBRCOMMON_LOGGER(info) << "Forwarding of bundles enabled." << IBRCOMMON_LOGGER_ENDL;
00531 BundleCore::forwarding = true;
00532 }
00533 else
00534 {
00535 IBRCOMMON_LOGGER(info) << "Forwarding of bundles disabled." << IBRCOMMON_LOGGER_ENDL;
00536 BundleCore::forwarding = false;
00537 }
00538
00539
00540 ibrcommon::LinkManager::initialize();
00541
00542 try {
00543
00544 createConvergenceLayers(core, conf, components, ipnd);
00545 } catch (const std::exception&) {
00546 return -1;
00547 }
00548
00549 if (conf.doAPI())
00550 {
00551 try {
00552 ibrcommon::File socket = conf.getAPISocket();
00553
00554 try {
00555
00556 components.push_back( new ApiServer(socket) );
00557 IBRCOMMON_LOGGER(info) << "API initialized using unix domain socket: " << socket.getPath() << IBRCOMMON_LOGGER_ENDL;
00558 } catch (const ibrcommon::vsocket_exception&) {
00559 IBRCOMMON_LOGGER(error) << "Unable to bind to unix domain socket " << socket.getPath() << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
00560 exit(-1);
00561 }
00562
00563 } catch (const Configuration::ParameterNotSetException&) {
00564 Configuration::NetConfig lo = conf.getAPIInterface();
00565
00566 try {
00567
00568 components.push_back( new ApiServer(lo.interface, lo.port) );
00569 IBRCOMMON_LOGGER(info) << "API initialized using tcp socket: " << lo.interface.toString() << ":" << lo.port << IBRCOMMON_LOGGER_ENDL;
00570 } catch (const ibrcommon::vsocket_exception&) {
00571 IBRCOMMON_LOGGER(error) << "Unable to bind to " << lo.interface.toString() << ":" << lo.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
00572 exit(-1);
00573 }
00574 }
00575 }
00576 else
00577 {
00578 IBRCOMMON_LOGGER(info) << "API disabled" << IBRCOMMON_LOGGER_ENDL;
00579 }
00580
00581
00582 if (conf.getStatistic().enabled())
00583 {
00584 try {
00585 if (conf.getStatistic().type() == "stdout")
00586 {
00587 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatistic().interval() ) );
00588 }
00589 else if (conf.getStatistic().type() == "syslog")
00590 {
00591 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_SYSLOG, conf.getStatistic().interval() ) );
00592 }
00593 else if (conf.getStatistic().type() == "plain")
00594 {
00595 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_PLAIN, conf.getStatistic().interval(), conf.getStatistic().logfile() ) );
00596 }
00597 else if (conf.getStatistic().type() == "csv")
00598 {
00599 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_CSV, conf.getStatistic().interval(), conf.getStatistic().logfile() ) );
00600 }
00601 else if (conf.getStatistic().type() == "stat")
00602 {
00603 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_STAT, conf.getStatistic().interval(), conf.getStatistic().logfile() ) );
00604 }
00605 else if (conf.getStatistic().type() == "udp")
00606 {
00607 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_UDP, conf.getStatistic().interval(), conf.getStatistic().address(), conf.getStatistic().port() ) );
00608 }
00609 } catch (const Configuration::ParameterNotSetException&) {
00610 IBRCOMMON_LOGGER(error) << "StatisticLogger: Parameter statistic_file is not set! Fallback to stdout logging." << IBRCOMMON_LOGGER_ENDL;
00611 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatistic().interval() ) );
00612 }
00613 }
00614
00615
00616 core.initialize();
00617
00618
00619 esw.initialize();
00620
00624 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00625 {
00626 IBRCOMMON_LOGGER_DEBUG(20) << "Initialize component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL;
00627 (*iter)->initialize();
00628 }
00629
00630
00631 core.startup();
00632
00636 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00637 {
00638 IBRCOMMON_LOGGER_DEBUG(20) << "Startup component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL;
00639 (*iter)->startup();
00640 }
00641
00642
00643 Debugger debugger;
00644
00645
00646 EchoWorker echo;
00647
00648
00649 DevNull devnull;
00650
00651
00652 list<Node> static_nodes = conf.getNetwork().getStaticNodes();
00653
00654 for (list<Node>::iterator iter = static_nodes.begin(); iter != static_nodes.end(); iter++)
00655 {
00656 core.addConnection(*iter);
00657 }
00658
00659 #ifdef HAVE_LIBDAEMON
00660 if (conf.getDaemon().daemonize())
00661 {
00662
00663 daemon_retval_send(0);
00664 daemon_log(LOG_INFO, "Sucessfully started");
00665 }
00666 #endif
00667
00668
00669 esw.loop();
00670
00671 IBRCOMMON_LOGGER(info) << "shutdown dtn node" << IBRCOMMON_LOGGER_ENDL;
00672
00673
00674 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00675
00679 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00680 {
00681 IBRCOMMON_LOGGER_DEBUG(20) << "Terminate component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL;
00682 (*iter)->terminate();
00683 }
00684
00685
00686 esw.terminate();
00687
00688
00689 core.terminate();
00690
00691
00692 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00693 {
00694 delete (*iter);
00695 }
00696
00697
00698 ibrcommon::Logger::stop();
00699
00700 return 0;
00701 };
00702
00703 static char* __daemon_pidfile__ = NULL;
00704
00705 static const char* __daemon_pid_file_proc__(void) {
00706 return __daemon_pidfile__;
00707 }
00708
00709 int main(int argc, char *argv[])
00710 {
00711
00712 Configuration &conf = Configuration::getInstance();
00713
00714
00715 conf.params(argc, argv);
00716
00717 #ifdef HAVE_LIBDAEMON
00718 if (conf.getDaemon().daemonize())
00719 {
00720 int ret = 0;
00721 pid_t pid;
00722
00723 #ifdef HAVE_DAEMON_RESET_SIGS
00724
00725 if (daemon_reset_sigs(-1) < 0) {
00726 daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno));
00727 return 1;
00728 }
00729
00730
00731 if (daemon_unblock_sigs(-1) < 0) {
00732 daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno));
00733 return 1;
00734 }
00735 #endif
00736
00737
00738 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]);
00739
00740
00741 try {
00742 std::string p = conf.getDaemon().getPidFile().getPath();
00743 __daemon_pidfile__ = new char[p.length() + 1];
00744 ::strcpy(__daemon_pidfile__, p.c_str());
00745 daemon_pid_file_proc = __daemon_pid_file_proc__;
00746 } catch (const Configuration::ParameterNotSetException&) { };
00747
00748
00749 if (conf.getDaemon().kill_daemon())
00750 {
00751 int ret;
00752
00753
00754
00755
00756 if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0)
00757 daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno));
00758
00759 return ret < 0 ? 1 : 0;
00760 }
00761
00762
00763 if ((pid = daemon_pid_file_is_running()) >= 0) {
00764 daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid);
00765 return 1;
00766 }
00767
00768
00769 if (daemon_retval_init() < 0) {
00770 daemon_log(LOG_ERR, "Failed to create pipe.");
00771 return 1;
00772 }
00773
00774
00775 if ((pid = daemon_fork()) < 0) {
00776
00777
00778 daemon_retval_done();
00779 return 1;
00780
00781 } else if (pid) {
00782 int ret;
00783
00784
00785 if ((ret = daemon_retval_wait(20)) < 0) {
00786 daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno));
00787 return 255;
00788 }
00789
00790
00791 return ret;
00792
00793 } else {
00794
00795 if (daemon_close_all(-1) < 0) {
00796 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno));
00797
00798
00799 daemon_retval_send(1);
00800 goto finish;
00801 }
00802
00803
00804 if (daemon_pid_file_create() < 0) {
00805 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno));
00806 daemon_retval_send(2);
00807 goto finish;
00808 }
00809
00810
00811 if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR1, SIGUSR2, 0) < 0) {
00812 daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno));
00813 daemon_retval_send(3);
00814 goto finish;
00815 }
00816
00817 ret = __daemon_run(conf);
00818
00819 finish:
00820
00821 daemon_log(LOG_INFO, "Exiting...");
00822 daemon_retval_send(255);
00823 daemon_signal_done();
00824 daemon_pid_file_remove();
00825 }
00826
00827 return ret;
00828 } else {
00829 #endif
00830
00831 return __daemon_run(conf);
00832 #ifdef HAVE_LIBDAEMON
00833 }
00834 #endif
00835 }