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