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