|
IBR-DTNSuite 0.6
|
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 "api/ApiServer.h" 00048 00049 #include "Configuration.h" 00050 #include "EchoWorker.h" 00051 #include "CapsuleWorker.h" 00052 #include "Notifier.h" 00053 #include "DevNull.h" 00054 #include "StatisticLogger.h" 00055 #include "Component.h" 00056 00057 #ifdef WITH_BUNDLE_SECURITY 00058 #include "security/SecurityManager.h" 00059 #include "security/SecurityKeyManager.h" 00060 #endif 00061 00062 #ifdef WITH_TLS 00063 #include "security/SecurityCertificateManager.h" 00064 #include "security/TLSStreamComponent.h" 00065 #endif 00066 00067 #ifdef HAVE_LIBDAEMON 00068 #include <libdaemon/daemon.h> 00069 #include <string.h> 00070 #endif 00071 00072 #include <csignal> 00073 #include <sys/types.h> 00074 #include <syslog.h> 00075 #include <set> 00076 #include <pwd.h> 00077 00078 using namespace dtn::core; 00079 using namespace dtn::daemon; 00080 using namespace dtn::utils; 00081 using namespace dtn::net; 00082 00083 #include "Debugger.h" 00084 00085 #define UNIT_MB * 1048576 00086 00091 // logging options 00092 unsigned char logopts = ibrcommon::Logger::LOG_DATETIME | ibrcommon::Logger::LOG_LEVEL; 00093 00094 // error filter 00095 const unsigned char logerr = ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT; 00096 00097 // logging filter, everything but debug, err and crit 00098 const unsigned char logstd = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT); 00099 00100 // syslog filter, everything but DEBUG and NOTICE 00101 const unsigned char logsys = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_NOTICE); 00102 00103 // debug off by default 00104 bool _debug = false; 00105 00106 // on interruption do this! 00107 void sighandler(int signal) 00108 { 00109 switch (signal) 00110 { 00111 case SIGTERM: 00112 case SIGINT: 00113 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN); 00114 break; 00115 case SIGUSR1: 00116 // activate debugging 00117 // init logger 00118 ibrcommon::Logger::setVerbosity(99); 00119 IBRCOMMON_LOGGER(info) << "debug level set to 99" << IBRCOMMON_LOGGER_ENDL; 00120 00121 if (!_debug) 00122 { 00123 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts); 00124 _debug = true; 00125 } 00126 break; 00127 case SIGUSR2: 00128 // activate debugging 00129 // init logger 00130 ibrcommon::Logger::setVerbosity(0); 00131 IBRCOMMON_LOGGER(info) << "debug level set to 0" << IBRCOMMON_LOGGER_ENDL; 00132 break; 00133 case SIGHUP: 00134 // send shutdown signal to unbound threads 00135 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_RELOAD); 00136 break; 00137 default: 00138 // dummy handler 00139 break; 00140 } 00141 } 00142 00143 void switchUser(Configuration &config) 00144 { 00145 try { 00146 // get the username if set 00147 std::string username = config.getUser(); 00148 00149 // resolve the username to a valid user id 00150 struct passwd *pw = getpwnam(username.c_str()); 00151 00152 if (pw != NULL) 00153 { 00154 if (setuid( pw->pw_uid ) < 0) return; 00155 setgid( pw->pw_gid ); 00156 00157 IBRCOMMON_LOGGER(info) << "Switching user to " << username << IBRCOMMON_LOGGER_ENDL; 00158 return; 00159 } 00160 } catch (const Configuration::ParameterNotSetException&) { } 00161 00162 try { 00163 setuid( config.getUID() ); 00164 IBRCOMMON_LOGGER(info) << "Switching UID to " << config.getUID() << IBRCOMMON_LOGGER_ENDL; 00165 } catch (const Configuration::ParameterNotSetException&) { } 00166 00167 try { 00168 setgid( config.getGID() ); 00169 IBRCOMMON_LOGGER(info) << "Switching GID to " << config.getGID() << IBRCOMMON_LOGGER_ENDL; 00170 } catch (const Configuration::ParameterNotSetException&) { } 00171 } 00172 00173 void setGlobalVars(Configuration &config) 00174 { 00175 // set the timezone 00176 dtn::utils::Clock::timezone = config.getTimezone(); 00177 00178 // set local eid 00179 dtn::core::BundleCore::local = config.getNodename(); 00180 IBRCOMMON_LOGGER(info) << "Local node name: " << config.getNodename() << IBRCOMMON_LOGGER_ENDL; 00181 00182 // set block size limit 00183 dtn::core::BundleCore::blocksizelimit = config.getLimit("blocksize"); 00184 if (dtn::core::BundleCore::blocksizelimit > 0) 00185 { 00186 IBRCOMMON_LOGGER(info) << "Block size limited to " << dtn::core::BundleCore::blocksizelimit << " bytes" << IBRCOMMON_LOGGER_ENDL; 00187 } 00188 } 00189 00190 void initialize_blobs(Configuration &config) 00191 { 00192 try { 00193 // the configured BLOB path 00194 ibrcommon::File blob_path = config.getPath("blob"); 00195 00196 // check if the BLOB path exists 00197 if (blob_path.exists()) 00198 { 00199 if (blob_path.isDirectory()) 00200 { 00201 IBRCOMMON_LOGGER(info) << "using BLOB path: " << blob_path.getPath() << IBRCOMMON_LOGGER_ENDL; 00202 ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), false); 00203 } 00204 else 00205 { 00206 IBRCOMMON_LOGGER(warning) << "BLOB path exists, but is not a directory! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL; 00207 } 00208 } 00209 else 00210 { 00211 // try to create the BLOB path 00212 ibrcommon::File::createDirectory(blob_path); 00213 00214 if (blob_path.exists()) 00215 { 00216 IBRCOMMON_LOGGER(info) << "using BLOB path: " << blob_path.getPath() << IBRCOMMON_LOGGER_ENDL; 00217 ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), false); 00218 } 00219 else 00220 { 00221 IBRCOMMON_LOGGER(warning) << "Could not create BLOB path! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL; 00222 } 00223 } 00224 } catch (const Configuration::ParameterNotSetException&) { 00225 } 00226 } 00227 00228 void createBundleStorage(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components) 00229 { 00230 dtn::core::BundleStorage *storage = NULL; 00231 00232 #ifdef HAVE_SQLITE 00233 if (conf.getStorage() == "sqlite") 00234 { 00235 try { 00236 // new methods for blobs 00237 ibrcommon::File path = conf.getPath("storage"); 00238 00239 // create workdir if needed 00240 if (!path.exists()) 00241 { 00242 ibrcommon::File::createDirectory(path); 00243 } 00244 00245 IBRCOMMON_LOGGER(info) << "using sqlite bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL; 00246 00247 dtn::core::SQLiteBundleStorage *sbs = new dtn::core::SQLiteBundleStorage(path, conf.getLimit("storage") ); 00248 00249 // use sqlite storage as BLOB provider, auto delete off 00250 ibrcommon::BLOB::changeProvider(sbs, false); 00251 00252 components.push_back(sbs); 00253 storage = sbs; 00254 } catch (const Configuration::ParameterNotSetException&) { 00255 IBRCOMMON_LOGGER(error) << "storage for bundles" << IBRCOMMON_LOGGER_ENDL; 00256 exit(-1); 00257 } 00258 } 00259 #endif 00260 00261 if ((conf.getStorage() == "simple") || (conf.getStorage() == "default")) 00262 { 00263 // default behavior if no bundle storage is set 00264 try { 00265 // new methods for blobs 00266 ibrcommon::File path = conf.getPath("storage"); 00267 00268 // create workdir if needed 00269 if (!path.exists()) 00270 { 00271 ibrcommon::File::createDirectory(path); 00272 } 00273 00274 IBRCOMMON_LOGGER(info) << "using simple bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL; 00275 00276 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(path, conf.getLimit("storage"), conf.getLimit("storage_buffer")); 00277 00278 // initialize BLOB mechanism 00279 initialize_blobs(conf); 00280 00281 components.push_back(sbs); 00282 storage = sbs; 00283 } catch (const Configuration::ParameterNotSetException&) { 00284 IBRCOMMON_LOGGER(info) << "using bundle storage in memory-only mode" << IBRCOMMON_LOGGER_ENDL; 00285 00286 dtn::core::MemoryBundleStorage *sbs = new dtn::core::MemoryBundleStorage(conf.getLimit("storage")); 00287 00288 // initialize BLOB mechanism 00289 initialize_blobs(conf); 00290 00291 components.push_back(sbs); 00292 storage = sbs; 00293 } 00294 } 00295 00296 if (storage == NULL) 00297 { 00298 IBRCOMMON_LOGGER(error) << "bundle storage module \"" << conf.getStorage() << "\" do not exists!" << IBRCOMMON_LOGGER_ENDL; 00299 exit(-1); 00300 } 00301 00302 // set the storage in the core 00303 core.setStorage(storage); 00304 } 00305 00306 void createConvergenceLayers(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components, dtn::net::IPNDAgent *ipnd) 00307 { 00308 // get the configuration of the convergence layers 00309 const std::list<Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces(); 00310 00311 // local cl map 00312 std::map<Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*> _cl_map; 00313 00314 // create the convergence layers 00315 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++) 00316 { 00317 const Configuration::NetConfig &net = (*iter); 00318 00319 try { 00320 switch (net.type) 00321 { 00322 case Configuration::NetConfig::NETWORK_UDP: 00323 { 00324 try { 00325 UDPConvergenceLayer *udpcl = new UDPConvergenceLayer( net.interface, net.port ); 00326 core.addConvergenceLayer(udpcl); 00327 components.push_back(udpcl); 00328 if (ipnd != NULL) ipnd->addService(udpcl); 00329 00330 IBRCOMMON_LOGGER(info) << "UDP ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL; 00331 } catch (const ibrcommon::Exception &ex) { 00332 IBRCOMMON_LOGGER(error) << "Failed to add UDP ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00333 } 00334 00335 break; 00336 } 00337 00338 case Configuration::NetConfig::NETWORK_TCP: 00339 { 00340 // look for an earlier instance of 00341 std::map<Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*>::iterator it = _cl_map.find(net.type); 00342 00343 if (it == _cl_map.end()) 00344 { 00345 try { 00346 TCPConvergenceLayer *tcpcl = new TCPConvergenceLayer(); 00347 tcpcl->bind(net.interface, net.port); 00348 00349 core.addConvergenceLayer(tcpcl); 00350 components.push_back(tcpcl); 00351 if (ipnd != NULL) ipnd->addService(tcpcl); 00352 _cl_map[net.type] = tcpcl; 00353 IBRCOMMON_LOGGER(info) << "TCP ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL; 00354 } catch (const ibrcommon::Exception &ex) { 00355 IBRCOMMON_LOGGER(error) << "Failed to add TCP ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00356 } 00357 } 00358 else 00359 { 00360 ConvergenceLayer *cl = it->second; 00361 TCPConvergenceLayer &tcpcl = dynamic_cast<TCPConvergenceLayer&>(*(cl)); 00362 tcpcl.bind(net.interface, net.port); 00363 } 00364 00365 break; 00366 } 00367 00368 #ifdef HAVE_LIBCURL 00369 case Configuration::NetConfig::NETWORK_HTTP: 00370 { 00371 try { 00372 HTTPConvergenceLayer *httpcl = new HTTPConvergenceLayer( net.url ); 00373 core.addConvergenceLayer(httpcl); 00374 components.push_back(httpcl); 00375 00376 IBRCOMMON_LOGGER(info) << "HTTP ConvergenceLayer added, Server: " << net.url << IBRCOMMON_LOGGER_ENDL; 00377 } catch (const ibrcommon::Exception &ex) { 00378 IBRCOMMON_LOGGER(error) << "Failed to add HTTP ConvergenceLayer, Server: " << net.url << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00379 } 00380 break; 00381 } 00382 #endif 00383 00384 #ifdef HAVE_LOWPAN_SUPPORT 00385 case Configuration::NetConfig::NETWORK_LOWPAN: 00386 { 00387 try { 00388 LOWPANConvergenceLayer *lowpancl = new LOWPANConvergenceLayer( net.interface, net.port ); 00389 core.addConvergenceLayer(lowpancl); 00390 components.push_back(lowpancl); 00391 if (ipnd != NULL) ipnd->addService(lowpancl); 00392 00393 IBRCOMMON_LOGGER(info) << "LOWPAN ConvergenceLayer added on " << net.interface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL; 00394 } catch (const ibrcommon::Exception &ex) { 00395 IBRCOMMON_LOGGER(error) << "Failed to add LOWPAN ConvergenceLayer on " << net.interface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00396 } 00397 00398 break; 00399 } 00400 #endif 00401 00402 default: 00403 break; 00404 } 00405 } catch (const std::exception &ex) { 00406 IBRCOMMON_LOGGER(error) << "Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00407 } 00408 } 00409 } 00410 00411 int __daemon_run(Configuration &conf) 00412 { 00413 // catch process signals 00414 signal(SIGINT, sighandler); 00415 signal(SIGTERM, sighandler); 00416 signal(SIGHUP, sighandler); 00417 signal(SIGQUIT, sighandler); 00418 signal(SIGUSR1, sighandler); 00419 signal(SIGUSR2, sighandler); 00420 00421 sigset_t blockset; 00422 sigemptyset(&blockset); 00423 sigaddset(&blockset, SIGPIPE); 00424 ::sigprocmask(SIG_BLOCK, &blockset, NULL); 00425 00426 // enable timestamps in logging if requested 00427 if (conf.getLogger().display_timestamps()) 00428 { 00429 logopts = (~(ibrcommon::Logger::LOG_DATETIME) & logopts) | ibrcommon::Logger::LOG_TIMESTAMP; 00430 } 00431 00432 // init syslog 00433 ibrcommon::Logger::enableAsync(); // enable asynchronous logging feature (thread-safe) 00434 ibrcommon::Logger::enableSyslog("ibrdtn-daemon", LOG_PID, LOG_DAEMON, logsys); 00435 00436 if (!conf.getDebug().quiet()) 00437 { 00438 // add logging to the cout 00439 ibrcommon::Logger::addStream(std::cout, logstd, logopts); 00440 00441 // add logging to the cerr 00442 ibrcommon::Logger::addStream(std::cerr, logerr, logopts); 00443 } 00444 00445 // greeting 00446 IBRCOMMON_LOGGER(info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL; 00447 00448 // activate debugging 00449 if (conf.getDebug().enabled() && !conf.getDebug().quiet()) 00450 { 00451 // init logger 00452 ibrcommon::Logger::setVerbosity(conf.getDebug().level()); 00453 00454 IBRCOMMON_LOGGER(info) << "debug level set to " << conf.getDebug().level() << IBRCOMMON_LOGGER_ENDL; 00455 00456 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts); 00457 00458 _debug = true; 00459 } 00460 00461 // load the configuration file 00462 conf.load(); 00463 00464 // logfile output stream 00465 ofstream logfile_stream; 00466 00467 try { 00468 const ibrcommon::File &lf = conf.getLogger().getLogfile(); 00469 logfile_stream.open(lf.getPath().c_str(), std::ios::out | std::ios::app); 00470 logfile_stream << "IBR-DTN daemon " << conf.version() << std::endl; 00471 ibrcommon::Logger::addStream(logfile_stream, ~(ibrcommon::Logger::LOGGER_DEBUG), logopts); 00472 IBRCOMMON_LOGGER(info) << "use logfile for output: " << lf.getPath() << IBRCOMMON_LOGGER_ENDL; 00473 } catch (const Configuration::ParameterNotSetException&) { }; 00474 00475 // switch the user is requested 00476 switchUser(conf); 00477 00478 // set global vars 00479 setGlobalVars(conf); 00480 00481 #ifdef WITH_BUNDLE_SECURITY 00482 const dtn::daemon::Configuration::Security &sec = conf.getSecurity(); 00483 00484 if (sec.enabled()) 00485 { 00486 // initialize the key manager for the security extensions 00487 dtn::security::SecurityKeyManager::getInstance().initialize( sec.getPath(), sec.getCA(), sec.getKey() ); 00488 } 00489 #endif 00490 00491 // list of components 00492 std::list< dtn::daemon::Component* > components; 00493 00494 // create a notifier if configured 00495 try { 00496 components.push_back( new dtn::daemon::Notifier( conf.getNotifyCommand() ) ); 00497 } catch (const Configuration::ParameterNotSetException&) { 00498 00499 } 00500 00501 // create the bundle core object 00502 BundleCore &core = BundleCore::getInstance(); 00503 00504 // create the event switch object 00505 dtn::core::EventSwitch &esw = dtn::core::EventSwitch::getInstance(); 00506 00507 // create a storage for bundles 00508 createBundleStorage(core, conf, components); 00509 00510 // initialize the DiscoveryAgent 00511 dtn::net::IPNDAgent *ipnd = NULL; 00512 00513 if (conf.getDiscovery().enabled()) 00514 { 00515 // get the discovery port 00516 int disco_port = conf.getDiscovery().port(); 00517 bool multicast = false; 00518 00519 // collect all interfaces of convergence layer instances 00520 std::set<ibrcommon::vinterface> interfaces; 00521 00522 const std::list<Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces(); 00523 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++) 00524 { 00525 const Configuration::NetConfig &net = (*iter); 00526 interfaces.insert(net.interface); 00527 } 00528 00529 try { 00530 const ibrcommon::vaddress addr = conf.getDiscovery().address(); 00531 multicast = addr.isMulticast(); 00532 ipnd = new dtn::net::IPNDAgent( disco_port, addr ); 00533 } catch (const Configuration::ParameterNotFoundException&) { 00534 ipnd = new dtn::net::IPNDAgent( disco_port, ibrcommon::vaddress(ibrcommon::vaddress::VADDRESS_INET, "255.255.255.255") ); 00535 } 00536 00537 for (std::set<ibrcommon::vinterface>::const_iterator iter = interfaces.begin(); iter != interfaces.end(); iter++) 00538 { 00539 const ibrcommon::vinterface &i = (*iter); 00540 if (i.empty() && multicast) 00541 { 00542 IBRCOMMON_LOGGER(warning) << "Multicast discovery will not work with bind on ANY interfaces." << IBRCOMMON_LOGGER_ENDL; 00543 } 00544 else 00545 { 00546 // add interfaces to discovery 00547 ipnd->bind(*iter); 00548 } 00549 } 00550 00551 components.push_back(ipnd); 00552 } 00553 else 00554 { 00555 IBRCOMMON_LOGGER(info) << "Discovery disabled" << IBRCOMMON_LOGGER_ENDL; 00556 } 00557 00558 // create the base router 00559 dtn::routing::BaseRouter *router = new dtn::routing::BaseRouter(core.getStorage()); 00560 00561 // add routing extensions 00562 switch (conf.getNetwork().getRoutingExtension()) 00563 { 00564 case Configuration::FLOOD_ROUTING: 00565 { 00566 IBRCOMMON_LOGGER(info) << "Using flooding routing extensions" << IBRCOMMON_LOGGER_ENDL; 00567 dtn::routing::FloodRoutingExtension *flooding = new dtn::routing::FloodRoutingExtension(); 00568 router->addExtension( flooding ); 00569 break; 00570 } 00571 00572 case Configuration::EPIDEMIC_ROUTING: 00573 { 00574 IBRCOMMON_LOGGER(info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL; 00575 router->addExtension( new dtn::routing::EpidemicRoutingExtension() ); 00576 break; 00577 } 00578 00579 default: 00580 IBRCOMMON_LOGGER(info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL; 00581 break; 00582 } 00583 00584 // add standard routing modules 00585 router->addExtension( new dtn::routing::StaticRoutingExtension( conf.getNetwork().getStaticRoutes() ) ); 00586 router->addExtension( new dtn::routing::NeighborRoutingExtension() ); 00587 router->addExtension( new dtn::routing::RetransmissionExtension() ); 00588 00589 components.push_back(router); 00590 00591 // enable or disable forwarding of bundles 00592 if (conf.getNetwork().doForwarding()) 00593 { 00594 IBRCOMMON_LOGGER(info) << "Forwarding of bundles enabled." << IBRCOMMON_LOGGER_ENDL; 00595 BundleCore::forwarding = true; 00596 } 00597 else 00598 { 00599 IBRCOMMON_LOGGER(info) << "Forwarding of bundles disabled." << IBRCOMMON_LOGGER_ENDL; 00600 BundleCore::forwarding = false; 00601 } 00602 00603 // enable netlink manager (watchdog for network interfaces) 00604 if (conf.getNetwork().doDynamicRebind()) 00605 { 00606 ibrcommon::LinkManager::initialize(); 00607 } 00608 00609 #ifdef WITH_TLS 00610 /* enable TLS support */ 00611 if ( conf.getSecurity().doTLS() ) 00612 { 00613 components.push_back(new dtn::security::TLSStreamComponent()); 00614 components.push_back(new dtn::security::SecurityCertificateManager()); 00615 IBRCOMMON_LOGGER(info) << "TLS security for TCP convergence layer enabled" << IBRCOMMON_LOGGER_ENDL; 00616 } 00617 #endif 00618 00619 try { 00620 // initialize all convergence layers 00621 createConvergenceLayers(core, conf, components, ipnd); 00622 } catch (const std::exception&) { 00623 return -1; 00624 } 00625 00626 if (conf.doAPI()) 00627 { 00628 Configuration::NetConfig lo = conf.getAPIInterface(); 00629 00630 try { 00631 ibrcommon::File socket = conf.getAPISocket(); 00632 00633 try { 00634 // use unix domain sockets for API 00635 components.push_back( new dtn::api::ApiServer(socket) ); 00636 IBRCOMMON_LOGGER(info) << "API initialized using unix domain socket: " << socket.getPath() << IBRCOMMON_LOGGER_ENDL; 00637 } catch (const ibrcommon::vsocket_exception&) { 00638 IBRCOMMON_LOGGER(error) << "Unable to bind to unix domain socket " << socket.getPath() << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL; 00639 exit(-1); 00640 } 00641 } 00642 catch (const Configuration::ParameterNotSetException&) 00643 { 00644 try { 00645 // instance a API server, first create a socket 00646 components.push_back( new dtn::api::ApiServer(lo.interface, lo.port) ); 00647 IBRCOMMON_LOGGER(info) << "API initialized using tcp socket: " << lo.interface.toString() << ":" << lo.port << IBRCOMMON_LOGGER_ENDL; 00648 } catch (const ibrcommon::vsocket_exception&) { 00649 IBRCOMMON_LOGGER(error) << "Unable to bind to " << lo.interface.toString() << ":" << lo.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL; 00650 exit(-1); 00651 } 00652 } 00653 } 00654 else 00655 { 00656 IBRCOMMON_LOGGER(info) << "API disabled" << IBRCOMMON_LOGGER_ENDL; 00657 } 00658 00659 // create a statistic logger if configured 00660 if (conf.getStatistic().enabled()) 00661 { 00662 try { 00663 if (conf.getStatistic().type() == "stdout") 00664 { 00665 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatistic().interval() ) ); 00666 } 00667 else if (conf.getStatistic().type() == "syslog") 00668 { 00669 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_SYSLOG, conf.getStatistic().interval() ) ); 00670 } 00671 else if (conf.getStatistic().type() == "plain") 00672 { 00673 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_PLAIN, conf.getStatistic().interval(), conf.getStatistic().logfile() ) ); 00674 } 00675 else if (conf.getStatistic().type() == "csv") 00676 { 00677 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_CSV, conf.getStatistic().interval(), conf.getStatistic().logfile() ) ); 00678 } 00679 else if (conf.getStatistic().type() == "stat") 00680 { 00681 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_STAT, conf.getStatistic().interval(), conf.getStatistic().logfile() ) ); 00682 } 00683 else if (conf.getStatistic().type() == "udp") 00684 { 00685 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_UDP, conf.getStatistic().interval(), conf.getStatistic().address(), conf.getStatistic().port() ) ); 00686 } 00687 } catch (const Configuration::ParameterNotSetException&) { 00688 IBRCOMMON_LOGGER(error) << "StatisticLogger: Parameter statistic_file is not set! Fallback to stdout logging." << IBRCOMMON_LOGGER_ENDL; 00689 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatistic().interval() ) ); 00690 } 00691 } 00692 00693 // initialize core component 00694 core.initialize(); 00695 00696 // initialize the event switch 00697 esw.initialize(); 00698 00702 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ ) 00703 { 00704 IBRCOMMON_LOGGER_DEBUG(20) << "Initialize component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL; 00705 (*iter)->initialize(); 00706 } 00707 00708 // run core component 00709 core.startup(); 00710 00714 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ ) 00715 { 00716 IBRCOMMON_LOGGER_DEBUG(20) << "Startup component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL; 00717 (*iter)->startup(); 00718 } 00719 00720 // Debugger 00721 Debugger debugger; 00722 00723 // add echo module 00724 EchoWorker echo; 00725 00726 // add bundle-in-bundle endpoint 00727 CapsuleWorker capsule; 00728 00729 // add DevNull module 00730 DevNull devnull; 00731 00732 // announce static nodes, create a list of static nodes 00733 list<Node> static_nodes = conf.getNetwork().getStaticNodes(); 00734 00735 for (list<Node>::iterator iter = static_nodes.begin(); iter != static_nodes.end(); iter++) 00736 { 00737 core.addConnection(*iter); 00738 } 00739 00740 #ifdef HAVE_LIBDAEMON 00741 if (conf.getDaemon().daemonize()) 00742 { 00743 /* Send OK to parent process */ 00744 daemon_retval_send(0); 00745 daemon_log(LOG_INFO, "Sucessfully started"); 00746 } 00747 #endif 00748 00749 // run the event switch loop forever 00750 esw.loop(); 00751 00752 IBRCOMMON_LOGGER(info) << "shutdown dtn node" << IBRCOMMON_LOGGER_ENDL; 00753 00754 // send shutdown signal to unbound threads 00755 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN); 00756 00760 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ ) 00761 { 00762 IBRCOMMON_LOGGER_DEBUG(20) << "Terminate component " << (*iter)->getName() << IBRCOMMON_LOGGER_ENDL; 00763 (*iter)->terminate(); 00764 } 00765 00766 // terminate event switch component 00767 esw.terminate(); 00768 00769 // terminate core component 00770 core.terminate(); 00771 00772 // delete all components 00773 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ ) 00774 { 00775 delete (*iter); 00776 } 00777 00778 // stop the asynchronous logger 00779 ibrcommon::Logger::stop(); 00780 00781 return 0; 00782 }; 00783 00784 static char* __daemon_pidfile__ = NULL; 00785 00786 static const char* __daemon_pid_file_proc__(void) { 00787 return __daemon_pidfile__; 00788 } 00789 00790 int main(int argc, char *argv[]) 00791 { 00792 // create a configuration 00793 Configuration &conf = Configuration::getInstance(); 00794 00795 // load parameter into the configuration 00796 conf.params(argc, argv); 00797 00798 #ifdef HAVE_LIBDAEMON 00799 if (conf.getDaemon().daemonize()) 00800 { 00801 int ret = 0; 00802 pid_t pid; 00803 00804 #ifdef HAVE_DAEMON_RESET_SIGS 00805 /* Reset signal handlers */ 00806 if (daemon_reset_sigs(-1) < 0) { 00807 daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); 00808 return 1; 00809 } 00810 00811 /* Unblock signals */ 00812 if (daemon_unblock_sigs(-1) < 0) { 00813 daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); 00814 return 1; 00815 } 00816 #endif 00817 00818 /* Set identification string for the daemon for both syslog and PID file */ 00819 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); 00820 00821 /* set the pid file path */ 00822 try { 00823 std::string p = conf.getDaemon().getPidFile().getPath(); 00824 __daemon_pidfile__ = new char[p.length() + 1]; 00825 ::strcpy(__daemon_pidfile__, p.c_str()); 00826 daemon_pid_file_proc = __daemon_pid_file_proc__; 00827 } catch (const Configuration::ParameterNotSetException&) { }; 00828 00829 /* Check if we are called with -k parameter */ 00830 if (conf.getDaemon().kill_daemon()) 00831 { 00832 int ret; 00833 00834 /* Kill daemon with SIGTERM */ 00835 00836 /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ 00837 if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) 00838 daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); 00839 00840 return ret < 0 ? 1 : 0; 00841 } 00842 00843 /* Check that the daemon is not rung twice a the same time */ 00844 if ((pid = daemon_pid_file_is_running()) >= 0) { 00845 daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); 00846 return 1; 00847 } 00848 00849 /* Prepare for return value passing from the initialization procedure of the daemon process */ 00850 if (daemon_retval_init() < 0) { 00851 daemon_log(LOG_ERR, "Failed to create pipe."); 00852 return 1; 00853 } 00854 00855 /* Do the fork */ 00856 if ((pid = daemon_fork()) < 0) { 00857 00858 /* Exit on error */ 00859 daemon_retval_done(); 00860 return 1; 00861 00862 } else if (pid) { /* The parent */ 00863 int ret; 00864 00865 /* Wait for 20 seconds for the return value passed from the daemon process */ 00866 if ((ret = daemon_retval_wait(20)) < 0) { 00867 daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); 00868 return 255; 00869 } 00870 00871 //daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); 00872 return ret; 00873 00874 } else { /* The daemon */ 00875 /* Close FDs */ 00876 if (daemon_close_all(-1) < 0) { 00877 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); 00878 00879 /* Send the error condition to the parent process */ 00880 daemon_retval_send(1); 00881 goto finish; 00882 } 00883 00884 /* Create the PID file */ 00885 if (daemon_pid_file_create() < 0) { 00886 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); 00887 daemon_retval_send(2); 00888 goto finish; 00889 } 00890 00891 /* Initialize signal handling */ 00892 if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR1, SIGUSR2, 0) < 0) { 00893 daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); 00894 daemon_retval_send(3); 00895 goto finish; 00896 } 00897 00898 ret = __daemon_run(conf); 00899 00900 finish: 00901 /* Do a cleanup */ 00902 daemon_log(LOG_INFO, "Exiting..."); 00903 daemon_retval_send(255); 00904 daemon_signal_done(); 00905 daemon_pid_file_remove(); 00906 } 00907 00908 return ret; 00909 } else { 00910 #endif 00911 // run the daemon 00912 return __daemon_run(conf); 00913 #ifdef HAVE_LIBDAEMON 00914 } 00915 #endif 00916 }