Free Electron
MessageReliableUDP.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __MessageReliableUDP_h__
8 #define __MessageReliableUDP_h__
9 
10 // Future improvements:
11 //
12 // 1. Track the percentage of failed packets and adjust the number of
13 // burst packets based on that percentage
14 //
15 // 2. Multiple transmit threads could be used for different IP addresses
16 //
17 // 3. Add the ability to add a max timeout of sending a message
18 //
19 // 4. Better unit tests - add the ability drop percentage of random packets
20 
21 #pragma pack(push, 1)
22 
23 namespace fe
24 {
25 namespace ext
26 {
27 
28 // Max number of bytes per packet
29 #define RELIABLE_UDP_PACKET_SIZE (1024)
30 
31 // Max number of packets of RELIABLE_UDP_PACKET_SIZE
32 #define RELIABLE_UDP_MAX_PACKETS (128)
33 
34 // Minimum time after last transmition to receiver before
35 // checking for missed packets
36 #define RELIABLE_UDP_MIN_RESPONSE_TIME (100)
37 
38 // Default max packets transmitted at one time before delaying to transmit more
39 #define RELIABLE_UDP_BURST_PACKET_LIMIT (10)
40 
41 #define RELIABLE_UDP_RECEIVED_MAX_LIST (64)
42 
43 //------------------------------------------------------------------------------
44 struct MultiPacketMsg
45 {
46  // Numbers re-cycled but any message in that hasn't been received before
47  // being re-cycled
48  uint16_t messageID;
49  // Port of sending verification messages to the sender
50  uint16_t verificationPort;
51  // Full message size
52  uint32_t messageSize;
53  // byte offset into message = offset * RELIABLE_UDP_PACKET_SIZE
54  uint16_t offset;
55  // Message size is assumed to be RELIABLE_UDP_PACKET_SIZE bytes unless
56  // it is the last packet and then it is calculated based on
57  // the full message size the full message size is sent
58  // with each message in case the first message is missed so
59  // the memory can be allocated on the receiving side
60  uint8_t data[RELIABLE_UDP_PACKET_SIZE];
61 };
62 
63 //------------------------------------------------------------------------------
64 // Single packet response of the state of all the multi-packet messages
65 //currently received by the client
66 struct MultiPacketResponseMsg
67 {
68  uint16_t messageID;
69  std::bitset<RELIABLE_UDP_MAX_PACKETS> packetsReceived;
70 };
71 
72 //------------------------------------------------------------------------------
73 struct MultiPacketMsgInProgress
74 {
75  uint16_t messageID; // Message ID
76  uint32_t messageSize; // Size of message
77 
78  // NOTE will be deleted when transmitted successfully or timed out
79  uint8_t* message; // Message buffer
80 
81  char ipAddress[INET_ADDRSTRLEN]; // ipAddress xxx.xxx.xxx.xxx\0
82  uint16_t port; // port
83  int64_t lastTransmitTime; // Last time a packet was sent
84  int64_t lastReceivedTime; // Last time a response was received
85 
86  // Bit array of packets sent
87  std::bitset<RELIABLE_UDP_MAX_PACKETS> packetsSent;
88  // Bit array of packets that have be verified received by the receiver
89  std::bitset<RELIABLE_UDP_MAX_PACKETS> packetsReceived;
90 
91  bool doInitialTransmition; // Initial transmition
92  bool updated; // Flag to msg was just updated
93 
94  bool partOfThisMessage(const MultiPacketMsg &msg, const char *msgIP) const
95  {
96  return(messageID == msg.messageID &&
97  port == msg.verificationPort &&
98  strncmp(ipAddress, msgIP, sizeof(ipAddress)) == 0);
99  }
100 
101  bool receivedFullMessage() const
102  {
103  return ((packetsReceived.count() * RELIABLE_UDP_PACKET_SIZE) >=
104  messageSize);
105  }
106 };
107 
108 //------------------------------------------------------------------------------
109 struct MultiPacketMsgReceived
110 {
111  uint16_t messageID; // Message ID
112  char ipAddress[INET_ADDRSTRLEN]; // received from xxx.xxx.xxx.xxx\0
113  uint16_t verificationPort; // verification port used by sender
114 
115  bool operator==(const MultiPacketMsgInProgress &msg) const
116  {
117  return(messageID == msg.messageID &&
118  verificationPort == msg.port &&
119  strncmp(ipAddress, msg.ipAddress, sizeof(ipAddress)) == 0);
120  }
121 };
122 
123 
124 /**************************************************************************//**
125  @brief Message Sender/Receiver multi-packet reliable over UDP
126 
127  @ingroup message
128 *//***************************************************************************/
129 class FE_DL_PUBLIC MessageReliableUDP : virtual public MessageReliableUDPI
130 {
131 public:
134 
135  virtual bool start(uint16_t receivePort) override;
136  virtual uint16_t getReceivePort() override;
137  virtual void shutdown() override;
138  virtual bool recvReliableFrom(uint8_t **msg, uint32_t &msgSize,
139  char *fromIPaddress) override;
140  virtual bool sendReliableTo(const uint8_t *msg, const uint32_t msgSize,
141  const char *ipAddress, uint16_t port) override;
142 
143 private:
144  bool sendPacket(MultiPacketMsgInProgress &msg, uint32_t offset);
145  void checkVerifications();
146  void transmitThread();
147  void receiveThread();
148  int64_t now();
149  bool sendResponseMsg(MultiPacketMsgInProgress &receivedMsg);
150  bool alreadyReceived(const MultiPacketMsg &msg, const char *msgIP);
151  bool alreadyReceived(const MultiPacketMsgInProgress &testMsg);
152 
153  bool m_initialized;
154  bool m_running;
155  Messagegram m_packetMsg;
156  Messagegram m_verificationMsg;
157  uint16_t m_msgID; // Next message ID to be assigned
158  uint16_t m_verificationPort;// Verification port
159  uint16_t m_receivePort; // Receive port
160  int m_burstPacketLimit; // Limits how many packets can be sent at once
161  // later improvements should very this based on
162  // the number of packets by the receiver
163 
164  fe::sp<fe::SingleMaster> m_spSingleMaster;
165 
166  bool m_transmitThreadDone;
167  fe::sp<MessageI> m_transmitMsgSystem;
168  std::thread* m_transmitThread;
169  std::mutex m_transmitListLock;
170  I32 m_transmitListLockCount;
171 
172  // List of messages being transmitted
173  std::list<MultiPacketMsgInProgress> m_transmitList;
174 
175  bool m_receiveThreadDone;
176  fe::sp<MessageI> m_receiveMsgSystem;
177  std::thread* m_receiveThread;
178  std::mutex m_receiveListLock;
179  I32 m_receiveListLockCount;
180 
181  // List of messages being received
182  std::list<MultiPacketMsgInProgress> m_receiveList;
183 
184  // List of messages that have already been received
185  // this is used to ignore any late re-transmit of old message in case the
186  // sender wasn't notified in time or lost the response message reply
187  std::list<MultiPacketMsgReceived> m_fullyreceivedMsgList;
188 };
189 
190 } // namespace ext
191 } // namespace fe
192 
193 #pragma pack(pop)
194 
195 #endif // __MessageReliableUDP_h__
Message Sender/Receiver multi-packet reliable over UDP.
Definition: MessageReliableUDP.h:129
kernel
Definition: namespace.dox:3
Message Sender/Receiver multi-packet reliable over UDP.
Definition: MessageReliableUDPI.h:18
BWORD operator==(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s.
Definition: DualString.h:208