libvisiontransfer  6.4.0
datablockprotocol.h
1 /*******************************************************************************
2  * Copyright (c) 2019 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #ifndef VISIONTRANSFER_DATABLOCKPROTOCOL_H
16 #define VISIONTRANSFER_DATABLOCKPROTOCOL_H
17 
18 #include <map>
19 #include <vector>
20 #include <memory>
21 #include <chrono>
22 #include <deque>
23 
24 #include "visiontransfer/alignedallocator.h"
25 
26 namespace visiontransfer {
27 namespace internal {
28 
46 public:
47  enum ProtocolType {
48  PROTOCOL_TCP,
49  PROTOCOL_UDP
50  };
51 
52  // Constants that are also used in other places.
53  static const int MAX_TCP_BYTES_TRANSFER = 0xFFFF; //64K - 1
54  static const int MAX_UDP_RECEPTION = 0x4000; //16K
55  static const int MAX_OUTSTANDING_BYTES = 2*MAX_TCP_BYTES_TRANSFER;
56 
65  DataBlockProtocol(bool server, ProtocolType protType, int maxUdpPacketSize);
66 
71  int getProtocolOverhead() const {
72  return protType == PROTOCOL_UDP ? sizeof(int) : 0;
73  }
74 
78  int getMaxReceptionSize() const;
79 
83  void resetTransfer();
84 
99  void setTransferHeader(unsigned char* data, int headerSize, int transferSize);
100 
115  void setTransferData(unsigned char* data, int validBytes = 0x7FFFFFFF);
116 
126  void setTransferValidBytes(int validBytes);
127 
137  const unsigned char* getTransferMessage(int& length);
138 
142  bool transferComplete();
143 
152  unsigned char* getNextReceiveBuffer(int maxLength);
153 
160  void resetReception(bool dropped);
161 
171  void processReceivedMessage(int length, bool& transferComplete);
172 
182  unsigned char* getReceivedData(int& length);
183 
195  unsigned char* getReceivedHeader(int& length);
196 
201  int getDroppedReceptions() const {
202  return droppedReceptions;
203  }
204 
212  bool newClientConnected();
213 
220  bool isConnected() const;
221 
232  const unsigned char* getNextControlMessage(int& length);
233 
234 private:
235  // The pimpl idiom is not necessary here, as this class is usually not
236  // used directly
237 
238  struct MissingReceiveSegment {
239  int offset;
240  int length;
241  bool isEof;
242  unsigned char subsequentData[4];
243  };
244 
245  static constexpr int HEARTBEAT_INTERVAL_MS = 1000;
246  static constexpr int RECONNECT_TIMEOUT_MS = 1000;
247 
248  static constexpr unsigned char CONNECTION_MESSAGE = 0x01;
249  static constexpr unsigned char CONFIRM_MESSAGE = 0x02;
250  static constexpr unsigned char HEADER_MESSAGE = 0x03;
251  static constexpr unsigned char RESEND_MESSAGE = 0x04;
252  static constexpr unsigned char EOF_MESSAGE = 0x05;
253  static constexpr unsigned char HEARTBEAT_MESSAGE = 0x06;
254 
255  bool isServer;
256  ProtocolType protType;
257  int maxPayloadSize;
258  int minPayloadSize;
259 
260  // Transfer related variables
261  bool transferDone;
262  unsigned char* rawData;
263  int rawValidBytes;
264  int transferOffset;
265  int transferSize;
266  int overwrittenTransferData;
267  int overwrittenTransferIndex;
268  unsigned char* transferHeaderData;
269  int transferHeaderSize;
270 
271  // Reliability related variables
272  std::deque<MissingReceiveSegment> missingReceiveSegments;
273  std::deque<std::pair<int, int> > missingTransferSegments;
274  bool waitingForMissingSegments;
275  int totalReceiveSize;
276 
277  unsigned char controlMessageBuffer[1024];
278 
279  // Connection related variables
280  bool connectionConfirmed;
281  bool confirmationMessagePending;
282  bool eofMessagePending;
283  bool clientConnectionPending;
284  bool resendMessagePending;
285  std::chrono::steady_clock::time_point lastRemoteHostActivity;
286  std::chrono::steady_clock::time_point lastSentHeartbeat;
287  std::chrono::steady_clock::time_point lastReceivedHeartbeat;
288 
289  // Reception related variables
290  std::vector<unsigned char, AlignedAllocator<unsigned char> > receiveBuffer;
291  int receiveDataSize;
292  int receiveOffset;
293  std::vector<unsigned char> receivedHeader;
294  bool finishedReception;
295  int droppedReceptions;
296  unsigned char unprocessedMsgPart[MAX_OUTSTANDING_BYTES];
297  int unprocessedMsgLength;
298  bool headerReceived;
299 
300  const unsigned char* extractPayload(const unsigned char* data, int& length, bool& error);
301  bool processControlMessage(int length);
302  void restoreTransferBuffer();
303  bool generateResendRequest(int& length);
304  void getNextTransferSegment(int& offset, int& length);
305  void parseResendMessage(int length);
306  void parseEofMessage(int length);
307  int getNextUdpReceiveOffset(int lastSegmentOffset, int lastSegmentSize);
308  void processReceivedUdpMessage(int length, bool& transferComplete);
309  void processReceivedTcpMessage(int length, bool& transferComplete);
310  void resizeReceiveBuffer();
311  int parseReceivedHeader(int length, int offset);
312 };
313 
314 }} // namespace
315 
316 #endif
void processReceivedMessage(int length, bool &transferComplete)
Handles a received network message.
bool newClientConnected()
Returns true if the last network message has established a new connection from a client.
bool transferComplete()
Returns true if the current transfer has been completed.
unsigned char * getNextReceiveBuffer(int maxLength)
Gets a buffer for receiving the next network message.
void resetTransfer()
Resets all transfer related internal variables.
DataBlockProtocol(bool server, ProtocolType protType, int maxUdpPacketSize)
Creates a new instance.
void resetReception(bool dropped)
Resets the message reception.
const unsigned char * getTransferMessage(int &length)
Gets the next network message for the current transfer.
int getDroppedReceptions() const
Returns the internal counter of dropped transfers during reception.
void setTransferValidBytes(int validBytes)
Updates the number of valid bytes in a partial transfer.
const unsigned char * getNextControlMessage(int &length)
If a control message is pending to be transmitted, then the message data will be returned by this met...
void setTransferData(unsigned char *data, int validBytes=0x7FFFFFFF)
Sets the payload data for the next transfer.
int getProtocolOverhead() const
Returns the size of the overhead data that is required for transferring a single network message...
unsigned char * getReceivedHeader(int &length)
Returns the header data that has been received for the current transfer.
int getMaxReceptionSize() const
Returns the maximum payload size that can be received.
void setTransferHeader(unsigned char *data, int headerSize, int transferSize)
Sets a user-defined header that shall be transmitted with the next transfer.
A protocol for transmitting large blocks of data over a network.
unsigned char * getReceivedData(int &length)
Returns the data that has been received for the current transfer.
bool isConnected() const
Returns true if a remote connection is established.
Nerian Vision Technologies