IBR-DTNSuite  0.8
daemon/src/routing/flooding/FloodRoutingExtension.cpp
Go to the documentation of this file.
00001 /*
00002  * FloodRoutingExtension.cpp
00003  *
00004  *  Created on: 18.02.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "routing/flooding/FloodRoutingExtension.h"
00009 #include "routing/QueueBundleEvent.h"
00010 #include "core/NodeEvent.h"
00011 #include "net/TransferCompletedEvent.h"
00012 #include "net/TransferAbortedEvent.h"
00013 #include "net/ConnectionEvent.h"
00014 #include "core/Node.h"
00015 #include "net/ConnectionManager.h"
00016 #include "Configuration.h"
00017 #include "core/BundleCore.h"
00018 
00019 #include <ibrdtn/data/MetaBundle.h>
00020 #include <ibrcommon/thread/MutexLock.h>
00021 #include <ibrcommon/Logger.h>
00022 
00023 #include <functional>
00024 #include <list>
00025 #include <algorithm>
00026 #include <iomanip>
00027 #include <ios>
00028 #include <iostream>
00029 #include <memory>
00030 
00031 #include <stdlib.h>
00032 #include <typeinfo>
00033 
00034 namespace dtn
00035 {
00036         namespace routing
00037         {
00038                 FloodRoutingExtension::FloodRoutingExtension()
00039                 {
00040                         // write something to the syslog
00041                         IBRCOMMON_LOGGER(info) << "Initializing flooding routing module" << IBRCOMMON_LOGGER_ENDL;
00042                 }
00043 
00044                 FloodRoutingExtension::~FloodRoutingExtension()
00045                 {
00046                         stop();
00047                         join();
00048                 }
00049 
00050                 void FloodRoutingExtension::notify(const dtn::core::Event *evt)
00051                 {
00052                         try {
00053                                 dynamic_cast<const QueueBundleEvent&>(*evt);
00054 
00055                                 // new bundles are forwarded to all neighbors
00056                                 const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getNeighbors();
00057 
00058                                 for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); iter++)
00059                                 {
00060                                         const dtn::core::Node &n = (*iter);
00061 
00062                                         // transfer the next bundle to this destination
00063                                         _taskqueue.push( new SearchNextBundleTask( n.getEID() ) );
00064                                 }
00065 
00066                                 return;
00067                         } catch (const std::bad_cast&) { };
00068 
00069                         try {
00070                                 const dtn::core::NodeEvent &nodeevent = dynamic_cast<const dtn::core::NodeEvent&>(*evt);
00071                                 const dtn::core::Node &n = nodeevent.getNode();
00072 
00073                                 if (nodeevent.getAction() == NODE_AVAILABLE)
00074                                 {
00075                                         const dtn::data::EID &eid = n.getEID();
00076 
00077                                         // send all (multi-hop) bundles in the storage to the neighbor
00078                                         _taskqueue.push( new SearchNextBundleTask(eid) );
00079                                 }
00080                                 return;
00081                         } catch (const std::bad_cast&) { };
00082 
00083                         try {
00084                                 const dtn::net::ConnectionEvent &ce = dynamic_cast<const dtn::net::ConnectionEvent&>(*evt);
00085 
00086                                 if (ce.state == dtn::net::ConnectionEvent::CONNECTION_UP)
00087                                 {
00088                                         // send all (multi-hop) bundles in the storage to the neighbor
00089                                         _taskqueue.push( new SearchNextBundleTask(ce.peer) );
00090                                 }
00091                                 return;
00092                         } catch (const std::bad_cast&) { };
00093 
00094                         // The bundle transfer has been aborted
00095                         try {
00096                                 const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
00097 
00098                                 // transfer the next bundle to this destination
00099                                 _taskqueue.push( new SearchNextBundleTask( aborted.getPeer() ) );
00100                                 return;
00101                         } catch (const std::bad_cast&) { };
00102 
00103                         // A bundle transfer was successful
00104                         try {
00105                                 const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
00106 
00107                                 // transfer the next bundle to this destination
00108                                 _taskqueue.push( new SearchNextBundleTask( completed.getPeer() ) );
00109                                 return;
00110                         } catch (const std::bad_cast&) { };
00111                 }
00112 
00113                 void FloodRoutingExtension::__cancellation()
00114                 {
00115                         _taskqueue.abort();
00116                 }
00117 
00118                 void FloodRoutingExtension::run()
00119                 {
00120                         class BundleFilter : public dtn::storage::BundleStorage::BundleFilterCallback
00121                         {
00122                         public:
00123                                 BundleFilter(const NeighborDatabase::NeighborEntry &entry)
00124                                  : _entry(entry)
00125                                 {};
00126 
00127                                 virtual ~BundleFilter() {};
00128 
00129                                 virtual size_t limit() const { return 10; };
00130 
00131                                 virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const
00132                                 {
00133                                         // check Scope Control Block - do not forward bundles with hop limit == 0
00134                                         if (meta.hopcount == 0)
00135                                         {
00136                                                 return false;
00137                                         }
00138 
00139                                         // do not forward any routing control message
00140                                         // this is done by the neighbor routing module
00141                                         if (isRouting(meta.source))
00142                                         {
00143                                                 return false;
00144                                         }
00145 
00146                                         // do not forward local bundles
00147                                         if ((meta.destination.getNode() == dtn::core::BundleCore::local)
00148                                                         && meta.get(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON)
00149                                                 )
00150                                         {
00151                                                 return false;
00152                                         }
00153 
00154                                         // check Scope Control Block - do not forward non-group bundles with hop limit <= 1
00155                                         if ((meta.hopcount <= 1) && (meta.get(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON)))
00156                                         {
00157                                                 return false;
00158                                         }
00159 
00160                                         // do not forward to any blacklisted destination
00161                                         const dtn::data::EID dest = meta.destination.getNode();
00162                                         if (_blacklist.find(dest) != _blacklist.end())
00163                                         {
00164                                                 return false;
00165                                         }
00166 
00167                                         // do not forward bundles already known by the destination
00168                                         if (_entry.has(meta))
00169                                         {
00170                                                 return false;
00171                                         }
00172 
00173                                         return true;
00174                                 };
00175 
00176                                 void blacklist(const dtn::data::EID& id)
00177                                 {
00178                                         _blacklist.insert(id);
00179                                 };
00180 
00181                         private:
00182                                 std::set<dtn::data::EID> _blacklist;
00183                                 const NeighborDatabase::NeighborEntry &_entry;
00184                         };
00185 
00186                         dtn::storage::BundleStorage &storage = (**this).getStorage();
00187 
00188                         while (true)
00189                         {
00190                                 try {
00191                                         Task *t = _taskqueue.getnpop(true);
00192                                         std::auto_ptr<Task> killer(t);
00193 
00194                                         IBRCOMMON_LOGGER_DEBUG(50) << "processing flooding task " << t->toString() << IBRCOMMON_LOGGER_ENDL;
00195 
00196                                         try {
00197                                                 try {
00198                                                         SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t);
00199                                                         NeighborDatabase &db = (**this).getNeighborDB();
00200 
00201                                                         ibrcommon::MutexLock l(db);
00202                                                         NeighborDatabase::NeighborEntry &entry = db.get(task.eid);
00203 
00204                                                         // get the bundle filter of the neighbor
00205                                                         BundleFilter filter(entry);
00206 
00207                                                         // some debug
00208                                                         IBRCOMMON_LOGGER_DEBUG(40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL;
00209 
00210                                                         // blacklist the neighbor itself, because this is handles by neighbor routing extension
00211                                                         filter.blacklist(task.eid);
00212 
00213                                                         // query all bundles from the storage
00214                                                         const std::list<dtn::data::MetaBundle> list = storage.get(filter);
00215 
00216                                                         // send the bundles as long as we have resources
00217                                                         for (std::list<dtn::data::MetaBundle>::const_iterator iter = list.begin(); iter != list.end(); iter++)
00218                                                         {
00219                                                                 try {
00220                                                                         // transfer the bundle to the neighbor
00221                                                                         transferTo(entry, *iter);
00222                                                                 } catch (const NeighborDatabase::AlreadyInTransitException&) { };
00223                                                         }
00224                                                 } catch (const NeighborDatabase::NoMoreTransfersAvailable&) {
00225                                                 } catch (const NeighborDatabase::NeighborNotAvailableException&) {
00226                                                 } catch (const std::bad_cast&) { };
00227                                         } catch (const ibrcommon::Exception &ex) {
00228                                                 IBRCOMMON_LOGGER_DEBUG(20) << "Exception occurred in FloodRoutingExtension: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00229                                         }
00230                                 } catch (const std::exception&) {
00231                                         return;
00232                                 }
00233 
00234                                 yield();
00235                         }
00236                 }
00237 
00238                 /****************************************/
00239 
00240                 FloodRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e)
00241                  : eid(e)
00242                 { }
00243 
00244                 FloodRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask()
00245                 { }
00246 
00247                 std::string FloodRoutingExtension::SearchNextBundleTask::toString()
00248                 {
00249                         return "SearchNextBundleTask: " + eid.getString();
00250                 }
00251         }
00252 }