|
IBR-DTNSuite 0.6
|
00001 /* 00002 * StaticRoutingExtension.cpp 00003 * 00004 * Created on: 16.02.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "routing/StaticRoutingExtension.h" 00009 #include "routing/QueueBundleEvent.h" 00010 #include "net/TransferAbortedEvent.h" 00011 #include "net/TransferCompletedEvent.h" 00012 #include "net/ConnectionEvent.h" 00013 #include "routing/RequeueBundleEvent.h" 00014 #include "core/NodeEvent.h" 00015 #include "core/SimpleBundleStorage.h" 00016 00017 #include <ibrcommon/Logger.h> 00018 #include <ibrcommon/AutoDelete.h> 00019 00020 #include <typeinfo> 00021 00022 namespace dtn 00023 { 00024 namespace routing 00025 { 00026 StaticRoutingExtension::StaticRoutingExtension(const std::list<StaticRoutingExtension::StaticRoute> &routes) 00027 : _routes(routes) 00028 { 00029 } 00030 00031 StaticRoutingExtension::~StaticRoutingExtension() 00032 { 00033 stop(); 00034 join(); 00035 } 00036 00037 void StaticRoutingExtension::stopExtension() 00038 { 00039 _taskqueue.abort(); 00040 } 00041 00042 bool StaticRoutingExtension::__cancellation() 00043 { 00044 _taskqueue.abort(); 00045 return true; 00046 } 00047 00048 void StaticRoutingExtension::run() 00049 { 00050 class BundleFilter : public dtn::core::BundleStorage::BundleFilterCallback 00051 { 00052 public: 00053 BundleFilter(const NeighborDatabase::NeighborEntry &entry, const std::list<StaticRoutingExtension::StaticRoute> &routes) 00054 : _entry(entry), _routes(routes) 00055 {}; 00056 00057 virtual ~BundleFilter() {}; 00058 00059 virtual size_t limit() const { return 10; }; 00060 00061 virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const 00062 { 00063 // do not forward to any blacklisted destination 00064 const dtn::data::EID dest = meta.destination.getNode(); 00065 if (_blacklist.find(dest) != _blacklist.end()) 00066 { 00067 return false; 00068 } 00069 00070 // do not forward bundles already known by the destination 00071 if (_entry.has(meta)) 00072 { 00073 return false; 00074 } 00075 00076 // search for one rule that match 00077 for (std::list<StaticRoutingExtension::StaticRoute>::const_iterator iter = _routes.begin(); 00078 iter != _routes.end(); iter++) 00079 { 00080 const StaticRoutingExtension::StaticRoute &route = (*iter); 00081 00082 if (route.match(meta.destination)) 00083 { 00084 return true; 00085 } 00086 } 00087 00088 return false; 00089 }; 00090 00091 void blacklist(const dtn::data::EID& id) 00092 { 00093 _blacklist.insert(id); 00094 }; 00095 00096 private: 00097 std::set<dtn::data::EID> _blacklist; 00098 const NeighborDatabase::NeighborEntry &_entry; 00099 const std::list<StaticRoutingExtension::StaticRoute> _routes; 00100 }; 00101 00102 dtn::core::BundleStorage &storage = (**this).getStorage(); 00103 00104 while (true) 00105 { 00106 NeighborDatabase &db = (**this).getNeighborDB(); 00107 00108 try { 00109 Task *t = _taskqueue.getnpop(true); 00110 ibrcommon::AutoDelete<Task> killer(t); 00111 00112 IBRCOMMON_LOGGER_DEBUG(5) << "processing static routing task " << t->toString() << IBRCOMMON_LOGGER_ENDL; 00113 00114 try { 00115 SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t); 00116 00117 std::list<StaticRoutingExtension::StaticRoute> routes; 00118 00119 // look for routes to this node 00120 for (std::list<StaticRoutingExtension::StaticRoute>::const_iterator iter = _routes.begin(); 00121 iter != _routes.end(); iter++) 00122 { 00123 const StaticRoutingExtension::StaticRoute &route = (*iter); 00124 if (route.getDestination() == task.eid) 00125 { 00126 // add to the valid routes 00127 routes.push_back(route); 00128 } 00129 } 00130 00131 if (routes.size() > 0) 00132 { 00133 // this destination is not handles by any static route 00134 ibrcommon::MutexLock l(db); 00135 NeighborDatabase::NeighborEntry &entry = db.get(task.eid); 00136 00137 // get the bundle filter of the neighbor 00138 BundleFilter filter(entry, routes); 00139 00140 // some debug 00141 IBRCOMMON_LOGGER_DEBUG(40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL; 00142 00143 // blacklist the neighbor itself, because this is handled by neighbor routing extension 00144 filter.blacklist(task.eid); 00145 00146 // query all bundles from the storage 00147 const std::list<dtn::data::MetaBundle> list = storage.get(filter); 00148 00149 // send the bundles as long as we have resources 00150 for (std::list<dtn::data::MetaBundle>::const_iterator iter = list.begin(); iter != list.end(); iter++) 00151 { 00152 try { 00153 // transfer the bundle to the neighbor 00154 transferTo(entry, *iter); 00155 } catch (const NeighborDatabase::AlreadyInTransitException&) { }; 00156 } 00157 } 00158 } catch (const NeighborDatabase::NoMoreTransfersAvailable&) { 00159 } catch (const NeighborDatabase::NeighborNotAvailableException&) { 00160 } catch (const std::bad_cast&) { }; 00161 00162 try { 00163 const ProcessBundleTask &task = dynamic_cast<ProcessBundleTask&>(*t); 00164 00165 // look for routes to this node 00166 for (std::list<StaticRoutingExtension::StaticRoute>::const_iterator iter = _routes.begin(); 00167 iter != _routes.end(); iter++) 00168 { 00169 const StaticRoutingExtension::StaticRoute &route = (*iter); 00170 try { 00171 if (route.match(task.bundle.destination)) 00172 { 00173 ibrcommon::MutexLock l(db); 00174 NeighborDatabase::NeighborEntry &n = db.get(route.getDestination()); 00175 00176 // transfer the bundle to the neighbor 00177 transferTo(n, task.bundle); 00178 } 00179 } catch (const NeighborDatabase::NeighborNotAvailableException&) { 00180 // neighbor is not available, can not forward this bundle 00181 } catch (const NeighborDatabase::NoMoreTransfersAvailable&) { 00182 } catch (const NeighborDatabase::AlreadyInTransitException&) { }; 00183 } 00184 } catch (const std::bad_cast&) { }; 00185 00186 } catch (const std::exception &ex) { 00187 IBRCOMMON_LOGGER_DEBUG(20) << "static routing failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00188 return; 00189 } 00190 00191 yield(); 00192 } 00193 } 00194 00195 void StaticRoutingExtension::notify(const dtn::core::Event *evt) 00196 { 00197 try { 00198 const QueueBundleEvent &queued = dynamic_cast<const QueueBundleEvent&>(*evt); 00199 _taskqueue.push( new ProcessBundleTask(queued.bundle, queued.origin) ); 00200 return; 00201 } catch (const std::bad_cast&) { }; 00202 00203 try { 00204 const dtn::core::NodeEvent &nodeevent = dynamic_cast<const dtn::core::NodeEvent&>(*evt); 00205 const dtn::core::Node &n = nodeevent.getNode(); 00206 00207 if (nodeevent.getAction() == NODE_AVAILABLE) 00208 { 00209 _taskqueue.push( new SearchNextBundleTask(n.getEID()) ); 00210 } 00211 return; 00212 } catch (const std::bad_cast&) { }; 00213 00214 try { 00215 const dtn::net::ConnectionEvent &ce = dynamic_cast<const dtn::net::ConnectionEvent&>(*evt); 00216 00217 if (ce.state == dtn::net::ConnectionEvent::CONNECTION_UP) 00218 { 00219 // send all (multi-hop) bundles in the storage to the neighbor 00220 _taskqueue.push( new SearchNextBundleTask(ce.peer) ); 00221 } 00222 return; 00223 } catch (const std::bad_cast&) { }; 00224 00225 // The bundle transfer has been aborted 00226 try { 00227 const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt); 00228 _taskqueue.push( new SearchNextBundleTask(aborted.getPeer()) ); 00229 return; 00230 } catch (const std::bad_cast&) { }; 00231 00232 // A bundle transfer was successful 00233 try { 00234 const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt); 00235 _taskqueue.push( new SearchNextBundleTask(completed.getPeer()) ); 00236 return; 00237 } catch (const std::bad_cast&) { }; 00238 } 00239 00240 StaticRoutingExtension::StaticRoute::StaticRoute(const std::string ®ex, const std::string &dest) 00241 : _dest(dest), _regex_str(regex), _invalid(false) 00242 { 00243 if ( regcomp(&_regex, regex.c_str(), 0) ) 00244 { 00245 IBRCOMMON_LOGGER(error) << "Could not compile regex: " << regex << IBRCOMMON_LOGGER_ENDL; 00246 _invalid = true; 00247 } 00248 } 00249 00250 StaticRoutingExtension::StaticRoute::~StaticRoute() 00251 { 00252 if (!_invalid) 00253 regfree(&_regex); 00254 } 00255 00256 StaticRoutingExtension::StaticRoute::StaticRoute(const StaticRoutingExtension::StaticRoute &obj) 00257 : _dest(obj._dest), _regex_str(obj._regex_str), _invalid(obj._invalid) 00258 { 00259 if ( regcomp(&_regex, _regex_str.c_str(), 0) ) 00260 { 00261 _invalid = true; 00262 } 00263 } 00264 00265 StaticRoutingExtension::StaticRoute& StaticRoutingExtension::StaticRoute::operator=(const StaticRoutingExtension::StaticRoute &obj) 00266 { 00267 if (!_invalid) 00268 { 00269 regfree(&_regex); 00270 } 00271 00272 _dest = obj._dest; 00273 _regex_str = obj._regex_str; 00274 _invalid = obj._invalid; 00275 00276 if (!_invalid) 00277 { 00278 if ( regcomp(&_regex, obj._regex_str.c_str(), 0) ) 00279 { 00280 IBRCOMMON_LOGGER(error) << "Could not compile regex: " << _regex_str << IBRCOMMON_LOGGER_ENDL; 00281 _invalid = true; 00282 } 00283 } 00284 00285 return *this; 00286 } 00287 00288 bool StaticRoutingExtension::StaticRoute::match(const dtn::data::EID &eid) const 00289 { 00290 if (_invalid) return false; 00291 00292 const std::string dest = eid.getString(); 00293 00294 // test against the regular expression 00295 int reti = regexec(&_regex, dest.c_str(), 0, NULL, 0); 00296 00297 if( !reti ) 00298 { 00299 // the expression match 00300 return true; 00301 } 00302 else if( reti == REG_NOMATCH ) 00303 { 00304 // the expression not match 00305 return false; 00306 } 00307 else 00308 { 00309 char msgbuf[100]; 00310 regerror(reti, &_regex, msgbuf, sizeof(msgbuf)); 00311 IBRCOMMON_LOGGER(error) << "Regex match failed: " << std::string(msgbuf) << IBRCOMMON_LOGGER_ENDL; 00312 return false; 00313 } 00314 } 00315 00316 const dtn::data::EID& StaticRoutingExtension::StaticRoute::getDestination() const 00317 { 00318 return _dest; 00319 } 00320 00321 /****************************************/ 00322 00323 StaticRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e) 00324 : eid(e) 00325 { } 00326 00327 StaticRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask() 00328 { } 00329 00330 std::string StaticRoutingExtension::SearchNextBundleTask::toString() 00331 { 00332 return "SearchNextBundleTask: " + eid.getString(); 00333 } 00334 00335 /****************************************/ 00336 00337 StaticRoutingExtension::ProcessBundleTask::ProcessBundleTask(const dtn::data::MetaBundle &meta, const dtn::data::EID &o) 00338 : bundle(meta), origin(o) 00339 { } 00340 00341 StaticRoutingExtension::ProcessBundleTask::~ProcessBundleTask() 00342 { } 00343 00344 std::string StaticRoutingExtension::ProcessBundleTask::toString() 00345 { 00346 return "ProcessBundleTask: " + bundle.toString(); 00347 } 00348 } 00349 }