IBR-DTNSuite  0.10
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"
34 #include "storage/BundleStorage.h"
37 #include "core/BundleEvent.h"
38 #include "core/NodeEvent.h"
39 #include "core/TimeEvent.h"
40 #include "core/BundlePurgeEvent.h"
43 
46 #include <ibrdtn/utils/Clock.h>
47 
48 #include <ibrcommon/Logger.h>
51 
52 #ifdef WITH_BUNDLE_SECURITY
54 #endif
55 
56 namespace dtn
57 {
58  namespace routing
59  {
60  const std::string BaseRouter::TAG = "BaseRouter";
61 
66  : _extension_state(false), _next_expiration(0)
67  {
68  // register myself for all extensions
69  RoutingExtension::_router = this;
70  }
71 
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
226  }
227 
229  {
230  // routine checked for throw() on 15.02.2013
244  }
245 
249  void BaseRouter::raiseEvent(const dtn::core::Event *evt) throw ()
250  {
251  // If a new neighbor comes available, send him a request for the summary vector
252  // If a neighbor went away we can free the stored database
253  try {
254  const dtn::core::NodeEvent &event = dynamic_cast<const dtn::core::NodeEvent&>(*evt);
255 
256  if (event.getAction() == NODE_AVAILABLE)
257  {
258  ibrcommon::MutexLock l(_neighbor_database);
259  _neighbor_database.create( event.getNode().getEID() );
260  }
261  else if (event.getAction() == NODE_UNAVAILABLE)
262  {
263  ibrcommon::MutexLock l(_neighbor_database);
264  _neighbor_database.create( event.getNode().getEID() ).reset();
265  }
266 
267  // pass event to all extensions
269  __forward_event(evt);
270  return;
271  } catch (const std::bad_cast&) { };
272 
273  try {
274  const dtn::net::TransferCompletedEvent &event = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
275 
276  // if a transfer is completed, then release the transfer resource of the peer
277  try {
278  // lock the list of neighbors
279  ibrcommon::MutexLock l(_neighbor_database);
280  NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer());
281  entry.releaseTransfer(event.getBundle());
282 
283  // add the bundle to the summary vector of the neighbor
284  entry.add(event.getBundle());
286 
287  // pass event to all extensions
289  __forward_event(evt);
290  return;
291  } catch (const std::bad_cast&) { };
292 
293  try {
294  const dtn::net::TransferAbortedEvent &event = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
295 
296  // if a transfer is aborted, then release the transfer resource of the peer
297  try {
298  // lock the list of neighbors
299  ibrcommon::MutexLock l(_neighbor_database);
300  NeighborDatabase::NeighborEntry &entry = _neighbor_database.create(event.getPeer());
301  entry.releaseTransfer(event.getBundleID());
302 
304  {
305  const dtn::data::MetaBundle meta = getStorage().get(event.getBundleID());
306 
307  // add the transferred bundle to the bloomfilter of the receiver
308  entry.add(meta);
309  }
310  } catch (const dtn::storage::NoBundleFoundException&) { };
311 
312  // pass event to all extensions
314  __forward_event(evt);
315  return;
316  } catch (const std::bad_cast&) { };
317 
318  try {
319  const dtn::net::BundleReceivedEvent &received = dynamic_cast<const dtn::net::BundleReceivedEvent&>(*evt);
320 
321  // Store incoming bundles into the storage
322  try {
323  if (received.fromlocal)
324  {
325  // store the bundle into a storage module
326  getStorage().store(received.bundle);
327 
328  // set the bundle as known
329  setKnown(received.bundle);
330 
331  // raise the queued event to notify all receivers about the new bundle
332  QueueBundleEvent::raise(received.bundle, received.peer);
333  }
334  // if the bundle is not known
335  else if (!filterKnown(received.bundle))
336  {
337  // security methods modifies the bundle, thus we need a copy of it
338  dtn::data::Bundle bundle = received.bundle;
339 
340 #ifdef WITH_BUNDLE_SECURITY
341  // lets see if signatures and hashes are correct and remove them if possible
343 #endif
344 
345  // increment value in the scope control hop limit block
346  try {
348  schl.increment();
350 
351  // modify TrackingBlock
352  try {
356 
357  // prevent loops
358  try {
359  ibrcommon::MutexLock l(_neighbor_database);
360 
361  // add the bundle to the summary vector of the neighbor
362  _neighbor_database.get(received.peer).add(received.bundle);
364 
365  // store the bundle into a storage module
366  getStorage().store(bundle);
367 
368  // raise the queued event to notify all receivers about the new bundle
369  QueueBundleEvent::raise(received.bundle, received.peer);
370  }
371  else
372  {
373  IBRCOMMON_LOGGER_DEBUG_TAG(BaseRouter::TAG, 5) << "Duplicate bundle " << received.bundle.toString() << " from " << received.peer.getString() << " ignored." << IBRCOMMON_LOGGER_ENDL;
374  }
375 
376  // finally create a bundle received event
378 #ifdef WITH_BUNDLE_SECURITY
380  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "Security checks failed (" << ex.what() << "), bundle will be dropped: " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
381 #endif
382  } catch (const ibrcommon::IOException &ex) {
383  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "Unable to store bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
384 
385  // raise BundleEvent because we have to drop the bundle
388  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "No space left for bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
389 
390  // raise BundleEvent because we have to drop the bundle
392  } catch (const ibrcommon::Exception &ex) {
393  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, error) << "Bundle " << received.bundle.toString() << " dropped: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
394 
395  // raise BundleEvent because we have to drop the bundle
397  }
398 
399  // no routing extension should be interested in this event
400  // everybody should listen to QueueBundleEvent instead
401  return;
402  } catch (const std::bad_cast&) { };
403 
404  try {
405  const dtn::core::BundleGeneratedEvent &generated = dynamic_cast<const dtn::core::BundleGeneratedEvent&>(*evt);
406 
407  // set the bundle as known
408  setKnown(generated.bundle);
409 
410  // Store incoming bundles into the storage
411  try {
412  // store the bundle into a storage module
413  getStorage().store(generated.bundle);
414 
415  // raise the queued event to notify all receivers about the new bundle
417  } catch (const ibrcommon::IOException &ex) {
418  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "Unable to store bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
420  IBRCOMMON_LOGGER_TAG(BaseRouter::TAG, notice) << "No space left for bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
421  }
422 
423  // do not pass this event to any extension
424  return;
425  } catch (const std::bad_cast&) { };
426 
427  try {
428  const dtn::core::BundlePurgeEvent &purge = dynamic_cast<const dtn::core::BundlePurgeEvent&>(*evt);
429 
430  // add the purged bundle to the purge vector
431  setPurged(purge.bundle);
432 
433  // since no routing module is interested in purge events yet - we exit here
434  return;
435  } catch (const std::bad_cast&) { }
436 
437  try {
438  const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt);
439  dtn::data::Timestamp expire_time = time.getTimestamp();
440 
441  // do the expiration only every 60 seconds
442  if (expire_time > _next_expiration) {
443  // store the next expiration time
444  _next_expiration = expire_time + 60;
445 
446  // expire all bundles and neighbors one minute late
447  if (expire_time <= 60) expire_time = 0;
448  else expire_time -= 60;
449 
450  {
451  ibrcommon::MutexLock l(_known_bundles_lock);
452  _known_bundles.expire(expire_time);
453  }
454 
455  {
456  ibrcommon::MutexLock l(_purged_bundles_lock);
457  _purged_bundles.expire(expire_time);
458  }
459 
460  {
461  ibrcommon::MutexLock l(_neighbor_database);
462 
463  // get all active neighbors
464  const std::set<dtn::core::Node> neighbors = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
465 
466  // touch all active neighbors
467  for (std::set<dtn::core::Node>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it) {
468  _neighbor_database.create( (*it).getEID() );
469  }
470 
471  // check all neighbor entries for expiration
472  _neighbor_database.expire(time.getTimestamp());
473  }
474  }
475 
476  // pass event to all extensions
478  __forward_event(evt);
479  return;
480  } catch (const std::bad_cast&) { };
481 
482  // pass event to all extensions
484  __forward_event(evt);
485  }
486 
487  void BaseRouter::__forward_event(const dtn::core::Event *evt) throw ()
488  {
489  // do not forward the event if the extensions are down
490  if (!_extension_state) return;
491 
492  _nh_extension.notify(evt);
493  _retransmission_extension.notify(evt);
494 
495  // notify all underlying extensions
496  for (extension_list::const_iterator iter = _extensions.begin(); iter != _extensions.end(); ++iter)
497  {
498  (*iter)->notify(evt);
499  }
500  }
501 
503  {
504  _nh_extension.doHandshake(eid);
505  }
506 
508  {
510  }
511 
513  {
515  }
516 
518  {
519  ibrcommon::MutexLock l(_known_bundles_lock);
520  return _known_bundles.add(meta);
521  }
522 
523  // check if the bundle is known
525  {
526  ibrcommon::MutexLock l(_known_bundles_lock);
527  return _known_bundles.has(id);
528  }
529 
530  // check if a bundle is known
531  // if the bundle is unkown add it to the known list and return
532  // false
534  {
535  ibrcommon::MutexLock l(_known_bundles_lock);
536  bool ret = _known_bundles.has(meta);
537  if (!ret) _known_bundles.add(meta);
538 
539  return ret;
540  }
541 
543  {
544  ibrcommon::MutexLock l(_known_bundles_lock);
545  return _known_bundles;
546  }
547 
548  // set the bundle as known
550  {
551  ibrcommon::MutexLock l(_purged_bundles_lock);
552  return _purged_bundles.has(id);
553  }
554 
556  {
557  ibrcommon::MutexLock l(_purged_bundles_lock);
558  return _purged_bundles.add(meta);
559  }
560 
562  {
563  ibrcommon::MutexLock l(_purged_bundles_lock);
564  return _purged_bundles;
565  }
566 
567  const std::string BaseRouter::getName() const
568  {
569  return "BaseRouter";
570  }
571 
573  {
574  return _neighbor_database;
575  }
576  }
577 }