IBR-DTNSuite 0.6

daemon/src/Main.cpp

Go to the documentation of this file.
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 }