CCRakNetSlidingWindow.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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. #include "CCRakNetSlidingWindow.h"
  11. #if USE_SLIDING_WINDOW_CONGESTION_CONTROL==1
  12. static const double UNSET_TIME_US=-1;
  13. #if CC_TIME_TYPE_BYTES==4
  14. static const CCTimeType SYN=10;
  15. #else
  16. static const CCTimeType SYN=10000;
  17. #endif
  18. #include "MTUSize.h"
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <stdlib.h>
  22. #include "RakAssert.h"
  23. #include "RakAlloca.h"
  24. using namespace RakNet;
  25. // ****************************************************** PUBLIC METHODS ******************************************************
  26. CCRakNetSlidingWindow::CCRakNetSlidingWindow()
  27. {
  28. }
  29. // ----------------------------------------------------------------------------------------------------------------------------
  30. CCRakNetSlidingWindow::~CCRakNetSlidingWindow()
  31. {
  32. }
  33. // ----------------------------------------------------------------------------------------------------------------------------
  34. void CCRakNetSlidingWindow::Init(CCTimeType curTime, uint32_t maxDatagramPayload)
  35. {
  36. (void) curTime;
  37. lastRtt=estimatedRTT=deviationRtt=UNSET_TIME_US;
  38. RakAssert(maxDatagramPayload <= MAXIMUM_MTU_SIZE);
  39. MAXIMUM_MTU_INCLUDING_UDP_HEADER=maxDatagramPayload;
  40. cwnd=maxDatagramPayload;
  41. ssThresh=0.0;
  42. oldestUnsentAck=0;
  43. nextDatagramSequenceNumber=0;
  44. nextCongestionControlBlock=0;
  45. backoffThisBlock=speedUpThisBlock=false;
  46. expectedNextSequenceNumber=0;
  47. _isContinuousSend=false;
  48. }
  49. // ----------------------------------------------------------------------------------------------------------------------------
  50. void CCRakNetSlidingWindow::Update(CCTimeType curTime, bool hasDataToSendOrResend)
  51. {
  52. (void) curTime;
  53. (void) hasDataToSendOrResend;
  54. }
  55. // ----------------------------------------------------------------------------------------------------------------------------
  56. int CCRakNetSlidingWindow::GetRetransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend)
  57. {
  58. (void) curTime;
  59. (void) isContinuousSend;
  60. (void) timeSinceLastTick;
  61. return unacknowledgedBytes;
  62. }
  63. // ----------------------------------------------------------------------------------------------------------------------------
  64. int CCRakNetSlidingWindow::GetTransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend)
  65. {
  66. (void) curTime;
  67. (void) timeSinceLastTick;
  68. _isContinuousSend=isContinuousSend;
  69. if (unacknowledgedBytes<=cwnd)
  70. return (int) (cwnd-unacknowledgedBytes);
  71. else
  72. return 0;
  73. }
  74. // ----------------------------------------------------------------------------------------------------------------------------
  75. bool CCRakNetSlidingWindow::ShouldSendACKs(CCTimeType curTime, CCTimeType estimatedTimeToNextTick)
  76. {
  77. CCTimeType rto = GetSenderRTOForACK();
  78. (void) estimatedTimeToNextTick;
  79. // iphone crashes on comparison between double and int64 http://www.jenkinssoftware.com/forum/index.php?topic=2717.0
  80. if (rto==(CCTimeType) UNSET_TIME_US)
  81. {
  82. // Unknown how long until the remote system will retransmit, so better send right away
  83. return true;
  84. }
  85. return curTime >= oldestUnsentAck + SYN;
  86. }
  87. // ----------------------------------------------------------------------------------------------------------------------------
  88. DatagramSequenceNumberType CCRakNetSlidingWindow::GetNextDatagramSequenceNumber(void)
  89. {
  90. return nextDatagramSequenceNumber;
  91. }
  92. // ----------------------------------------------------------------------------------------------------------------------------
  93. DatagramSequenceNumberType CCRakNetSlidingWindow::GetAndIncrementNextDatagramSequenceNumber(void)
  94. {
  95. DatagramSequenceNumberType dsnt=nextDatagramSequenceNumber;
  96. nextDatagramSequenceNumber++;
  97. return dsnt;
  98. }
  99. // ----------------------------------------------------------------------------------------------------------------------------
  100. void CCRakNetSlidingWindow::OnSendBytes(CCTimeType curTime, uint32_t numBytes)
  101. {
  102. (void) curTime;
  103. (void) numBytes;
  104. }
  105. // ----------------------------------------------------------------------------------------------------------------------------
  106. void CCRakNetSlidingWindow::OnGotPacketPair(DatagramSequenceNumberType datagramSequenceNumber, uint32_t sizeInBytes, CCTimeType curTime)
  107. {
  108. (void) curTime;
  109. (void) sizeInBytes;
  110. (void) datagramSequenceNumber;
  111. }
  112. // ----------------------------------------------------------------------------------------------------------------------------
  113. bool CCRakNetSlidingWindow::OnGotPacket(DatagramSequenceNumberType datagramSequenceNumber, bool isContinuousSend, CCTimeType curTime, uint32_t sizeInBytes, uint32_t *skippedMessageCount)
  114. {
  115. (void) curTime;
  116. (void) sizeInBytes;
  117. (void) isContinuousSend;
  118. if (oldestUnsentAck==0)
  119. oldestUnsentAck=curTime;
  120. if (datagramSequenceNumber==expectedNextSequenceNumber)
  121. {
  122. *skippedMessageCount=0;
  123. expectedNextSequenceNumber=datagramSequenceNumber+(DatagramSequenceNumberType)1;
  124. }
  125. else if (GreaterThan(datagramSequenceNumber, expectedNextSequenceNumber))
  126. {
  127. *skippedMessageCount=datagramSequenceNumber-expectedNextSequenceNumber;
  128. // Sanity check, just use timeout resend if this was really valid
  129. if (*skippedMessageCount>1000)
  130. {
  131. // During testing, the nat punchthrough server got 51200 on the first packet. I have no idea where this comes from, but has happened twice
  132. if (*skippedMessageCount>(uint32_t)50000)
  133. return false;
  134. *skippedMessageCount=1000;
  135. }
  136. expectedNextSequenceNumber=datagramSequenceNumber+(DatagramSequenceNumberType)1;
  137. }
  138. else
  139. {
  140. *skippedMessageCount=0;
  141. }
  142. return true;
  143. }
  144. // ----------------------------------------------------------------------------------------------------------------------------
  145. void CCRakNetSlidingWindow::OnResend(CCTimeType curTime, RakNet::TimeUS nextActionTime)
  146. {
  147. (void) curTime;
  148. (void) nextActionTime;
  149. if (_isContinuousSend && backoffThisBlock==false && cwnd>MAXIMUM_MTU_INCLUDING_UDP_HEADER*2)
  150. {
  151. // Spec says 1/2 cwnd, but it never recovers because cwnd increases too slowly
  152. //ssThresh=cwnd-8.0 * (MAXIMUM_MTU_INCLUDING_UDP_HEADER*MAXIMUM_MTU_INCLUDING_UDP_HEADER/cwnd);
  153. ssThresh=cwnd/2;
  154. if (ssThresh<MAXIMUM_MTU_INCLUDING_UDP_HEADER)
  155. ssThresh=MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  156. cwnd=MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  157. // Only backoff once per period
  158. nextCongestionControlBlock=nextDatagramSequenceNumber;
  159. backoffThisBlock=true;
  160. // CC PRINTF
  161. //printf("-- %.0f (Resend) Enter slow start.\n", cwnd);
  162. }
  163. }
  164. // ----------------------------------------------------------------------------------------------------------------------------
  165. void CCRakNetSlidingWindow::OnNAK(CCTimeType curTime, DatagramSequenceNumberType nakSequenceNumber)
  166. {
  167. (void) nakSequenceNumber;
  168. (void) curTime;
  169. if (_isContinuousSend && backoffThisBlock==false)
  170. {
  171. // Start congestion avoidance
  172. ssThresh=cwnd/2;
  173. // CC PRINTF
  174. //printf("- %.0f (NAK) Set congestion avoidance.\n", cwnd);
  175. }
  176. }
  177. // ----------------------------------------------------------------------------------------------------------------------------
  178. void CCRakNetSlidingWindow::OnAck(CCTimeType curTime, CCTimeType rtt, bool hasBAndAS, BytesPerMicrosecond _B, BytesPerMicrosecond _AS, double totalUserDataBytesAcked, bool isContinuousSend, DatagramSequenceNumberType sequenceNumber )
  179. {
  180. (void) _B;
  181. (void) totalUserDataBytesAcked;
  182. (void) _AS;
  183. (void) hasBAndAS;
  184. (void) curTime;
  185. (void) rtt;
  186. lastRtt=(double) rtt;
  187. if (estimatedRTT==UNSET_TIME_US)
  188. {
  189. estimatedRTT=(double) rtt;
  190. deviationRtt=(double)rtt;
  191. }
  192. else
  193. {
  194. double d = .05;
  195. double difference = rtt - estimatedRTT;
  196. estimatedRTT = estimatedRTT + d * difference;
  197. deviationRtt = deviationRtt + d * (abs(difference) - deviationRtt);
  198. }
  199. _isContinuousSend=isContinuousSend;
  200. if (isContinuousSend==false)
  201. return;
  202. bool isNewCongestionControlPeriod;
  203. isNewCongestionControlPeriod = GreaterThan(sequenceNumber, nextCongestionControlBlock);
  204. if (isNewCongestionControlPeriod)
  205. {
  206. backoffThisBlock=false;
  207. speedUpThisBlock=false;
  208. nextCongestionControlBlock=nextDatagramSequenceNumber;
  209. }
  210. if (IsInSlowStart())
  211. {
  212. cwnd+=MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  213. if (cwnd > ssThresh && ssThresh!=0)
  214. cwnd = ssThresh + MAXIMUM_MTU_INCLUDING_UDP_HEADER*MAXIMUM_MTU_INCLUDING_UDP_HEADER/cwnd;
  215. // CC PRINTF
  216. // printf("++ %.0f Slow start increase.\n", cwnd);
  217. }
  218. else if (isNewCongestionControlPeriod)
  219. {
  220. cwnd+=MAXIMUM_MTU_INCLUDING_UDP_HEADER*MAXIMUM_MTU_INCLUDING_UDP_HEADER/cwnd;
  221. // CC PRINTF
  222. // printf("+ %.0f Congestion avoidance increase.\n", cwnd);
  223. }
  224. }
  225. // ----------------------------------------------------------------------------------------------------------------------------
  226. void CCRakNetSlidingWindow::OnDuplicateAck( CCTimeType curTime, DatagramSequenceNumberType sequenceNumber )
  227. {
  228. (void) curTime;
  229. (void) sequenceNumber;
  230. }
  231. // ----------------------------------------------------------------------------------------------------------------------------
  232. void CCRakNetSlidingWindow::OnSendAckGetBAndAS(CCTimeType curTime, bool *hasBAndAS, BytesPerMicrosecond *_B, BytesPerMicrosecond *_AS)
  233. {
  234. (void) curTime;
  235. (void) _B;
  236. (void) _AS;
  237. *hasBAndAS=false;
  238. }
  239. // ----------------------------------------------------------------------------------------------------------------------------
  240. void CCRakNetSlidingWindow::OnSendAck(CCTimeType curTime, uint32_t numBytes)
  241. {
  242. (void) curTime;
  243. (void) numBytes;
  244. oldestUnsentAck=0;
  245. }
  246. // ----------------------------------------------------------------------------------------------------------------------------
  247. void CCRakNetSlidingWindow::OnSendNACK(CCTimeType curTime, uint32_t numBytes)
  248. {
  249. (void) curTime;
  250. (void) numBytes;
  251. }
  252. // ----------------------------------------------------------------------------------------------------------------------------
  253. CCTimeType CCRakNetSlidingWindow::GetRTOForRetransmission(unsigned char timesSent) const
  254. {
  255. (void) timesSent;
  256. #if CC_TIME_TYPE_BYTES==4
  257. const CCTimeType maxThreshold=2000;
  258. //const CCTimeType minThreshold=100;
  259. const CCTimeType additionalVariance=30;
  260. #else
  261. const CCTimeType maxThreshold=2000000;
  262. //const CCTimeType minThreshold=100000;
  263. const CCTimeType additionalVariance=30000;
  264. #endif
  265. if (estimatedRTT==UNSET_TIME_US)
  266. return maxThreshold;
  267. //double u=1.0f;
  268. double u=2.0f;
  269. double q=4.0f;
  270. CCTimeType threshhold = (CCTimeType) (u * estimatedRTT + q * deviationRtt) + additionalVariance;
  271. if (threshhold > maxThreshold)
  272. return maxThreshold;
  273. return threshhold;
  274. }
  275. // ----------------------------------------------------------------------------------------------------------------------------
  276. void CCRakNetSlidingWindow::SetMTU(uint32_t bytes)
  277. {
  278. RakAssert(bytes < MAXIMUM_MTU_SIZE);
  279. MAXIMUM_MTU_INCLUDING_UDP_HEADER=bytes;
  280. }
  281. // ----------------------------------------------------------------------------------------------------------------------------
  282. uint32_t CCRakNetSlidingWindow::GetMTU(void) const
  283. {
  284. return MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  285. }
  286. // ----------------------------------------------------------------------------------------------------------------------------
  287. BytesPerMicrosecond CCRakNetSlidingWindow::GetLocalReceiveRate(CCTimeType currentTime) const
  288. {
  289. (void) currentTime;
  290. return 0; // TODO
  291. }
  292. // ----------------------------------------------------------------------------------------------------------------------------
  293. double CCRakNetSlidingWindow::GetRTT(void) const
  294. {
  295. if (lastRtt==UNSET_TIME_US)
  296. return 0.0;
  297. return lastRtt;
  298. }
  299. // ----------------------------------------------------------------------------------------------------------------------------
  300. bool CCRakNetSlidingWindow::GreaterThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b)
  301. {
  302. // a > b?
  303. const DatagramSequenceNumberType halfSpan =(DatagramSequenceNumberType) (((DatagramSequenceNumberType)(const uint32_t)-1)/(DatagramSequenceNumberType)2);
  304. return b!=a && b-a>halfSpan;
  305. }
  306. // ----------------------------------------------------------------------------------------------------------------------------
  307. bool CCRakNetSlidingWindow::LessThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b)
  308. {
  309. // a < b?
  310. const DatagramSequenceNumberType halfSpan = ((DatagramSequenceNumberType)(const uint32_t)-1)/(DatagramSequenceNumberType)2;
  311. return b!=a && b-a<halfSpan;
  312. }
  313. // ----------------------------------------------------------------------------------------------------------------------------
  314. uint64_t CCRakNetSlidingWindow::GetBytesPerSecondLimitByCongestionControl(void) const
  315. {
  316. return 0; // TODO
  317. }
  318. // ----------------------------------------------------------------------------------------------------------------------------
  319. CCTimeType CCRakNetSlidingWindow::GetSenderRTOForACK(void) const
  320. {
  321. if (lastRtt==UNSET_TIME_US)
  322. return (CCTimeType) UNSET_TIME_US;
  323. return (CCTimeType)(lastRtt + SYN);
  324. }
  325. // ----------------------------------------------------------------------------------------------------------------------------
  326. bool CCRakNetSlidingWindow::IsInSlowStart(void) const
  327. {
  328. return cwnd <= ssThresh || ssThresh==0;
  329. }
  330. // ----------------------------------------------------------------------------------------------------------------------------
  331. #endif
粤ICP备19079148号