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 "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 &regex, 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 }