IBR-DTN  1.0.0
DatagramConnection.h
Go to the documentation of this file.
1 /*
2  * DatagramConnection.h
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 
22 #ifndef DATAGRAMCONNECTION_H_
23 #define DATAGRAMCONNECTION_H_
24 
25 #include "net/ConvergenceLayer.h"
26 #include "net/DatagramService.h"
27 #include <ibrcommon/thread/Thread.h>
28 #include <ibrcommon/thread/Queue.h>
29 #include <ibrcommon/thread/Conditional.h>
30 #include <ibrcommon/TimeMeasurement.h>
31 #include <streambuf>
32 #include <iostream>
33 #include <vector>
34 #include <stdint.h>
35 
36 namespace dtn
37 {
38  namespace net
39  {
40  class DatagramConnection;
41 
43  {
44  public:
46  virtual void callback_send(DatagramConnection &connection, const char &flags, const unsigned int &seqno, const std::string &destination, const char *buf, const dtn::data::Length &len) throw (DatagramException) = 0;
47  virtual void callback_ack(DatagramConnection &connection, const unsigned int &seqno, const std::string &destination) throw (DatagramException) = 0;
48  virtual void callback_nack(DatagramConnection &connection, const unsigned int &seqno, const std::string &destination) throw (DatagramException) = 0;
49 
50  virtual void connectionUp(const DatagramConnection *conn) = 0;
51  virtual void connectionDown(const DatagramConnection *conn) = 0;
52 
53  virtual void reportSuccess(size_t retries, double rtt) { };
54  virtual void reportFailure() { };
55 
57  };
58 
59  class DatagramConnection : public ibrcommon::JoinableThread
60  {
61  static const std::string TAG;
62 
63  public:
64  DatagramConnection(const std::string &identifier, const DatagramService::Parameter &params, DatagramConnectionCallback &callback);
65  virtual ~DatagramConnection();
66 
67  void run() throw ();
68  void setup() throw ();
69  void finally() throw ();
70 
71  virtual void __cancellation() throw ();
72 
73  void shutdown();
74 
75  const std::string& getIdentifier() const;
76 
81  void queue(const dtn::net::BundleTransfer &job);
82 
88  void queue(const char &flags, const unsigned int &seqno, const char *buf, const dtn::data::Length &len);
89 
94  void ack(const unsigned int &seqno);
95 
99  void nack(const unsigned int &seqno, const bool temporary);
100 
105  void setPeerEID(const dtn::data::EID &peer);
106 
110  const dtn::data::EID& getPeerEID();
111 
112  private:
113  enum SEND_FLOW {
114  SEND_IDLE,
115  SEND_WAIT_ACK,
116  SEND_NEXT,
117  SEND_ERROR
118  } _send_state;
119 
120  enum RECV_FLOW {
121  RECV_IDLE,
122  RECV_HEAD,
123  RECV_TRANSMISSION,
124  RECV_ERROR
125  } _recv_state;
126 
127  class Stream : public std::basic_streambuf<char, std::char_traits<char> >, public std::iostream
128  {
129  public:
130  Stream(DatagramConnection &conn, const dtn::data::Length &maxmsglen);
131  virtual ~Stream();
132 
138  void queue(const char *buf, const dtn::data::Length &len, bool isFirst) throw (DatagramException);
139 
144  void close();
145 
149  void skip();
150 
154  void reject();
155 
156  protected:
157  virtual int sync();
158  virtual std::char_traits<char>::int_type overflow(std::char_traits<char>::int_type = std::char_traits<char>::eof());
159  virtual std::char_traits<char>::int_type underflow();
160 
161  private:
162  // buffer size and maximum message size
163  const dtn::data::Length _buf_size;
164 
165  // true, if the next segment if the first of the bundle
166  bool _first_segment;
167 
168  // will be set to true if the next segment is the last
169  // of the bundle
170  bool _last_segment;
171 
172  // buffer for incoming data to queue
173  // the underflow method will block until
174  // this buffer contains any data
175  std::vector<char> _queue_buf;
176 
177  // the number of bytes available in the queue buffer
178  dtn::data::Length _queue_buf_len;
179 
180  // true if the frame in the queue is the head of the frame-set
181  bool _queue_buf_head;
182 
183  // conditional to lock the queue buffer and the
184  // corresponding length variable
185  ibrcommon::Conditional _queue_buf_cond;
186 
187  // outgoing data from the upper layer is stored
188  // here first and processed by the overflow() method
189  std::vector<char> _out_buf;
190 
191  // incoming data to deliver data to the upper layer
192  // is stored in this buffer by the underflow() method
193  std::vector<char> _in_buf;
194 
195  // this variable is set to true to shutdown
196  // this stream
197  bool _abort;
198 
199  // this variable is set to true if the outgoing
200  // frame set should be skipped
201  bool _skip;
202 
203  // this variable is set to true if the incoming
204  // frame set should skipped
205  bool _reject;
206 
207  // callback to the corresponding connection object
208  DatagramConnection &_callback;
209  };
210 
211  class Sender : public ibrcommon::JoinableThread
212  {
213  public:
214  Sender(DatagramConnection &conn, Stream &stream);
215  ~Sender();
216 
220  void skip() throw ();
221 
222  void run() throw ();
223  void finally() throw ();
224  void __cancellation() throw ();
225 
226  ibrcommon::Queue<dtn::net::BundleTransfer> queue;
227 
228  private:
229  DatagramConnection::Stream &_stream;
230 
231  // callback to the corresponding connection object
232  DatagramConnection &_connection;
233 
234  bool _skip;
235  };
236 
240  void stream_send(const char *buf, const dtn::data::Length &len, bool last) throw (DatagramException);
241 
245  void adjust_rtt(double value);
246 
250  bool sw_frames_full();
251 
255  void sw_timeout(bool last);
256 
257  DatagramConnectionCallback &_callback;
258  const std::string _identifier;
259  DatagramConnection::Stream _stream;
260  DatagramConnection::Sender _sender;
261 
262  ibrcommon::Conditional _ack_cond;
263  unsigned int _last_ack;
264  unsigned int _next_seqno;
265 
266  // stores the head of each connection
267  // the head is hold back until at least a second
268  // or the last segment was received
269  std::vector<char> _head_buf;
270  dtn::data::Length _head_len;
271 
272  const DatagramService::Parameter _params;
273 
274  double _avg_rtt;
275 
276  dtn::data::EID _peer_eid;
277 
278  // buffer for sliding window approach
279  class window_frame {
280  public:
281  // default constructor
282  window_frame()
283  : flags(0), seqno(0), retry(0) { }
284 
285  // destructor
286  virtual ~window_frame() { }
287 
288  char flags;
289  unsigned int seqno;
290  std::vector<char> buf;
291  unsigned int retry;
292  ibrcommon::TimeMeasurement tm;
293  };
294  std::list<window_frame> _sw_frames;
295  };
296  } /* namespace data */
297 } /* namespace dtn */
298 #endif /* DATAGRAMCONNECTION_H_ */
void nack(const unsigned int &seqno, const bool temporary)
virtual dtn::core::Node::Protocol getDiscoveryProtocol() const =0
size_t Length
Definition: Number.h:33
virtual void callback_ack(DatagramConnection &connection, const unsigned int &seqno, const std::string &destination)=0
void queue(const dtn::net::BundleTransfer &job)
virtual void callback_send(DatagramConnection &connection, const char &flags, const unsigned int &seqno, const std::string &destination, const char *buf, const dtn::data::Length &len)=0
virtual void reportSuccess(size_t retries, double rtt)
virtual void connectionUp(const DatagramConnection *conn)=0
virtual void callback_nack(DatagramConnection &connection, const unsigned int &seqno, const std::string &destination)=0
virtual void connectionDown(const DatagramConnection *conn)=0
DatagramConnection(const std::string &identifier, const DatagramService::Parameter &params, DatagramConnectionCallback &callback)
const dtn::data::EID & getPeerEID()
const std::string & getIdentifier() const
void setPeerEID(const dtn::data::EID &peer)
void ack(const unsigned int &seqno)