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