UDPMessageConnection.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. #pragma once
  12. /** @file UDPMessageConnection.h
  13. @brief The UDPMessageConnection class. */
  14. // Modified by Lasse Oorni for Urho3D
  15. #include "MessageConnection.h"
  16. #include "SequentialIntegerSet.h"
  17. #include "Array.h"
  18. #include "OrderedHashTable.h"
  19. /*
  20. UDP packet format: 3 bytes if InOrder=false. 5-6 bytes if InOrder=true.
  21. 1bit - InOrder packet. This packet contains InOrder messages.
  22. 1bit - Reliable packet. This packet is expected to be Acked by the receiver.
  23. 6 bits - The six lowest bits of the PacketID.
  24. u16 The 16 next bits of the PacketID. This gives 22 bits of the PacketID in total.
  25. * u8 InOrder array length.
  26. * N x u8-u16 InOrder PacketID delta counter. VLE-encoded 1.7/8 Only present if InOrder=true.
  27. .Message.
  28. .Message.
  29. ...
  30. .Message.
  31. Message format: 2 bytes if FRGSTART=FRAGMENT=false.
  32. 1bit - FRGSTART. This is the first fragment of the message (offset=0)
  33. 1bit - FRAGMENT. This message is a fragment of a bigger message -flag. If FRGSTART=true, this field is not read and is assumed to be true.
  34. 1bit - InOrder. This message may be processed by the application only after all the previous InOrder messages have been processed.
  35. * 1bit - InOrder. This message may be processed by the application only after all the previous InOrder messages have been processed.
  36. * 1bit - InOrder. This message may be processed by the application only after all the previous InOrder messages have been processed.
  37. (Old: 1bit - Unused.)
  38. (Old: 1bit - Unused.)
  39. 11 bits Content length (includes both the length of MessageID and Content Data fields)
  40. * u8 InOrder array index. Only present if InOrder=7 (111 in base 2).
  41. u8-u32 # of Fragments in whole message VLE-encoded 1.7/1.7/16 Only present if FRGSTART=true.
  42. u8 Fragment Transfer ID Only present if FRAGMENT=true or FRGSTART=true.
  43. * New: u8-u32 Fragment number VLE-encoded 1.7/1.7/16 Only present if FRAGMENT=true and FRGSTART=false.
  44. (Old: u8-u16 Fragment number VLE-encoded 1.7/8 Only present if FRAGMENT=true.)
  45. .Content.
  46. Content format:
  47. u8-u32 MessageID VLE-encoded 1.7/1.7/16
  48. N bytes Content data
  49. */
  50. namespace kNet
  51. {
  52. class UDPMessageConnection : public MessageConnection
  53. {
  54. public:
  55. UDPMessageConnection(Network *owner, NetworkServer *ownerServer, Socket *socket, ConnectionState startingState);
  56. ~UDPMessageConnection();
  57. float RetransmissionTimeout() const { return retransmissionTimeout; }
  58. float DatagramSendRate() const { return datagramSendRate; }
  59. void SetDatagramSendRate(float newRateDgramsPerSecond) { datagramSendRate = newRateDgramsPerSecond; }
  60. float SmoothedRtt() const { return smoothedRTT; }
  61. float RttVariation() const { return rttVariation; }
  62. size_t NumOutboundUnackedDatagrams() const { return outboundPacketAckTrack.Size(); }
  63. size_t NumReceivedUnackedDatagrams() const { return inboundPacketAckTrack.size(); }
  64. float PacketLossCount() const { return packetLossCount; }
  65. float PacketLossRate() const { return packetLossRate; }
  66. private:
  67. /// Reads all the new bytes available in the socket.
  68. /// @return The number of bytes successfully read.
  69. virtual SocketReadResult ReadSocket(size_t &bytesRead); // [worker thread]
  70. /// Parses bytes with have previously been read from the socket to actual application-level messages.
  71. void ExtractMessages(const char *data, size_t numBytes); // [worker thread]
  72. /// Reads all available bytes from a datagram socket. This function will read in multiple datagrams
  73. /// as long as there are available ones to process.
  74. /// @param bytesRead [out] Returns the total number of bytes containes in the datagrams that were read.
  75. SocketReadResult UDPReadSocket(size_t &bytesRead); // [worker thread]
  76. void UpdateRTOCounterOnPacketAck(float rtt); // [worker thread]
  77. void UpdateRTOCounterOnPacketLoss(); // [worker thread]
  78. // Closing down the connection:
  79. void SendDisconnectMessage(bool isInternal); // [main thread]
  80. void HandleDisconnectMessage(); // [worker thread]
  81. void SendDisconnectAckMessage(); // [worker thread]
  82. void HandleDisconnectAckMessage(); // [worker thread]
  83. // Acknowledging reliable datagrams:
  84. void PerformPacketAckSends(); // [worker thread]
  85. void SendPacketAckMessage(); // [worker thread]
  86. void HandlePacketAckMessage(const char *data, size_t numBytes); // [worker thread]
  87. bool HandleMessage(packet_id_t packetID, message_id_t messageID, const char *data, size_t numBytes); // [worker thread]
  88. /// Refreshes Packet Loss related statistics.
  89. void ComputePacketLoss(); // [worker thread]
  90. /// Marks that we have received a datagram with the given ID.
  91. void AddReceivedPacketIDStats(packet_id_t packetID); // [worker thread]
  92. /// @return True if we have received a packet with the given packetID already.
  93. bool HaveReceivedPacketID(packet_id_t packetID) const; // [worker thread]
  94. /// Copies the given message to an internal queue to wait to be processed by the worker thread that owns this connection.
  95. void QueueInboundDatagram(const char *data, size_t numBytes); // [thread-safe].
  96. /// Handles all the previously queued datagrams this connection has received.
  97. void ProcessQueuedDatagrams(); // [worker thread]
  98. /// Specifies the PacketID of the last received datagram with InOrder flag set.
  99. packet_id_t lastReceivedInOrderPacketID;
  100. /// Specifies the PacketID of the last sent datagram with InOrder flag set.
  101. packet_id_t lastSentInOrderPacketID;
  102. /// A running index to identify packet datagrams as they are send out to the stream.
  103. packet_id_t datagramPacketIDCounter;
  104. /// Specifies in milliseconds the currently recommended datagram timeout value for any packet that is sent out at the present time.
  105. float retransmissionTimeout;
  106. /// The flow control operates on fixed time window intervals called 'frames'. This variable remembers
  107. /// when the previous frame ended, and the currently elapsed frame starts.
  108. tick_t lastFrameTime;
  109. int numAcksLastFrame;
  110. int numLossesLastFrame;
  111. /// The flow control algorithm:
  112. float datagramSendRate; ///< The number of datagrams/second to send.
  113. float lowestDatagramSendRateOnPacketLoss;
  114. int slowModeDelay; ///< Go into slow increase mode for some time on receiving loss
  115. // These variables correspond to RFC2988, http://tools.ietf.org/html/rfc2988 , section 2.
  116. bool rttCleared; ///< If true, smoothedRTT and rttVariation do not contain meaningful values, but "are clear".
  117. float smoothedRTT;
  118. float rttVariation;
  119. // The following are used for statistics purposes:
  120. float packetLossRate; ///< The currently estimated datagram packet loss rate, [0, 1].
  121. float packetLossCount; ///< The current packet loss in absolute packets/sec.
  122. /// Info struct used to track acks of reliable packets.
  123. struct PacketAckTrack
  124. {
  125. PacketAckTrack()
  126. :sendCount(0)
  127. {
  128. }
  129. /// The timestamp of when a packet with this ID was last sent out.
  130. tick_t sentTick;
  131. /// The timestamp of when this packet will time out and can be resent (at the earliest. It will get queued and be resent later)
  132. tick_t timeoutTick;
  133. /// The packet ID of the packet that was sent out.
  134. packet_id_t packetID;
  135. /// The packet send rate we had when this packet was sent out.
  136. float datagramSendRate;
  137. /// The number of times this packet has been sent. 1 denotes no resends. 2 - this packet's been resent once, and so on.
  138. int sendCount;
  139. /// If true, the packet with this ID was an inOrder packet.
  140. bool inOrder;
  141. /// if inOrder==true, this tells the packetID of the previous in-order packet that was transmitted.
  142. packet_id_t previousInOrderPacketID;
  143. Array<NetworkMessage*> messages;
  144. static int Hash(const PacketAckTrack &item, int maxElemsMask) { return item.packetID & maxElemsMask; }
  145. static int Hash(int key, int maxElemsMask) { return key & maxElemsMask; }
  146. };
  147. void ProcessPacketTimeouts(); // [worker thread]
  148. void HandleFlowControl(); // [worker thread]
  149. void DoUpdateConnection(); // [worker thread]
  150. PacketSendResult SendOutPacket(); // [worker thread]
  151. void SendOutPackets(); // [worker thread]
  152. unsigned long TimeUntilCanSendPacket() const; // [worker thread]
  153. void PerformDisconnection(); // [main thread]
  154. /// Returns OK if it is acceptable by the flow control timer to send out a new datagram.
  155. bool CanSendOutNewDatagram() const; // [worker thread]
  156. /// Called whenever we have sent a new datagram to recompute the datagram send throttle timer.
  157. void NewDatagramSent(); // [worker thread]
  158. /// Used to perform flow control on outbound UDP messages.
  159. mutable tick_t lastDatagramSendTime; ///\todo. No mutable. Rename to nextDatagramSendTime.
  160. /// Connection control update timer.
  161. PolledTimer udpUpdateTimer;
  162. PolledTimer statsUpdateTimer;
  163. typedef std::map<packet_id_t, PacketAckTrack> PacketAckTrackMap;
  164. /// Contains the messages we have sent out that we are waiting for the other party to Ack.
  165. // PacketAckTrackMap outboundPacketAckTrack;
  166. typedef WaitFreeQueue<PacketAckTrack> PacketAckTrackQueue;
  167. PacketAckTrackQueue outboundPacketAckTrack;
  168. // typedef OrderedHashTable<PacketAckTrack, PacketAckTrack> PacketAckTrackTable;
  169. // PacketAckTrackTable outboundPacketAckTrack;
  170. static int BiasedBinarySearchFindPacketIndex(UDPMessageConnection::PacketAckTrackQueue &queue, packet_id_t packetID);
  171. WaitFreeQueue<Datagram> queuedInboundDatagrams;
  172. void FreeOutboundPacketAckTrack(packet_id_t packetID); // [worker thread]
  173. // Contains a list of all messages we've received that we need to Ack at some point.
  174. PacketAckTrackMap inboundPacketAckTrack;
  175. /// Contains the reliable message numbers of all reliable messages we've received.
  176. /// Used to detect and discard duplicate messages we've received.
  177. std::set<unsigned long> receivedReliableMessages;
  178. SequentialIntegerSet receivedPacketIDs;
  179. /// Specifies the packet ID of the most recent datagram we sent. Used currently only
  180. /// for statistics purposes.
  181. packet_id_t previousReceivedPacketID;
  182. // The following are temporary data structures used by various internal routines for processing.
  183. // They are created here as members to avoid having to create objects on the stack at each call to
  184. // time-sensitive functions.
  185. std::vector<NetworkMessage *> datagramSerializedMessages; // MessageConnection::UDPSendOutPacket()
  186. std::vector<NetworkMessage *> skippedMessages; // MessageConnection::UDPSendOutPacket()
  187. std::vector<char> assembledData; // MessageConnection::DatagramExtractMessages
  188. /// Returns the average number of inbound packet loss, packets/sec.
  189. float GetPacketLossCount() const { return packetLossCount; }
  190. /// Returns the percentage of inbound packets that are being lost, [0, 1].
  191. float GetPacketLossRate() const { return packetLossRate; }
  192. void DumpConnectionStatus() const;
  193. friend class NetworkServer;
  194. };
  195. } // ~kNet