IBR-DTNSuite
0.8
|
00001 /* 00002 * RetransmissionExtension.cpp 00003 * 00004 * Created on: 09.03.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "routing/RetransmissionExtension.h" 00009 #include "routing/RequeueBundleEvent.h" 00010 #include "core/TimeEvent.h" 00011 #include "core/BundleCore.h" 00012 #include "core/BundleExpiredEvent.h" 00013 #include "net/TransferAbortedEvent.h" 00014 #include "net/TransferCompletedEvent.h" 00015 00016 #include <ibrdtn/utils/Clock.h> 00017 #include <ibrdtn/data/Exceptions.h> 00018 #include <ibrcommon/thread/MutexLock.h> 00019 00020 00021 namespace dtn 00022 { 00023 namespace routing 00024 { 00025 RetransmissionExtension::RetransmissionExtension() 00026 { 00027 } 00028 00029 RetransmissionExtension::~RetransmissionExtension() 00030 { 00031 } 00032 00033 void RetransmissionExtension::notify(const dtn::core::Event *evt) 00034 { 00035 try { 00036 const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt); 00037 00038 ibrcommon::MutexLock l(_mutex); 00039 if (!_queue.empty()) 00040 { 00041 const RetransmissionData &data = _queue.front(); 00042 00043 if ( data.getTimestamp() <= time.getTimestamp() ) 00044 { 00045 // retransmit the bundle 00046 dtn::core::BundleCore::getInstance().transferTo(data.destination, data); 00047 00048 // remove the item off the queue 00049 _queue.pop(); 00050 } 00051 } 00052 return; 00053 } catch (const std::bad_cast&) { }; 00054 00055 try { 00056 const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt); 00057 00058 // remove the bundleid in our list 00059 RetransmissionData data(completed.getBundle(), completed.getPeer()); 00060 _set.erase(data); 00061 00062 return; 00063 } catch (const std::bad_cast&) { }; 00064 00065 try { 00066 const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt); 00067 00068 // remove the bundleid in our list 00069 RetransmissionData data(aborted.getBundleID(), aborted.getPeer()); 00070 _set.erase(data); 00071 00072 return; 00073 } catch (const std::bad_cast&) { }; 00074 00075 try { 00076 const dtn::routing::RequeueBundleEvent &requeue = dynamic_cast<const dtn::routing::RequeueBundleEvent&>(*evt); 00077 00078 const RetransmissionData data(requeue._bundle, requeue._peer); 00079 00080 ibrcommon::MutexLock l(_mutex); 00081 std::set<RetransmissionData>::const_iterator iter = _set.find(data); 00082 00083 if (iter != _set.end()) 00084 { 00085 // increment the retry counter 00086 RetransmissionData data2 = (*iter); 00087 data2++; 00088 00089 // remove the item 00090 _set.erase(data); 00091 00092 if (data2.getCount() <= 8) 00093 { 00094 // requeue the bundle 00095 _set.insert(data2); 00096 _queue.push(data2); 00097 } 00098 else 00099 { 00100 dtn::net::TransferAbortedEvent::raise(requeue._peer, requeue._bundle, dtn::net::TransferAbortedEvent::REASON_RETRY_LIMIT_REACHED); 00101 } 00102 } 00103 else 00104 { 00105 // queue the bundle 00106 _set.insert(data); 00107 _queue.push(data); 00108 } 00109 00110 return; 00111 } catch (const std::bad_cast&) { }; 00112 00113 try { 00114 const dtn::core::BundleExpiredEvent &expired = dynamic_cast<const dtn::core::BundleExpiredEvent&>(*evt); 00115 00116 // delete all matching elements in the queue 00117 ibrcommon::MutexLock l(_mutex); 00118 00119 size_t elements = _queue.size(); 00120 for (size_t i = 0; i < elements; i++) 00121 { 00122 const RetransmissionData &data = _queue.front(); 00123 00124 if ((dtn::data::BundleID&)data == expired._bundle) 00125 { 00126 dtn::net::TransferAbortedEvent::raise(data.destination, data, dtn::net::TransferAbortedEvent::REASON_BUNDLE_DELETED); 00127 } 00128 else 00129 { 00130 _queue.push(data); 00131 } 00132 00133 _queue.pop(); 00134 } 00135 00136 return; 00137 } catch (const std::bad_cast&) { }; 00138 } 00139 00140 bool RetransmissionExtension::RetransmissionData::operator!=(const RetransmissionData &obj) 00141 { 00142 const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj); 00143 const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this); 00144 00145 if (id1 != id2) return true; 00146 if (obj.destination != destination) return true; 00147 00148 return false; 00149 } 00150 00151 bool RetransmissionExtension::RetransmissionData::operator==(const RetransmissionData &obj) 00152 { 00153 const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj); 00154 const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this); 00155 00156 if (id1 != id2) return false; 00157 if (obj.destination != destination) return false; 00158 00159 return true; 00160 } 00161 00162 size_t RetransmissionExtension::RetransmissionData::getCount() const 00163 { 00164 return _count; 00165 } 00166 00167 size_t RetransmissionExtension::RetransmissionData::getTimestamp() const 00168 { 00169 return _timestamp; 00170 } 00171 00172 RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++(int) 00173 { 00174 _count++; 00175 _timestamp = dtn::utils::Clock::getTime(); 00176 size_t backoff = pow((float)retry, (int)_count -1); 00177 _timestamp += backoff; 00178 00179 return (*this); 00180 } 00181 00182 RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++() 00183 { 00184 _count++; 00185 _timestamp = dtn::utils::Clock::getTime(); 00186 size_t backoff = pow((float)retry, (int)_count -1); 00187 _timestamp += backoff; 00188 00189 return (*this); 00190 } 00191 00192 RetransmissionExtension::RetransmissionData::RetransmissionData(const dtn::data::BundleID &id, dtn::data::EID d, size_t r) 00193 : dtn::data::BundleID(id), destination(d), _timestamp(0), _count(0), retry(r) 00194 { 00195 (*this)++; 00196 } 00197 00198 RetransmissionExtension::RetransmissionData::~RetransmissionData() 00199 { 00200 } 00201 } 00202 }