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