IBR-DTN  1.0.0
BaseRouter.cpp
Go to the documentation of this file.
1 /*
2  * BaseRouter.cpp
3  *
4  * Copyright (C) 2011 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 "Configuration.h"
24 
25 #include "routing/BaseRouter.h"
26 #include "core/BundleCore.h"
27 #include "core/EventDispatcher.h"
28 #include "storage/BundleStorage.h"
29 #include "core/BundleEvent.h"
30 
33 #include <ibrdtn/utils/Clock.h>
34 
35 #include <ibrcommon/Logger.h>
36 #include <ibrcommon/thread/MutexLock.h>
37 #include <ibrcommon/thread/RWLock.h>
38 
39 #include <ibrdtn/ibrdtn.h>
40 #ifdef IBRDTN_SUPPORT_BSP
42 #endif
43 
44 namespace dtn
45 {
46  namespace routing
47  {
48  const std::string BaseRouter::TAG = "BaseRouter";
49 
54  : _known_bundles("router-known-bundles"), _purged_bundles("router-purged-bundles"), _extension_state(false), _next_expiration(0)
55  {
56  // make the router globally available
58  }
59 
61  {
62  // unregister this router from the core
64 
65  // delete all extensions
67  }
68 
74  {
75  ibrcommon::RWLock l(_extensions_mutex);
76  _extensions.insert(extension);
77  }
78 
80  {
81  ibrcommon::RWLock l(_extensions_mutex);
82  _extensions.erase(extension);
83  }
84 
85  ibrcommon::RWMutex& BaseRouter::getExtensionMutex() throw ()
86  {
87  return _extensions_mutex;
88  }
89 
91  {
92  return _extensions;
93  }
94 
96  {
97  ibrcommon::RWLock l(_extensions_mutex);
98 
99  // delete all extensions
100  for (extension_list::iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
101  {
102  delete (*iter);
103  }
104 
105  _extensions.clear();
106  }
107 
108  void BaseRouter::extensionsUp() throw ()
109  {
110  ibrcommon::MutexLock l(_extensions_mutex);
111 
112  _nh_extension.componentUp();
113  _retransmission_extension.componentUp();
114 
115  for (extension_list::iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
116  {
117  RoutingExtension &ex = (**iter);
118  ex.componentUp();
119  }
120 
121  _extension_state = true;
122 
123  // trigger all routing modules to react to initial topology
124  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
125 
126  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
127  {
128  const dtn::core::Node &n = (*iter);
129 
130  // trigger all routing modules to search for bundles to forward
131  __eventDataChanged( n.getEID() );
132  }
133  }
134 
136  {
137  ibrcommon::MutexLock l(_extensions_mutex);
138 
139  _extension_state = false;
140 
141  // stop all extensions
142  for (extension_list::iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
143  {
144  RoutingExtension &ex = (**iter);
145  ex.componentDown();
146  }
147 
148  _retransmission_extension.componentDown();
149  _nh_extension.componentDown();
150  }
151 
153  {
154  ibrcommon::MutexLock l(getExtensionMutex());
155 
156  // walk through all extensions to process the contents of the response
157  const BaseRouter::extension_list& extensions = getExtensions();
158 
159  // process this handshake using the NodeHandshakeExtension
160  _nh_extension.processHandshake(source, answer);
161 
162  // process this handshake using the retransmission extension
163  _retransmission_extension.processHandshake(source, answer);
164 
165  for (BaseRouter::extension_list::const_iterator iter = extensions.begin(); iter != extensions.end(); ++iter)
166  {
167  RoutingExtension &extension = (**iter);
168  extension.processHandshake(source, answer);
169  }
170  }
171 
172  void BaseRouter::responseHandshake(const dtn::data::EID &source, const NodeHandshake &request, NodeHandshake &answer)
173  {
174  ibrcommon::MutexLock l(getExtensionMutex());
175 
176  // walk through all extensions to process the contents of the response
177  const BaseRouter::extension_list& extensions = getExtensions();
178 
179  // process this handshake using the NodeHandshakeExtension
180  _nh_extension.responseHandshake(source, request, answer);
181 
182  // process this handshake using the retransmission extension
183  _retransmission_extension.responseHandshake(source, request, answer);
184 
185  for (BaseRouter::extension_list::const_iterator iter = extensions.begin(); iter != extensions.end(); ++iter)
186  {
187  RoutingExtension &extension = (**iter);
188  extension.responseHandshake(source, request, answer);
189  }
190  }
191 
192  void BaseRouter::requestHandshake(const dtn::data::EID &destination, NodeHandshake &request)
193  {
194  ibrcommon::MutexLock l(getExtensionMutex());
195 
196  // walk through all extensions to process the contents of the response
197  const BaseRouter::extension_list& extensions = getExtensions();
198 
199  // process this handshake using the NodeHandshakeExtension
200  _nh_extension.requestHandshake(destination, request);
201 
202  // process this handshake using the retransmission extension
203  _retransmission_extension.requestHandshake(destination, request);
204 
205  for (BaseRouter::extension_list::const_iterator iter = extensions.begin(); iter != extensions.end(); ++iter)
206  {
207  RoutingExtension &extension = (**iter);
208  extension.requestHandshake(destination, request);
209  }
210  }
211 
212  void BaseRouter::componentUp() throw ()
213  {
214  // routine checked for throw() on 15.02.2013
223  }
224 
226  {
227  // routine checked for throw() on 15.02.2013
236  }
237 
242  {
243  // if a transfer is completed, then release the transfer resource of the peer
244  try {
245  // lock the list of neighbors
246  ibrcommon::MutexLock l(_neighbor_database);
247  NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer());
248  entry.releaseTransfer(event.getBundle());
249 
250  // add the bundle to the summary vector of the neighbor
251  entry.add(event.getBundle());
252  } catch (const NeighborDatabase::EntryNotFoundException&) { };
253 
254  // trigger all routing modules to search for bundles to forward
255  __eventTransferCompleted(event.getPeer(), event.getBundle());
256 
257  // trigger all routing modules to search for bundles to forward
258  __eventDataChanged(event.getPeer());
259  }
260 
262  {
263  // check Scope Control Block - do not forward bundles with hop limit == 0
264  if (event.bundle.hopcount == 0) return;
265 
266  // if bundles are addressed to singletons ...
268  {
269  // ... do not them if they are address to the local EID
270  if (event.bundle.destination.sameHost(dtn::core::BundleCore::local)) return;
271  }
272 
273  // If an incoming bundle is received, forward it to all connected neighbors
274  // trigger all routing modules to forward the new bundle
275  __eventBundleQueued(event.origin, event.bundle);
276  }
277 
279  {
281 
282  // Store incoming bundles into the storage
283  try {
284  if (event.fromlocal)
285  {
286  // store the bundle into a storage module
287  getStorage().store(event.bundle);
288 
289  // set the bundle as known
290  setKnown(m);
291 
292  // raise the queued event to notify all receivers about the new bundle
293  QueueBundleEvent::raise(m, event.peer);
294  }
295  // if the bundle is not known
296  else if (!filterKnown(m))
297  {
298  // security methods modifies the bundle, thus we need a copy of it
299  dtn::data::Bundle bundle = event.bundle;
300 
301  // increment value in the scope control hop limit block
302  try {
304  schl.increment();
306 
307  // modify TrackingBlock
308  try {
312 
313  // prevent loops
314  try {
315  ibrcommon::MutexLock l(_neighbor_database);
316 
317  // add the bundle to the summary vector of the neighbor
318  _neighbor_database.get(event.peer).add(m);
319  } catch (const NeighborDatabase::EntryNotFoundException&) { };
320 
321  // store the bundle into a storage module
322  getStorage().store(bundle);
323 
324  // raise the queued event to notify all receivers about the new bundle
325  QueueBundleEvent::raise(m, event.peer);
326  }
327  else
328  {
329  IBRCOMMON_LOGGER_DEBUG_TAG(BaseRouter::TAG, 5) << "Duplicate bundle " << event.bundle.toString() << " from " << event.peer.getString() << " ignored." << IBRCOMMON_LOGGER_ENDL;
330  }
331 
332  // finally create a bundle received event
334 #ifdef IBRDTN_SUPPORT_BSP
335  } catch (const dtn::security::VerificationFailedException &ex) {
336  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "Security checks failed (" << ex.what() << "), bundle will be dropped: " << event.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
337 #endif
338  } catch (const ibrcommon::IOException &ex) {
339  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "Unable to store bundle " << event.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
340 
341  // raise BundleEvent because we have to drop the bundle
344  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "No space left for bundle " << event.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
345 
346  // raise BundleEvent because we have to drop the bundle
348  } catch (const ibrcommon::Exception &ex) {
349  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, error) << "Bundle " << event.bundle.toString() << " dropped: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
350 
351  // raise BundleEvent because we have to drop the bundle
353  }
354  }
355 
357  {
358  // if a transfer is aborted, then release the transfer resource of the peer
359  try {
360  // lock the list of neighbors
361  ibrcommon::MutexLock l(_neighbor_database);
362  NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer());
363  entry.releaseTransfer(event.getBundleID());
364 
366  {
367  const dtn::data::MetaBundle meta = getStorage().info(event.getBundleID());
368 
369  // add the transferred bundle to the bloomfilter of the receiver
370  entry.add(meta);
371  }
373  {
374  const dtn::data::MetaBundle meta = getStorage().info(event.getBundleID());
375 
376  // add the bundle to the bloomfilter of the receiver to avoid further retries
377  entry.add(meta);
378  }
380  } catch (const dtn::storage::NoBundleFoundException&) { };
381 
382  // trigger all routing modules to search for bundles to forward
383  __eventDataChanged(event.getPeer());
384  }
385 
386  void BaseRouter::raiseEvent(const dtn::core::NodeEvent &event) throw ()
387  {
388  // If a new neighbor comes available, send him a request for the summary vector
389  // If a neighbor went away we can free the stored database
390  if (event.getAction() == NODE_AVAILABLE)
391  {
392  {
393  ibrcommon::MutexLock l(_neighbor_database);
394  _neighbor_database.create( event.getNode().getEID() );
395  }
396 
397  // trigger all routing modules to search for bundles to forward
398  __eventDataChanged(event.getNode().getEID());
399  }
400  else if (event.getAction() == NODE_DATA_ADDED)
401  {
402  // trigger all routing modules to search for bundles to forward
403  __eventDataChanged(event.getNode().getEID());
404  }
405  else if (event.getAction() == NODE_UNAVAILABLE)
406  {
407  try {
408  ibrcommon::MutexLock l(_neighbor_database);
409  _neighbor_database.get( event.getNode().getEID() ).reset();
410  } catch (const NeighborDatabase::EntryNotFoundException&) { };
411 
412  // new bundles trigger a re-check for all neighbors
413  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
414 
415  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
416  {
417  const dtn::core::Node &n = (*iter);
418 
419  // trigger all routing modules to search for bundles to forward
420  __eventDataChanged( n.getEID() );
421  }
422  }
423  }
424 
426  {
427  if (event.getState() == dtn::net::ConnectionEvent::CONNECTION_UP)
428  {
429  // create a neighbor entry if that does not exists
430  {
431  ibrcommon::MutexLock l(_neighbor_database);
432  _neighbor_database.create( event.getNode().getEID() );
433  }
434 
435  // trigger all routing modules to search for bundles to forward
436  __eventDataChanged( event.getNode().getEID() );
437  }
438  }
439 
441  {
442  if ((event.reason == dtn::core::BundlePurgeEvent::DELIVERED) ||
444  {
445  // add the purged bundle to the purge vector
446  setPurged(event.bundle);
447  }
448  }
449 
450  void BaseRouter::raiseEvent(const dtn::core::TimeEvent &event) throw ()
451  {
452  dtn::data::Timestamp expire_time = event.getTimestamp();
453 
454  // do the expiration only every 60 seconds
455  if (expire_time > _next_expiration) {
456  // store the next expiration time
457  _next_expiration = expire_time + 60;
458 
459  // expire all bundles and neighbors one minute late
460  if (expire_time <= 60) expire_time = 0;
461  else expire_time -= 60;
462 
463  {
464  ibrcommon::MutexLock l(_known_bundles_lock);
465  _known_bundles.expire(expire_time);
466 
467  // sync known bundles to disk
468  _known_bundles.sync();
469  }
470 
471  {
472  ibrcommon::MutexLock l(_purged_bundles_lock);
473  _purged_bundles.expire(expire_time);
474 
475  // sync purged bundles to disk
476  _purged_bundles.sync();
477  }
478 
479  {
480  ibrcommon::MutexLock l(_neighbor_database);
481 
482  // get all active neighbors
483  const std::set<dtn::core::Node> neighbors = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
484 
485  // touch all active neighbors
486  for (std::set<dtn::core::Node>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it) {
487  try {
488  _neighbor_database.get( (*it).getEID() );
489  } catch (const NeighborDatabase::EntryNotFoundException&) { };
490  }
491 
492  // check all neighbor entries for expiration
493  _neighbor_database.expire(event.getTimestamp());
494  }
495  }
496  }
497 
498  void BaseRouter::__eventDataChanged(const dtn::data::EID &peer) throw ()
499  {
500  // do not forward the event if the extensions are down
501  if (!_extension_state) return;
502 
503  _nh_extension.eventDataChanged(peer);
504  _retransmission_extension.eventDataChanged(peer);
505 
506  // notify all underlying extensions
507  for (extension_list::const_iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
508  {
509  (*iter)->eventDataChanged(peer);
510  }
511  }
512 
513  void BaseRouter::__eventBundleQueued(const dtn::data::EID &peer, const dtn::data::MetaBundle &meta) throw ()
514  {
515  // do not forward the event if the extensions are down
516  if (!_extension_state) return;
517 
518  _nh_extension.eventBundleQueued(peer, meta);
519  _retransmission_extension.eventBundleQueued(peer, meta);
520 
521  // notify all underlying extensions
522  for (extension_list::const_iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
523  {
524  (*iter)->eventBundleQueued(peer, meta);
525  }
526  }
527 
528  void BaseRouter::__eventTransferCompleted(const dtn::data::EID &peer, const dtn::data::MetaBundle &meta) throw ()
529  {
530  // do not forward the event if the extensions are down
531  if (!_extension_state) return;
532 
533  _nh_extension.eventTransferCompleted(peer, meta);
534  _retransmission_extension.eventTransferCompleted(peer, meta);
535 
536  // notify all underlying extensions
537  for (extension_list::const_iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
538  {
539  (*iter)->eventTransferCompleted(peer, meta);
540  }
541  }
542 
544  {
545  _nh_extension.doHandshake(eid);
546  }
547 
549  {
550  _nh_extension.pushHandshakeUpdated(id);
551  }
552 
554  {
556  }
557 
559  {
561  }
562 
564  {
565  ibrcommon::MutexLock l(_known_bundles_lock);
566  return _known_bundles.add(meta);
567  }
568 
569  // check if the bundle is known
571  {
572  ibrcommon::MutexLock l(_known_bundles_lock);
573  return _known_bundles.has(id);
574  }
575 
576  // check if a bundle is known
577  // if the bundle is unkown add it to the known list and return
578  // false
580  {
581  ibrcommon::MutexLock l(_known_bundles_lock);
582  bool ret = _known_bundles.has(meta);
583  if (!ret) _known_bundles.add(meta);
584 
585  return ret;
586  }
587 
589  {
590  ibrcommon::MutexLock l(_known_bundles_lock);
591  return _known_bundles;
592  }
593 
594  // set the bundle as known
596  {
597  ibrcommon::MutexLock l(_purged_bundles_lock);
598  return _purged_bundles.has(id);
599  }
600 
602  {
603  ibrcommon::MutexLock l(_purged_bundles_lock);
604  return _purged_bundles.add(meta);
605  }
606 
608  {
609  ibrcommon::MutexLock l(_purged_bundles_lock);
610  return _purged_bundles;
611  }
612 
613  const std::string BaseRouter::getName() const
614  {
615  return "BaseRouter";
616  }
617 
619  {
620  return _neighbor_database;
621  }
622  }
623 }
void add(RoutingExtension *extension)
Definition: BaseRouter.cpp:73
const extension_list & getExtensions() const
Definition: BaseRouter.cpp:90
const std::set< dtn::core::Node > getNeighbors()
void processHandshake(const dtn::data::EID &source, NodeHandshake &answer)
Definition: BaseRouter.cpp:152
void add(const dtn::data::MetaBundle &)
static dtn::data::EID local
Definition: BundleCore.h:79
static void add(EventReceiver< E > *receiver)
ibrcommon::RWMutex & getExtensionMutex()
Definition: BaseRouter.cpp:85
std::set< RoutingExtension * > extension_list
Definition: BaseRouter.h:104
void doHandshake(const dtn::data::EID &eid)
Definition: BaseRouter.cpp:543
static void raise(const dtn::data::MetaBundle &bundle, const dtn::data::EID &origin)
void pushHandshakeUpdated(const NodeHandshakeItem::IDENTIFIER id)
Definition: BaseRouter.cpp:548
void requestHandshake(const dtn::data::EID &destination, NodeHandshake &request) const
static void remove(const EventReceiver< E > *receiver)
void setRouter(dtn::routing::BaseRouter *router)
Definition: BundleCore.cpp:222
void setKnown(const dtn::data::MetaBundle &meta)
Definition: BaseRouter.cpp:563
dtn::net::ConnectionManager & getConnectionManager()
Definition: BundleCore.cpp:260
void requestHandshake(const dtn::data::EID &destination, NodeHandshake &request)
Definition: BaseRouter.cpp:192
const dtn::data::BundleSet getPurgedBundles()
Definition: BaseRouter.cpp:607
dtn::storage::BundleSeeker & getSeeker()
Definition: BundleCore.cpp:246
virtual void processHandshake(const dtn::data::EID &, NodeHandshake &)
virtual void add(const dtn::data::MetaBundle &bundle)
Definition: BundleSet.cpp:95
virtual void componentDown()
Definition: BaseRouter.cpp:225
void append(const dtn::data::EID &eid)
void pushHandshakeUpdated(const NodeHandshakeItem::IDENTIFIER id)
bool isPurged(const dtn::data::BundleID &id)
Definition: BaseRouter.cpp:595
void responseHandshake(const dtn::data::EID &source, const NodeHandshake &request, NodeHandshake &answer)
void remove(RoutingExtension *extension)
Definition: BaseRouter.cpp:79
void doHandshake(const dtn::data::EID &eid)
bool isKnown(const dtn::data::BundleID &id)
Definition: BaseRouter.cpp:570
virtual bool has(const dtn::data::BundleID &bundle) const
Definition: BundleSet.cpp:105
virtual void responseHandshake(const dtn::data::EID &, const NodeHandshake &, NodeHandshake &)
dtn::storage::BundleStorage & getStorage()
Definition: BaseRouter.cpp:553
void setPurged(const dtn::data::MetaBundle &meta)
Definition: BaseRouter.cpp:601
const dtn::data::BundleSet getKnownBundles()
Definition: BaseRouter.cpp:588
NeighborDatabase & getNeighborDB()
Definition: BaseRouter.cpp:618
iterator find(block_t blocktype)
Definition: Bundle.cpp:307
static void raise(const dtn::data::MetaBundle &bundle, EventBundleAction action, dtn::data::StatusReportBlock::REASON_CODE reason=dtn::data::StatusReportBlock::NO_ADDITIONAL_INFORMATION)
Definition: BundleEvent.cpp:78
static MetaBundle create(const dtn::data::BundleID &id)
Definition: MetaBundle.cpp:34
dtn::storage::BundleSeeker & getSeeker()
Definition: BaseRouter.cpp:558
void processHandshake(const dtn::data::EID &source, NodeHandshake &answer)
const dtn::data::EID & getEID() const
Definition: Node.cpp:406
virtual void componentUp()
Definition: BaseRouter.cpp:212
virtual void requestHandshake(const dtn::data::EID &, NodeHandshake &) const
bool filterKnown(const dtn::data::MetaBundle &meta)
Definition: BaseRouter.cpp:579
dtn::storage::BundleStorage & getStorage()
Definition: BundleCore.cpp:237
void raiseEvent(const dtn::net::TransferAbortedEvent &evt)
Definition: BaseRouter.cpp:356
virtual const std::string getName() const
Definition: BaseRouter.cpp:613
void responseHandshake(const dtn::data::EID &, const NodeHandshake &, NodeHandshake &)
Definition: BaseRouter.cpp:172
virtual void componentDown()=0
static BundleCore & getInstance()
Definition: BundleCore.cpp:82
void releaseTransfer(const dtn::data::BundleID &id)