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