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