• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1