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