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