IBR-DTNSuite  0.12
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"
28 #include <ibrcommon/thread/Queue.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  };
56 
58  {
59  static const std::string TAG;
60 
61  public:
62  DatagramConnection(const std::string &identifier, const DatagramService::Parameter &params, DatagramConnectionCallback &callback);
63  virtual ~DatagramConnection();
64 
65  void run() throw ();
66  void setup() throw ();
67  void finally() throw ();
68 
69  virtual void __cancellation() throw ();
70 
71  void shutdown();
72 
73  const std::string& getIdentifier() const;
74 
79  void queue(const dtn::net::BundleTransfer &job);
80 
86  void queue(const char &flags, const unsigned int &seqno, const char *buf, const dtn::data::Length &len);
87 
92  void ack(const unsigned int &seqno);
93 
97  void nack(const unsigned int &seqno, const bool temporary);
98 
103  void setPeerEID(const dtn::data::EID &peer);
104 
108  const dtn::data::EID& getPeerEID();
109 
110  private:
111  enum SEND_FLOW {
112  SEND_IDLE,
113  SEND_WAIT_ACK,
114  SEND_NEXT,
115  SEND_ERROR
116  } _send_state;
117 
118  enum RECV_FLOW {
119  RECV_IDLE,
120  RECV_HEAD,
121  RECV_TRANSMISSION,
122  RECV_ERROR
123  } _recv_state;
124 
125  class Stream : public std::basic_streambuf<char, std::char_traits<char> >, public std::iostream
126  {
127  public:
128  Stream(DatagramConnection &conn, const dtn::data::Length &maxmsglen);
129  virtual ~Stream();
130 
136  void queue(const char *buf, const dtn::data::Length &len, bool isFirst) throw (DatagramException);
137 
142  void close();
143 
147  void skip();
148 
152  void reject();
153 
154  protected:
155  virtual int sync();
156  virtual std::char_traits<char>::int_type overflow(std::char_traits<char>::int_type = std::char_traits<char>::eof());
157  virtual std::char_traits<char>::int_type underflow();
158 
159  private:
160  // buffer size and maximum message size
161  const dtn::data::Length _buf_size;
162 
163  // true, if the next segment if the first of the bundle
164  bool _first_segment;
165 
166  // will be set to true if the next segment is the last
167  // of the bundle
168  bool _last_segment;
169 
170  // buffer for incoming data to queue
171  // the underflow method will block until
172  // this buffer contains any data
173  std::vector<char> _queue_buf;
174 
175  // the number of bytes available in the queue buffer
176  dtn::data::Length _queue_buf_len;
177 
178  // true if the frame in the queue is the head of the frame-set
179  bool _queue_buf_head;
180 
181  // conditional to lock the queue buffer and the
182  // corresponding length variable
183  ibrcommon::Conditional _queue_buf_cond;
184 
185  // outgoing data from the upper layer is stored
186  // here first and processed by the overflow() method
187  std::vector<char> _out_buf;
188 
189  // incoming data to deliver data to the upper layer
190  // is stored in this buffer by the underflow() method
191  std::vector<char> _in_buf;
192 
193  // this variable is set to true to shutdown
194  // this stream
195  bool _abort;
196 
197  // this variable is set to true if the outgoing
198  // frame set should be skipped
199  bool _skip;
200 
201  // this variable is set to true if the incoming
202  // frame set should skipped
203  bool _reject;
204 
205  // callback to the corresponding connection object
206  DatagramConnection &_callback;
207  };
208 
209  class Sender : public ibrcommon::JoinableThread
210  {
211  public:
212  Sender(DatagramConnection &conn, Stream &stream);
213  ~Sender();
214 
218  void skip() throw ();
219 
220  void run() throw ();
221  void finally() throw ();
222  void __cancellation() throw ();
223 
225 
226  private:
227  DatagramConnection::Stream &_stream;
228 
229  // callback to the corresponding connection object
230  DatagramConnection &_connection;
231 
232  bool _skip;
233  };
234 
238  void stream_send(const char *buf, const dtn::data::Length &len, bool last) throw (DatagramException);
239 
243  void adjust_rtt(double value);
244 
248  bool sw_frames_full();
249 
253  void sw_timeout(bool last);
254 
255  DatagramConnectionCallback &_callback;
256  const std::string _identifier;
257  DatagramConnection::Stream _stream;
258  DatagramConnection::Sender _sender;
259 
260  ibrcommon::Conditional _ack_cond;
261  unsigned int _last_ack;
262  unsigned int _next_seqno;
263 
264  // stores the head of each connection
265  // the head is hold back until at least a second
266  // or the last segment was received
267  std::vector<char> _head_buf;
268  dtn::data::Length _head_len;
269 
270  const DatagramService::Parameter _params;
271 
272  double _avg_rtt;
273 
274  dtn::data::EID _peer_eid;
275 
276  // buffer for sliding window approach
277  class window_frame {
278  public:
279  // default constructor
280  window_frame()
281  : flags(0), seqno(0), retry(0) { }
282 
283  // destructor
284  virtual ~window_frame() { }
285 
286  char flags;
287  unsigned int seqno;
288  std::vector<char> buf;
289  unsigned int retry;
291  };
292  std::list<window_frame> _sw_frames;
293  };
294  } /* namespace data */
295 } /* namespace dtn */
296 #endif /* DATAGRAMCONNECTION_H_ */