IBR-DTNSuite  0.12
NativeDaemon.cpp
Go to the documentation of this file.
1 /*
2  * NativeDaemon.cpp
3  *
4  * Copyright (C) 2013 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "config.h"
23 #include "NativeDaemon.h"
24 
25 #include <ibrcommon/data/BLOB.h>
26 #include <ibrcommon/data/File.h>
28 #include <ibrcommon/Logger.h>
30 #include <ibrdtn/utils/Clock.h>
31 #include <ibrdtn/utils/Utils.h>
33 #include <list>
34 
35 #include "storage/BundleStorage.h"
36 #include "storage/BundleSeeker.h"
39 
40 #include "core/BundleCore.h"
41 #include "net/ConnectionManager.h"
42 #include "core/FragmentManager.h"
43 #include "core/Node.h"
44 #include "core/EventSwitch.h"
45 #include "core/EventDispatcher.h"
46 
47 #include "routing/BaseRouter.h"
54 
55 #include "core/GlobalEvent.h"
64 
68 
69 #ifdef HAVE_SYS_INOTIFY_H
70 #include "net/FileMonitor.h"
71 #endif
72 
74 #include "net/UDPDatagramService.h"
75 
76 #ifdef HAVE_SQLITE
78 #endif
79 
80 #ifdef HAVE_LIBCURL
82 #endif
83 
84 #ifdef HAVE_LOWPAN_SUPPORT
87 #endif
88 
89 #include "net/IPNDAgent.h"
90 
91 #include "api/ApiServer.h"
92 
93 #include "Configuration.h"
94 #include "EchoWorker.h"
95 #include "CapsuleWorker.h"
96 #include "DTNTPWorker.h"
97 #include "DevNull.h"
98 #include "Component.h"
99 
100 #ifdef WITH_WIFIP2P
101 #include "net/WifiP2PManager.h"
102 #endif
103 
104 #ifdef HAVE_VMIME
106 #endif
107 
108 #ifdef WITH_BUNDLE_SECURITY
111 #endif
112 
113 #ifdef WITH_TLS
115 #endif
116 
117 #ifdef WITH_DHT_NAMESERVICE
118 #include "net/DHTNameService.h"
119 #endif
120 
121 #include "Debugger.h"
122 #include "core/EventDebugger.h"
123 
125 #include "core/NodeEvent.h"
126 #include "core/GlobalEvent.h"
127 #include "core/CustodyEvent.h"
129 #include "net/BundleReceivedEvent.h"
132 #include "net/ConnectionEvent.h"
133 
134 #define UNIT_MB * 1048576
135 
136 namespace dtn
137 {
138  namespace daemon
139  {
141  {
142  }
143 
145  {
146  }
147 
148  const std::string NativeDaemon::TAG = "NativeDaemon";
149 
151  : _runlevel(RUNLEVEL_ZERO), _statecb(statecb), _eventcb(eventcb), _event_loop(NULL)
152  {
153 
154  }
155 
157  {
158  }
159 
160  std::vector<std::string> NativeDaemon::getVersion() const throw ()
161  {
162  std::vector<std::string> ret;
163  ret.push_back(VERSION);
164  ret.push_back(BUILD_NUMBER);
165  return ret;
166  }
167 
168  void NativeDaemon::clearStorage() const throw ()
169  {
171  }
172 
173  void NativeDaemon::startDiscovery() const throw ()
174  {
176  }
177 
178  void NativeDaemon::stopDiscovery() const throw ()
179  {
181  }
182 
183  void NativeDaemon::bindEvents()
184  {
185  if (_eventcb != NULL) {
186  // bind to several events
195  }
196  }
197 
198  void NativeDaemon::unbindEvents()
199  {
200  if (_eventcb != NULL) {
201  // unbind to events
210  }
211  }
212 
213  void NativeDaemon::addEventData(const dtn::data::Bundle &b, std::vector<std::string> &data) const
214  {
215  // add the bundle data
216  data.push_back("Source: " + b.source.getString());
217  data.push_back("Timestamp: " + b.timestamp.toString());
218  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
219  data.push_back("Lifetime: " + b.lifetime.toString());
220  data.push_back("Procflags: " + b.procflags.toString());
221 
222  // add the destination eid
223  data.push_back("Destination: " + b.destination.getString());
224 
226  {
227  // add fragmentation values
228  data.push_back("Appdatalength: " + b.appdatalength.toString());
229  data.push_back("Fragmentoffset: " + b.fragmentoffset.toString());
230  }
231  }
232 
233  void NativeDaemon::addEventData(const dtn::data::MetaBundle &b, std::vector<std::string> &data) const
234  {
235  // add the bundle data
236  data.push_back("Source: " + b.source.getString());
237  data.push_back("Timestamp: " + b.timestamp.toString());
238  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
239  data.push_back("Lifetime: " + b.lifetime.toString());
240  data.push_back("Procflags: " + b.procflags.toString());
241 
242  // add the destination eid
243  data.push_back("Destination: " + b.destination.getString());
244 
246  {
247  // add fragmentation values
248  data.push_back("Appdatalength: " + b.appdatalength.toString());
249  data.push_back("Fragmentoffset: " + b.fragmentoffset.toString());
250  }
251  }
252 
253  void NativeDaemon::addEventData(const dtn::data::BundleID &b, std::vector<std::string> &data) const
254  {
255  // add the bundle data
256  data.push_back("Source: " + b.source.getString());
257  data.push_back("Timestamp: " + b.timestamp.toString());
258  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
259 
260  if (b.isFragment())
261  {
262  // add fragmentation values
263  data.push_back("Fragmentoffset: " + b.fragmentoffset.toString());
264  data.push_back("Fragmentpayload: " + b.getPayloadLength());
265  }
266  }
267 
268  void NativeDaemon::raiseEvent(const dtn::core::Event *evt) throw ()
269  {
270  const std::string event = evt->getName();
271  std::string action;
272  std::vector<std::string> data;
273 
274  try {
275  const dtn::core::NodeEvent &node = dynamic_cast<const dtn::core::NodeEvent&>(*evt);
276 
277  // set action
278  switch (node.getAction())
279  {
281  action = "available";
282  break;
284  action = "unavailable";
285  break;
287  action = "data_added";
288  break;
290  action = "data_removed";
291  break;
292  default:
293  break;
294  }
295 
296  // add the node eid
297  data.push_back("EID: " + node.getNode().getEID().getString());
298  } catch (const std::bad_cast&) { };
299 
300  try {
301  const dtn::core::GlobalEvent &global = dynamic_cast<const dtn::core::GlobalEvent&>(*evt);
302 
303  // set action
304  switch (global.getAction())
305  {
307  action = "busy";
308  break;
310  action = "idle";
311  break;
313  action = "resume";
314  break;
316  action = "reload";
317  break;
319  action = "shutdown";
320  break;
322  action = "suspend";
323  break;
325  action = "internet available";
326  break;
328  action = "internet unavailable";
329  break;
331  action = "discovery start";
332  break;
334  action = "discovery stop";
335  break;
336  default:
337  break;
338  }
339  } catch (const std::bad_cast&) { };
340 
341  try {
342  const dtn::net::BundleReceivedEvent &received = dynamic_cast<const dtn::net::BundleReceivedEvent&>(*evt);
343 
344  // set action
345  action = "received";
346 
347  data.push_back("Peer: " + received.peer.getString());
348  data.push_back("Local: " + (received.fromlocal ? std::string("true") : std::string("false")));
349 
350  // add bundle data
351  addEventData(received.bundle, data);
352  } catch (const std::bad_cast&) { };
353 
354  try {
355  const dtn::core::CustodyEvent &custody = dynamic_cast<const dtn::core::CustodyEvent&>(*evt);
356 
357  // set action
358  switch (custody.getAction())
359  {
361  action = "accept";
362  break;
364  action = "reject";
365  break;
366  default:
367  break;
368  }
369 
370  // add bundle data
371  addEventData(custody.getBundle(), data);
372  } catch (const std::bad_cast&) { };
373 
374  try {
375  const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
376 
377  // set action
378  action = "aborted";
379 
380  data.push_back("Peer: " + aborted.getPeer().getString());
381 
382  // add bundle data
383  addEventData(aborted.getBundleID(), data);
384  } catch (const std::bad_cast&) { };
385 
386  try {
387  const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
388 
389  // set action
390  action = "completed";
391 
392  data.push_back("Peer: " + completed.getPeer().getString());
393 
394  // add bundle data
395  addEventData(completed.getBundle(), data);
396  } catch (const std::bad_cast&) { };
397 
398  try {
399  const dtn::net::ConnectionEvent &connection = dynamic_cast<const dtn::net::ConnectionEvent&>(*evt);
400 
401  // set action
402  switch (connection.getState())
403  {
405  action = "up";
406  break;
408  action = "down";
409  break;
411  action = "setup";
412  break;
414  action = "timeout";
415  break;
416  default:
417  break;
418  }
419 
420  // write the peer eid
421  data.push_back("Peer: " + connection.getNode().getEID().getString());
422  } catch (const std::bad_cast&) { };
423 
424  try {
425  const dtn::routing::QueueBundleEvent &queued = dynamic_cast<const dtn::routing::QueueBundleEvent&>(*evt);
426 
427  // set action
428  action = "queued";
429 
430  // add bundle data
431  addEventData(queued.bundle, data);
432  } catch (const std::bad_cast&) { };
433 
434  // signal event to the callback interface
435  _eventcb->eventRaised(event, action, data);
436  }
437 
438  std::string NativeDaemon::getLocalUri() const throw ()
439  {
441  }
442 
444  {
445  NativeStats ret;
446 
447  ret.uptime = dtn::utils::Clock::getUptime().get<size_t>();
448  ret.timestamp = dtn::utils::Clock::getTime().get<size_t>();
451 
455 
464 
467 
470 
471  for (dtn::net::ConvergenceLayer::stats_data::const_iterator iter = data.begin(); iter != data.end(); ++iter) {
472  const dtn::net::ConvergenceLayer::stats_pair &pair = (*iter);
473  ret.addData(pair.first, pair.second);
474  }
475 
476  return ret;
477  }
478 
479  NativeNode NativeDaemon::getInfo(const std::string &neighbor_eid) const throw (NativeDaemonException)
480  {
481  NativeNode nn(neighbor_eid);
482 
483  dtn::data::EID eid(neighbor_eid);
484  try {
486  dtn::core::Node::URI uri = n.getAll().front();
487  switch (uri.type) {
489  throw NativeDaemonException("Node is not available");
490  break;
491 
494  break;
495 
498  break;
499 
502  break;
503 
506  break;
507 
510  break;
511 
514  break;
515  }
516  } catch (const NeighborNotAvailableException &ex) {
517  throw NativeDaemonException(ex.what());
518  }
519 
520  return nn;
521  }
522 
523  std::vector<std::string> NativeDaemon::getNeighbors() const throw ()
524  {
525  std::vector<std::string> ret;
526 
527  // get neighbors
528  const std::set<dtn::core::Node> nlist = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
529  for (std::set<dtn::core::Node>::const_iterator iter = nlist.begin(); iter != nlist.end(); ++iter)
530  {
531  const dtn::core::Node &n = (*iter);
532  ret.push_back(n.getEID().getString());
533  }
534 
535  return ret;
536  }
537 
538  void NativeDaemon::addConnection(std::string eid, std::string protocol, std::string address, std::string service, bool local) const throw ()
539  {
540  dtn::core::Node n(eid);
542 
543  if (local) t = dtn::core::Node::NODE_STATIC_LOCAL;
544 
545  if (protocol == "tcp")
546  {
547  std::string uri = "ip=" + address + ";port=" + service + ";";
550  }
551  else if (protocol == "udp")
552  {
553  std::string uri = "ip=" + address + ";port=" + service + ";";
556  }
557  else if (protocol == "file")
558  {
561  }
562  }
563 
564  void NativeDaemon::removeConnection(std::string eid, std::string protocol, std::string address, std::string service, bool local) const throw ()
565  {
566  dtn::core::Node n(eid);
568 
569  if (local) t = dtn::core::Node::NODE_STATIC_LOCAL;
570 
571  if (protocol == "tcp")
572  {
573  std::string uri = "ip=" + address + ";port=" + service + ";";
576  }
577  else if (protocol == "udp")
578  {
579  std::string uri = "ip=" + address + ";port=" + service + ";";
582  }
583  else if (protocol == "file")
584  {
587  }
588  }
589 
590  void NativeDaemon::initiateConnection(std::string eid)
591  {
592  dtn::data::EID neighbor(eid);
594 
595  try {
596  const dtn::core::Node n = cm.getNeighbor(neighbor);
597  cm.open(n);
598  } catch (const ibrcommon::Exception&) {
599  // ignore errors
600  }
601  }
602 
603  void NativeDaemon::setLogging(const std::string &defaultTag, int logLevel) const throw ()
604  {
609  // set default logging
611 
612  // activate info messages and warnings
613  if (logLevel > 0) {
616  }
617 
618  // activate frequent notice messages
619  if (logLevel > 1) {
621  }
622 
623  // activate debugging
624  if (logLevel > 2) {
626  }
627 
628  // set default logging tag
630 
631  // enable logging to Android's logcat
632  ibrcommon::Logger::enableSyslog("ibrdtn-daemon", 0, 0, logsys);
633  }
634 
635  void NativeDaemon::setConfigFile(const std::string &path)
636  {
637  _config_file = ibrcommon::File(path);
638 
639  // load the configuration file
641  conf.load(_config_file.getPath());
642 
643  // reload bundle core configuration
645 
646 #ifdef WITH_BUNDLE_SECURITY
647  // initialize the key manager for the security extensions
649 #endif
650  }
651 
655  void NativeDaemon::setLogFile(const std::string &path, int logLevel) const throw ()
656  {
657  // logging options
659 
660  // set default logging
662 
663  // deactivate logging if logLevel is below zero
664  if (logLevel < 0) {
665  logsys = 0;
666  }
667 
668  // activate info messages and warnings
669  if (logLevel > 0) {
672  }
673 
674  // activate frequent notice messages
675  if (logLevel > 1) {
677  }
678 
679  // activate debugging
680  if (logLevel > 2) {
682  }
683 
684  const ibrcommon::File lf(path);
685  ibrcommon::Logger::setLogfile(lf, logsys, logopts);
686  }
687 
689  {
690  return _runlevel;
691  }
692 
694  {
695  ibrcommon::MutexLock l(_runlevel_cond);
696  if (_runlevel < rl) {
697  for (; _runlevel < rl; _runlevel = DaemonRunLevel(_runlevel + 1)) {
698  init_up(DaemonRunLevel(_runlevel + 1));
699  _runlevel_cond.signal(true);
700  }
701  } else if (_runlevel > rl) {
702  for (; _runlevel > rl; _runlevel = DaemonRunLevel(_runlevel - 1)) {
703  init_down(_runlevel);
704  _runlevel_cond.signal(true);
705  }
706  }
707  }
708 
709  void NativeDaemon::init_up(DaemonRunLevel rl) throw (NativeDaemonException)
710  {
711  switch (rl) {
712  case RUNLEVEL_ZERO:
713  // nothing to do here
714  break;
715 
716  case RUNLEVEL_CORE:
717  init_core();
718  break;
719 
720  case RUNLEVEL_STORAGE:
721  init_storage();
722  break;
723 
724  case RUNLEVEL_ROUTING:
725  init_routing();
726  break;
727 
728  case RUNLEVEL_API:
729  init_api();
730  break;
731 
732  case RUNLEVEL_NETWORK:
733  init_network();
734  break;
735 
737  init_routing_extensions();
738  break;
739  }
740 
744  component_list &components = _components[rl];
745  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
746  {
747  (*it)->initialize();
748  }
749 
753  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
754  {
755  (*it)->startup();
756  }
757 
758  if (_statecb != NULL) {
759  _statecb->levelChanged(rl);
760  }
761 
762  IBRCOMMON_LOGGER_DEBUG_TAG(NativeDaemon::TAG, 5) << "runlevel " << rl << " reached" << IBRCOMMON_LOGGER_ENDL;
763  }
764 
765  void NativeDaemon::init_down(DaemonRunLevel rl) throw (NativeDaemonException)
766  {
770  component_list &components = _components[rl];
771  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
772  {
773  (*it)->terminate();
774  }
775 
776  switch (rl) {
777  case RUNLEVEL_ZERO:
778  // nothing to do here
779  break;
780 
781  case RUNLEVEL_CORE:
782  shutdown_core();
783  break;
784 
785  case RUNLEVEL_STORAGE:
786  shutdown_storage();
787  break;
788 
789  case RUNLEVEL_ROUTING:
790  shutdown_routing();
791  break;
792 
793  case RUNLEVEL_API:
794  shutdown_api();
795  break;
796 
797  case RUNLEVEL_NETWORK:
798  shutdown_network();
799  break;
800 
802  shutdown_routing_extensions();
803  break;
804  }
805 
809  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
810  {
811  delete (*it);
812  }
813  components.clear();
814 
815  if (_statecb != NULL) {
816  _statecb->levelChanged(DaemonRunLevel(rl-1));
817  }
818 
819  IBRCOMMON_LOGGER_DEBUG_TAG(NativeDaemon::TAG, 5) << "runlevel " << (rl-1) << " reached" << IBRCOMMON_LOGGER_ENDL;
820  }
821 
823  {
824  try {
825  ibrcommon::MutexLock l(_runlevel_cond);
826  while (_runlevel != rl) _runlevel_cond.wait();
828  // wait aborted
829  }
830  }
831 
832  void NativeDaemon::init_core() throw (NativeDaemonException)
833  {
834  // enable link manager
836 
837  // get the core
839 
840  // reset and get configuration
842 
843  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL;
844 
845  // load configuration
846  if (_config_file.exists()) {
847  conf.load(_config_file.getPath());
848  } else {
849  conf.load();
850  }
851 
852  //configure link manager
853  size_t interval = conf.getNetwork().getLinkRequestInterval();
855 
856  // greeting
857  if (conf.getDebug().enabled())
858  {
859  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "debug level set to " << conf.getDebug().level() << IBRCOMMON_LOGGER_ENDL;
860  }
861 
862  try {
863  const ibrcommon::File &lf = conf.getLogger().getLogfile();
864  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "use logfile for output: " << lf.getPath() << IBRCOMMON_LOGGER_ENDL;
866 
867  if (conf.getDaemon().getThreads() > 1)
868  {
869  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Parallel event processing enabled using " << conf.getDaemon().getThreads() << " processes." << IBRCOMMON_LOGGER_ENDL;
870  }
871 
872  // initialize the event switch
874 
875  // listen to events
876  bindEvents();
877 
878  // create a thread for the main loop
879  _event_loop = new NativeEventLoop(*this);
880 
881  // start the event switch
882  _event_loop->start();
883 
884 #ifdef WITH_TLS
885  /* enable TLS support */
886  if ( conf.getSecurity().doTLS() )
887  {
888  _components[RUNLEVEL_CORE].push_back(new dtn::security::SecurityCertificateManager());
889  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "TLS security enabled" << IBRCOMMON_LOGGER_ENDL;
890  }
891 #endif
892 
893 #ifdef WITH_BUNDLE_SECURITY
894  // initialize the key manager for the security extensions
896 #endif
897 
898  // initialize core component
899  core.initialize();
900  }
901 
902  void NativeDaemon::shutdown_core() throw (NativeDaemonException)
903  {
904  // shutdown the event switch
905  _event_loop->stop();
906  _event_loop->join();
907 
908  delete _event_loop;
909  _event_loop = NULL;
910 
911  // unlisten to events
912  unbindEvents();
913 
914  // get the core
916 
917  // shutdown the core component
918  core.terminate();
919 
920 #ifdef WITH_BUNDLE_SECURITY
921  // reset configuration
923 
924  // initialize the key manager for the security extensions
926 #endif
927  }
928 
929  void NativeDaemon::init_storage() throw (NativeDaemonException)
930  {
932 
933  // create a storage for bundles
934  dtn::storage::BundleStorage *storage = NULL;
935 
936 #ifdef HAVE_SQLITE
937  if (conf.getStorage() == "sqlite")
938  {
939  try {
940  // new methods for blobs
941  ibrcommon::File path = conf.getPath("storage");
942 
943  // create workdir if needed
944  if (!path.exists())
945  {
947  }
948 
949  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using sqlite bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
950 
951 
953  if (conf.getUsePersistentBundleSets())
954  {
955  sbs = new dtn::storage::SQLiteBundleStorage(path, conf.getLimit("storage"), true);
956  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using persistent bundle-sets" << IBRCOMMON_LOGGER_ENDL;
957  }
958  else
959  {
960  sbs = new dtn::storage::SQLiteBundleStorage(path, conf.getLimit("storage"), false);
961  }
962 
963  _components[RUNLEVEL_STORAGE].push_back(sbs);
964  storage = sbs;
966  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "storage for bundles" << IBRCOMMON_LOGGER_ENDL;
967  throw NativeDaemonException("initialization of the bundle storage failed");
968  }
969  }
970 
971 
972 #endif
973 
974  if ((conf.getStorage() == "simple") || (conf.getStorage() == "default"))
975  {
976  // default behavior if no bundle storage is set
977  try {
978  // new methods for blobs
979  ibrcommon::File path = conf.getPath("storage");
980 
981  // create workdir if needed
982  if (!path.exists()) ibrcommon::File::createDirectory(path);
983 
984  if (conf.getUsePersistentBundleSets())
985  {
986  dtn::data::MemoryBundleSet::setPath(path.get("bundle-set"));
987  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using persistent bundle-sets" << IBRCOMMON_LOGGER_ENDL;
988  }
989 
990  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using simple bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
991  dtn::storage::SimpleBundleStorage *sbs = new dtn::storage::SimpleBundleStorage(path, conf.getLimit("storage"), static_cast<unsigned int>(conf.getLimit("storage_buffer")));
992  _components[RUNLEVEL_STORAGE].push_back(sbs);
993  storage = sbs;
995  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using bundle storage in memory-only mode" << IBRCOMMON_LOGGER_ENDL;
997  _components[RUNLEVEL_STORAGE].push_back(sbs);
998  storage = sbs;
999  }
1000  }
1001 
1002  if (storage == NULL)
1003  {
1004  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "bundle storage module \"" << conf.getStorage() << "\" do not exists!" << IBRCOMMON_LOGGER_ENDL;
1005  throw NativeDaemonException("bundle storage not available");
1006  }
1007 
1008  // set the storage in the core
1010 
1011  // use scheduling?
1012  if (dtn::daemon::Configuration::getInstance().getNetwork().doScheduling())
1013  {
1014  // create a new bundle index
1016 
1017  // attach index to the storage
1018  storage->attach(bundle_index);
1019 
1020  // set this bundle index as default bundle seeker which is used to find bundles to transfer
1022 
1023  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Enable extended bundle index for scheduling" << IBRCOMMON_LOGGER_ENDL;
1024  } else {
1025  // set the storage as default seeker
1027  }
1028 
1032  try {
1033  // the configured BLOB path
1034  ibrcommon::File blob_path = conf.getPath("blob");
1035 
1036  // check if the BLOB path exists
1037  if (!blob_path.exists()) {
1038  // try to create the BLOB path
1040  }
1041 
1042  if (blob_path.exists() && blob_path.isDirectory())
1043  {
1044  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using BLOB path: " << blob_path.getPath() << IBRCOMMON_LOGGER_ENDL;
1046  }
1047  else
1048  {
1049  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, warning) << "BLOB path exists, but is not a directory! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL;
1051  }
1053  }
1054 
1055  void NativeDaemon::shutdown_storage() const throw (NativeDaemonException)
1056  {
1057  // reset BLOB provider to memory based
1059 
1060  // set the seeker in the core to NULL
1062 
1063  // set the storage in the core to NULL
1065  }
1066 
1067  void NativeDaemon::init_routing() throw (NativeDaemonException)
1068  {
1069  // create the base router
1071 
1072  // add the router to the components list
1073  _components[RUNLEVEL_ROUTING].push_back(router);
1074  }
1075 
1076  void NativeDaemon::shutdown_routing() const throw (NativeDaemonException)
1077  {
1078  }
1079 
1080  void NativeDaemon::init_api() throw (NativeDaemonException)
1081  {
1083 
1084  // create event debugger
1085  _components[RUNLEVEL_API].push_back( new dtn::core::EventDebugger() );
1086 
1087  // Debugger
1088  _apps.push_back( new dtn::daemon::Debugger() );
1089 
1090  // add echo module
1091  _apps.push_back( new dtn::daemon::EchoWorker() );
1092 
1093  // add bundle-in-bundle endpoint
1094  _apps.push_back( new dtn::daemon::CapsuleWorker() );
1095 
1096  // add DT-NTP worker
1097  _apps.push_back( new dtn::daemon::DTNTPWorker() );
1098 
1099  // add DevNull module
1100  _apps.push_back( new dtn::daemon::DevNull() );
1101 
1102  if (conf.getNetwork().doFragmentation())
1103  {
1104  // manager class for fragmentations
1105  _components[RUNLEVEL_API].push_back( new dtn::core::FragmentManager() );
1106  }
1107 
1108 #ifndef ANDROID
1109  if (conf.doAPI())
1110  {
1111  try {
1112  ibrcommon::File socket = conf.getAPISocket();
1113 
1114  try {
1115  // use unix domain sockets for API
1116  _components[RUNLEVEL_API].push_back(new dtn::api::ApiServer(socket));
1117  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "API initialized using unix domain socket: " << socket.getPath() << IBRCOMMON_LOGGER_ENDL;
1118  } catch (const ibrcommon::socket_exception&) {
1119  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Unable to bind to unix domain socket " << socket.getPath() << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
1120  exit(-1);
1121  }
1124 
1125  try {
1126  // instance a API server, first create a socket
1127  _components[RUNLEVEL_API].push_back(new dtn::api::ApiServer(apiconf.iface, apiconf.port));
1128  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "API initialized using tcp socket: " << apiconf.iface.toString() << ":" << apiconf.port << IBRCOMMON_LOGGER_ENDL;
1129  } catch (const ibrcommon::socket_exception&) {
1130  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Unable to bind to " << apiconf.iface.toString() << ":" << apiconf.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
1131  exit(-1);
1132  }
1133  };
1134  }
1135  else
1136  {
1137  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "API disabled" << IBRCOMMON_LOGGER_ENDL;
1138  }
1139 #endif
1140  }
1141 
1142  void NativeDaemon::shutdown_api() throw (NativeDaemonException)
1143  {
1144  for (app_list::iterator it = _apps.begin(); it != _apps.end(); ++it)
1145  {
1146  delete (*it);
1147  }
1148  _apps.clear();
1149  }
1150 
1151  void NativeDaemon::init_network() throw (NativeDaemonException)
1152  {
1155 
1156  // get the configuration of the convergence layers
1157  const std::list<dtn::daemon::Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces();
1158 
1159  // local cl map
1160  std::map<dtn::daemon::Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*> _cl_map;
1161 
1162  // holder for file convergence layer
1163  FileConvergenceLayer *filecl = NULL;
1164 
1165  // add file monitor
1166 #ifdef HAVE_SYS_INOTIFY_H
1167  FileMonitor *fm = NULL;
1168 #endif
1169 
1170  // create the convergence layers
1171  for (std::list<dtn::daemon::Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); ++iter)
1172  {
1173  const dtn::daemon::Configuration::NetConfig &net = (*iter);
1174 
1175  try {
1176  switch (net.type)
1177  {
1179  {
1180  try {
1181  if (filecl == NULL)
1182  {
1183  filecl = new FileConvergenceLayer();
1184  _components[RUNLEVEL_NETWORK].push_back(filecl);
1185  }
1186 
1187 #ifdef HAVE_SYS_INOTIFY_H
1188  if (net.url.size() > 0)
1189  {
1190  ibrcommon::File path(net.url);
1191 
1192  if (path.exists())
1193  {
1194  if (fm == NULL)
1195  {
1196  fm = new FileMonitor();
1197  _components[RUNLEVEL_NETWORK].push_back(fm);
1198  }
1199  ibrcommon::File path(net.url);
1200  fm->watch(path);
1201  }
1202  }
1203 #endif
1204  } catch (const ibrcommon::Exception &ex) {
1205  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add FileConvergenceLayer: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1206  }
1207  break;
1208  }
1209 
1211  {
1212  try {
1213  _components[RUNLEVEL_NETWORK].push_back( new dtn::net::UDPConvergenceLayer( net.iface, net.port, net.mtu ) );
1214  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "UDP ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1215  } catch (const ibrcommon::Exception &ex) {
1216  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add UDP ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1217  }
1218 
1219  break;
1220  }
1221 
1223  {
1224  // look for an earlier instance of
1225  std::map<dtn::daemon::Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*>::iterator it = _cl_map.find(net.type);
1226 
1227  TCPConvergenceLayer *tcpcl = NULL;
1228 
1229  if (it == _cl_map.end()) {
1230  tcpcl = new TCPConvergenceLayer();
1231  } else {
1232  tcpcl = dynamic_cast<TCPConvergenceLayer*>(it->second);
1233  }
1234 
1235  try {
1236  tcpcl->add(net.iface, net.port);
1237 
1238  if (it == _cl_map.end()) {
1239  _components[RUNLEVEL_NETWORK].push_back(tcpcl);
1240  _cl_map[net.type] = tcpcl;
1241  }
1242 
1243  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "TCP ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1244  } catch (const ibrcommon::Exception &ex) {
1245  if (it == _cl_map.end()) {
1246  delete tcpcl;
1247  }
1248 
1249  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add TCP ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1250  }
1251 
1252  break;
1253  }
1254 
1255 #ifdef HAVE_LIBCURL
1257  {
1258  try {
1259  _components[RUNLEVEL_NETWORK].push_back( new HTTPConvergenceLayer( net.url ) );
1260  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "HTTP ConvergenceLayer added, Server: " << net.url << IBRCOMMON_LOGGER_ENDL;
1261  } catch (const ibrcommon::Exception &ex) {
1262  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add HTTP ConvergenceLayer, Server: " << net.url << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1263  }
1264  break;
1265  }
1266 #endif
1267 
1268 #ifdef HAVE_LOWPAN_SUPPORT
1270  {
1271  try {
1272  _components[RUNLEVEL_NETWORK].push_back( new LOWPANConvergenceLayer( net.iface, static_cast<uint16_t>(net.port) ) );
1273  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "LOWPAN ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1274  } catch (const ibrcommon::Exception &ex) {
1275  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add LOWPAN ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1276  }
1277 
1278  break;
1279  }
1280 
1282  {
1283  try {
1284  LOWPANDatagramService *lowpan_service = new LOWPANDatagramService( net.iface, static_cast<uint16_t>(net.port) );
1285  _components[RUNLEVEL_NETWORK].push_back( new DatagramConvergenceLayer(lowpan_service) );
1286  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Datagram ConvergenceLayer (LowPAN) added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1287  } catch (const ibrcommon::Exception &ex) {
1288  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add Datagram ConvergenceLayer (LowPAN) on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1289  }
1290  break;
1291  }
1292 #endif
1293 
1295  {
1296  try {
1297  UDPDatagramService *dgram_service = new UDPDatagramService( net.iface, net.port, net.mtu );
1298  _components[RUNLEVEL_NETWORK].push_back( new DatagramConvergenceLayer(dgram_service) );
1299  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Datagram ConvergenceLayer (UDP) added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1300  } catch (const ibrcommon::Exception &ex) {
1301  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add Datagram ConvergenceLayer (UDP) on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1302  }
1303  break;
1304  }
1305 
1306 #ifdef HAVE_VMIME
1308  {
1309  try {
1310  _components[RUNLEVEL_NETWORK].push_back( new EMailConvergenceLayer() );
1311  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "EMail Convergence Layer (MCL) added" << IBRCOMMON_LOGGER_ENDL;
1312  }catch(const ibrcommon::Exception &ex) {
1313  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add EMail Convergence Layer (MCL): " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1314  }
1315  break;
1316  }
1317 #endif
1318 
1319  default:
1320  break;
1321  }
1322  } catch (const std::exception &ex) {
1323  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1324  }
1325  }
1326 
1327  /****
1328  * Init DHT
1329  */
1330 
1331 #ifdef WITH_DHT_NAMESERVICE
1332  // create dht naming service if configured
1333  if (conf.getDHT().enabled()) {
1334  IBRCOMMON_LOGGER_DEBUG_TAG(NativeDaemon::TAG, 50) << "DHT: is enabled!" << IBRCOMMON_LOGGER_ENDL;
1335  _components[RUNLEVEL_NETWORK].push_back( new dtn::dht::DHTNameService() );
1336  }
1337 #endif
1338 
1339 #ifdef WITH_WIFIP2P
1340  if (conf.getP2P().enabled())
1341  {
1342  const std::string wifip2p_ctrlpath = conf.getP2P().getCtrlPath();
1343 
1344  // create a wifi-p2p manager
1345  _components[RUNLEVEL_NETWORK].push_back( new dtn::net::WifiP2PManager(wifip2p_ctrlpath) );
1346  }
1347 #endif
1348 
1349  /***
1350  * Init Discovery
1351  */
1352  if (conf.getDiscovery().enabled())
1353  {
1354  // get the discovery port
1355  int disco_port = conf.getDiscovery().port();
1356 
1357  // create the IPND agent
1358  dtn::net::IPNDAgent *ipnd = new dtn::net::IPNDAgent( disco_port );
1359 
1360  try {
1361  const std::set<ibrcommon::vaddress> addr = conf.getDiscovery().address();
1362  for (std::set<ibrcommon::vaddress>::const_iterator iter = addr.begin(); iter != addr.end(); ++iter) {
1363  ipnd->add(*iter);
1364  }
1366  // by default set multicast equivalent of broadcast
1367  ipnd->add(ibrcommon::vaddress("ff02::142", disco_port, AF_INET6));
1368  ipnd->add(ibrcommon::vaddress("224.0.0.142", disco_port, AF_INET));
1369  }
1370 
1371  // add all CL interfaces to discovery
1372  for (std::list<dtn::daemon::Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); ++iter)
1373  {
1374  const dtn::daemon::Configuration::NetConfig &net = (*iter);
1375  if (!net.iface.empty())
1376  ipnd->bind(net.iface);
1377  }
1378 
1379  _components[RUNLEVEL_NETWORK].push_back(ipnd);
1380  }
1381  else
1382  {
1383  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Discovery disabled" << IBRCOMMON_LOGGER_ENDL;
1384  }
1385 
1389  component_list &clist = _components[RUNLEVEL_NETWORK];
1390  for (component_list::iterator it = clist.begin(); it != clist.end(); ++it)
1391  {
1392  try {
1393  ConvergenceLayer *cl = dynamic_cast<ConvergenceLayer*>(*it);
1394  if (cl != NULL) {
1395  core.getConnectionManager().add(cl);
1396  }
1397  } catch (const std::bad_cast&) { }
1398  }
1399 
1400  // announce static nodes, create a list of static nodes
1401  const std::list<Node> &static_nodes = conf.getNetwork().getStaticNodes();
1402 
1403  for (list<Node>::const_iterator iter = static_nodes.begin(); iter != static_nodes.end(); ++iter)
1404  {
1405  core.getConnectionManager().add(*iter);
1406  }
1407  }
1408 
1409  void NativeDaemon::shutdown_network() throw (NativeDaemonException)
1410  {
1413 
1414  // announce static nodes, create a list of static nodes
1415  const std::list<Node> &static_nodes = conf.getNetwork().getStaticNodes();
1416 
1417  for (list<Node>::const_iterator iter = static_nodes.begin(); iter != static_nodes.end(); ++iter)
1418  {
1419  core.getConnectionManager().remove(*iter);
1420  }
1421 
1425  component_list &clist = _components[RUNLEVEL_NETWORK];
1426  for (component_list::iterator it = clist.begin(); it != clist.end(); ++it)
1427  {
1428  try {
1429  ConvergenceLayer *cl = dynamic_cast<ConvergenceLayer*>(*it);
1430  if (cl != NULL) {
1431  core.getConnectionManager().remove(cl);
1432  }
1433  } catch (const std::bad_cast&) { }
1434  }
1435  }
1436 
1437  void NativeDaemon::init_routing_extensions() throw (NativeDaemonException)
1438  {
1441 
1442  // add static routing extension
1443  router.add( new dtn::routing::StaticRoutingExtension() );
1444 
1445  // add other routing extensions depending on the configuration
1446  switch (conf.getNetwork().getRoutingExtension())
1447  {
1449  {
1450  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using flooding routing extensions" << IBRCOMMON_LOGGER_ENDL;
1451  router.add( new dtn::routing::FloodRoutingExtension() );
1452 
1453  // add neighbor routing (direct-delivery) extension
1455  break;
1456  }
1457 
1459  {
1460  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL;
1462 
1463  // add neighbor routing (direct-delivery) extension
1465  break;
1466  }
1467 
1469  {
1471  std::string strategy_name = prophet_config.forwarding_strategy;
1472  dtn::routing::ForwardingStrategy *forwarding_strategy;
1473  if(strategy_name == "GRTR"){
1474  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GRTR_Strategy();
1475  }
1476  else if(strategy_name == "GTMX"){
1477  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GTMX_Strategy(prophet_config.gtmx_nf_max);
1478  }
1479  else{
1480  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Prophet forwarding strategy " << strategy_name << " not found. Using GRTR as fallback." << IBRCOMMON_LOGGER_ENDL;
1481  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GRTR_Strategy();
1482  }
1483  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using prophet routing extensions with " << strategy_name << " as forwarding strategy." << IBRCOMMON_LOGGER_ENDL;
1484  router.add( new dtn::routing::ProphetRoutingExtension(forwarding_strategy, prophet_config.p_encounter_max,
1485  prophet_config.p_encounter_first, prophet_config.p_first_threshold,
1486  prophet_config.beta, prophet_config.gamma, prophet_config.delta,
1487  prophet_config.time_unit, prophet_config.i_typ,
1488  prophet_config.next_exchange_timeout));
1489 
1490  // add neighbor routing (direct-delivery) extension
1492  break;
1493  }
1494 
1496  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Dynamic routing extensions disabled" << IBRCOMMON_LOGGER_ENDL;
1497  break;
1498 
1499  default:
1500  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL;
1501 
1502  // add neighbor routing (direct-delivery) extension
1504  break;
1505  }
1506 
1507  // initialize all routing extensions
1508  router.extensionsUp();
1509  }
1510 
1511  void NativeDaemon::shutdown_routing_extensions() const throw (NativeDaemonException)
1512  {
1514 
1515  // disable all routing extensions
1516  router.extensionsDown();
1517 
1518  // delete all routing extensions
1519  router.clearExtensions();
1520  }
1521 
1525  void NativeDaemon::reload() throw ()
1526  {
1527  // reload logger
1529 
1530  // send reload signal to all modules
1532  }
1533 
1537  void NativeDaemon::setDebug(int level) throw ()
1538  {
1539  // activate debugging
1541  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "debug level set to " << level << IBRCOMMON_LOGGER_ENDL;
1542  }
1543 
1545  : _daemon(daemon)
1546  {
1547  }
1548 
1550  {
1551  }
1552 
1553  void NativeEventLoop::run(void) throw ()
1554  {
1556 
1557  // create the event switch object
1559 
1560  // run the event switch loop forever
1561  if (conf.getDaemon().getThreads() > 1)
1562  {
1563  esw.loop( conf.getDaemon().getThreads() );
1564  }
1565  else
1566  {
1567  esw.loop();
1568  }
1569 
1570  // terminate event switch component
1571  esw.terminate();
1572  }
1573 
1575  {
1578  }
1579  } /* namespace daemon */
1580 } /* namespace dtn */