IBR-DTNSuite  0.10
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>
32 #include <list>
33 
34 #include "storage/BundleStorage.h"
35 #include "storage/BundleSeeker.h"
38 
39 #include "core/BundleCore.h"
40 #include "net/ConnectionManager.h"
41 #include "core/FragmentManager.h"
42 #include "core/Node.h"
43 #include "core/EventSwitch.h"
44 #include "core/EventDispatcher.h"
45 
46 #include "routing/BaseRouter.h"
53 
54 #include "core/GlobalEvent.h"
63 
67 
68 #ifdef HAVE_SYS_INOTIFY_H
69 #include "net/FileMonitor.h"
70 #endif
71 
73 #include "net/UDPDatagramService.h"
74 
75 #ifdef HAVE_SQLITE
77 #endif
78 
79 #ifdef HAVE_LIBCURL
81 #endif
82 
83 #ifdef HAVE_LOWPAN_SUPPORT
86 #endif
87 
88 #include "net/IPNDAgent.h"
89 
90 #include "api/ApiServer.h"
91 
92 #include "Configuration.h"
93 #include "EchoWorker.h"
94 #include "CapsuleWorker.h"
95 #include "DTNTPWorker.h"
96 #include "DevNull.h"
97 #include "Component.h"
98 
99 #ifdef WITH_WIFIP2P
100 #include "net/WifiP2PManager.h"
101 #endif
102 
103 #ifdef WITH_BUNDLE_SECURITY
106 #endif
107 
108 #ifdef WITH_TLS
110 #endif
111 
112 #ifdef WITH_DHT_NAMESERVICE
113 #include "net/DHTNameService.h"
114 #endif
115 
116 #include "Debugger.h"
117 #include "core/EventDebugger.h"
118 
120 #include "core/NodeEvent.h"
121 #include "core/GlobalEvent.h"
122 #include "core/CustodyEvent.h"
124 #include "net/BundleReceivedEvent.h"
127 #include "net/ConnectionEvent.h"
128 
129 #define UNIT_MB * 1048576
130 
131 namespace dtn
132 {
133  namespace daemon
134  {
136  {
137  }
138 
140  {
141  }
142 
143  const std::string NativeDaemon::TAG = "NativeDaemon";
144 
146  : _runlevel(RUNLEVEL_ZERO), _statecb(statecb), _eventcb(eventcb), _event_loop(NULL)
147  {
148 
149  }
150 
152  {
153  }
154 
155  std::vector<std::string> NativeDaemon::getVersion() const throw ()
156  {
157  std::vector<std::string> ret;
158  ret.push_back(VERSION);
159  ret.push_back(BUILD_NUMBER);
160  return ret;
161  }
162 
163  void NativeDaemon::clearStorage() const throw ()
164  {
166  }
167 
168  void NativeDaemon::bindEvents()
169  {
170  if (_eventcb != NULL) {
171  // bind to several events
180  }
181  }
182 
183  void NativeDaemon::unbindEvents()
184  {
185  if (_eventcb != NULL) {
186  // unbind to events
195  }
196  }
197 
198  void NativeDaemon::addEventData(const dtn::data::Bundle &b, std::vector<std::string> &data) const
199  {
200  // add the bundle data
201  data.push_back("Source: " + b.source.getString());
202  data.push_back("Timestamp: " + b.timestamp.toString());
203  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
204  data.push_back("Lifetime: " + b.lifetime.toString());
205  data.push_back("Procflags: " + b.procflags.toString());
206 
207  // add the destination eid
208  data.push_back("Destination: " + b.destination.getString());
209 
211  {
212  // add fragmentation values
213  data.push_back("Appdatalength: " + b.appdatalength.toString());
214  data.push_back("Fragmentoffset: " + b.fragmentoffset.toString());
215  }
216  }
217 
218  void NativeDaemon::addEventData(const dtn::data::MetaBundle &b, std::vector<std::string> &data) const
219  {
220  // add the bundle data
221  data.push_back("Source: " + b.source.getString());
222  data.push_back("Timestamp: " + b.timestamp.toString());
223  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
224  data.push_back("Lifetime: " + b.lifetime.toString());
225  data.push_back("Procflags: " + b.procflags.toString());
226 
227  // add the destination eid
228  data.push_back("Destination: " + b.destination.getString());
229 
231  {
232  // add fragmentation values
233  data.push_back("Appdatalength: " + b.appdatalength.toString());
234  data.push_back("Fragmentoffset: " + b.offset.toString());
235  }
236  }
237 
238  void NativeDaemon::addEventData(const dtn::data::BundleID &b, std::vector<std::string> &data) const
239  {
240  // add the bundle data
241  data.push_back("Source: " + b.source.getString());
242  data.push_back("Timestamp: " + b.timestamp.toString());
243  data.push_back("Sequencenumber: " + b.sequencenumber.toString());
244 
245  if (b.fragment)
246  {
247  // add fragmentation values
248  data.push_back("Fragmentoffset: " + b.offset.toString());
249  }
250  }
251 
252  void NativeDaemon::raiseEvent(const Event *evt) throw ()
253  {
254  std::string event = evt->getName();
255  std::string action;
256  std::vector<std::string> data;
257 
258  try {
259  const dtn::core::NodeEvent &node = dynamic_cast<const dtn::core::NodeEvent&>(*evt);
260 
261  // set action
262  switch (node.getAction())
263  {
265  action = "available";
266  break;
268  action = "unavailable";
269  break;
271  action = "data_added";
272  break;
274  action = "data_removed";
275  break;
276  default:
277  break;
278  }
279 
280  // add the node eid
281  data.push_back("EID: " + node.getNode().getEID().getString());
282  } catch (const std::bad_cast&) { };
283 
284  try {
285  const dtn::core::GlobalEvent &global = dynamic_cast<const dtn::core::GlobalEvent&>(*evt);
286 
287  // set action
288  switch (global.getAction())
289  {
291  action = "busy";
292  break;
294  action = "idle";
295  break;
297  action = "powersave";
298  break;
300  action = "reload";
301  break;
303  action = "shutdown";
304  break;
306  action = "suspend";
307  break;
309  action = "internet available";
310  break;
312  action = "internet unavailable";
313  break;
314  default:
315  break;
316  }
317  } catch (const std::bad_cast&) { };
318 
319  try {
320  const dtn::net::BundleReceivedEvent &received = dynamic_cast<const dtn::net::BundleReceivedEvent&>(*evt);
321 
322  // set action
323  action = "received";
324 
325  data.push_back("Peer: " + received.peer.getString());
326  data.push_back("Local: " + (received.fromlocal ? std::string("true") : std::string("false")));
327 
328  // add bundle data
329  addEventData(received.bundle, data);
330  } catch (const std::bad_cast&) { };
331 
332  try {
333  const dtn::core::CustodyEvent &custody = dynamic_cast<const dtn::core::CustodyEvent&>(*evt);
334 
335  // set action
336  switch (custody.getAction())
337  {
339  action = "accept";
340  break;
342  action = "reject";
343  break;
344  default:
345  break;
346  }
347 
348  // add bundle data
349  addEventData(custody.getBundle(), data);
350  } catch (const std::bad_cast&) { };
351 
352  try {
353  const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
354 
355  // set action
356  action = "aborted";
357 
358  data.push_back("Peer: " + aborted.getPeer().getString());
359 
360  // add bundle data
361  addEventData(aborted.getBundleID(), data);
362  } catch (const std::bad_cast&) { };
363 
364  try {
365  const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
366 
367  // set action
368  action = "completed";
369 
370  data.push_back("Peer: " + completed.getPeer().getString());
371 
372  // add bundle data
373  addEventData(completed.getBundle(), data);
374  } catch (const std::bad_cast&) { };
375 
376  try {
377  const dtn::net::ConnectionEvent &connection = dynamic_cast<const dtn::net::ConnectionEvent&>(*evt);
378 
379  // set action
380  switch (connection.state)
381  {
383  action = "up";
384  break;
386  action = "down";
387  break;
389  action = "setup";
390  break;
392  action = "timeout";
393  break;
394  default:
395  break;
396  }
397 
398  // write the peer eid
399  data.push_back("Peer: " + connection.peer.getString());
400  } catch (const std::bad_cast&) { };
401 
402  try {
403  const dtn::routing::QueueBundleEvent &queued = dynamic_cast<const dtn::routing::QueueBundleEvent&>(*evt);
404 
405  // set action
406  action = "queued";
407 
408  // add bundle data
409  addEventData(queued.bundle, data);
410  } catch (const std::bad_cast&) { };
411 
412  // signal event to the callback interface
413  _eventcb->eventRaised(event, action, data);
414  }
415 
416  std::string NativeDaemon::getLocalUri() const throw ()
417  {
419  }
420 
422  {
423  NativeStats ret;
424 
425  ret.uptime = dtn::utils::Clock::getUptime().get<size_t>();
426  ret.timestamp = dtn::utils::Clock::getTime().get<size_t>();
429 
433 
442 
445 
447 
448  for (ConnectionManager::stats_list::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
449  const ConnectionManager::stats_pair &pair = (*iter);
450  const ConvergenceLayer::stats_map &map = pair.second;
451 
452  for (ConvergenceLayer::stats_map::const_iterator map_it = map.begin(); map_it != map.end(); ++map_it) {
453  std::string tag = dtn::core::Node::toString(pair.first) + "|" + (*map_it).first;
454  ret.addData(tag, (*map_it).second);
455  }
456  }
457 
458  return ret;
459  }
460 
461  NativeNode NativeDaemon::getInfo(const std::string &neighbor_eid) const throw (NativeDaemonException)
462  {
463  NativeNode nn(neighbor_eid);
464 
465  dtn::data::EID eid(neighbor_eid);
466  try {
468  dtn::core::Node::URI uri = n.getAll().front();
469  switch (uri.type) {
471  throw NativeDaemonException("Node is not available");
472  break;
473 
476  break;
477 
480  break;
481 
484  break;
485 
488  break;
489 
492  break;
493 
496  break;
497  }
498  } catch (const NeighborNotAvailableException &ex) {
499  throw NativeDaemonException(ex.what());
500  }
501 
502  return nn;
503  }
504 
505  std::vector<std::string> NativeDaemon::getNeighbors() const throw ()
506  {
507  std::vector<std::string> ret;
508 
509  // get neighbors
510  const std::set<dtn::core::Node> nlist = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
511  for (std::set<dtn::core::Node>::const_iterator iter = nlist.begin(); iter != nlist.end(); ++iter)
512  {
513  const dtn::core::Node &n = (*iter);
514  ret.push_back(n.getEID().getString());
515  }
516 
517  return ret;
518  }
519 
520  void NativeDaemon::addConnection(std::string eid, std::string protocol, std::string address, std::string service, bool local) const throw ()
521  {
522  dtn::core::Node n(eid);
524 
525  if (local) t = dtn::core::Node::NODE_STATIC_LOCAL;
526 
527  if (protocol == "tcp")
528  {
529  std::string uri = "ip=" + address + ";port=" + service + ";";
532  }
533  else if (protocol == "udp")
534  {
535  std::string uri = "ip=" + address + ";port=" + service + ";";
538  }
539  else if (protocol == "file")
540  {
543  }
544  }
545 
546  void NativeDaemon::removeConnection(std::string eid, std::string protocol, std::string address, std::string service, bool local) const throw ()
547  {
548  dtn::core::Node n(eid);
550 
551  if (local) t = dtn::core::Node::NODE_STATIC_LOCAL;
552 
553  if (protocol == "tcp")
554  {
555  std::string uri = "ip=" + address + ";port=" + service + ";";
558  }
559  else if (protocol == "udp")
560  {
561  std::string uri = "ip=" + address + ";port=" + service + ";";
564  }
565  else if (protocol == "file")
566  {
569  }
570  }
571 
572  void NativeDaemon::initiateConnection(std::string eid)
573  {
574  dtn::data::EID neighbor(eid);
576 
577  try {
578  const dtn::core::Node n = cm.getNeighbor(neighbor);
579  cm.open(n);
580  } catch (const ibrcommon::Exception&) {
581  // ignore errors
582  }
583  }
584 
585  void NativeDaemon::setLogging(const std::string &defaultTag, int logLevel) const throw ()
586  {
591  // set default logging
593 
594  // activate info messages and warnings
595  if (logLevel > 0) {
598  }
599 
600  // activate frequent notice messages
601  if (logLevel > 1) {
603  }
604 
605  // activate debugging
606  if (logLevel > 2) {
608  }
609 
610  // set default logging tag
612 
613  // enable logging to Android's logcat
614  ibrcommon::Logger::enableSyslog("ibrdtn-daemon", 0, 0, logsys);
615  }
616 
617  void NativeDaemon::setConfigFile(const std::string &path)
618  {
619  _config_file = ibrcommon::File(path);
620 
621  // load the configuration file
623  conf.load(_config_file.getPath());
624 
625  // reload bundle core configuration
627 
628 #ifdef WITH_BUNDLE_SECURITY
629  // initialize the key manager for the security extensions
631 #endif
632  }
633 
637  void NativeDaemon::setLogFile(const std::string &path, int logLevel) const throw ()
638  {
639  // logging options
641 
642  // set default logging
644 
645  // deactivate logging if logLevel is below zero
646  if (logLevel < 0) {
647  logsys = 0;
648  }
649 
650  // activate info messages and warnings
651  if (logLevel > 0) {
654  }
655 
656  // activate frequent notice messages
657  if (logLevel > 1) {
659  }
660 
661  // activate debugging
662  if (logLevel > 2) {
664  }
665 
666  const ibrcommon::File lf(path);
667  ibrcommon::Logger::setLogfile(lf, logsys, logopts);
668  }
669 
671  {
672  return _runlevel;
673  }
674 
676  {
677  ibrcommon::MutexLock l(_runlevel_cond);
678  if (_runlevel < rl) {
679  for (; _runlevel < rl; _runlevel = DaemonRunLevel(_runlevel + 1)) {
680  init_up(DaemonRunLevel(_runlevel + 1));
681  _runlevel_cond.signal(true);
682  }
683  } else if (_runlevel > rl) {
684  for (; _runlevel >= rl; _runlevel = DaemonRunLevel(_runlevel - 1)) {
685  init_down(_runlevel);
686  _runlevel_cond.signal(true);
687  }
688  }
689  }
690 
691  void NativeDaemon::init_up(DaemonRunLevel rl) throw (NativeDaemonException)
692  {
693  switch (rl) {
694  case RUNLEVEL_ZERO:
695  // nothing to do here
696  break;
697 
698  case RUNLEVEL_CORE:
699  init_core();
700  break;
701 
702  case RUNLEVEL_STORAGE:
703  init_storage();
704  break;
705 
706  case RUNLEVEL_ROUTING:
707  init_routing();
708  break;
709 
710  case RUNLEVEL_API:
711  init_api();
712  break;
713 
714  case RUNLEVEL_NETWORK:
715  init_network();
716  break;
717 
719  init_routing_extensions();
720  break;
721  }
722 
726  component_list &components = _components[rl];
727  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
728  {
729  (*it)->initialize();
730  }
731 
735  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
736  {
737  (*it)->startup();
738  }
739 
740  if (_statecb != NULL) {
741  _statecb->levelChanged(rl);
742  }
743 
744  IBRCOMMON_LOGGER_DEBUG_TAG(NativeDaemon::TAG, 5) << "runlevel " << rl << " reached" << IBRCOMMON_LOGGER_ENDL;
745  }
746 
747  void NativeDaemon::init_down(DaemonRunLevel rl) throw (NativeDaemonException)
748  {
752  component_list &components = _components[rl];
753  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
754  {
755  (*it)->terminate();
756  }
757 
758  switch (rl) {
759  case RUNLEVEL_ZERO:
760  // nothing to do here
761  break;
762 
763  case RUNLEVEL_CORE:
764  shutdown_core();
765  break;
766 
767  case RUNLEVEL_STORAGE:
768  shutdown_storage();
769  break;
770 
771  case RUNLEVEL_ROUTING:
772  shutdown_routing();
773  break;
774 
775  case RUNLEVEL_API:
776  shutdown_api();
777  break;
778 
779  case RUNLEVEL_NETWORK:
780  shutdown_network();
781  break;
782 
784  shutdown_routing_extensions();
785  break;
786  }
787 
791  for (component_list::iterator it = components.begin(); it != components.end(); ++it)
792  {
793  delete (*it);
794  }
795  components.clear();
796 
797  if (_statecb != NULL) {
798  _statecb->levelChanged(rl);
799  }
800 
801  IBRCOMMON_LOGGER_DEBUG_TAG(NativeDaemon::TAG, 5) << "runlevel " << rl << " reached" << IBRCOMMON_LOGGER_ENDL;
802  }
803 
805  {
806  try {
807  ibrcommon::MutexLock l(_runlevel_cond);
808  while (_runlevel != rl) _runlevel_cond.wait();
810  // wait aborted
811  }
812  }
813 
814  void NativeDaemon::init_core() throw (NativeDaemonException)
815  {
816  // enable link manager
818 
819  // get the core
821 
822  // reset and get configuration
824 
825  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "IBR-DTN daemon " << conf.version() << IBRCOMMON_LOGGER_ENDL;
826 
827  // load configuration
828  if (_config_file.exists()) {
829  conf.load(_config_file.getPath());
830  } else {
831  conf.load();
832  }
833 
834  // greeting
835  if (conf.getDebug().enabled())
836  {
837  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "debug level set to " << conf.getDebug().level() << IBRCOMMON_LOGGER_ENDL;
838  }
839 
840  try {
841  const ibrcommon::File &lf = conf.getLogger().getLogfile();
842  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "use logfile for output: " << lf.getPath() << IBRCOMMON_LOGGER_ENDL;
844 
845  if (conf.getDaemon().getThreads() > 1)
846  {
847  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Parallel event processing enabled using " << conf.getDaemon().getThreads() << " processes." << IBRCOMMON_LOGGER_ENDL;
848  }
849 
850  // initialize the event switch
852 
853  // listen to events
854  bindEvents();
855 
856  // create a thread for the main loop
857  _event_loop = new NativeEventLoop(*this);
858 
859  // start the event switch
860  _event_loop->start();
861 
862 #ifdef WITH_TLS
863  /* enable TLS support */
864  if ( conf.getSecurity().doTLS() )
865  {
866  _components[RUNLEVEL_CORE].push_back(new dtn::security::SecurityCertificateManager());
867  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "TLS security enabled" << IBRCOMMON_LOGGER_ENDL;
868  }
869 #endif
870 
871 #ifdef WITH_BUNDLE_SECURITY
872  // initialize the key manager for the security extensions
874 #endif
875 
876  // initialize core component
877  core.initialize();
878  }
879 
880  void NativeDaemon::shutdown_core() throw (NativeDaemonException)
881  {
882  // shutdown the event switch
883  _event_loop->stop();
884  _event_loop->join();
885 
886  delete _event_loop;
887  _event_loop = NULL;
888 
889  // unlisten to events
890  unbindEvents();
891 
892  // get the core
894 
895  // shutdown the core component
896  core.terminate();
897 
898 #ifdef WITH_BUNDLE_SECURITY
899  // reset configuration
901 
902  // initialize the key manager for the security extensions
904 #endif
905  }
906 
907  void NativeDaemon::init_storage() throw (NativeDaemonException)
908  {
910 
911  // create a storage for bundles
912  dtn::storage::BundleStorage *storage = NULL;
913 
914 #ifdef HAVE_SQLITE
915  if (conf.getStorage() == "sqlite")
916  {
917  try {
918  // new methods for blobs
919  ibrcommon::File path = conf.getPath("storage");
920 
921  // create workdir if needed
922  if (!path.exists())
923  {
925  }
926 
927  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using sqlite bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
928 
930 
931  _components[RUNLEVEL_STORAGE].push_back(sbs);
932  storage = sbs;
935  throw NativeDaemonException("initialization of the bundle storage failed");
936  }
937  }
938 #endif
939 
940  if ((conf.getStorage() == "simple") || (conf.getStorage() == "default"))
941  {
942  // default behavior if no bundle storage is set
943  try {
944  // new methods for blobs
945  ibrcommon::File path = conf.getPath("storage");
946 
947  // create workdir if needed
948  if (!path.exists())
949  {
951  }
952 
953  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using simple bundle storage in " << path.getPath() << IBRCOMMON_LOGGER_ENDL;
954  dtn::storage::SimpleBundleStorage *sbs = new dtn::storage::SimpleBundleStorage(path, conf.getLimit("storage"), static_cast<unsigned int>(conf.getLimit("storage_buffer")));
955  _components[RUNLEVEL_STORAGE].push_back(sbs);
956  storage = sbs;
958  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using bundle storage in memory-only mode" << IBRCOMMON_LOGGER_ENDL;
960  _components[RUNLEVEL_STORAGE].push_back(sbs);
961  storage = sbs;
962  }
963  }
964 
965  if (storage == NULL)
966  {
967  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "bundle storage module \"" << conf.getStorage() << "\" do not exists!" << IBRCOMMON_LOGGER_ENDL;
968  throw NativeDaemonException("bundle storage not available");
969  }
970 
971  // set the storage in the core
973 
974  // use scheduling?
975  if (dtn::daemon::Configuration::getInstance().getNetwork().doScheduling())
976  {
977  // create a new bundle index
979 
980  // attach index to the storage
981  storage->attach(bundle_index);
982 
983  // set this bundle index as default bundle seeker which is used to find bundles to transfer
985 
986  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Enable extended bundle index for scheduling" << IBRCOMMON_LOGGER_ENDL;
987  } else {
988  // set the storage as default seeker
990  }
991 
995  try {
996  // the configured BLOB path
997  ibrcommon::File blob_path = conf.getPath("blob");
998 
999  // check if the BLOB path exists
1000  if (!blob_path.exists()) {
1001  // try to create the BLOB path
1003  }
1004 
1005  if (blob_path.exists() && blob_path.isDirectory())
1006  {
1007  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "using BLOB path: " << blob_path.getPath() << IBRCOMMON_LOGGER_ENDL;
1009  }
1010  else
1011  {
1012  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, warning) << "BLOB path exists, but is not a directory! Fallback to memory based mode." << IBRCOMMON_LOGGER_ENDL;
1014  }
1016  }
1017 
1018  void NativeDaemon::shutdown_storage() const throw (NativeDaemonException)
1019  {
1020  // reset BLOB provider to memory based
1022 
1023  // set the seeker in the core to NULL
1025 
1026  // set the storage in the core to NULL
1028  }
1029 
1030  void NativeDaemon::init_routing() throw (NativeDaemonException)
1031  {
1032  // create the base router
1034 
1035  // make the router globally available
1037 
1038  // add the router to the components list
1039  _components[RUNLEVEL_ROUTING].push_back(router);
1040  }
1041 
1042  void NativeDaemon::shutdown_routing() const throw (NativeDaemonException)
1043  {
1044  // set the global router to NULL
1046  }
1047 
1048  void NativeDaemon::init_api() throw (NativeDaemonException)
1049  {
1051 
1052  // create event debugger
1053  _components[RUNLEVEL_API].push_back( new dtn::core::EventDebugger() );
1054 
1055  // Debugger
1056  _apps.push_back( new dtn::daemon::Debugger() );
1057 
1058  // add echo module
1059  _apps.push_back( new dtn::daemon::EchoWorker() );
1060 
1061  // add bundle-in-bundle endpoint
1062  _apps.push_back( new dtn::daemon::CapsuleWorker() );
1063 
1064  // add DT-NTP worker
1065  _apps.push_back( new dtn::daemon::DTNTPWorker() );
1066 
1067  // add DevNull module
1068  _apps.push_back( new dtn::daemon::DevNull() );
1069 
1070  if (conf.getNetwork().doFragmentation())
1071  {
1072  // manager class for fragmentations
1073  _components[RUNLEVEL_API].push_back( new dtn::core::FragmentManager() );
1074  }
1075 
1076 #ifndef ANDROID
1077  if (conf.doAPI())
1078  {
1079  try {
1080  ibrcommon::File socket = conf.getAPISocket();
1081 
1082  try {
1083  // use unix domain sockets for API
1084  _components[RUNLEVEL_API].push_back(new dtn::api::ApiServer(socket));
1085  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "API initialized using unix domain socket: " << socket.getPath() << IBRCOMMON_LOGGER_ENDL;
1086  } catch (const ibrcommon::socket_exception&) {
1087  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Unable to bind to unix domain socket " << socket.getPath() << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
1088  exit(-1);
1089  }
1092 
1093  try {
1094  // instance a API server, first create a socket
1095  _components[RUNLEVEL_API].push_back(new dtn::api::ApiServer(apiconf.iface, apiconf.port));
1096  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "API initialized using tcp socket: " << apiconf.iface.toString() << ":" << apiconf.port << IBRCOMMON_LOGGER_ENDL;
1097  } catch (const ibrcommon::socket_exception&) {
1098  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Unable to bind to " << apiconf.iface.toString() << ":" << apiconf.port << ". API not initialized!" << IBRCOMMON_LOGGER_ENDL;
1099  exit(-1);
1100  }
1101  };
1102  }
1103  else
1104  {
1106  }
1107 #endif
1108  }
1109 
1110  void NativeDaemon::shutdown_api() throw (NativeDaemonException)
1111  {
1112  for (app_list::iterator it = _apps.begin(); it != _apps.end(); ++it)
1113  {
1114  delete (*it);
1115  }
1116  _apps.clear();
1117  }
1118 
1119  void NativeDaemon::init_network() throw (NativeDaemonException)
1120  {
1123 
1124  // get the configuration of the convergence layers
1125  const std::list<dtn::daemon::Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces();
1126 
1127  // local cl map
1128  std::map<dtn::daemon::Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*> _cl_map;
1129 
1130  // holder for file convergence layer
1131  FileConvergenceLayer *filecl = NULL;
1132 
1133  // add file monitor
1134 #ifdef HAVE_SYS_INOTIFY_H
1135  FileMonitor *fm = NULL;
1136 #endif
1137 
1138  // create the convergence layers
1139  for (std::list<dtn::daemon::Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); ++iter)
1140  {
1141  const dtn::daemon::Configuration::NetConfig &net = (*iter);
1142 
1143  try {
1144  switch (net.type)
1145  {
1147  {
1148  try {
1149  if (filecl == NULL)
1150  {
1151  filecl = new FileConvergenceLayer();
1152  _components[RUNLEVEL_NETWORK].push_back(filecl);
1153  }
1154 
1155 #ifdef HAVE_SYS_INOTIFY_H
1156  if (net.url.size() > 0)
1157  {
1158  ibrcommon::File path(net.url);
1159 
1160  if (path.exists())
1161  {
1162  if (fm == NULL)
1163  {
1164  fm = new FileMonitor();
1165  _components[RUNLEVEL_NETWORK].push_back(fm);
1166  }
1167  ibrcommon::File path(net.url);
1168  fm->watch(path);
1169  }
1170  }
1171 #endif
1172  } catch (const ibrcommon::Exception &ex) {
1173  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add FileConvergenceLayer: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1174  }
1175  break;
1176  }
1177 
1179  {
1180  try {
1181  _components[RUNLEVEL_NETWORK].push_back( new dtn::net::UDPConvergenceLayer( net.iface, net.port, net.mtu ) );
1182  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "UDP ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1183  } catch (const ibrcommon::Exception &ex) {
1184  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add UDP ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1185  }
1186 
1187  break;
1188  }
1189 
1191  {
1192  // look for an earlier instance of
1193  std::map<dtn::daemon::Configuration::NetConfig::NetType, dtn::net::ConvergenceLayer*>::iterator it = _cl_map.find(net.type);
1194 
1195  TCPConvergenceLayer *tcpcl = NULL;
1196 
1197  if (it == _cl_map.end()) {
1198  tcpcl = new TCPConvergenceLayer();
1199  } else {
1200  tcpcl = dynamic_cast<TCPConvergenceLayer*>(it->second);
1201  }
1202 
1203  try {
1204  tcpcl->add(net.iface, net.port);
1205 
1206  if (it == _cl_map.end()) {
1207  _components[RUNLEVEL_NETWORK].push_back(tcpcl);
1208  _cl_map[net.type] = tcpcl;
1209  }
1210 
1211  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "TCP ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1212  } catch (const ibrcommon::Exception &ex) {
1213  if (it == _cl_map.end()) {
1214  delete tcpcl;
1215  }
1216 
1217  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add TCP ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1218  }
1219 
1220  break;
1221  }
1222 
1223 #ifdef HAVE_LIBCURL
1225  {
1226  try {
1227  _components[RUNLEVEL_NETWORK].push_back( new HTTPConvergenceLayer( net.url ) );
1228  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "HTTP ConvergenceLayer added, Server: " << net.url << IBRCOMMON_LOGGER_ENDL;
1229  } catch (const ibrcommon::Exception &ex) {
1230  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add HTTP ConvergenceLayer, Server: " << net.url << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1231  }
1232  break;
1233  }
1234 #endif
1235 
1236 #ifdef HAVE_LOWPAN_SUPPORT
1238  {
1239  try {
1240  _components[RUNLEVEL_NETWORK].push_back( new LOWPANConvergenceLayer( net.iface, static_cast<uint16_t>(net.port) ) );
1241  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "LOWPAN ConvergenceLayer added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1242  } catch (const ibrcommon::Exception &ex) {
1243  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add LOWPAN ConvergenceLayer on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1244  }
1245 
1246  break;
1247  }
1248 
1250  {
1251  try {
1252  LOWPANDatagramService *lowpan_service = new LOWPANDatagramService( net.iface, static_cast<uint16_t>(net.port) );
1253  _components[RUNLEVEL_NETWORK].push_back( new DatagramConvergenceLayer(lowpan_service) );
1254  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Datagram ConvergenceLayer (LowPAN) added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1255  } catch (const ibrcommon::Exception &ex) {
1256  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add Datagram ConvergenceLayer (LowPAN) on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1257  }
1258  break;
1259  }
1260 #endif
1261 
1263  {
1264  try {
1265  UDPDatagramService *dgram_service = new UDPDatagramService( net.iface, net.port, net.mtu );
1266  _components[RUNLEVEL_NETWORK].push_back( new DatagramConvergenceLayer(dgram_service) );
1267  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Datagram ConvergenceLayer (UDP) added on " << net.iface.toString() << ":" << net.port << IBRCOMMON_LOGGER_ENDL;
1268  } catch (const ibrcommon::Exception &ex) {
1269  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Failed to add Datagram ConvergenceLayer (UDP) on " << net.iface.toString() << ": " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1270  }
1271  break;
1272  }
1273 
1274  default:
1275  break;
1276  }
1277  } catch (const std::exception &ex) {
1278  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Error: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
1279  }
1280  }
1281 
1282  /****
1283  * Init DHT
1284  */
1285 
1286 #ifdef WITH_DHT_NAMESERVICE
1287  // create dht naming service if configured
1288  if (conf.getDHT().enabled()) {
1290  _components[RUNLEVEL_NETWORK].push_back( new dtn::dht::DHTNameService() );
1291  }
1292 #endif
1293 
1294 #ifdef WITH_WIFIP2P
1295  if (conf.getP2P().enabled())
1296  {
1297  const std::string wifip2p_ctrlpath = conf.getP2P().getCtrlPath();
1298 
1299  // create a wifi-p2p manager
1300  _components[RUNLEVEL_NETWORK].push_back( new dtn::net::WifiP2PManager(wifip2p_ctrlpath) );
1301  }
1302 #endif
1303 
1304  /***
1305  * Init Discovery
1306  */
1307  if (conf.getDiscovery().enabled())
1308  {
1309  // get the discovery port
1310  int disco_port = conf.getDiscovery().port();
1311 
1312  // collect all interfaces of convergence layer instances
1313  std::set<ibrcommon::vinterface> interfaces;
1314 
1315  const std::list<dtn::daemon::Configuration::NetConfig> &nets = conf.getNetwork().getInterfaces();
1316  for (std::list<dtn::daemon::Configuration::NetConfig>::const_iterator iter = nets.begin(); iter != nets.end(); ++iter)
1317  {
1318  const dtn::daemon::Configuration::NetConfig &net = (*iter);
1319  if (!net.iface.empty())
1320  interfaces.insert(net.iface);
1321  }
1322 
1323  dtn::net::IPNDAgent *ipnd = new dtn::net::IPNDAgent( disco_port );
1324 
1325  try {
1326  const std::set<ibrcommon::vaddress> addr = conf.getDiscovery().address();
1327  for (std::set<ibrcommon::vaddress>::const_iterator iter = addr.begin(); iter != addr.end(); ++iter) {
1328  ipnd->add(*iter);
1329  }
1331  // by default set multicast equivalent of broadcast
1332  ipnd->add(ibrcommon::vaddress("ff02::142", disco_port, AF_INET6));
1333  ipnd->add(ibrcommon::vaddress("224.0.0.142", disco_port, AF_INET));
1334  }
1335 
1336  for (std::set<ibrcommon::vinterface>::const_iterator iter = interfaces.begin(); iter != interfaces.end(); ++iter)
1337  {
1338  const ibrcommon::vinterface &i = (*iter);
1339 
1340  // add interfaces to discovery
1341  ipnd->bind(i);
1342  }
1343 
1347  for (app_list::iterator it = _apps.begin(); it != _apps.end(); ++it)
1348  {
1349  try {
1350  DiscoveryServiceProvider *dsp = dynamic_cast<DiscoveryServiceProvider*>(*it);
1351  if (dsp != NULL) {
1352  ipnd->addService(dsp);
1353  }
1354  } catch (const std::bad_cast&) { }
1355  }
1356 
1360  component_list &clist = _components[RUNLEVEL_NETWORK];
1361  for (component_list::iterator it = clist.begin(); it != clist.end(); ++it)
1362  {
1363  try {
1364  DiscoveryServiceProvider *dsp = dynamic_cast<DiscoveryServiceProvider*>(*it);
1365  if (dsp != NULL) {
1366  ipnd->addService(dsp);
1367  }
1368  } catch (const std::bad_cast&) { }
1369  }
1370 
1371  _components[RUNLEVEL_NETWORK].push_back(ipnd);
1372  }
1373  else
1374  {
1376  }
1377 
1381  component_list &clist = _components[RUNLEVEL_NETWORK];
1382  for (component_list::iterator it = clist.begin(); it != clist.end(); ++it)
1383  {
1384  try {
1385  ConvergenceLayer *cl = dynamic_cast<ConvergenceLayer*>(*it);
1386  if (cl != NULL) {
1387  core.getConnectionManager().add(cl);
1388  }
1389  } catch (const std::bad_cast&) { }
1390  }
1391 
1392  // announce static nodes, create a list of static nodes
1393  const std::list<Node> &static_nodes = conf.getNetwork().getStaticNodes();
1394 
1395  for (list<Node>::const_iterator iter = static_nodes.begin(); iter != static_nodes.end(); ++iter)
1396  {
1397  core.getConnectionManager().add(*iter);
1398  }
1399  }
1400 
1401  void NativeDaemon::shutdown_network() throw (NativeDaemonException)
1402  {
1405 
1406  // announce static nodes, create a list of static nodes
1407  const std::list<Node> &static_nodes = conf.getNetwork().getStaticNodes();
1408 
1409  for (list<Node>::const_iterator iter = static_nodes.begin(); iter != static_nodes.end(); ++iter)
1410  {
1411  core.getConnectionManager().remove(*iter);
1412  }
1413 
1417  component_list &clist = _components[RUNLEVEL_NETWORK];
1418  for (component_list::iterator it = clist.begin(); it != clist.end(); ++it)
1419  {
1420  try {
1421  ConvergenceLayer *cl = dynamic_cast<ConvergenceLayer*>(*it);
1422  if (cl != NULL) {
1423  core.getConnectionManager().remove(cl);
1424  }
1425  } catch (const std::bad_cast&) { }
1426  }
1427  }
1428 
1429  void NativeDaemon::init_routing_extensions() throw (NativeDaemonException)
1430  {
1433 
1434  // add static routing extension
1435  router.add( new dtn::routing::StaticRoutingExtension() );
1436 
1437  // add other routing extensions depending on the configuration
1438  switch (conf.getNetwork().getRoutingExtension())
1439  {
1441  {
1442  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using flooding routing extensions" << IBRCOMMON_LOGGER_ENDL;
1443  router.add( new dtn::routing::FloodRoutingExtension() );
1444 
1445  // add neighbor routing (direct-delivery) extension
1447  break;
1448  }
1449 
1451  {
1452  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using epidemic routing extensions" << IBRCOMMON_LOGGER_ENDL;
1454 
1455  // add neighbor routing (direct-delivery) extension
1457  break;
1458  }
1459 
1461  {
1463  std::string strategy_name = prophet_config.forwarding_strategy;
1464  dtn::routing::ForwardingStrategy *forwarding_strategy;
1465  if(strategy_name == "GRTR"){
1466  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GRTR_Strategy();
1467  }
1468  else if(strategy_name == "GTMX"){
1469  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GTMX_Strategy(prophet_config.gtmx_nf_max);
1470  }
1471  else{
1472  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, error) << "Prophet forwarding strategy " << strategy_name << " not found. Using GRTR as fallback." << IBRCOMMON_LOGGER_ENDL;
1473  forwarding_strategy = new dtn::routing::ProphetRoutingExtension::GRTR_Strategy();
1474  }
1475  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using prophet routing extensions with " << strategy_name << " as forwarding strategy." << IBRCOMMON_LOGGER_ENDL;
1476  router.add( new dtn::routing::ProphetRoutingExtension(forwarding_strategy, prophet_config.p_encounter_max,
1477  prophet_config.p_encounter_first, prophet_config.p_first_threshold,
1478  prophet_config.beta, prophet_config.gamma, prophet_config.delta,
1479  prophet_config.time_unit, prophet_config.i_typ,
1480  prophet_config.next_exchange_timeout));
1481 
1482  // add neighbor routing (direct-delivery) extension
1484  break;
1485  }
1486 
1488  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Dynamic routing extensions disabled" << IBRCOMMON_LOGGER_ENDL;
1489  break;
1490 
1491  default:
1492  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "Using default routing extensions" << IBRCOMMON_LOGGER_ENDL;
1493 
1494  // add neighbor routing (direct-delivery) extension
1496  break;
1497  }
1498 
1499  // initialize all routing extensions
1500  router.extensionsUp();
1501  }
1502 
1503  void NativeDaemon::shutdown_routing_extensions() const throw (NativeDaemonException)
1504  {
1506 
1507  // disable all routing extensions
1508  router.extensionsDown();
1509 
1510  // delete all routing extensions
1511  router.clearExtensions();
1512  }
1513 
1517  void NativeDaemon::reload() throw ()
1518  {
1519  // reload logger
1521 
1522  // send reload signal to all modules
1524  }
1525 
1529  void NativeDaemon::setDebug(int level) throw ()
1530  {
1531  // activate debugging
1533  IBRCOMMON_LOGGER_TAG(NativeDaemon::TAG, info) << "debug level set to " << level << IBRCOMMON_LOGGER_ENDL;
1534  }
1535 
1537  : _daemon(daemon)
1538  {
1539  }
1540 
1542  {
1543  }
1544 
1545  void NativeEventLoop::run(void) throw ()
1546  {
1548 
1549  // create the event switch object
1551 
1552  // run the event switch loop forever
1553  if (conf.getDaemon().getThreads() > 1)
1554  {
1555  esw.loop( conf.getDaemon().getThreads() );
1556  }
1557  else
1558  {
1559  esw.loop();
1560  }
1561 
1562  // terminate event switch component
1563  esw.terminate();
1564  }
1565 
1567  {
1570  }
1571  } /* namespace daemon */
1572 } /* namespace dtn */