IBR-DTNSuite  0.12
EpidemicRoutingExtension.cpp
Go to the documentation of this file.
1 /*
2  * EpidemicRoutingExtension.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 
23 
28 #include "core/NodeEvent.h"
29 #include "core/Node.h"
30 #include "net/ConnectionEvent.h"
31 #include "net/ConnectionManager.h"
32 #include "Configuration.h"
33 #include "core/BundleCore.h"
34 #include "core/EventDispatcher.h"
35 #include "core/BundleEvent.h"
36 
37 #include <ibrdtn/data/MetaBundle.h>
39 #include <ibrcommon/Logger.h>
40 
41 #include <functional>
42 #include <list>
43 #include <algorithm>
44 
45 #include <iomanip>
46 #include <ios>
47 #include <iostream>
48 #include <set>
49 #include <memory>
50 
51 #include <stdlib.h>
52 #include <typeinfo>
53 
54 namespace dtn
55 {
56  namespace routing
57  {
58  const std::string EpidemicRoutingExtension::TAG = "EpidemicRoutingExtension";
59 
61  {
62  // write something to the syslog
63  IBRCOMMON_LOGGER_TAG(EpidemicRoutingExtension::TAG, info) << "Initializing epidemic routing module" << IBRCOMMON_LOGGER_ENDL;
64  }
65 
67  {
68  join();
69  }
70 
72  {
74  }
75 
77  {
78  // transfer the next bundle to this destination
79  _taskqueue.push( new SearchNextBundleTask( peer ) );
80  }
81 
83  {
84  // new bundles trigger a recheck for all neighbors
85  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
86 
87  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
88  {
89  const dtn::core::Node &n = (*iter);
90 
91  if (n.getEID() != peer)
92  {
93  // trigger all routing modules to search for bundles to forward
94  eventDataChanged(n.getEID());
95  }
96  }
97  }
98 
100  {
101  try {
102  const NodeHandshakeEvent &handshake = dynamic_cast<const NodeHandshakeEvent&>(*evt);
103 
105  {
106  // transfer the next bundle to this destination
107  _taskqueue.push( new SearchNextBundleTask( handshake.peer ) );
108  }
109  else if (handshake.state == NodeHandshakeEvent::HANDSHAKE_COMPLETED)
110  {
111  // transfer the next bundle to this destination
112  _taskqueue.push( new SearchNextBundleTask( handshake.peer ) );
113  }
114  return;
115  } catch (const std::bad_cast&) { };
116  }
117 
119  {
121 
122  // reset the task queue
123  _taskqueue.reset();
124 
125  // routine checked for throw() on 15.02.2013
126  try {
127  // run the thread
128  start();
129  } catch (const ibrcommon::ThreadException &ex) {
130  IBRCOMMON_LOGGER_TAG(EpidemicRoutingExtension::TAG, error) << "componentUp failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
131  }
132  }
133 
135  {
137 
138  try {
139  // stop the thread
140  stop();
141  join();
142  } catch (const ibrcommon::ThreadException &ex) {
143  IBRCOMMON_LOGGER_TAG(EpidemicRoutingExtension::TAG, error) << "componentDown failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
144  }
145  }
146 
148  {
149  _taskqueue.abort();
150  }
151 
153  {
154  class BundleFilter : public dtn::storage::BundleSelector
155  {
156  public:
157  BundleFilter(const NeighborDatabase::NeighborEntry &entry, const std::set<dtn::core::Node> &neighbors)
158  : _entry(entry), _neighbors(neighbors)
159  {};
160 
161  virtual ~BundleFilter() {};
162 
163  virtual dtn::data::Size limit() const throw () { return _entry.getFreeTransferSlots(); };
164 
165  virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const throw (dtn::storage::BundleSelectorException)
166  {
167  // check Scope Control Block - do not forward bundles with hop limit == 0
168  if (meta.hopcount == 0)
169  {
170  return false;
171  }
172 
173  // do not forward local bundles
176  )
177  {
178  return false;
179  }
180 
181  // check Scope Control Block - do not forward non-group bundles with hop limit <= 1
183  {
184  return false;
185  }
186 
187  // do not forward bundles addressed to this neighbor,
188  // because this is handled by neighbor routing extension
189  if (_entry.eid == meta.destination.getNode())
190  {
191  return false;
192  }
193 
194  // if this is a singleton bundle ...
196  {
197  const dtn::core::Node n(meta.destination.getNode());
198 
199  // do not forward the bundle if the final destination is available
200  if (_neighbors.find(n) != _neighbors.end())
201  {
202  return false;
203  }
204  }
205 
206  // do not forward bundles already known by the destination
207  // throws BloomfilterNotAvailableException if no filter is available or it is expired
208  try {
209  if (_entry.has(meta, true))
210  {
211  return false;
212  }
215  }
216 
217  return true;
218  };
219 
220  private:
221  const NeighborDatabase::NeighborEntry &_entry;
222  const std::set<dtn::core::Node> &_neighbors;
223  };
224 
225  // list for bundles
227 
228  // set of known neighbors
229  std::set<dtn::core::Node> neighbors;
230 
231  while (true)
232  {
233  try {
234  Task *t = _taskqueue.getnpop(true);
235  std::auto_ptr<Task> killer(t);
236 
237  IBRCOMMON_LOGGER_DEBUG_TAG(EpidemicRoutingExtension::TAG, 50) << "processing task " << t->toString() << IBRCOMMON_LOGGER_ENDL;
238 
239  try {
245  try {
246  SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t);
247 
248  // lock the neighbor database while searching for bundles
249  try {
250  NeighborDatabase &db = (**this).getNeighborDB();
251  ibrcommon::MutexLock l(db);
252  NeighborDatabase::NeighborEntry &entry = db.get(task.eid, true);
253 
254  // check if enough transfer slots available (threshold reached)
255  if (!entry.isTransferThresholdReached())
257 
259  // get current neighbor list
261  } else {
262  // "prefer direct" option disabled - clear the list of neighbors
263  neighbors.clear();
264  }
265 
266  // get the bundle filter of the neighbor
267  const BundleFilter filter(entry, neighbors);
268 
269  // some debug output
270  IBRCOMMON_LOGGER_DEBUG_TAG(EpidemicRoutingExtension::TAG, 40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL;
271 
272  // query some unknown bundle from the storage
273  list.clear();
274  (**this).getSeeker().get(filter, list);
275  } catch (const dtn::storage::BundleSelectorException&) {
276  // query a new summary vector from this neighbor
277  (**this).doHandshake(task.eid);
278  }
279 
280  // send the bundles as long as we have resources
281  for (std::list<dtn::data::MetaBundle>::const_iterator iter = list.begin(); iter != list.end(); ++iter)
282  {
283  try {
284  // transfer the bundle to the neighbor
285  transferTo(task.eid, *iter);
286  } catch (const NeighborDatabase::AlreadyInTransitException&) { };
287  }
288  } catch (const NeighborDatabase::NoMoreTransfersAvailable &ex) {
289  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
291  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
292  } catch (const dtn::storage::NoBundleFoundException &ex) {
293  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
294  } catch (const std::bad_cast&) { };
295  } catch (const ibrcommon::Exception &ex) {
296  IBRCOMMON_LOGGER_DEBUG_TAG(EpidemicRoutingExtension::TAG, 20) << "task failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
297  }
298  } catch (const std::exception &ex) {
299  IBRCOMMON_LOGGER_DEBUG_TAG(EpidemicRoutingExtension::TAG, 15) << "terminated due to " << ex.what() << IBRCOMMON_LOGGER_ENDL;
300  return;
301  }
302 
303  yield();
304  }
305  }
306 
307  /****************************************/
308 
309  EpidemicRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e)
310  : eid(e)
311  { }
312 
313  EpidemicRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask()
314  { }
315 
316  std::string EpidemicRoutingExtension::SearchNextBundleTask::toString()
317  {
318  return "SearchNextBundleTask: " + eid.getString();
319  }
320  }
321 }