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
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
00108 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00109 } catch (const dtn::net::ConnectionNotAvailableException &ex) {
00110
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
00158
00159 bool delivered = false;
00160
00161
00162 dtn::data::Bundle bundle = getStorage().get(meta);
00163
00164 try {
00165
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
00175 }
00176
00177 if (delivered)
00178 {
00179
00180 dtn::core::BundleEvent::raise(meta, BUNDLE_DELIVERED);
00181 }
00182 else
00183 {
00184
00185 dtn::core::BundleEvent::raise(meta, BUNDLE_DELETED, StatusReportBlock::DESTINATION_ENDPOINT_ID_UNINTELLIGIBLE);
00186 }
00187
00188
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
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 if (!BundleCore::forwarding)
00210 {
00211 if (!p._destination.sameHost(BundleCore::local))
00212 {
00213
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
00225
00226
00227
00228
00229
00230
00231
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
00244
00245
00246
00247
00248
00249
00250
00251
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
00260
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
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
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
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 }