CCRakNetSlidingWindow.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /*
  11. http://www.ssfnet.org/Exchange/tcp/tcpTutorialNotes.html
  12. cwnd=max bytes allowed on wire at once
  13. Start:
  14. cwnd=mtu
  15. ssthresh=unlimited
  16. Slow start:
  17. On ack cwnd*=2
  18. congestion avoidance:
  19. On ack during new period
  20. cwnd+=mtu*mtu/cwnd
  21. on loss or duplicate ack during period:
  22. sshtresh=cwnd/2
  23. cwnd=MTU
  24. This reenters slow start
  25. If cwnd < ssthresh, then use slow start
  26. else use congestion avoidance
  27. */
  28. #include "RakNetDefines.h"
  29. #if USE_SLIDING_WINDOW_CONGESTION_CONTROL==1
  30. #ifndef __CONGESTION_CONTROL_SLIDING_WINDOW_H
  31. #define __CONGESTION_CONTROL_SLIDING_WINDOW_H
  32. #include "NativeTypes.h"
  33. #include "RakNetTime.h"
  34. #include "RakNetTypes.h"
  35. #include "DS_Queue.h"
  36. /// Sizeof an UDP header in byte
  37. #define UDP_HEADER_SIZE 28
  38. #define CC_DEBUG_PRINTF_1(x)
  39. #define CC_DEBUG_PRINTF_2(x,y)
  40. #define CC_DEBUG_PRINTF_3(x,y,z)
  41. #define CC_DEBUG_PRINTF_4(x,y,z,a)
  42. #define CC_DEBUG_PRINTF_5(x,y,z,a,b)
  43. //#define CC_DEBUG_PRINTF_1(x) printf(x)
  44. //#define CC_DEBUG_PRINTF_2(x,y) printf(x,y)
  45. //#define CC_DEBUG_PRINTF_3(x,y,z) printf(x,y,z)
  46. //#define CC_DEBUG_PRINTF_4(x,y,z,a) printf(x,y,z,a)
  47. //#define CC_DEBUG_PRINTF_5(x,y,z,a,b) printf(x,y,z,a,b)
  48. /// Set to 4 if you are using the iPod Touch TG. See http://www.jenkinssoftware.com/forum/index.php?topic=2717.0
  49. #define CC_TIME_TYPE_BYTES 8
  50. #if CC_TIME_TYPE_BYTES==8
  51. typedef RakNet::TimeUS CCTimeType;
  52. #else
  53. typedef RakNet::TimeMS CCTimeType;
  54. #endif
  55. typedef RakNet::uint24_t DatagramSequenceNumberType;
  56. typedef double BytesPerMicrosecond;
  57. typedef double BytesPerSecond;
  58. typedef double MicrosecondsPerByte;
  59. namespace RakNet
  60. {
  61. class CCRakNetSlidingWindow
  62. {
  63. public:
  64. CCRakNetSlidingWindow();
  65. ~CCRakNetSlidingWindow();
  66. /// Reset all variables to their initial states, for a new connection
  67. void Init(CCTimeType curTime, uint32_t maxDatagramPayload);
  68. /// Update over time
  69. void Update(CCTimeType curTime, bool hasDataToSendOrResend);
  70. int GetRetransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend);
  71. int GetTransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend);
  72. /// Acks do not have to be sent immediately. Instead, they can be buffered up such that groups of acks are sent at a time
  73. /// This reduces overall bandwidth usage
  74. /// How long they can be buffered depends on the retransmit time of the sender
  75. /// Should call once per update tick, and send if needed
  76. bool ShouldSendACKs(CCTimeType curTime, CCTimeType estimatedTimeToNextTick);
  77. /// Every data packet sent must contain a sequence number
  78. /// Call this function to get it. The sequence number is passed into OnGotPacketPair()
  79. DatagramSequenceNumberType GetAndIncrementNextDatagramSequenceNumber(void);
  80. DatagramSequenceNumberType GetNextDatagramSequenceNumber(void);
  81. /// Call this when you send packets
  82. /// Every 15th and 16th packets should be sent as a packet pair if possible
  83. /// When packets marked as a packet pair arrive, pass to OnGotPacketPair()
  84. /// When any packets arrive, (additionally) pass to OnGotPacket
  85. /// Packets should contain our system time, so we can pass rtt to OnNonDuplicateAck()
  86. void OnSendBytes(CCTimeType curTime, uint32_t numBytes);
  87. /// Call this when you get a packet pair
  88. void OnGotPacketPair(DatagramSequenceNumberType datagramSequenceNumber, uint32_t sizeInBytes, CCTimeType curTime);
  89. /// Call this when you get a packet (including packet pairs)
  90. /// If the DatagramSequenceNumberType is out of order, skippedMessageCount will be non-zero
  91. /// In that case, send a NAK for every sequence number up to that count
  92. bool OnGotPacket(DatagramSequenceNumberType datagramSequenceNumber, bool isContinuousSend, CCTimeType curTime, uint32_t sizeInBytes, uint32_t *skippedMessageCount);
  93. /// Call when you get a NAK, with the sequence number of the lost message
  94. /// Affects the congestion control
  95. void OnResend(CCTimeType curTime, RakNet::TimeUS nextActionTime);
  96. void OnNAK(CCTimeType curTime, DatagramSequenceNumberType nakSequenceNumber);
  97. /// Call this when an ACK arrives.
  98. /// hasBAndAS are possibly written with the ack, see OnSendAck()
  99. /// B and AS are used in the calculations in UpdateWindowSizeAndAckOnAckPerSyn
  100. /// B and AS are updated at most once per SYN
  101. void OnAck(CCTimeType curTime, CCTimeType rtt, bool hasBAndAS, BytesPerMicrosecond _B, BytesPerMicrosecond _AS, double totalUserDataBytesAcked, bool isContinuousSend, DatagramSequenceNumberType sequenceNumber );
  102. void OnDuplicateAck( CCTimeType curTime, DatagramSequenceNumberType sequenceNumber );
  103. /// Call when you send an ack, to see if the ack should have the B and AS parameters transmitted
  104. /// Call before calling OnSendAck()
  105. void OnSendAckGetBAndAS(CCTimeType curTime, bool *hasBAndAS, BytesPerMicrosecond *_B, BytesPerMicrosecond *_AS);
  106. /// Call when we send an ack, to write B and AS if needed
  107. /// B and AS are only written once per SYN, to prevent slow calculations
  108. /// Also updates SND, the period between sends, since data is written out
  109. /// Be sure to call OnSendAckGetBAndAS() before calling OnSendAck(), since whether you write it or not affects \a numBytes
  110. void OnSendAck(CCTimeType curTime, uint32_t numBytes);
  111. /// Call when we send a NACK
  112. /// Also updates SND, the period between sends, since data is written out
  113. void OnSendNACK(CCTimeType curTime, uint32_t numBytes);
  114. /// Retransmission time out for the sender
  115. /// If the time difference between when a message was last transmitted, and the current time is greater than RTO then packet is eligible for retransmission, pending congestion control
  116. /// RTO = (RTT + 4 * RTTVar) + SYN
  117. /// If we have been continuously sending for the last RTO, and no ACK or NAK at all, SND*=2;
  118. /// This is per message, which is different from UDT, but RakNet supports packetloss with continuing data where UDT is only RELIABLE_ORDERED
  119. /// Minimum value is 100 milliseconds
  120. CCTimeType GetRTOForRetransmission(unsigned char timesSent) const;
  121. /// Set the maximum amount of data that can be sent in one datagram
  122. /// Default to MAXIMUM_MTU_SIZE-UDP_HEADER_SIZE
  123. void SetMTU(uint32_t bytes);
  124. /// Return what was set by SetMTU()
  125. uint32_t GetMTU(void) const;
  126. /// Query for statistics
  127. BytesPerMicrosecond GetLocalSendRate(void) const {return 0;}
  128. BytesPerMicrosecond GetLocalReceiveRate(CCTimeType currentTime) const;
  129. BytesPerMicrosecond GetRemoveReceiveRate(void) const {return 0;}
  130. //BytesPerMicrosecond GetEstimatedBandwidth(void) const {return B;}
  131. BytesPerMicrosecond GetEstimatedBandwidth(void) const {return GetLinkCapacityBytesPerSecond()*1000000.0;}
  132. double GetLinkCapacityBytesPerSecond(void) const {return 0;}
  133. /// Query for statistics
  134. double GetRTT(void) const;
  135. bool GetIsInSlowStart(void) const {return IsInSlowStart();}
  136. uint32_t GetCWNDLimit(void) const {return (uint32_t) 0;}
  137. /// Is a > b, accounting for variable overflow?
  138. static bool GreaterThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b);
  139. /// Is a < b, accounting for variable overflow?
  140. static bool LessThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b);
  141. // void SetTimeBetweenSendsLimit(unsigned int bitsPerSecond);
  142. uint64_t GetBytesPerSecondLimitByCongestionControl(void) const;
  143. protected:
  144. // Maximum amount of bytes that the user can send, e.g. the size of one full datagram
  145. uint32_t MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  146. double cwnd; // max bytes on wire
  147. double ssThresh; // Threshhold between slow start and congestion avoidance
  148. /// When we get an ack, if oldestUnsentAck==0, set it to the current time
  149. /// When we send out acks, set oldestUnsentAck to 0
  150. CCTimeType oldestUnsentAck;
  151. CCTimeType GetSenderRTOForACK(void) const;
  152. /// Every outgoing datagram is assigned a sequence number, which increments by 1 every assignment
  153. DatagramSequenceNumberType nextDatagramSequenceNumber;
  154. DatagramSequenceNumberType nextCongestionControlBlock;
  155. bool backoffThisBlock, speedUpThisBlock;
  156. /// Track which datagram sequence numbers have arrived.
  157. /// If a sequence number is skipped, send a NAK for all skipped messages
  158. DatagramSequenceNumberType expectedNextSequenceNumber;
  159. bool _isContinuousSend;
  160. bool IsInSlowStart(void) const;
  161. double lastRtt, estimatedRTT, deviationRtt;
  162. };
  163. }
  164. #endif
  165. #endif
粤ICP备19079148号