• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

daemon/src/core/BundleCore.cpp

Go to the documentation of this file.
00001 #include "config.h"
00002 #include "core/BundleCore.h"
00003 #include "core/GlobalEvent.h"
00004 #include "routing/RequeueBundleEvent.h"
00005 #include "routing/QueueBundleEvent.h"
00006 #include "core/BundleEvent.h"
00007 #include "core/TimeEvent.h"
00008 
00009 #include <ibrcommon/data/BLOB.h>
00010 #include <ibrdtn/data/MetaBundle.h>
00011 #include <ibrdtn/data/Exceptions.h>
00012 #include <ibrdtn/data/EID.h>
00013 #include <ibrdtn/utils/Clock.h>
00014 #include <ibrcommon/Logger.h>
00015 
00016 #include "limits.h"
00017 #include <iostream>
00018 #include <typeinfo>
00019 #include <stdint.h>
00020 
00021 #ifdef WITH_BUNDLE_SECURITY
00022 #include "security/SecurityManager.h"
00023 #endif
00024 
00025 using namespace dtn::data;
00026 using namespace dtn::utils;
00027 using namespace std;
00028 
00029 namespace dtn
00030 {
00031         namespace core
00032         {
00033                 dtn::data::EID BundleCore::local;
00034                 size_t BundleCore::blocksizelimit = 0;
00035                 bool BundleCore::forwarding = true;
00036 
00037                 BundleCore& BundleCore::getInstance()
00038                 {
00039                         static BundleCore instance;
00040                         return instance;
00041                 }
00042 
00043                 BundleCore::BundleCore()
00044                  : _clock(1), _storage(NULL)
00045                 {
00049                         if (dtn::utils::Clock::getTime() > 0)
00050                         {
00051                                 dtn::utils::Clock::quality = 1;
00052                         }
00053                         else
00054                         {
00055                                 IBRCOMMON_LOGGER(warning) << "The local clock seems to be wrong. Expiration disabled." << IBRCOMMON_LOGGER_ENDL;
00056                         }
00057 
00058                         bindEvent(dtn::routing::QueueBundleEvent::className);
00059                         bindEvent(dtn::core::TimeEvent::className);
00060                 }
00061 
00062                 BundleCore::~BundleCore()
00063                 {
00064                         unbindEvent(dtn::routing::QueueBundleEvent::className);
00065                         unbindEvent(dtn::core::TimeEvent::className);
00066                 }
00067 
00068                 void BundleCore::componentUp()
00069                 {
00070                         _connectionmanager.initialize();
00071                         _clock.initialize();
00072 
00073                         // start a clock
00074                         _clock.startup();
00075                 }
00076 
00077                 void BundleCore::componentDown()
00078                 {
00079                         _connectionmanager.terminate();
00080                         _clock.terminate();
00081                 }
00082 
00083                 void BundleCore::setStorage(dtn::core::BundleStorage *storage)
00084                 {
00085                         _storage = storage;
00086                 }
00087 
00088                 dtn::core::BundleStorage& BundleCore::getStorage()
00089                 {
00090                         if (_storage == NULL)
00091                         {
00092                                 throw ibrcommon::Exception("No bundle storage is set! Use BundleCore::setStorage() to set a storage.");
00093                         }
00094                         return *_storage;
00095                 }
00096 
00097                 WallClock& BundleCore::getClock()
00098                 {
00099                         return _clock;
00100                 }
00101 
00102                 void BundleCore::transferTo(const dtn::data::EID &destination, const dtn::data::BundleID &bundle)
00103                 {
00104                         try {
00105                                 _connectionmanager.queue(destination, bundle);
00106                         } catch (const dtn::net::NeighborNotAvailableException &ex) {
00107                                 // signal interruption of the transfer
00108                                 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00109                         } catch (const dtn::net::ConnectionNotAvailableException &ex) {
00110                                 // signal interruption of the transfer
00111                                 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00112                         } catch (const ibrcommon::Exception&) {
00113                                 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00114                         }
00115                 }
00116 
00117                 void BundleCore::addConvergenceLayer(dtn::net::ConvergenceLayer *cl)
00118                 {
00119                         _connectionmanager.addConvergenceLayer(cl);
00120                 }
00121 
00122                 void BundleCore::addConnection(const dtn::core::Node &n)
00123                 {
00124                         _connectionmanager.addConnection(n);
00125                 }
00126 
00127                 const std::set<dtn::core::Node> BundleCore::getNeighbors()
00128                 {
00129                         return _connectionmanager.getNeighbors();
00130                 }
00131 
00132                 void BundleCore::raiseEvent(const dtn::core::Event *evt)
00133                 {
00134                         try {
00135                                 dynamic_cast<const dtn::core::TimeEvent&>(*evt);
00136 
00140                                 if (dtn::utils::Clock::quality == 0)
00141                                 {
00142                                         if (dtn::utils::Clock::getTime() > 0)
00143                                         {
00144                                                 dtn::utils::Clock::quality = 1;
00145                                                 IBRCOMMON_LOGGER(warning) << "The local clock seems to be okay again. Expiration enabled." << IBRCOMMON_LOGGER_ENDL;
00146                                         }
00147                                 }
00148 
00149                         } catch (const std::bad_cast&) { }
00150 
00151                         try {
00152                                 const dtn::routing::QueueBundleEvent &queued = dynamic_cast<const dtn::routing::QueueBundleEvent&>(*evt);
00153                                 const dtn::data::MetaBundle &meta = queued.bundle;
00154 
00155                                 if (meta.destination == local)
00156                                 {
00157                                         // if the delivered variable is still false at the end of this block.
00158                                         // we send a not delivered report.
00159                                         bool delivered = false;
00160 
00161                                         // process this bundle locally
00162                                         dtn::data::Bundle bundle = getStorage().get(meta);
00163 
00164                                         try {
00165                                                 // check for a custody signal
00166                                                 dtn::data::CustodySignalBlock custody = bundle.getBlock<dtn::data::CustodySignalBlock>();
00167                                                 dtn::data::BundleID id(custody._source, custody._bundle_timestamp.getValue(), custody._bundle_sequence.getValue(), (custody._fragment_length.getValue() > 0), custody._fragment_offset.getValue());
00168                                                 getStorage().releaseCustody(bundle._source, id);
00169 
00170                                                 IBRCOMMON_LOGGER_DEBUG(5) << "custody released for " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00171 
00172                                                 delivered = true;
00173                                         } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) {
00174                                                 // no custody signal available
00175                                         }
00176 
00177                                         if (delivered)
00178                                         {
00179                                                 // gen a report
00180                                                 dtn::core::BundleEvent::raise(meta, BUNDLE_DELIVERED);
00181                                         }
00182                                         else
00183                                         {
00184                                                 // gen a report
00185                                                 dtn::core::BundleEvent::raise(meta, BUNDLE_DELETED, StatusReportBlock::DESTINATION_ENDPOINT_ID_UNINTELLIGIBLE);
00186                                         }
00187 
00188                                         // delete the bundle
00189                                         getStorage().remove(meta);
00190                                 }
00191                         } catch (const dtn::core::BundleStorage::NoBundleFoundException&) {
00192                         } catch (const std::bad_cast&) {}
00193                 }
00194 
00195                 void BundleCore::validate(const dtn::data::PrimaryBlock &p) const throw (dtn::data::Validator::RejectedException)
00196                 {
00197                         /*
00198                          *
00199                          * TODO: reject a bundle if...
00200                          * ... it is expired
00201                          * ... already in the storage
00202                          * ... a fragment of an already received bundle in the storage
00203                          *
00204                          * throw dtn::data::DefaultDeserializer::RejectedException();
00205                          *
00206                          */
00207 
00208                         // if we do not forward bundles
00209                         if (!BundleCore::forwarding)
00210                         {
00211                                 if (!p._destination.sameHost(BundleCore::local))
00212                                 {
00213                                         // ... we reject all non-local bundles.
00214                                         IBRCOMMON_LOGGER(warning) << "non-local bundle rejected: " << p.toString() << IBRCOMMON_LOGGER_ENDL;
00215                                         throw dtn::data::Validator::RejectedException("bundle is not local");
00216                                 }
00217                         }
00218                 }
00219 
00220                 void BundleCore::validate(const dtn::data::Block&, const size_t size) const throw (dtn::data::Validator::RejectedException)
00221                 {
00222                         /*
00223                          *
00224                          * TODO: reject a block if
00225                          * ... it exceeds the payload limit
00226                          *
00227                          * throw dtn::data::DefaultDeserializer::RejectedException();
00228                          *
00229                          */
00230 
00231                         // check for the size of the block
00232                         if ((BundleCore::blocksizelimit > 0) && (size > BundleCore::blocksizelimit))
00233                         {
00234                                 IBRCOMMON_LOGGER(warning) << "bundle rejected: block size of " << size << " is too big" << IBRCOMMON_LOGGER_ENDL;
00235                                 throw dtn::data::Validator::RejectedException("block size is too big");
00236                         }
00237                 }
00238 
00239                 void BundleCore::validate(const dtn::data::Bundle &b) const throw (dtn::data::Validator::RejectedException)
00240                 {
00241                         /*
00242                          *
00243                          * TODO: reject a bundle if
00244                          * ... the security checks (DTNSEC) failed
00245                          * ... a checksum mismatch is detected (CRC)
00246                          *
00247                          * throw dtn::data::DefaultDeserializer::RejectedException();
00248                          *
00249                          */
00250 
00251                         // check if the bundle is expired
00252                         if (dtn::utils::Clock::isExpired(b))
00253                         {
00254                                 IBRCOMMON_LOGGER(warning) << "bundle rejected: bundle has expired (" << b.toString() << ")" << IBRCOMMON_LOGGER_ENDL;
00255                                 throw dtn::data::Validator::RejectedException("bundle is expired");
00256                         }
00257 
00258 #ifdef WITH_BUNDLE_SECURITY
00259                         // lets see if signatures and hashes are correct and it decrypts if needed
00260                         // the const_cast is dangerous, but in BundleReceivedEvent::raise() bundle was not const, so I think it will be ok
00261                         try {
00262                                 dtn::security::SecurityManager::getInstance().fastverify(b);
00263                         } catch (const dtn::security::SecurityManager::VerificationFailedException &ex) {
00264                                 IBRCOMMON_LOGGER(notice) << "bundle rejected: security checks failed: " << b.toString() << IBRCOMMON_LOGGER_ENDL;
00265                                 throw dtn::data::Validator::RejectedException("security checks failed");
00266                         }
00267 #endif
00268 
00269                         // check for invalid blocks
00270                         const std::list<const dtn::data::Block*> bl = b.getBlocks();
00271                         for (std::list<const dtn::data::Block*>::const_iterator iter = bl.begin(); iter != bl.end(); iter++)
00272                         {
00273                                 try {
00274                                         const dtn::data::ExtensionBlock &e = dynamic_cast<const dtn::data::ExtensionBlock&>(**iter);
00275 
00276                                         if (e.get(dtn::data::Block::DELETE_BUNDLE_IF_NOT_PROCESSED))
00277                                         {
00278                                                 // reject the hole bundle
00279                                                 throw dtn::data::Validator::RejectedException("bundle contains unintelligible blocks");
00280                                         }
00281 
00282                                         if (e.get(dtn::data::Block::TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED))
00283                                         {
00284                                                 // transmit status report, because we can not process this block
00285                                                 dtn::core::BundleEvent::raise(b, BUNDLE_RECEIVED, dtn::data::StatusReportBlock::BLOCK_UNINTELLIGIBLE);
00286                                         }
00287                                 } catch (const std::bad_cast&) { }
00288                         }
00289                 }
00290 
00291                 const std::string BundleCore::getName() const
00292                 {
00293                         return "BundleCore";
00294                 }
00295         }
00296 }

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1