CCRakNetUDT.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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 "CCRakNetUDT.h"
  11. #if USE_SLIDING_WINDOW_CONGESTION_CONTROL!=1
  12. #include "Rand.h"
  13. #include "MTUSize.h"
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <stdlib.h>
  17. //#include <memory.h>
  18. #include "RakAssert.h"
  19. #include "RakAlloca.h"
  20. using namespace RakNet;
  21. static const double UNSET_TIME_US=-1;
  22. static const double CWND_MIN_THRESHOLD=2.0;
  23. static const double UNDEFINED_TRANSFER_RATE=0.0;
  24. /// Interval at which to update aspects of the system
  25. /// 1. send acks
  26. /// 2. update time interval between outgoing packets
  27. /// 3, Yodate retransmit timeout
  28. #if CC_TIME_TYPE_BYTES==4
  29. static const CCTimeType SYN=10;
  30. #else
  31. static const CCTimeType SYN=10000;
  32. #endif
  33. #if CC_TIME_TYPE_BYTES==4
  34. #define MAX_RTT 1000
  35. #define RTT_TOLERANCE 30
  36. #else
  37. #define MAX_RTT 1000000
  38. #define RTT_TOLERANCE 30000
  39. #endif
  40. double RTTVarMultiple=4.0;
  41. // ****************************************************** PUBLIC METHODS ******************************************************
  42. CCRakNetUDT::CCRakNetUDT()
  43. {
  44. }
  45. // ----------------------------------------------------------------------------------------------------------------------------
  46. CCRakNetUDT::~CCRakNetUDT()
  47. {
  48. }
  49. // ----------------------------------------------------------------------------------------------------------------------------
  50. void CCRakNetUDT::Init(CCTimeType curTime, uint32_t maxDatagramPayload)
  51. {
  52. (void) curTime;
  53. nextSYNUpdate=0;
  54. packetPairRecieptHistoryWriteIndex=0;
  55. packetArrivalHistoryWriteIndex=0;
  56. packetArrivalHistoryWriteCount=0;
  57. RTT=UNSET_TIME_US;
  58. // RTTVar=UNSET_TIME_US;
  59. isInSlowStart=true;
  60. NAKCount=1000;
  61. AvgNAKNum=1;
  62. DecInterval=1;
  63. DecCount=0;
  64. nextDatagramSequenceNumber=0;
  65. lastPacketPairPacketArrivalTime=0;
  66. lastPacketPairSequenceNumber=(DatagramSequenceNumberType)(const uint32_t)-1;
  67. lastPacketArrivalTime=0;
  68. CWND=CWND_MIN_THRESHOLD;
  69. lastUpdateWindowSizeAndAck=0;
  70. lastTransmitOfBAndAS=0;
  71. ExpCount=1.0;
  72. totalUserDataBytesSent=0;
  73. oldestUnsentAck=0;
  74. MAXIMUM_MTU_INCLUDING_UDP_HEADER=maxDatagramPayload;
  75. CWND_MAX_THRESHOLD=RESEND_BUFFER_ARRAY_LENGTH;
  76. #if CC_TIME_TYPE_BYTES==4
  77. const BytesPerMicrosecond DEFAULT_TRANSFER_RATE=(BytesPerMicrosecond) 3.6;
  78. #else
  79. const BytesPerMicrosecond DEFAULT_TRANSFER_RATE=(BytesPerMicrosecond) .0036;
  80. #endif
  81. #if CC_TIME_TYPE_BYTES==4
  82. lastRttOnIncreaseSendRate=1000;
  83. #else
  84. lastRttOnIncreaseSendRate=1000000;
  85. #endif
  86. nextCongestionControlBlock=0;
  87. lastRtt=0;
  88. // B=DEFAULT_TRANSFER_RATE;
  89. AS=UNDEFINED_TRANSFER_RATE;
  90. const MicrosecondsPerByte DEFAULT_BYTE_INTERVAL=(MicrosecondsPerByte) (1.0/DEFAULT_TRANSFER_RATE);
  91. SND=DEFAULT_BYTE_INTERVAL;
  92. expectedNextSequenceNumber=0;
  93. sendBAndASCount=0;
  94. packetArrivalHistoryContinuousGapsIndex=0;
  95. //packetPairRecipetHistoryGapsIndex=0;
  96. hasWrittenToPacketPairReceiptHistory=false;
  97. InitPacketArrivalHistory();
  98. estimatedLinkCapacityBytesPerSecond=0;
  99. bytesCanSendThisTick=0;
  100. hadPacketlossThisBlock=false;
  101. pingsLastInterval.Clear(__FILE__,__LINE__);
  102. }
  103. // ----------------------------------------------------------------------------------------------------------------------------
  104. void CCRakNetUDT::SetMTU(uint32_t bytes)
  105. {
  106. MAXIMUM_MTU_INCLUDING_UDP_HEADER=bytes;
  107. }
  108. // ----------------------------------------------------------------------------------------------------------------------------
  109. uint32_t CCRakNetUDT::GetMTU(void) const
  110. {
  111. return MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  112. }
  113. // ----------------------------------------------------------------------------------------------------------------------------
  114. void CCRakNetUDT::Update(CCTimeType curTime, bool hasDataToSendOrResend)
  115. {
  116. (void) hasDataToSendOrResend;
  117. (void) curTime;
  118. return;
  119. // I suspect this is causing major lag
  120. /*
  121. if (hasDataToSendOrResend==false)
  122. halveSNDOnNoDataTime=0;
  123. else if (halveSNDOnNoDataTime==0)
  124. {
  125. UpdateHalveSNDOnNoDataTime(curTime);
  126. ExpCount=1.0;
  127. }
  128. // If you send, and get no data at all from that time to RTO, then halve send rate7
  129. if (HasHalveSNDOnNoDataTimeElapsed(curTime))
  130. {
  131. /// 2000 bytes per second
  132. /// 0.0005 seconds per byte
  133. /// 0.5 milliseconds per byte
  134. /// 500 microseconds per byte
  135. // printf("No incoming data, halving send rate\n");
  136. SND*=2.0;
  137. CapMinSnd(_FILE_AND_LINE_);
  138. ExpCount+=1.0;
  139. if (ExpCount>8.0)
  140. ExpCount=8.0;
  141. UpdateHalveSNDOnNoDataTime(curTime);
  142. }
  143. */
  144. }
  145. // ----------------------------------------------------------------------------------------------------------------------------
  146. int CCRakNetUDT::GetRetransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend)
  147. {
  148. (void) curTime;
  149. if (isInSlowStart)
  150. {
  151. uint32_t CWNDLimit = (uint32_t) (CWND*MAXIMUM_MTU_INCLUDING_UDP_HEADER);
  152. return CWNDLimit;
  153. }
  154. return GetTransmissionBandwidth(curTime,timeSinceLastTick,unacknowledgedBytes,isContinuousSend);
  155. }
  156. // ----------------------------------------------------------------------------------------------------------------------------
  157. int CCRakNetUDT::GetTransmissionBandwidth(CCTimeType curTime, CCTimeType timeSinceLastTick, uint32_t unacknowledgedBytes, bool isContinuousSend)
  158. {
  159. (void) curTime;
  160. if (isInSlowStart)
  161. {
  162. uint32_t CWNDLimit = (uint32_t) (CWND*MAXIMUM_MTU_INCLUDING_UDP_HEADER-unacknowledgedBytes);
  163. return CWNDLimit;
  164. }
  165. if (bytesCanSendThisTick>0)
  166. bytesCanSendThisTick=0;
  167. #if CC_TIME_TYPE_BYTES==4
  168. if (isContinuousSend==false && timeSinceLastTick>100)
  169. timeSinceLastTick=100;
  170. #else
  171. if (isContinuousSend==false && timeSinceLastTick>100000)
  172. timeSinceLastTick=100000;
  173. #endif
  174. bytesCanSendThisTick=(int)((double)timeSinceLastTick*((double)1.0/SND)+(double)bytesCanSendThisTick);
  175. if (bytesCanSendThisTick>0)
  176. return bytesCanSendThisTick;
  177. return 0;
  178. }
  179. uint64_t CCRakNetUDT::GetBytesPerSecondLimitByCongestionControl(void) const
  180. {
  181. if (isInSlowStart)
  182. return 0;
  183. #if CC_TIME_TYPE_BYTES==4
  184. return (uint64_t) ((double)1.0/(SND*1000.0));
  185. #else
  186. return (uint64_t) ((double)1.0/(SND*1000000.0));
  187. #endif
  188. }
  189. // ----------------------------------------------------------------------------------------------------------------------------
  190. bool CCRakNetUDT::ShouldSendACKs(CCTimeType curTime, CCTimeType estimatedTimeToNextTick)
  191. {
  192. CCTimeType rto = GetSenderRTOForACK();
  193. // iphone crashes on comparison between double and int64 http://www.jenkinssoftware.com/forum/index.php?topic=2717.0
  194. if (rto==(CCTimeType) UNSET_TIME_US)
  195. {
  196. // Unknown how long until the remote system will retransmit, so better send right away
  197. return true;
  198. }
  199. // CCTimeType remoteRetransmitTime=oldestUnsentAck+rto-RTT*.5;
  200. // CCTimeType ackArrivalTimeIfWeDelay=RTT*.5+estimatedTimeToNextTick+curTime;
  201. // return ackArrivalTimeIfWeDelay<remoteRetransmitTime;
  202. // Simplified equation
  203. // GU: At least one ACK should be sent per SYN, otherwise your protocol will increase slower.
  204. return curTime >= oldestUnsentAck + SYN ||
  205. estimatedTimeToNextTick+curTime < oldestUnsentAck+rto-RTT;
  206. }
  207. // ----------------------------------------------------------------------------------------------------------------------------
  208. DatagramSequenceNumberType CCRakNetUDT::GetNextDatagramSequenceNumber(void)
  209. {
  210. return nextDatagramSequenceNumber;
  211. }
  212. // ----------------------------------------------------------------------------------------------------------------------------
  213. DatagramSequenceNumberType CCRakNetUDT::GetAndIncrementNextDatagramSequenceNumber(void)
  214. {
  215. DatagramSequenceNumberType dsnt=nextDatagramSequenceNumber;
  216. nextDatagramSequenceNumber++;
  217. return dsnt;
  218. }
  219. // ----------------------------------------------------------------------------------------------------------------------------
  220. void CCRakNetUDT::OnSendBytes(CCTimeType curTime, uint32_t numBytes)
  221. {
  222. (void) curTime;
  223. totalUserDataBytesSent+=numBytes;
  224. if (isInSlowStart==false)
  225. bytesCanSendThisTick-=numBytes;
  226. }
  227. // ****************************************************** PROTECTED METHODS ******************************************************
  228. void CCRakNetUDT::SetNextSYNUpdate(CCTimeType currentTime)
  229. {
  230. nextSYNUpdate+=SYN;
  231. if (nextSYNUpdate < currentTime)
  232. nextSYNUpdate=currentTime+SYN;
  233. }
  234. // ----------------------------------------------------------------------------------------------------------------------------
  235. BytesPerMicrosecond CCRakNetUDT::ReceiverCalculateDataArrivalRate(CCTimeType curTime) const
  236. {
  237. (void) curTime;
  238. // Not an instantaneous measurement
  239. /*
  240. if (continuousBytesReceivedStartTime!=0 && curTime>continuousBytesReceivedStartTime)
  241. {
  242. #if CC_TIME_TYPE_BYTES==4
  243. const CCTimeType threshold=100;
  244. #else
  245. const CCTimeType threshold=100000;
  246. #endif
  247. if (curTime-continuousBytesReceivedStartTime>threshold)
  248. return (BytesPerMicrosecond) continuousBytesReceived/(BytesPerMicrosecond) (curTime-continuousBytesReceivedStartTime);
  249. }
  250. return UNDEFINED_TRANSFER_RATE;
  251. */
  252. if (packetArrivalHistoryWriteCount<CC_RAKNET_UDT_PACKET_HISTORY_LENGTH)
  253. return UNDEFINED_TRANSFER_RATE;
  254. BytesPerMicrosecond median = ReceiverCalculateDataArrivalRateMedian();
  255. int i;
  256. const BytesPerMicrosecond oneEighthMedian=median*(1.0/8.0);
  257. const BytesPerMicrosecond eightTimesMedian=median*8.0f;
  258. BytesPerMicrosecond medianListLength=0.0;
  259. BytesPerMicrosecond sum=0.0;
  260. // Find average of acceptedMedianValues
  261. for (i=0; i < CC_RAKNET_UDT_PACKET_HISTORY_LENGTH; i++)
  262. {
  263. if (packetArrivalHistory[i]>=oneEighthMedian &&
  264. packetArrivalHistory[i]<eightTimesMedian)
  265. {
  266. medianListLength=medianListLength+1.0;
  267. sum+=packetArrivalHistory[i];
  268. }
  269. }
  270. if (medianListLength==0.0)
  271. return UNDEFINED_TRANSFER_RATE;
  272. return sum/medianListLength;
  273. }
  274. // ----------------------------------------------------------------------------------------------------------------------------
  275. BytesPerMicrosecond CCRakNetUDT::ReceiverCalculateDataArrivalRateMedian(void) const
  276. {
  277. return CalculateListMedianRecursive(packetArrivalHistory, CC_RAKNET_UDT_PACKET_HISTORY_LENGTH, 0, 0);
  278. }
  279. // ----------------------------------------------------------------------------------------------------------------------------
  280. BytesPerMicrosecond CCRakNetUDT::CalculateListMedianRecursive(const BytesPerMicrosecond inputList[CC_RAKNET_UDT_PACKET_HISTORY_LENGTH], int inputListLength, int lessThanSum, int greaterThanSum)
  281. {
  282. BytesPerMicrosecond lessThanMedian[CC_RAKNET_UDT_PACKET_HISTORY_LENGTH], greaterThanMedian[CC_RAKNET_UDT_PACKET_HISTORY_LENGTH];
  283. int lessThanMedianListLength=0, greaterThanMedianListLength=0;
  284. BytesPerMicrosecond median=inputList[0];
  285. int i;
  286. for (i=1; i < inputListLength; i++)
  287. {
  288. // If same value, spread among lists evenly
  289. if (inputList[i]<median || ((i&1)==0 && inputList[i]==median))
  290. lessThanMedian[lessThanMedianListLength++]=inputList[i];
  291. else
  292. greaterThanMedian[greaterThanMedianListLength++]=inputList[i];
  293. }
  294. RakAssert(CC_RAKNET_UDT_PACKET_HISTORY_LENGTH%2==0);
  295. if (lessThanMedianListLength+lessThanSum==greaterThanMedianListLength+greaterThanSum+1 ||
  296. lessThanMedianListLength+lessThanSum==greaterThanMedianListLength+greaterThanSum-1)
  297. return median;
  298. if (lessThanMedianListLength+lessThanSum < greaterThanMedianListLength+greaterThanSum)
  299. {
  300. lessThanMedian[lessThanMedianListLength++]=median;
  301. return CalculateListMedianRecursive(greaterThanMedian, greaterThanMedianListLength, lessThanMedianListLength+lessThanSum, greaterThanSum);
  302. }
  303. else
  304. {
  305. greaterThanMedian[greaterThanMedianListLength++]=median;
  306. return CalculateListMedianRecursive(lessThanMedian, lessThanMedianListLength, lessThanSum, greaterThanMedianListLength+greaterThanSum);
  307. }
  308. }
  309. // ----------------------------------------------------------------------------------------------------------------------------
  310. bool CCRakNetUDT::GreaterThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b)
  311. {
  312. // a > b?
  313. const DatagramSequenceNumberType halfSpan =(DatagramSequenceNumberType) (((DatagramSequenceNumberType)(const uint32_t)-1)/(DatagramSequenceNumberType)2);
  314. return b!=a && b-a>halfSpan;
  315. }
  316. // ----------------------------------------------------------------------------------------------------------------------------
  317. bool CCRakNetUDT::LessThan(DatagramSequenceNumberType a, DatagramSequenceNumberType b)
  318. {
  319. // a < b?
  320. const DatagramSequenceNumberType halfSpan = ((DatagramSequenceNumberType)(const uint32_t)-1)/(DatagramSequenceNumberType)2;
  321. return b!=a && b-a<halfSpan;
  322. }
  323. // ----------------------------------------------------------------------------------------------------------------------------
  324. CCTimeType CCRakNetUDT::GetSenderRTOForACK(void) const
  325. {
  326. if (RTT==UNSET_TIME_US)
  327. return (CCTimeType) UNSET_TIME_US;
  328. double RTTVar = maxRTT-minRTT;
  329. return (CCTimeType)(RTT + RTTVarMultiple * RTTVar + SYN);
  330. }
  331. // ----------------------------------------------------------------------------------------------------------------------------
  332. CCTimeType CCRakNetUDT::GetRTOForRetransmission(unsigned char timesSent) const
  333. {
  334. #if CC_TIME_TYPE_BYTES==4
  335. const CCTimeType maxThreshold=10000;
  336. const CCTimeType minThreshold=100;
  337. #else
  338. const CCTimeType maxThreshold=1000000;
  339. const CCTimeType minThreshold=100000;
  340. #endif
  341. if (RTT==UNSET_TIME_US)
  342. {
  343. return (CCTimeType) maxThreshold;
  344. }
  345. CCTimeType ret = lastRttOnIncreaseSendRate*2;
  346. if (ret<minThreshold)
  347. return minThreshold;
  348. if (ret>maxThreshold)
  349. return maxThreshold;
  350. return ret;
  351. }
  352. // ----------------------------------------------------------------------------------------------------------------------------
  353. void CCRakNetUDT::OnResend(CCTimeType curTime, RakNet::TimeUS nextActionTime)
  354. {
  355. (void) curTime;
  356. if (isInSlowStart)
  357. {
  358. if (AS!=UNDEFINED_TRANSFER_RATE)
  359. EndSlowStart();
  360. return;
  361. }
  362. if (hadPacketlossThisBlock==false)
  363. {
  364. // Logging
  365. // printf("Sending SLOWER due to Resend, Rate=%f MBPS. Rtt=%i\n", GetLocalSendRate(), lastRtt );
  366. IncreaseTimeBetweenSends();
  367. hadPacketlossThisBlock=true;
  368. }
  369. }
  370. // ----------------------------------------------------------------------------------------------------------------------------
  371. void CCRakNetUDT::OnNAK(CCTimeType curTime, DatagramSequenceNumberType nakSequenceNumber)
  372. {
  373. (void) nakSequenceNumber;
  374. (void) curTime;
  375. if (isInSlowStart)
  376. {
  377. if (AS!=UNDEFINED_TRANSFER_RATE)
  378. EndSlowStart();
  379. return;
  380. }
  381. if (hadPacketlossThisBlock==false)
  382. {
  383. // Logging
  384. //printf("Sending SLOWER due to NAK, Rate=%f MBPS. Rtt=%i\n", GetLocalSendRate(), lastRtt );
  385. if (pingsLastInterval.Size()>10)
  386. {
  387. for (int i=0; i < 10; i++)
  388. printf("%i, ", pingsLastInterval[pingsLastInterval.Size()-1-i]/1000);
  389. }
  390. printf("\n");
  391. IncreaseTimeBetweenSends();
  392. hadPacketlossThisBlock=true;
  393. }
  394. }
  395. // ----------------------------------------------------------------------------------------------------------------------------
  396. void CCRakNetUDT::EndSlowStart(void)
  397. {
  398. RakAssert(isInSlowStart==true);
  399. RakAssert(AS!=UNDEFINED_TRANSFER_RATE);
  400. // This overestimates
  401. estimatedLinkCapacityBytesPerSecond=AS * 1000000.0;
  402. isInSlowStart=false;
  403. SND=1.0/AS;
  404. CapMinSnd(_FILE_AND_LINE_);
  405. // printf("ENDING SLOW START\n");
  406. #if CC_TIME_TYPE_BYTES==4
  407. // printf("Initial SND=%f Kilobytes per second\n", 1.0/SND);
  408. #else
  409. // printf("Initial SND=%f Megabytes per second\n", 1.0/SND);
  410. #endif
  411. if (SND > .1)
  412. PrintLowBandwidthWarning();
  413. }
  414. // ----------------------------------------------------------------------------------------------------------------------------
  415. void CCRakNetUDT::OnGotPacketPair(DatagramSequenceNumberType datagramSequenceNumber, uint32_t sizeInBytes, CCTimeType curTime)
  416. {
  417. (void) datagramSequenceNumber;
  418. (void) sizeInBytes;
  419. (void) curTime;
  420. }
  421. // ----------------------------------------------------------------------------------------------------------------------------
  422. bool CCRakNetUDT::OnGotPacket(DatagramSequenceNumberType datagramSequenceNumber, bool isContinuousSend, CCTimeType curTime, uint32_t sizeInBytes, uint32_t *skippedMessageCount)
  423. {
  424. CC_DEBUG_PRINTF_2("R%i ",datagramSequenceNumber.val);
  425. if (datagramSequenceNumber==expectedNextSequenceNumber)
  426. {
  427. *skippedMessageCount=0;
  428. expectedNextSequenceNumber=datagramSequenceNumber+(DatagramSequenceNumberType)1;
  429. }
  430. else if (GreaterThan(datagramSequenceNumber, expectedNextSequenceNumber))
  431. {
  432. *skippedMessageCount=datagramSequenceNumber-expectedNextSequenceNumber;
  433. // Sanity check, just use timeout resend if this was really valid
  434. if (*skippedMessageCount>1000)
  435. {
  436. // During testing, the nat punchthrough server got 51200 on the first packet. I have no idea where this comes from, but has happened twice
  437. if (*skippedMessageCount>(uint32_t)50000)
  438. return false;
  439. *skippedMessageCount=1000;
  440. }
  441. expectedNextSequenceNumber=datagramSequenceNumber+(DatagramSequenceNumberType)1;
  442. }
  443. else
  444. {
  445. *skippedMessageCount=0;
  446. }
  447. if (curTime>lastPacketArrivalTime)
  448. {
  449. CCTimeType interval = curTime-lastPacketArrivalTime;
  450. // printf("Packet arrival gap is %I64u\n", (interval));
  451. if (isContinuousSend)
  452. {
  453. continuousBytesReceived+=sizeInBytes;
  454. if (continuousBytesReceivedStartTime==0)
  455. continuousBytesReceivedStartTime=lastPacketArrivalTime;
  456. mostRecentPacketArrivalHistory=(BytesPerMicrosecond)sizeInBytes/(BytesPerMicrosecond)interval;
  457. // if (mostRecentPacketArrivalHistory < (BytesPerMicrosecond)0.0035)
  458. // {
  459. // printf("%s:%i LIKELY BUG: Calculated packetArrivalHistory is below 28.8 Kbps modem\nReport to rakkar@jenkinssoftware.com with file and line number\n", _FILE_AND_LINE_);
  460. // }
  461. packetArrivalHistoryContinuousGaps[packetArrivalHistoryContinuousGapsIndex++]=(int) interval;
  462. packetArrivalHistoryContinuousGapsIndex&=(CC_RAKNET_UDT_PACKET_HISTORY_LENGTH-1);
  463. packetArrivalHistoryWriteCount++;
  464. packetArrivalHistory[packetArrivalHistoryWriteIndex++]=mostRecentPacketArrivalHistory;
  465. // Wrap to 0 at the end of the range
  466. // Assumes power of 2 for CC_RAKNET_UDT_PACKET_HISTORY_LENGTH
  467. packetArrivalHistoryWriteIndex&=(CC_RAKNET_UDT_PACKET_HISTORY_LENGTH-1);
  468. }
  469. else
  470. {
  471. continuousBytesReceivedStartTime=0;
  472. continuousBytesReceived=0;
  473. }
  474. lastPacketArrivalTime=curTime;
  475. }
  476. return true;
  477. }
  478. // ----------------------------------------------------------------------------------------------------------------------------
  479. void CCRakNetUDT::OnAck(CCTimeType curTime, CCTimeType rtt, bool hasBAndAS, BytesPerMicrosecond _B, BytesPerMicrosecond _AS, double totalUserDataBytesAcked, bool isContinuousSend, DatagramSequenceNumberType sequenceNumber )
  480. {
  481. #if CC_TIME_TYPE_BYTES==4
  482. RakAssert(rtt < 10000);
  483. #else
  484. RakAssert(rtt < 10000000);
  485. #endif
  486. (void) _B;
  487. if (hasBAndAS)
  488. {
  489. /// RakAssert(_B!=UNDEFINED_TRANSFER_RATE && _AS!=UNDEFINED_TRANSFER_RATE);
  490. // B=B * .875 + _B * .125;
  491. // AS is packet arrival rate
  492. RakAssert(_AS!=UNDEFINED_TRANSFER_RATE);
  493. AS=_AS;
  494. CC_DEBUG_PRINTF_4("ArrivalRate=%f linkCap=%f incomingLinkCap=%f\n", _AS,B,_B);
  495. }
  496. if (oldestUnsentAck==0)
  497. oldestUnsentAck=curTime;
  498. if (isInSlowStart==true)
  499. {
  500. nextCongestionControlBlock=nextDatagramSequenceNumber;
  501. lastRttOnIncreaseSendRate=rtt;
  502. UpdateWindowSizeAndAckOnAckPreSlowStart(totalUserDataBytesAcked);
  503. }
  504. else
  505. {
  506. UpdateWindowSizeAndAckOnAckPerSyn(curTime, rtt, isContinuousSend, sequenceNumber);
  507. }
  508. lastUpdateWindowSizeAndAck=curTime;
  509. }
  510. // ----------------------------------------------------------------------------------------------------------------------------
  511. void CCRakNetUDT::OnSendAckGetBAndAS(CCTimeType curTime, bool *hasBAndAS, BytesPerMicrosecond *_B, BytesPerMicrosecond *_AS)
  512. {
  513. if (curTime>lastTransmitOfBAndAS+SYN)
  514. {
  515. *_B=0;
  516. *_AS=ReceiverCalculateDataArrivalRate(curTime);
  517. if (*_AS==UNDEFINED_TRANSFER_RATE)
  518. {
  519. *hasBAndAS=false;
  520. }
  521. else
  522. {
  523. *hasBAndAS=true;
  524. }
  525. }
  526. else
  527. {
  528. *hasBAndAS=false;
  529. }
  530. }
  531. // ----------------------------------------------------------------------------------------------------------------------------
  532. void CCRakNetUDT::OnSendAck(CCTimeType curTime, uint32_t numBytes)
  533. {
  534. (void) numBytes;
  535. (void) curTime;
  536. // This is not accounted for on the remote system, and thus causes bandwidth to be underutilized
  537. //UpdateNextAllowedSend(curTime, numBytes+UDP_HEADER_SIZE);
  538. oldestUnsentAck=0;
  539. }
  540. // ----------------------------------------------------------------------------------------------------------------------------
  541. void CCRakNetUDT::OnSendNACK(CCTimeType curTime, uint32_t numBytes)
  542. {
  543. (void) numBytes;
  544. (void) curTime;
  545. // This is not accounted for on the remote system, and thus causes bandwidth to be underutilized
  546. // UpdateNextAllowedSend(curTime, numBytes+UDP_HEADER_SIZE);
  547. }
  548. // ----------------------------------------------------------------------------------------------------------------------------
  549. void CCRakNetUDT::UpdateWindowSizeAndAckOnAckPreSlowStart(double totalUserDataBytesAcked)
  550. {
  551. // During slow start, max window size is the number of full packets that have been sent out
  552. // CWND=(double) ((double)totalUserDataBytesSent/(double)MAXIMUM_MTU_INCLUDING_UDP_HEADER);
  553. CC_DEBUG_PRINTF_3("CWND increasing from %f to %f\n", CWND, (double) ((double)totalUserDataBytesAcked/(double)MAXIMUM_MTU_INCLUDING_UDP_HEADER));
  554. CWND=(double) ((double)totalUserDataBytesAcked/(double)MAXIMUM_MTU_INCLUDING_UDP_HEADER);
  555. if (CWND>=CWND_MAX_THRESHOLD)
  556. {
  557. CWND=CWND_MAX_THRESHOLD;
  558. if (AS!=UNDEFINED_TRANSFER_RATE)
  559. EndSlowStart();
  560. }
  561. if (CWND<CWND_MIN_THRESHOLD)
  562. CWND=CWND_MIN_THRESHOLD;
  563. }
  564. // ----------------------------------------------------------------------------------------------------------------------------
  565. void CCRakNetUDT::UpdateWindowSizeAndAckOnAckPerSyn(CCTimeType curTime, CCTimeType rtt, bool isContinuousSend, DatagramSequenceNumberType sequenceNumber)
  566. {
  567. (void) curTime;
  568. (void) sequenceNumber;
  569. if (isContinuousSend==false)
  570. {
  571. nextCongestionControlBlock=nextDatagramSequenceNumber;
  572. pingsLastInterval.Clear(__FILE__,__LINE__);
  573. return;
  574. }
  575. pingsLastInterval.Push(rtt,__FILE__,__LINE__);
  576. static const int intervalSize=33; // Should be odd
  577. if (pingsLastInterval.Size()>intervalSize)
  578. pingsLastInterval.Pop();
  579. if (GreaterThan(sequenceNumber, nextCongestionControlBlock) &&
  580. sequenceNumber-nextCongestionControlBlock>=intervalSize &&
  581. pingsLastInterval.Size()==intervalSize)
  582. {
  583. double slopeSum=0.0;
  584. double average=(double) pingsLastInterval[0];
  585. int sampleSize=pingsLastInterval.Size();
  586. for (int i=1; i < sampleSize; i++)
  587. {
  588. slopeSum+=(double)pingsLastInterval[i]-(double)pingsLastInterval[i-1];
  589. average+=pingsLastInterval[i];
  590. }
  591. average/=sampleSize;
  592. if (hadPacketlossThisBlock==true)
  593. {
  594. }
  595. else if (slopeSum < -.10*average)
  596. {
  597. // Logging
  598. //printf("Ping dropping. slope=%f%%. Rate=%f MBPS. Rtt=%i\n", 100.0*slopeSum/average, GetLocalSendRate(), rtt );
  599. }
  600. else if (slopeSum > .10*average)
  601. {
  602. // Logging
  603. //printf("Ping rising. slope=%f%%. Rate=%f MBPS. Rtt=%i\n", 100.0*slopeSum/average, GetLocalSendRate(), rtt );
  604. IncreaseTimeBetweenSends();
  605. }
  606. else
  607. {
  608. // Logging
  609. //printf("Ping stable. slope=%f%%. Rate=%f MBPS. Rtt=%i\n", 100.0*slopeSum/average, GetLocalSendRate(), rtt );
  610. // No packetloss over time threshhold, and rtt decreased, so send faster
  611. lastRttOnIncreaseSendRate=rtt;
  612. DecreaseTimeBetweenSends();
  613. }
  614. pingsLastInterval.Clear(__FILE__,__LINE__);
  615. hadPacketlossThisBlock=false;
  616. nextCongestionControlBlock=nextDatagramSequenceNumber;
  617. }
  618. lastRtt=rtt;
  619. }
  620. // ----------------------------------------------------------------------------------------------------------------------------
  621. double CCRakNetUDT::BytesPerMicrosecondToPacketsPerMillisecond(BytesPerMicrosecond in)
  622. {
  623. #if CC_TIME_TYPE_BYTES==4
  624. const BytesPerMicrosecond factor = 1.0 / (BytesPerMicrosecond) MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  625. #else
  626. const BytesPerMicrosecond factor = 1000.0 / (BytesPerMicrosecond) MAXIMUM_MTU_INCLUDING_UDP_HEADER;
  627. #endif
  628. return in * factor;
  629. }
  630. // ----------------------------------------------------------------------------------------------------------------------------
  631. void CCRakNetUDT::InitPacketArrivalHistory(void)
  632. {
  633. unsigned int i;
  634. for (i=0; i < CC_RAKNET_UDT_PACKET_HISTORY_LENGTH; i++)
  635. {
  636. packetArrivalHistory[i]=UNDEFINED_TRANSFER_RATE;
  637. packetArrivalHistoryContinuousGaps[i]=0;
  638. }
  639. packetArrivalHistoryWriteCount=0;
  640. continuousBytesReceived=0;
  641. continuousBytesReceivedStartTime=0;
  642. }
  643. // ----------------------------------------------------------------------------------------------------------------------------
  644. void CCRakNetUDT::PrintLowBandwidthWarning(void)
  645. {
  646. /*
  647. printf("\n-------LOW BANDWIDTH -----\n");
  648. if (isInSlowStart==false)
  649. printf("SND=%f Megabytes per second\n", 1.0/SND);
  650. printf("Window size=%f\n", CWND);
  651. printf("Pipe from packet pair = %f megabytes per second\n", B);
  652. printf("RTT=%f milliseconds\n", RTT/1000.0);
  653. printf("RTT Variance=%f milliseconds\n", RTTVar/1000.0);
  654. printf("Retransmission=%i milliseconds\n", GetRTOForRetransmission(1)/1000);
  655. printf("Packet arrival rate on the remote system=%f megabytes per second\n", AS);
  656. printf("Packet arrival rate on our system=%f megabytes per second\n", ReceiverCalculateDataArrivalRate());
  657. printf("isInSlowStart=%i\n", isInSlowStart);
  658. printf("---------------\n");
  659. */
  660. }
  661. BytesPerMicrosecond CCRakNetUDT::GetLocalReceiveRate(CCTimeType currentTime) const
  662. {
  663. return ReceiverCalculateDataArrivalRate(currentTime);
  664. }
  665. double CCRakNetUDT::GetRTT(void) const
  666. {
  667. if (RTT==UNSET_TIME_US)
  668. return 0.0;
  669. return RTT;
  670. }
  671. void CCRakNetUDT::CapMinSnd(const char *file, int line)
  672. {
  673. (void) file;
  674. (void) line;
  675. if (SND > 500)
  676. {
  677. SND=500;
  678. CC_DEBUG_PRINTF_3("%s:%i LIKELY BUG: SND has gotten above 500 microseconds between messages (28.8 modem)\nReport to rakkar@jenkinssoftware.com with file and line number\n", file, line);
  679. }
  680. }
  681. void CCRakNetUDT::IncreaseTimeBetweenSends(void)
  682. {
  683. // In order to converge, bigger numbers have to increase slower and decrease faster
  684. // SND==500 then increment is .02
  685. // SND==0 then increment is near 0
  686. // (SND+1.0) brings it to the range of 1 to 501
  687. // Square the number, which is the range of 1 to 251001
  688. // Divide by 251001, which is the range of 1/251001 to 1
  689. double increment;
  690. increment = .02 * ((SND+1.0) * (SND+1.0)) / (501.0*501.0) ;
  691. // SND=500 then increment=.02
  692. // SND=0 then increment=near 0
  693. SND*=(1.02 - increment);
  694. // SND=0 then fast increase, slow decrease
  695. // SND=500 then slow increase, fast decrease
  696. CapMinSnd(__FILE__,__LINE__);
  697. }
  698. void CCRakNetUDT::DecreaseTimeBetweenSends(void)
  699. {
  700. double increment;
  701. increment = .01 * ((SND+1.0) * (SND+1.0)) / (501.0*501.0) ;
  702. // SND=500 then increment=.01
  703. // SND=0 then increment=near 0
  704. SND*=(.99 - increment);
  705. }
  706. /*
  707. void CCRakNetUDT::SetTimeBetweenSendsLimit(unsigned int bitsPerSecond)
  708. {
  709. // bitsPerSecond / 1000000 = bitsPerMicrosecond
  710. // bitsPerMicrosecond / 8 = BytesPerMicrosecond
  711. // 1 / BytesPerMicrosecond = MicrosecondsPerByte
  712. // 1 / ( (bitsPerSecond / 1000000) / 8 ) =
  713. // 1 / (bitsPerSecond / 8000000) =
  714. // 8000000 / bitsPerSecond
  715. #if CC_TIME_TYPE_BYTES==4
  716. MicrosecondsPerByte limit = (MicrosecondsPerByte) 8000 / (MicrosecondsPerByte)bitsPerSecond;
  717. #else
  718. MicrosecondsPerByte limit = (MicrosecondsPerByte) 8000000 / (MicrosecondsPerByte)bitsPerSecond;
  719. #endif
  720. if (limit > SND)
  721. SND=limit;
  722. }
  723. */
  724. #endif
粤ICP备19079148号