IBR-DTNSuite
0.8
|
00001 /* 00002 * BaseRouter.cpp 00003 * 00004 * Created on: 15.02.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "config.h" 00009 #include "routing/BaseRouter.h" 00010 #include "core/BundleCore.h" 00011 00012 #include "net/TransferAbortedEvent.h" 00013 #include "net/TransferCompletedEvent.h" 00014 #include "net/BundleReceivedEvent.h" 00015 #include "net/ConnectionEvent.h" 00016 #include "routing/QueueBundleEvent.h" 00017 #include "routing/RequeueBundleEvent.h" 00018 #include "storage/BundleStorage.h" 00019 #include "core/BundleGeneratedEvent.h" 00020 #include "core/BundleExpiredEvent.h" 00021 #include "core/BundleEvent.h" 00022 #include "core/NodeEvent.h" 00023 #include "core/TimeEvent.h" 00024 #include "routing/NodeHandshakeEvent.h" 00025 #include "routing/StaticRouteChangeEvent.h" 00026 00027 #include "routing/StaticRoutingExtension.h" 00028 #include "routing/NeighborRoutingExtension.h" 00029 #include "routing/NodeHandshakeExtension.h" 00030 #include "routing/RetransmissionExtension.h" 00031 00032 #include <ibrdtn/utils/Clock.h> 00033 00034 #include <ibrcommon/Logger.h> 00035 #include <ibrcommon/thread/MutexLock.h> 00036 00037 #ifdef WITH_BUNDLE_SECURITY 00038 #include "security/SecurityManager.h" 00039 #endif 00040 00041 namespace dtn 00042 { 00043 namespace routing 00044 { 00045 BaseRouter *BaseRouter::Extension::_router = NULL; 00046 00050 BaseRouter::ThreadedExtension::ThreadedExtension() 00051 { } 00052 00053 BaseRouter::ThreadedExtension::~ThreadedExtension() 00054 { 00055 join(); 00056 } 00057 00061 BaseRouter::Extension::Extension() 00062 { } 00063 00064 BaseRouter::Extension::~Extension() 00065 { } 00066 00067 BaseRouter& BaseRouter::Extension::operator*() 00068 { 00069 return *_router; 00070 } 00071 00077 void BaseRouter::Extension::transferTo(const dtn::data::EID &destination, const dtn::data::BundleID &id) 00078 { 00079 // lock the list of neighbors 00080 ibrcommon::MutexLock l(_router->getNeighborDB()); 00081 00082 // get the neighbor entry for the next hop 00083 NeighborDatabase::NeighborEntry &entry = _router->getNeighborDB().get(destination); 00084 00085 // transfer bundle to the neighbor 00086 transferTo(entry, id); 00087 } 00088 00089 void BaseRouter::Extension::transferTo(NeighborDatabase::NeighborEntry &entry, const dtn::data::BundleID &id) 00090 { 00091 // acquire the transfer of this bundle, could throw already in transit or no resource left exception 00092 entry.acquireTransfer(id); 00093 00094 // transfer the bundle to the next hop 00095 dtn::core::BundleCore::getInstance().transferTo(entry.eid, id); 00096 } 00097 00098 bool BaseRouter::Extension::isRouting(const dtn::data::EID &eid) 00099 { 00100 if (eid.getApplication() == "routing") 00101 { 00102 return true; 00103 } 00104 else if ((eid.getScheme() == dtn::data::EID::CBHE_SCHEME) && (eid.getApplication() == "50")) 00105 { 00106 return true; 00107 } 00108 00109 return false; 00110 } 00111 00115 BaseRouter::Endpoint::Endpoint() 00116 { } 00117 00118 BaseRouter::Endpoint::~Endpoint() 00119 { } 00120 00124 BaseRouter::VirtualEndpoint::VirtualEndpoint(dtn::data::EID name) 00125 : _client(NULL), _name(name) 00126 { } 00127 00128 BaseRouter::VirtualEndpoint::~VirtualEndpoint() 00129 { } 00130 00134 BaseRouter::BaseRouter(dtn::storage::BundleStorage &storage) 00135 : _storage(storage), _nh_extension(NULL) 00136 { 00137 // register myself for all extensions 00138 Extension::_router = this; 00139 00140 // add standard routing modules 00141 _nh_extension = new dtn::routing::NodeHandshakeExtension(); 00142 addExtension( _nh_extension ); 00143 addExtension( new dtn::routing::StaticRoutingExtension() ); 00144 addExtension( new dtn::routing::NeighborRoutingExtension() ); 00145 addExtension( new dtn::routing::RetransmissionExtension() ); 00146 } 00147 00148 BaseRouter::~BaseRouter() 00149 { 00150 // delete all extensions 00151 for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++) 00152 { 00153 delete (*iter); 00154 } 00155 } 00156 00161 void BaseRouter::addExtension(BaseRouter::Extension *extension) 00162 { 00163 _extensions.push_back(extension); 00164 } 00165 00166 const std::list<BaseRouter::Extension*>& BaseRouter::getExtensions() const 00167 { 00168 return _extensions; 00169 } 00170 00171 void BaseRouter::componentUp() 00172 { 00173 bindEvent(dtn::net::TransferAbortedEvent::className); 00174 bindEvent(dtn::net::TransferCompletedEvent::className); 00175 bindEvent(dtn::net::BundleReceivedEvent::className); 00176 bindEvent(dtn::routing::QueueBundleEvent::className); 00177 bindEvent(dtn::routing::RequeueBundleEvent::className); 00178 bindEvent(dtn::routing::NodeHandshakeEvent::className); 00179 bindEvent(dtn::routing::StaticRouteChangeEvent::className); 00180 bindEvent(dtn::core::NodeEvent::className); 00181 bindEvent(dtn::core::BundleExpiredEvent::className); 00182 bindEvent(dtn::core::TimeEvent::className); 00183 bindEvent(dtn::core::BundleGeneratedEvent::className); 00184 bindEvent(dtn::net::ConnectionEvent::className); 00185 00186 for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++) 00187 { 00188 ThreadedExtension *thread = dynamic_cast<ThreadedExtension*>(*iter); 00189 00190 if (thread != NULL) 00191 { 00192 try { 00193 // run the thread 00194 thread->start(); 00195 } catch (const ibrcommon::ThreadException &ex) { 00196 IBRCOMMON_LOGGER(error) << "failed to start component in BaseRouter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL; 00197 } 00198 } 00199 } 00200 } 00201 00202 void BaseRouter::componentDown() 00203 { 00204 unbindEvent(dtn::net::TransferAbortedEvent::className); 00205 unbindEvent(dtn::net::TransferCompletedEvent::className); 00206 unbindEvent(dtn::net::BundleReceivedEvent::className); 00207 unbindEvent(dtn::routing::QueueBundleEvent::className); 00208 unbindEvent(dtn::routing::RequeueBundleEvent::className); 00209 unbindEvent(dtn::routing::NodeHandshakeEvent::className); 00210 unbindEvent(dtn::routing::StaticRouteChangeEvent::className); 00211 unbindEvent(dtn::core::NodeEvent::className); 00212 unbindEvent(dtn::core::BundleExpiredEvent::className); 00213 unbindEvent(dtn::core::TimeEvent::className); 00214 unbindEvent(dtn::core::BundleGeneratedEvent::className); 00215 unbindEvent(dtn::net::ConnectionEvent::className); 00216 00217 // stop all extensions 00218 for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++) 00219 { 00220 ThreadedExtension *thread = dynamic_cast<ThreadedExtension*>(*iter); 00221 00222 if (thread != NULL) 00223 { 00224 try { 00225 // run the thread 00226 thread->stop(); 00227 thread->join(); 00228 } catch (const ibrcommon::ThreadException &ex) { 00229 IBRCOMMON_LOGGER(error) << "failed to stop component in BaseRouter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL; 00230 } 00231 } 00232 } 00233 } 00234 00238 void BaseRouter::raiseEvent(const dtn::core::Event *evt) 00239 { 00240 // If a new neighbor comes available, send him a request for the summary vector 00241 // If a neighbor went away we can free the stored database 00242 try { 00243 const dtn::core::NodeEvent &event = dynamic_cast<const dtn::core::NodeEvent&>(*evt); 00244 00245 if (event.getAction() == NODE_AVAILABLE) 00246 { 00247 ibrcommon::MutexLock l(_neighbor_database); 00248 _neighbor_database.create( event.getNode().getEID() ); 00249 } 00250 else if (event.getAction() == NODE_UNAVAILABLE) 00251 { 00252 ibrcommon::MutexLock l(_neighbor_database); 00253 _neighbor_database.reset( event.getNode().getEID() ); 00254 } 00255 } catch (const std::bad_cast&) { }; 00256 00257 try { 00258 const dtn::net::TransferCompletedEvent &event = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt); 00259 00260 // if a transfer is completed, then release the transfer resource of the peer 00261 try { 00262 try { 00263 // add this bundle to the purge vector if it is delivered to its destination 00264 if (( event.getPeer().getNode() == event.getBundle().destination.getNode() ) && (event.getBundle().procflags & dtn::data::Bundle::DESTINATION_IS_SINGLETON)) 00265 { 00266 IBRCOMMON_LOGGER(notice) << "singleton bundle added to purge vector: " << event.getBundle().toString() << IBRCOMMON_LOGGER_ENDL; 00267 00268 // add it to the purge vector 00269 ibrcommon::MutexLock l(_purged_bundles_lock); 00270 _purged_bundles.add(event.getBundle()); 00271 } 00272 } catch (const dtn::storage::BundleStorage::NoBundleFoundException&) { }; 00273 00274 // lock the list of neighbors 00275 ibrcommon::MutexLock l(_neighbor_database); 00276 NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer()); 00277 entry.releaseTransfer(event.getBundle()); 00278 00279 // add the bundle to the summary vector of the neighbor 00280 _neighbor_database.addBundle(event.getPeer(), event.getBundle()); 00281 } catch (const NeighborDatabase::NeighborNotAvailableException&) { }; 00282 00283 } catch (const std::bad_cast&) { }; 00284 00285 try { 00286 const dtn::net::TransferAbortedEvent &event = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt); 00287 00288 // if a tranfer is aborted, then release the transfer resource of the peer 00289 try { 00290 // lock the list of neighbors 00291 ibrcommon::MutexLock l(_neighbor_database); 00292 NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer()); 00293 entry.releaseTransfer(event.getBundleID()); 00294 00295 if (event.reason == dtn::net::TransferAbortedEvent::REASON_REFUSED) 00296 { 00297 const dtn::data::MetaBundle meta = _storage.get(event.getBundleID()); 00298 00299 // add the transferred bundle to the bloomfilter of the receiver 00300 _neighbor_database.addBundle(event.getPeer(), meta); 00301 } 00302 } catch (const NeighborDatabase::NeighborNotAvailableException&) { }; 00303 } catch (const std::bad_cast&) { }; 00304 00305 try { 00306 const dtn::net::BundleReceivedEvent &received = dynamic_cast<const dtn::net::BundleReceivedEvent&>(*evt); 00307 00308 // drop bundles to the NULL-destination 00309 if (received.bundle._destination == EID("dtn:null")) return; 00310 00311 // drop expired bundles 00312 if (dtn::utils::Clock::isExpired(received.bundle)) return; 00313 00314 // Store incoming bundles into the storage 00315 try { 00316 if (received.fromlocal) 00317 { 00318 // store the bundle into a storage module 00319 _storage.store(received.bundle); 00320 00321 // set the bundle as known 00322 setKnown(received.bundle); 00323 00324 // raise the queued event to notify all receivers about the new bundle 00325 QueueBundleEvent::raise(received.bundle, received.peer); 00326 } 00327 // if the bundle is not known 00328 else if (!filterKnown(received.bundle)) 00329 { 00330 #ifdef WITH_BUNDLE_SECURITY 00331 // security methods modifies the bundle, thus we need a copy of it 00332 dtn::data::Bundle bundle = received.bundle; 00333 00334 // lets see if signatures and hashes are correct and remove them if possible 00335 dtn::security::SecurityManager::getInstance().verify(bundle); 00336 00337 // prevent loops 00338 { 00339 ibrcommon::MutexLock l(_neighbor_database); 00340 00341 // add the bundle to the summary vector of the neighbor 00342 _neighbor_database.addBundle(received.peer, received.bundle); 00343 } 00344 00345 // store the bundle into a storage module 00346 _storage.store(bundle); 00347 #else 00348 // store the bundle into a storage module 00349 _storage.store(received.bundle); 00350 #endif 00351 00352 // raise the queued event to notify all receivers about the new bundle 00353 QueueBundleEvent::raise(received.bundle, received.peer); 00354 } 00355 00356 // finally create a bundle received event 00357 dtn::core::BundleEvent::raise(received.bundle, dtn::core::BUNDLE_RECEIVED); 00358 #ifdef WITH_BUNDLE_SECURITY 00359 } catch (const dtn::security::SecurityManager::VerificationFailedException &ex) { 00360 IBRCOMMON_LOGGER(notice) << "Security checks failed, bundle will be dropped: " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00361 #endif 00362 } catch (const ibrcommon::IOException &ex) { 00363 IBRCOMMON_LOGGER(notice) << "Unable to store bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00364 00365 // raise BundleEvent because we have to drop the bundle 00366 dtn::core::BundleEvent::raise(received.bundle, dtn::core::BUNDLE_DELETED, dtn::data::StatusReportBlock::DEPLETED_STORAGE); 00367 } catch (const dtn::storage::BundleStorage::StorageSizeExeededException &ex) { 00368 IBRCOMMON_LOGGER(notice) << "No space left for bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00369 00370 // raise BundleEvent because we have to drop the bundle 00371 dtn::core::BundleEvent::raise(received.bundle, dtn::core::BUNDLE_DELETED, dtn::data::StatusReportBlock::DEPLETED_STORAGE); 00372 } 00373 00374 return; 00375 } catch (const std::bad_cast&) { 00376 } 00377 00378 try { 00379 const dtn::core::BundleGeneratedEvent &generated = dynamic_cast<const dtn::core::BundleGeneratedEvent&>(*evt); 00380 00381 // set the bundle as known 00382 setKnown(generated.bundle); 00383 00384 // Store incoming bundles into the storage 00385 try { 00386 // store the bundle into a storage module 00387 _storage.store(generated.bundle); 00388 00389 // raise the queued event to notify all receivers about the new bundle 00390 QueueBundleEvent::raise(generated.bundle, dtn::core::BundleCore::local); 00391 } catch (const ibrcommon::IOException &ex) { 00392 IBRCOMMON_LOGGER(notice) << "Unable to store bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00393 } catch (const dtn::storage::BundleStorage::StorageSizeExeededException &ex) { 00394 IBRCOMMON_LOGGER(notice) << "No space left for bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00395 } 00396 00397 return; 00398 } catch (const std::bad_cast&) { 00399 } 00400 00401 try { 00402 const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt); 00403 { 00404 ibrcommon::MutexLock l(_known_bundles_lock); 00405 _known_bundles.expire(time.getTimestamp() + 60); 00406 } 00407 00408 { 00409 ibrcommon::MutexLock l(_purged_bundles_lock); 00410 _purged_bundles.expire(time.getTimestamp() + 60); 00411 } 00412 00413 { 00414 ibrcommon::MutexLock l(_neighbor_database); 00415 _neighbor_database.expire(time.getTimestamp()); 00416 } 00417 } catch (const std::bad_cast&) { 00418 } 00419 00420 // notify all underlying extensions 00421 for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++) 00422 { 00423 (*iter)->notify(evt); 00424 } 00425 } 00426 00432 dtn::data::Bundle BaseRouter::getBundle(const dtn::data::BundleID &id) 00433 { 00434 return _storage.get(id); 00435 } 00436 00437 void BaseRouter::doHandshake(const dtn::data::EID &eid) 00438 { 00439 _nh_extension->doHandshake(eid); 00440 } 00441 00442 dtn::storage::BundleStorage& BaseRouter::getStorage() 00443 { 00444 return _storage; 00445 } 00446 00447 void BaseRouter::setKnown(const dtn::data::MetaBundle &meta) 00448 { 00449 ibrcommon::MutexLock l(_known_bundles_lock); 00450 return _known_bundles.add(meta); 00451 } 00452 00453 // set the bundle as known 00454 bool BaseRouter::isKnown(const dtn::data::BundleID &id) 00455 { 00456 ibrcommon::MutexLock l(_known_bundles_lock); 00457 return _known_bundles.contains(id); 00458 } 00459 00460 // check if a bundle is known 00461 // if the bundle is unkown add it to the known list and return 00462 // false 00463 bool BaseRouter::filterKnown(const dtn::data::MetaBundle &meta) 00464 { 00465 ibrcommon::MutexLock l(_known_bundles_lock); 00466 bool ret = _known_bundles.contains(meta); 00467 if (!ret) _known_bundles.add(meta); 00468 00469 return ret; 00470 } 00471 00472 const SummaryVector BaseRouter::getSummaryVector() 00473 { 00474 ibrcommon::MutexLock l(_known_bundles_lock); 00475 return _known_bundles.getSummaryVector(); 00476 } 00477 00478 void BaseRouter::addPurgedBundle(const dtn::data::MetaBundle &meta) 00479 { 00480 ibrcommon::MutexLock l(_purged_bundles_lock); 00481 return _purged_bundles.add(meta); 00482 } 00483 00484 const SummaryVector BaseRouter::getPurgedBundles() 00485 { 00486 ibrcommon::MutexLock l(_purged_bundles_lock); 00487 return _purged_bundles.getSummaryVector(); 00488 } 00489 00490 const std::string BaseRouter::getName() const 00491 { 00492 return "BaseRouter"; 00493 } 00494 00495 NeighborDatabase& BaseRouter::getNeighborDB() 00496 { 00497 return _neighbor_database; 00498 } 00499 } 00500 }