IBR-DTNSuite
0.8
|
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 }