00001 #include "core/BundleCore.h"
00002 #include "core/GlobalEvent.h"
00003 #include "routing/RequeueBundleEvent.h"
00004 #include "routing/QueueBundleEvent.h"
00005 #include "core/BundleEvent.h"
00006 #include "core/TimeEvent.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 using namespace dtn::data;
00021 using namespace dtn::utils;
00022 using namespace std;
00023
00024 namespace dtn
00025 {
00026 namespace core
00027 {
00028 dtn::data::EID BundleCore::local;
00029 size_t BundleCore::blocksizelimit = 0;
00030 bool BundleCore::forwarding = true;
00031
00032 BundleCore& BundleCore::getInstance()
00033 {
00034 static BundleCore instance;
00035 return instance;
00036 }
00037
00038 BundleCore::BundleCore()
00039 : _clock(1), _storage(NULL)
00040 {
00044 if (dtn::utils::Clock::getTime() > 0)
00045 {
00046 dtn::utils::Clock::quality = 1;
00047 }
00048 else
00049 {
00050 IBRCOMMON_LOGGER(warning) << "The local clock seems to be wrong. Expiration disabled." << IBRCOMMON_LOGGER_ENDL;
00051 }
00052
00053 bindEvent(dtn::routing::QueueBundleEvent::className);
00054 bindEvent(dtn::core::TimeEvent::className);
00055 }
00056
00057 BundleCore::~BundleCore()
00058 {
00059 unbindEvent(dtn::routing::QueueBundleEvent::className);
00060 unbindEvent(dtn::core::TimeEvent::className);
00061 }
00062
00063 void BundleCore::componentUp()
00064 {
00065 _connectionmanager.initialize();
00066 _clock.initialize();
00067
00068
00069 _clock.startup();
00070 }
00071
00072 void BundleCore::componentDown()
00073 {
00074 _connectionmanager.terminate();
00075 _clock.terminate();
00076 }
00077
00078 void BundleCore::setStorage(dtn::core::BundleStorage *storage)
00079 {
00080 _storage = storage;
00081 }
00082
00083 dtn::core::BundleStorage& BundleCore::getStorage()
00084 {
00085 return *_storage;
00086 }
00087
00088 WallClock& BundleCore::getClock()
00089 {
00090 return _clock;
00091 }
00092
00093 void BundleCore::transferTo(const dtn::data::EID &destination, dtn::data::Bundle &bundle)
00094 {
00095 try {
00096 _connectionmanager.queue(destination, bundle);
00097 } catch (dtn::net::NeighborNotAvailableException ex) {
00098
00099 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00100 } catch (dtn::net::ConnectionNotAvailableException ex) {
00101
00102 dtn::routing::RequeueBundleEvent::raise(destination, bundle);
00103 }
00104 }
00105
00106 void BundleCore::addConvergenceLayer(dtn::net::ConvergenceLayer *cl)
00107 {
00108 _connectionmanager.addConvergenceLayer(cl);
00109 }
00110
00111 void BundleCore::addConnection(const dtn::core::Node &n)
00112 {
00113 _connectionmanager.addConnection(n);
00114 }
00115
00116 const std::set<dtn::core::Node> BundleCore::getNeighbors()
00117 {
00118 return _connectionmanager.getNeighbors();
00119 }
00120
00121 void BundleCore::raiseEvent(const dtn::core::Event *evt)
00122 {
00123 try {
00124 dynamic_cast<const dtn::core::TimeEvent&>(*evt);
00125
00129 if (dtn::utils::Clock::quality == 0)
00130 {
00131 if (dtn::utils::Clock::getTime() > 0)
00132 {
00133 dtn::utils::Clock::quality = 1;
00134 IBRCOMMON_LOGGER(warning) << "The local clock seems to be okay again. Expiration enabled." << IBRCOMMON_LOGGER_ENDL;
00135 }
00136 }
00137
00138 } catch (std::bad_cast ex) {
00139
00140 }
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
00149
00150 bool delivered = false;
00151
00152
00153 dtn::data::Bundle bundle = getStorage().get(meta);
00154
00155 try {
00156
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(id);
00160
00161 IBRCOMMON_LOGGER_DEBUG(5) << "custody released for " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00162
00163 delivered = true;
00164 } catch (dtn::data::Bundle::NoSuchBlockFoundException) {
00165
00166 }
00167
00168 if (delivered)
00169 {
00170
00171 dtn::core::BundleEvent::raise(meta, BUNDLE_DELIVERED);
00172 }
00173 else
00174 {
00175
00176 dtn::core::BundleEvent::raise(meta, BUNDLE_DELETED, StatusReportBlock::DESTINATION_ENDPOINT_ID_UNINTELLIGIBLE);
00177 }
00178
00179
00180 getStorage().remove(meta);
00181 }
00182 } catch (std::bad_cast ex) {
00183
00184 }
00185 }
00186
00187 void BundleCore::validate(const dtn::data::PrimaryBlock &p) const throw (dtn::data::Validator::RejectedException)
00188 {
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 if (!BundleCore::forwarding)
00202 {
00203 if (!p._destination.sameHost(BundleCore::local))
00204 {
00205
00206 IBRCOMMON_LOGGER(warning) << "non-local bundle rejected: " << p.toString() << IBRCOMMON_LOGGER_ENDL;
00207 throw dtn::data::Validator::RejectedException("bundle is not local");
00208 }
00209 }
00210
00211
00212 if (p.isExpired())
00213 {
00214 IBRCOMMON_LOGGER(warning) << "bundle rejected: bundle has expired (" << p.toString() << ")" << IBRCOMMON_LOGGER_ENDL;
00215 throw dtn::data::Validator::RejectedException("bundle is expired");
00216 }
00217 }
00218
00219 void BundleCore::validate(const dtn::data::Block&, const size_t size) const throw (dtn::data::Validator::RejectedException)
00220 {
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 if ((BundleCore::blocksizelimit > 0) && (size > BundleCore::blocksizelimit))
00232 {
00233 IBRCOMMON_LOGGER(warning) << "bundle rejected: block size of " << size << " is too big" << IBRCOMMON_LOGGER_ENDL;
00234 throw dtn::data::Validator::RejectedException("block size is too big");
00235 }
00236 }
00237
00238 void BundleCore::validate(const dtn::data::Bundle&) const throw (dtn::data::Validator::RejectedException)
00239 {
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 }
00250 }
00251 }