IBR-DTNSuite  0.12
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"
26 #include "core/EventDispatcher.h"
30 
31 #include <ibrdtn/utils/Clock.h>
32 #include <ibrdtn/data/Exceptions.h>
34 
35 
36 namespace dtn
37 {
38  namespace routing
39  {
41  {
42  }
43 
45  {
46  }
47 
49  {
54  }
55 
57  {
62  }
63 
65  {
66  // remove the bundleid in our list
67  RetransmissionData data(meta, peer);
68  _set.erase(data);
69  }
70 
72  {
73  try {
74  const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt);
75 
76  ibrcommon::MutexLock l(_mutex);
77  if (!_queue.empty())
78  {
79  const RetransmissionData &data = _queue.front();
80 
81  if ( data.getTimestamp() <= time.getTimestamp() )
82  {
83  try {
85 
86  try {
87  // create a new bundle transfer
88  dtn::net::BundleTransfer transfer(data.destination, meta);
89 
90  // re-queue the bundle
92  } catch (const ibrcommon::Exception&) {
93  // do nothing here
94  }
95  } catch (const ibrcommon::Exception&) {
96  // bundle is not available, abort transmission
98  }
99 
100  // remove the item off the queue
101  _queue.pop();
102  }
103  }
104  return;
105  } catch (const std::bad_cast&) { };
106 
107  try {
108  const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
109 
110  // remove the bundleid in our list
111  RetransmissionData data(aborted.getBundleID(), aborted.getPeer());
112  _set.erase(data);
113 
114  return;
115  } catch (const std::bad_cast&) { };
116 
117  try {
118  const dtn::routing::RequeueBundleEvent &requeue = dynamic_cast<const dtn::routing::RequeueBundleEvent&>(*evt);
119 
120  const RetransmissionData data(requeue.getBundle(), requeue.getPeer());
121 
122  ibrcommon::MutexLock l(_mutex);
123  std::set<RetransmissionData>::const_iterator iter = _set.find(data);
124 
125  if (iter != _set.end())
126  {
127  // increment the retry counter
128  RetransmissionData data2 = (*iter);
129  data2++;
130 
131  // remove the item
132  _set.erase(data);
133 
134  if (data2.getCount() <= 8)
135  {
136  // requeue the bundle
137  _set.insert(data2);
138  _queue.push(data2);
139  }
140  else
141  {
143  }
144  }
145  else
146  {
147  // queue the bundle
148  _set.insert(data);
149  _queue.push(data);
150  }
151 
152  return;
153  } catch (const std::bad_cast&) { };
154 
155  try {
156  const dtn::core::BundleExpiredEvent &expired = dynamic_cast<const dtn::core::BundleExpiredEvent&>(*evt);
157 
158  // delete all matching elements in the queue
159  ibrcommon::MutexLock l(_mutex);
160 
161  dtn::data::Size elements = _queue.size();
162  for (dtn::data::Size i = 0; i < elements; ++i)
163  {
164  const RetransmissionData &data = _queue.front();
165 
166  if ((dtn::data::BundleID&)data == expired.getBundle())
167  {
169  }
170  else
171  {
172  _queue.push(data);
173  }
174 
175  _queue.pop();
176  }
177 
178  return;
179  } catch (const std::bad_cast&) { };
180  }
181 
182  bool RetransmissionExtension::RetransmissionData::operator!=(const RetransmissionData &obj)
183  {
184  const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
185  const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
186 
187  if (id1 != id2) return true;
188  if (obj.destination != destination) return true;
189 
190  return false;
191  }
192 
193  bool RetransmissionExtension::RetransmissionData::operator==(const RetransmissionData &obj)
194  {
195  const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
196  const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
197 
198  if (id1 != id2) return false;
199  if (obj.destination != destination) return false;
200 
201  return true;
202  }
203 
204  dtn::data::Size RetransmissionExtension::RetransmissionData::getCount() const
205  {
206  return _count;
207  }
208 
209  const dtn::data::Timestamp& RetransmissionExtension::RetransmissionData::getTimestamp() const
210  {
211  return _timestamp;
212  }
213 
214  RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++(int)
215  {
216  _count++;
217  _timestamp = dtn::utils::Clock::getTime();
218  float backoff = ::pow((float)retry, (int)_count -1);
219  _timestamp += static_cast<dtn::data::Size>(backoff);
220 
221  return (*this);
222  }
223 
224  RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++()
225  {
226  _count++;
227  _timestamp = dtn::utils::Clock::getTime();
228  float backoff = ::pow((float)retry, (int)_count -1);
229  _timestamp += static_cast<dtn::data::Size>(backoff);
230 
231  return (*this);
232  }
233 
234  RetransmissionExtension::RetransmissionData::RetransmissionData(const dtn::data::BundleID &id, const dtn::data::EID &d, const dtn::data::Size r)
235  : dtn::data::BundleID(id), destination(d), _timestamp(0), _count(0), retry(r)
236  {
237  (*this)++;
238  }
239 
240  RetransmissionExtension::RetransmissionData::~RetransmissionData()
241  {
242  }
243  }
244 }