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