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