IBR-DTNSuite 0.6

daemon/src/routing/RetransmissionExtension.cpp

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