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/RetransmissionExtension.h"
00026
00027 #include "net/UDPConvergenceLayer.h"
00028 #include "net/TCPConvergenceLayer.h"
00029
00030 #ifdef HAVE_LIBCURL
00031 #include "net/HTTPConvergenceLayer.h"
00032 #endif
00033
00034 #include "net/IPNDAgent.h"
00035
00036 #include "ApiServer.h"
00037 #include "Configuration.h"
00038 #include "EchoWorker.h"
00039 #include "Notifier.h"
00040 #include "DevNull.h"
00041 #include "StatisticLogger.h"
00042 #include "Component.h"
00043
00044 #include <csignal>
00045 #include <sys/types.h>
00046 #include <syslog.h>
00047 #include <set>
00048
00049 using namespace dtn::core;
00050 using namespace dtn::daemon;
00051 using namespace dtn::utils;
00052 using namespace dtn::net;
00053
00054 #include "Debugger.h"
00055
00056 #define UNIT_MB * 1048576
00057
00058
00059 void term(int signal)
00060 {
00061 if (signal >= 1)
00062 {
00063 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00064 }
00065 }
00066
00067 void reload(int)
00068 {
00069
00070 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_RELOAD);
00071 }
00072
00073 void switchUser(Configuration &config)
00074 {
00075 try {
00076 setuid( config.getUID() );
00077 IBRCOMMON_LOGGER(info) << "Switching UID to " << config.getUID() << IBRCOMMON_LOGGER_ENDL;
00078 } catch (Configuration::ParameterNotSetException ex) {
00079
00080 }
00081
00082 try {
00083 setuid( config.getGID() );
00084 IBRCOMMON_LOGGER(info) << "Switching GID to " << config.getGID() << IBRCOMMON_LOGGER_ENDL;
00085 } catch (Configuration::ParameterNotSetException ex) {
00086
00087 }
00088 }
00089
00090 void setGlobalVars(Configuration &config)
00091 {
00092
00093
00094
00095 dtn::utils::Clock::timezone = config.getTimezone();
00096
00097
00098 dtn::core::BundleCore::local = config.getNodename();
00099 IBRCOMMON_LOGGER(info) << "Local node name: " << config.getNodename() << IBRCOMMON_LOGGER_ENDL;
00100
00101 try {
00102
00103 ibrcommon::BLOB::tmppath = config.getPath("blob");
00104 } catch (Configuration::ParameterNotSetException ex) {
00105
00106 }
00107
00108
00109 dtn::core::BundleCore::blocksizelimit = config.getLimit("blocksize");
00110 if (dtn::core::BundleCore::blocksizelimit > 0)
00111 {
00112 IBRCOMMON_LOGGER(info) << "Block size limited to " << dtn::core::BundleCore::blocksizelimit << " bytes" << IBRCOMMON_LOGGER_ENDL;
00113 }
00114 }
00115
00116 void createBundleStorage(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components)
00117 {
00118 dtn::core::BundleStorage *storage = NULL;
00119
00120 try {
00121
00122
00123 ibrcommon::File path = conf.getPath("storage");
00124
00125
00126 if (!path.exists())
00127 {
00128 ibrcommon::File::createDirectory(path);
00129 }
00130
00131 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(path, conf.getLimit("storage"));
00132 components.push_back(sbs);
00133 storage = sbs;
00134 } catch (Configuration::ParameterNotSetException ex) {
00135 dtn::core::SimpleBundleStorage *sbs = new dtn::core::SimpleBundleStorage(conf.getLimit("storage"));
00136 components.push_back(sbs);
00137 storage = sbs;
00138 }
00139
00140
00141 core.setStorage(storage);
00142 }
00143
00144 void createConvergenceLayers(BundleCore &core, Configuration &conf, std::list< dtn::daemon::Component* > &components, dtn::net::IPNDAgent *ipnd)
00145 {
00146
00147 std::list<Configuration::NetConfig> nets = conf.getInterfaces();
00148
00149
00150 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00151 {
00152 const Configuration::NetConfig &net = (*iter);
00153
00154 try {
00155 switch (net.type)
00156 {
00157 case Configuration::NetConfig::NETWORK_UDP:
00158 {
00159 UDPConvergenceLayer *udpcl = new UDPConvergenceLayer( net.interface, net.port );
00160 core.addConvergenceLayer(udpcl);
00161 components.push_back(udpcl);
00162 if (ipnd != NULL) ipnd->addService(udpcl);
00163
00164 IBRCOMMON_LOGGER(info) << "UDP ConvergenceLayer added on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00165
00166 break;
00167 }
00168
00169 case Configuration::NetConfig::NETWORK_TCP:
00170 {
00171 TCPConvergenceLayer *tcpcl = new TCPConvergenceLayer( net.interface, net.port );
00172 core.addConvergenceLayer(tcpcl);
00173 components.push_back(tcpcl);
00174 if (ipnd != NULL) ipnd->addService(tcpcl);
00175
00176 IBRCOMMON_LOGGER(info) << "TCP ConvergenceLayer added on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00177
00178 break;
00179 }
00180
00181 #ifdef HAVE_LIBCURL
00182 case Configuration::NetConfig::NETWORK_HTTP:
00183 {
00184 HTTPConvergenceLayer *httpcl = new HTTPConvergenceLayer( net.address );
00185 core.addConvergenceLayer(httpcl);
00186 components.push_back(httpcl);
00187
00188 IBRCOMMON_LOGGER(info) << "HTTP ConvergenceLayer added, Server: " << net.address << IBRCOMMON_LOGGER_ENDL;
00189 break;
00190 }
00191 #endif
00192
00193 default:
00194 break;
00195 }
00196 } catch (ibrcommon::SocketException ex) {
00197 IBRCOMMON_LOGGER(error) << "Failed to add TCP ConvergenceLayer on " << net.interface.getAddress() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
00198 IBRCOMMON_LOGGER(error) << " Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00199 throw ex;
00200 }
00201 }
00202 }
00203
00204 int main(int argc, char *argv[])
00205 {
00206
00207 signal(SIGINT, term);
00208 signal(SIGTERM, term);
00209 signal(SIGHUP, reload);
00210
00211
00212 Configuration &conf = Configuration::getInstance();
00213
00214
00215 conf.params(argc, argv);
00216
00217
00218 {
00219
00220 unsigned char logopts = ibrcommon::Logger::LOG_TIMESTAMP | ibrcommon::Logger::LOG_LEVEL;
00221
00222
00223 unsigned int logerr = ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT;
00224
00225
00226 unsigned int logstd = ~(ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT);
00227
00228
00229 ibrcommon::Logger::enableSyslog("ibrdtn-daemon", LOG_PID, LOG_DAEMON, ibrcommon::Logger::LOGGER_INFO | ibrcommon::Logger::LOGGER_NOTICE);
00230
00231 if (!conf.beQuiet())
00232 {
00233
00234 ibrcommon::Logger::addStream(std::cout, logstd, logopts);
00235
00236
00237 ibrcommon::Logger::addStream(std::cerr, logerr, logopts);
00238 }
00239
00240
00241 IBRCOMMON_LOGGER(info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL;
00242
00243
00244 if (conf.doDebug() && !conf.beQuiet())
00245 {
00246
00247 ibrcommon::Logger::setVerbosity(conf.getDebugLevel());
00248
00249 IBRCOMMON_LOGGER(info) << "debug level set to " << conf.getDebugLevel() << IBRCOMMON_LOGGER_ENDL;
00250
00251 ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);
00252 }
00253 }
00254
00255
00256 conf.load();
00257
00258
00259 switchUser(conf);
00260
00261
00262 setGlobalVars(conf);
00263
00264
00265 std::list< dtn::daemon::Component* > components;
00266
00267
00268 try {
00269 components.push_back( new dtn::daemon::Notifier( conf.getNotifyCommand() ) );
00270 } catch (Configuration::ParameterNotSetException ex) {
00271
00272 }
00273
00274
00275 BundleCore &core = BundleCore::getInstance();
00276
00277
00278 dtn::core::EventSwitch &esw = dtn::core::EventSwitch::getInstance();
00279
00280
00281 createBundleStorage(core, conf, components);
00282
00283
00284 dtn::net::IPNDAgent *ipnd = NULL;
00285
00286 if (conf.doDiscovery())
00287 {
00288
00289 int disco_port = conf.getDiscoveryPort();
00290
00291 try {
00292 ipnd = new dtn::net::IPNDAgent( disco_port, conf.getDiscoveryAddress() );
00293 } catch (Configuration::ParameterNotFoundException ex) {
00294 ipnd = new dtn::net::IPNDAgent( disco_port, "255.255.255.255" );
00295 }
00296
00297
00298 std::set<ibrcommon::NetInterface> interfaces;
00299
00300 std::list<Configuration::NetConfig> nets = conf.getInterfaces();
00301 for (std::list<Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00302 {
00303 const Configuration::NetConfig &net = (*iter);
00304 interfaces.insert(net.interface);
00305 }
00306
00307 for (std::set<ibrcommon::NetInterface>::const_iterator iter = interfaces.begin(); iter != interfaces.end(); iter++)
00308 {
00309
00310 ipnd->bind(*iter);
00311 }
00312
00313 components.push_back(ipnd);
00314 }
00315 else
00316 {
00317 IBRCOMMON_LOGGER(info) << "Discovery disabled" << IBRCOMMON_LOGGER_ENDL;
00318 }
00319
00320
00321 dtn::routing::BaseRouter *router = new dtn::routing::BaseRouter(core.getStorage());
00322
00323
00324 switch (conf.getRoutingExtension())
00325 {
00326 case Configuration::EPIDEMIC_ROUTING:
00327 {
00328 IBRCOMMON_LOGGER(info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL;
00329 dtn::routing::EpidemicRoutingExtension *epidemic = new dtn::routing::EpidemicRoutingExtension();
00330 router->addExtension( epidemic );
00331 router->addExtension( new dtn::routing::RetransmissionExtension() );
00332 if (ipnd != NULL) ipnd->addService(epidemic);
00333 break;
00334 }
00335
00336 default:
00337 IBRCOMMON_LOGGER(info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL;
00338 router->addExtension( new dtn::routing::StaticRoutingExtension( conf.getStaticRoutes() ) );
00339 router->addExtension( new dtn::routing::NeighborRoutingExtension() );
00340 break;
00341 }
00342
00343 components.push_back(router);
00344
00345
00346 if (conf.doForwarding())
00347 {
00348 IBRCOMMON_LOGGER(info) << "Forwarding of bundles enabled." << IBRCOMMON_LOGGER_ENDL;
00349 BundleCore::forwarding = true;
00350 }
00351 else
00352 {
00353 IBRCOMMON_LOGGER(info) << "Forwarding of bundles disabled." << IBRCOMMON_LOGGER_ENDL;
00354 BundleCore::forwarding = false;
00355 }
00356
00357
00358 createConvergenceLayers(core, conf, components, ipnd);
00359
00360 if (conf.doAPI())
00361 {
00362 Configuration::NetConfig lo = conf.getAPIInterface();
00363
00364 try {
00365
00366 components.push_back( new ApiServer(lo.interface, lo.port) );
00367 } catch (ibrcommon::SocketException ex) {
00368 IBRCOMMON_LOGGER(error) << "Unable to bind to " << lo.interface.getAddress() << ":" << lo.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
00369 exit(-1);
00370 }
00371 }
00372 else
00373 {
00374 IBRCOMMON_LOGGER(info) << "API disabled" << IBRCOMMON_LOGGER_ENDL;
00375 }
00376
00377
00378 if (conf.useStatLogger())
00379 {
00380 try {
00381 if (conf.getStatLogType() == "stdout")
00382 {
00383 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatLogInterval() ) );
00384 }
00385 else if (conf.getStatLogType() == "syslog")
00386 {
00387 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_SYSLOG, conf.getStatLogInterval() ) );
00388 }
00389 else if (conf.getStatLogType() == "plain")
00390 {
00391 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_PLAIN, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00392 }
00393 else if (conf.getStatLogType() == "csv")
00394 {
00395 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_CSV, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00396 }
00397 else if (conf.getStatLogType() == "stat")
00398 {
00399 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_FILE_STAT, conf.getStatLogInterval(), conf.getStatLogfile() ) );
00400 }
00401 else if (conf.getStatLogType() == "udp")
00402 {
00403 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_UDP, conf.getStatLogInterval(), conf.getStatAddress(), conf.getStatPort() ) );
00404 }
00405 } catch (Configuration::ParameterNotSetException ex) {
00406 IBRCOMMON_LOGGER(error) << "StatisticLogger: Parameter statistic_file is not set! Fallback to stdout logging." << IBRCOMMON_LOGGER_ENDL;
00407 components.push_back( new StatisticLogger( dtn::daemon::StatisticLogger::LOGGER_STDOUT, conf.getStatLogInterval() ) );
00408 }
00409 }
00410
00411
00412 core.initialize();
00413
00414
00415 esw.initialize();
00416
00420 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00421 {
00422 (*iter)->initialize();
00423 }
00424
00425
00426 core.startup();
00427
00431 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00432 {
00433 (*iter)->startup();
00434 }
00435
00436
00437 Debugger debugger;
00438
00439
00440 EchoWorker echo;
00441
00442
00443 DevNull devnull;
00444
00445
00446 list<Node> static_nodes = conf.getStaticNodes();
00447
00448 for (list<Node>::iterator iter = static_nodes.begin(); iter != static_nodes.end(); iter++)
00449 {
00450 core.addConnection(*iter);
00451 }
00452
00453
00454 esw.loop();
00455
00456 IBRCOMMON_LOGGER(info) << "shutdown dtn node" << IBRCOMMON_LOGGER_ENDL;
00457
00458
00459 dtn::core::GlobalEvent::raise(dtn::core::GlobalEvent::GLOBAL_SHUTDOWN);
00460
00464 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00465 {
00466 (*iter)->terminate();
00467 }
00468
00469
00470 esw.terminate();
00471
00472
00473 core.terminate();
00474
00475
00476 for (std::list< dtn::daemon::Component* >::iterator iter = components.begin(); iter != components.end(); iter++ )
00477 {
00478 delete (*iter);
00479 }
00480
00481 return 0;
00482 };