IBR-DTNSuite 0.6

daemon/src/routing/StaticRoutingExtension.cpp

Go to the documentation of this file.
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 &regex, 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 }