IBR-DTNSuite 0.6

daemon/src/routing/BaseRouter.cpp

Go to the documentation of this file.
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 "core/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 
00025 #include <ibrcommon/Logger.h>
00026 #include <ibrcommon/thread/MutexLock.h>
00027 
00028 #ifdef WITH_BUNDLE_SECURITY
00029 #include "security/SecurityManager.h"
00030 #endif
00031 
00032 namespace dtn
00033 {
00034         namespace routing
00035         {
00036                 BaseRouter *BaseRouter::Extension::_router = NULL;
00037 
00041                 BaseRouter::ThreadedExtension::ThreadedExtension()
00042                 { }
00043 
00044                 BaseRouter::ThreadedExtension::~ThreadedExtension()
00045                 {
00046                         join();
00047                 }
00048 
00052                 BaseRouter::Extension::Extension()
00053                 { }
00054 
00055                 BaseRouter::Extension::~Extension()
00056                 { }
00057 
00058                 BaseRouter& BaseRouter::Extension::operator*()
00059                 {
00060                         return *_router;
00061                 }
00062 
00068                 void BaseRouter::Extension::transferTo(const dtn::data::EID &destination, const dtn::data::BundleID &id)
00069                 {
00070                         // lock the list of neighbors
00071                         ibrcommon::MutexLock l(_router->getNeighborDB());
00072 
00073                         // get the neighbor entry for the next hop
00074                         NeighborDatabase::NeighborEntry &entry = _router->getNeighborDB().get(destination);
00075 
00076                         // transfer bundle to the neighbor
00077                         transferTo(entry, id);
00078                 }
00079 
00080                 void BaseRouter::Extension::transferTo(NeighborDatabase::NeighborEntry &entry, const dtn::data::BundleID &id)
00081                 {
00082                         // acquire the transfer of this bundle, could throw already in transit or no resource left exception
00083                         entry.acquireTransfer(id);
00084 
00085                         // transfer the bundle to the next hop
00086                         dtn::core::BundleCore::getInstance().transferTo(entry.eid, id);
00087                 }
00088 
00092                 BaseRouter::Endpoint::Endpoint()
00093                 { }
00094 
00095                 BaseRouter::Endpoint::~Endpoint()
00096                 { }
00097 
00101                 BaseRouter::VirtualEndpoint::VirtualEndpoint(dtn::data::EID name)
00102                  : _client(NULL), _name(name)
00103                 { }
00104 
00105                 BaseRouter::VirtualEndpoint::~VirtualEndpoint()
00106                 { }
00107 
00111                 BaseRouter::BaseRouter(dtn::core::BundleStorage &storage)
00112                  : _storage(storage)
00113                 {
00114                         // register myself for all extensions
00115                         Extension::_router = this;
00116                 }
00117 
00118                 BaseRouter::~BaseRouter()
00119                 {
00120                 }
00121 
00126                 void BaseRouter::addExtension(BaseRouter::Extension *extension)
00127                 {
00128                         _extensions.push_back(extension);
00129                 }
00130 
00131                 void BaseRouter::componentUp()
00132                 {
00133                         bindEvent(dtn::net::TransferAbortedEvent::className);
00134                         bindEvent(dtn::net::TransferCompletedEvent::className);
00135                         bindEvent(dtn::net::BundleReceivedEvent::className);
00136                         bindEvent(dtn::routing::QueueBundleEvent::className);
00137                         bindEvent(dtn::routing::RequeueBundleEvent::className);
00138                         bindEvent(dtn::core::NodeEvent::className);
00139                         bindEvent(dtn::core::BundleExpiredEvent::className);
00140                         bindEvent(dtn::core::TimeEvent::className);
00141                         bindEvent(dtn::core::BundleGeneratedEvent::className);
00142                         bindEvent(dtn::net::ConnectionEvent::className);
00143 
00144                         for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++)
00145                         {
00146                                 ThreadedExtension *thread = dynamic_cast<ThreadedExtension*>(*iter);
00147 
00148                                 if (thread != NULL)
00149                                 {
00150                                         try {
00151                                                 // run the thread
00152                                                 thread->start();
00153                                         } catch (const ibrcommon::ThreadException &ex) {
00154                                                 IBRCOMMON_LOGGER(error) << "failed to start component in BaseRouter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL;
00155                                         }
00156                                 }
00157                         }
00158                 }
00159 
00160                 void BaseRouter::componentDown()
00161                 {
00162                         unbindEvent(dtn::net::TransferAbortedEvent::className);
00163                         unbindEvent(dtn::net::TransferCompletedEvent::className);
00164                         unbindEvent(dtn::net::BundleReceivedEvent::className);
00165                         unbindEvent(dtn::routing::QueueBundleEvent::className);
00166                         unbindEvent(dtn::routing::RequeueBundleEvent::className);
00167                         unbindEvent(dtn::core::NodeEvent::className);
00168                         unbindEvent(dtn::core::BundleExpiredEvent::className);
00169                         unbindEvent(dtn::core::TimeEvent::className);
00170                         unbindEvent(dtn::core::BundleGeneratedEvent::className);
00171                         unbindEvent(dtn::net::ConnectionEvent::className);
00172 
00173                         // delete all extensions
00174                         for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++)
00175                         {
00176                                 ThreadedExtension *thread = dynamic_cast<ThreadedExtension*>(*iter);
00177 
00178                                 if (thread != NULL)
00179                                 {
00180                                         try {
00181                                                 // run the thread
00182                                                 thread->stop();
00183                                         } catch (const ibrcommon::ThreadException &ex) {
00184                                                 IBRCOMMON_LOGGER(error) << "failed to stop component in BaseRouter\n" << ex.what() << IBRCOMMON_LOGGER_ENDL;
00185                                         }
00186                                 }
00187 
00188                                 delete (*iter);
00189                         }
00190                 }
00191 
00195                 void BaseRouter::raiseEvent(const dtn::core::Event *evt)
00196                 {
00197                         // If a new neighbor comes available, send him a request for the summary vector
00198                         // If a neighbor went away we can free the stored database
00199                         try {
00200                                 const dtn::core::NodeEvent &event = dynamic_cast<const dtn::core::NodeEvent&>(*evt);
00201 
00202                                 if (event.getAction() == NODE_AVAILABLE)
00203                                 {
00204                                         ibrcommon::MutexLock l(_neighbor_database);
00205                                         _neighbor_database.create( event.getNode().getEID() );
00206                                 }
00207                                 else if (event.getAction() == NODE_UNAVAILABLE)
00208                                 {
00209                                         ibrcommon::MutexLock l(_neighbor_database);
00210                                         _neighbor_database.reset( event.getNode().getEID() );
00211                                 }
00212                         } catch (const std::bad_cast&) { };
00213 
00214                         try {
00215                                 const dtn::net::TransferCompletedEvent &event = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
00216 
00217                                 // if a tranfer is completed, then release the transfer resource of the peer
00218                                 try {
00219                                         // lock the list of neighbors
00220                                         ibrcommon::MutexLock l(_neighbor_database);
00221                                         NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer());
00222                                         entry.releaseTransfer(event.getBundle());
00223 
00224                                         // add the bundle to the summary vector of the neighbor
00225                                         _neighbor_database.addBundle(event.getPeer(), event.getBundle());
00226                                 } catch (const NeighborDatabase::NeighborNotAvailableException&) { };
00227 
00228                         } catch (const std::bad_cast&) { };
00229 
00230                         try {
00231                                 const dtn::net::TransferAbortedEvent &event = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
00232 
00233                                 // if a tranfer is aborted, then release the transfer resource of the peer
00234                                 try {
00235                                         // lock the list of neighbors
00236                                         ibrcommon::MutexLock l(_neighbor_database);
00237                                         NeighborDatabase::NeighborEntry &entry = _neighbor_database.get(event.getPeer());
00238                                         entry.releaseTransfer(event.getBundleID());
00239 
00240                                         if (event.reason == dtn::net::TransferAbortedEvent::REASON_REFUSED)
00241                                         {
00242                                                 const dtn::data::MetaBundle meta = _storage.get(event.getBundleID());
00243 
00244                                                 // add the transferred bundle to the bloomfilter of the receiver
00245                                                 _neighbor_database.addBundle(event.getPeer(), meta);
00246                                         }
00247                                 } catch (const NeighborDatabase::NeighborNotAvailableException&) { };
00248                         } catch (const std::bad_cast&) { };
00249 
00250                         try {
00251                                 const dtn::net::BundleReceivedEvent &received = dynamic_cast<const dtn::net::BundleReceivedEvent&>(*evt);
00252 
00253                                 // drop bundles to the NULL-destination
00254                                 if (received.bundle._destination == EID("dtn:null")) return;
00255 
00256                                 // Store incoming bundles into the storage
00257                                 try {
00258                                         if (received.fromlocal)
00259                                         {
00260                                                 // store the bundle into a storage module
00261                                                 _storage.store(received.bundle);
00262 
00263                                                 // set the bundle as known
00264                                                 setKnown(received.bundle);
00265 
00266                                                 // raise the queued event to notify all receivers about the new bundle
00267                                                 QueueBundleEvent::raise(received.bundle, received.peer);
00268                                         }
00269                                         // if the bundle is not known
00270                                         else if (!isKnown(received.bundle))
00271                                         {
00272 #ifdef WITH_BUNDLE_SECURITY
00273                                                 // security methods modifies the bundle, thus we need a copy of it
00274                                                 dtn::data::Bundle bundle = received.bundle;
00275 
00276                                                 // lets see if signatures and hashes are correct and remove them if possible
00277                                                 dtn::security::SecurityManager::getInstance().verify(bundle);
00278 
00279                                                 // prevent loops
00280                                                 {
00281                                                         ibrcommon::MutexLock l(_neighbor_database);
00282 
00283                                                         // add the bundle to the summary vector of the neighbor
00284                                                         _neighbor_database.addBundle(received.peer, received.bundle);
00285                                                 }
00286 
00287                                                 // store the bundle into a storage module
00288                                                 _storage.store(bundle);
00289 #else
00290                                                 // store the bundle into a storage module
00291                                                 _storage.store(received.bundle);
00292 #endif
00293                                                 // set the bundle as known
00294                                                 setKnown(received.bundle);
00295 
00296                                                 // raise the queued event to notify all receivers about the new bundle
00297                                                 QueueBundleEvent::raise(received.bundle, received.peer);
00298                                         }
00299 
00300                                         // finally create a bundle received event
00301                                         dtn::core::BundleEvent::raise(received.bundle, dtn::core::BUNDLE_RECEIVED);
00302 #ifdef WITH_BUNDLE_SECURITY
00303                                 } catch (const dtn::security::SecurityManager::VerificationFailedException &ex) {
00304                                         IBRCOMMON_LOGGER(notice) << "Security checks failed, bundle will be dropped: " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00305 #endif
00306                                 } catch (const ibrcommon::IOException &ex) {
00307                                         IBRCOMMON_LOGGER(notice) << "Unable to store bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00308                                 } catch (const dtn::core::BundleStorage::StorageSizeExeededException &ex) {
00309                                         IBRCOMMON_LOGGER(notice) << "No space left for bundle " << received.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00310                                 }
00311 
00312                                 return;
00313                         } catch (const std::bad_cast&) {
00314                         }
00315 
00316                         try {
00317                                 const dtn::core::BundleGeneratedEvent &generated = dynamic_cast<const dtn::core::BundleGeneratedEvent&>(*evt);
00318                                 
00319                                 // set the bundle as known
00320                                 setKnown(generated.bundle);
00321 
00322                                 // Store incoming bundles into the storage
00323                                 try {
00324                                         // store the bundle into a storage module
00325                                         _storage.store(generated.bundle);
00326 
00327                                         // raise the queued event to notify all receivers about the new bundle
00328                                         QueueBundleEvent::raise(generated.bundle, dtn::core::BundleCore::local);
00329                                 } catch (const ibrcommon::IOException &ex) {
00330                                         IBRCOMMON_LOGGER(notice) << "Unable to store bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00331                                 } catch (const dtn::core::BundleStorage::StorageSizeExeededException &ex) {
00332                                         IBRCOMMON_LOGGER(notice) << "No space left for bundle " << generated.bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00333                                 }
00334 
00335                                 return;
00336                         } catch (const std::bad_cast&) {
00337                         }
00338 
00339                         try {
00340                                 const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt);
00341                                 {
00342                                         ibrcommon::MutexLock l(_known_bundles_lock);
00343                                         _known_bundles.expire(time.getTimestamp());
00344                                 }
00345 
00346                                 {
00347                                         ibrcommon::MutexLock l(_neighbor_database);
00348                                         _neighbor_database.expire(time.getTimestamp());
00349                                 }
00350                         } catch (const std::bad_cast&) {
00351                         }
00352 
00353                         // notify all underlying extensions
00354                         for (std::list<BaseRouter::Extension*>::iterator iter = _extensions.begin(); iter != _extensions.end(); iter++)
00355                         {
00356                                 (*iter)->notify(evt);
00357                         }
00358                 }
00359 
00365                 dtn::data::Bundle BaseRouter::getBundle(const dtn::data::BundleID &id)
00366                 {
00367                         return _storage.get(id);
00368                 }
00369 
00370                 dtn::core::BundleStorage& BaseRouter::getStorage()
00371                 {
00372                         return _storage;
00373                 }
00374 
00375                 void BaseRouter::setKnown(const dtn::data::MetaBundle &meta)
00376                 {
00377                         ibrcommon::MutexLock l(_known_bundles_lock);
00378                         return _known_bundles.add(meta);
00379                 }
00380 
00381                 // set the bundle as known
00382                 bool BaseRouter::isKnown(const dtn::data::BundleID &id)
00383                 {
00384                         ibrcommon::MutexLock l(_known_bundles_lock);
00385                         return _known_bundles.contains(id);
00386                 }
00387 
00388                 const SummaryVector BaseRouter::getSummaryVector()
00389                 {
00390                         ibrcommon::MutexLock l(_known_bundles_lock);
00391                         return _known_bundles.getSummaryVector();
00392                 }
00393 
00394                 const std::string BaseRouter::getName() const
00395                 {
00396                         return "BaseRouter";
00397                 }
00398 
00399                 NeighborDatabase& BaseRouter::getNeighborDB()
00400                 {
00401                         return _neighbor_database;
00402                 }
00403         }
00404 }