IBR-DTNSuite  0.10
RetransmissionExtension.cpp
Go to the documentation of this file.
1 /*
2  * RetransmissionExtension.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
24 #include "core/TimeEvent.h"
25 #include "core/BundleCore.h"
29 
30 #include <ibrdtn/utils/Clock.h>
31 #include <ibrdtn/data/Exceptions.h>
33 
34 
35 namespace dtn
36 {
37  namespace routing
38  {
40  {
41  }
42 
44  {
45  }
46 
48  {
49  try {
50  const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt);
51 
52  ibrcommon::MutexLock l(_mutex);
53  if (!_queue.empty())
54  {
55  const RetransmissionData &data = _queue.front();
56 
57  if ( data.getTimestamp() <= time.getTimestamp() )
58  {
59  try {
61 
62  // retransmit the bundle
63  dtn::net::BundleTransfer transfer(data.destination, meta);
65  } catch (const dtn::core::P2PDialupException&) {
66  // do nothing here
67  dtn::routing::RequeueBundleEvent::raise(data.destination, data);
68  } catch (const ibrcommon::Exception&) {
69  // do nothing here
71  }
72 
73  // remove the item off the queue
74  _queue.pop();
75  }
76  }
77  return;
78  } catch (const std::bad_cast&) { };
79 
80  try {
81  const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
82 
83  // remove the bundleid in our list
84  RetransmissionData data(completed.getBundle(), completed.getPeer());
85  _set.erase(data);
86 
87  return;
88  } catch (const std::bad_cast&) { };
89 
90  try {
91  const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
92 
93  // remove the bundleid in our list
94  RetransmissionData data(aborted.getBundleID(), aborted.getPeer());
95  _set.erase(data);
96 
97  return;
98  } catch (const std::bad_cast&) { };
99 
100  try {
101  const dtn::routing::RequeueBundleEvent &requeue = dynamic_cast<const dtn::routing::RequeueBundleEvent&>(*evt);
102 
103  const RetransmissionData data(requeue._bundle, requeue._peer);
104 
105  ibrcommon::MutexLock l(_mutex);
106  std::set<RetransmissionData>::const_iterator iter = _set.find(data);
107 
108  if (iter != _set.end())
109  {
110  // increment the retry counter
111  RetransmissionData data2 = (*iter);
112  data2++;
113 
114  // remove the item
115  _set.erase(data);
116 
117  if (data2.getCount() <= 8)
118  {
119  // requeue the bundle
120  _set.insert(data2);
121  _queue.push(data2);
122  }
123  else
124  {
126  }
127  }
128  else
129  {
130  // queue the bundle
131  _set.insert(data);
132  _queue.push(data);
133  }
134 
135  return;
136  } catch (const std::bad_cast&) { };
137 
138  try {
139  const dtn::core::BundleExpiredEvent &expired = dynamic_cast<const dtn::core::BundleExpiredEvent&>(*evt);
140 
141  // delete all matching elements in the queue
142  ibrcommon::MutexLock l(_mutex);
143 
144  dtn::data::Size elements = _queue.size();
145  for (dtn::data::Size i = 0; i < elements; ++i)
146  {
147  const RetransmissionData &data = _queue.front();
148 
149  if ((dtn::data::BundleID&)data == expired._bundle)
150  {
152  }
153  else
154  {
155  _queue.push(data);
156  }
157 
158  _queue.pop();
159  }
160 
161  return;
162  } catch (const std::bad_cast&) { };
163  }
164 
165  bool RetransmissionExtension::RetransmissionData::operator!=(const RetransmissionData &obj)
166  {
167  const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
168  const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
169 
170  if (id1 != id2) return true;
171  if (obj.destination != destination) return true;
172 
173  return false;
174  }
175 
176  bool RetransmissionExtension::RetransmissionData::operator==(const RetransmissionData &obj)
177  {
178  const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
179  const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
180 
181  if (id1 != id2) return false;
182  if (obj.destination != destination) return false;
183 
184  return true;
185  }
186 
187  dtn::data::Size RetransmissionExtension::RetransmissionData::getCount() const
188  {
189  return _count;
190  }
191 
192  const dtn::data::Timestamp& RetransmissionExtension::RetransmissionData::getTimestamp() const
193  {
194  return _timestamp;
195  }
196 
197  RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++(int)
198  {
199  _count++;
200  _timestamp = dtn::utils::Clock::getTime();
201  float backoff = ::pow((float)retry, (int)_count -1);
202  _timestamp += static_cast<dtn::data::Size>(backoff);
203 
204  return (*this);
205  }
206 
207  RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++()
208  {
209  _count++;
210  _timestamp = dtn::utils::Clock::getTime();
211  float backoff = ::pow((float)retry, (int)_count -1);
212  _timestamp += static_cast<dtn::data::Size>(backoff);
213 
214  return (*this);
215  }
216 
217  RetransmissionExtension::RetransmissionData::RetransmissionData(const dtn::data::BundleID &id, const dtn::data::EID &d, const dtn::data::Size r)
218  : dtn::data::BundleID(id), destination(d), _timestamp(0), _count(0), retry(r)
219  {
220  (*this)++;
221  }
222 
223  RetransmissionExtension::RetransmissionData::~RetransmissionData()
224  {
225  }
226  }
227 }