MsgChannel.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "MsgChannel.h"
  23. /*
  24. packet header
  25. -------------
  26. 2 bytes id
  27. 4 bytes outgoing sequence. high bit will be set if this is a fragmented message.
  28. 2 bytes optional fragment start byte if fragment bit is set.
  29. 2 bytes optional fragment length if fragment bit is set. if < FRAGMENT_SIZE, this is the last fragment.
  30. If the id is -1, the packet should be handled as an out-of-band
  31. message instead of as part of the message channel.
  32. All fragments will have the same sequence numbers.
  33. */
  34. #define MAX_PACKETLEN 1400 // max size of a network packet
  35. #define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
  36. #define FRAGMENT_BIT (1<<31)
  37. idCVar net_channelShowPackets( "net_channelShowPackets", "0", CVAR_SYSTEM | CVAR_BOOL, "show all packets" );
  38. idCVar net_channelShowDrop( "net_channelShowDrop", "0", CVAR_SYSTEM | CVAR_BOOL, "show dropped packets" );
  39. /*
  40. ===============
  41. idMsgQueue::idMsgQueue
  42. ===============
  43. */
  44. idMsgQueue::idMsgQueue( void ) {
  45. Init( 0 );
  46. }
  47. /*
  48. ===============
  49. idMsgQueue::Init
  50. ===============
  51. */
  52. void idMsgQueue::Init( int sequence ) {
  53. first = last = sequence;
  54. startIndex = endIndex = 0;
  55. }
  56. /*
  57. ===============
  58. idMsgQueue::Add
  59. ===============
  60. */
  61. bool idMsgQueue::Add( const byte *data, const int size ) {
  62. if ( GetSpaceLeft() < size + 8 ) {
  63. return false;
  64. }
  65. int sequence = last;
  66. WriteShort( size );
  67. WriteLong( sequence );
  68. WriteData( data, size );
  69. last++;
  70. return true;
  71. }
  72. /*
  73. ===============
  74. idMsgQueue::Get
  75. ===============
  76. */
  77. bool idMsgQueue::Get( byte *data, int &size ) {
  78. if ( first == last ) {
  79. size = 0;
  80. return false;
  81. }
  82. int sequence;
  83. size = ReadShort();
  84. sequence = ReadLong();
  85. ReadData( data, size );
  86. assert( sequence == first );
  87. first++;
  88. return true;
  89. }
  90. /*
  91. ===============
  92. idMsgQueue::GetTotalSize
  93. ===============
  94. */
  95. int idMsgQueue::GetTotalSize( void ) const {
  96. if ( startIndex <= endIndex ) {
  97. return ( endIndex - startIndex );
  98. } else {
  99. return ( sizeof( buffer ) - startIndex + endIndex );
  100. }
  101. }
  102. /*
  103. ===============
  104. idMsgQueue::GetSpaceLeft
  105. ===============
  106. */
  107. int idMsgQueue::GetSpaceLeft( void ) const {
  108. if ( startIndex <= endIndex ) {
  109. return sizeof( buffer ) - ( endIndex - startIndex ) - 1;
  110. } else {
  111. return ( startIndex - endIndex ) - 1;
  112. }
  113. }
  114. /*
  115. ===============
  116. idMsgQueue::CopyToBuffer
  117. ===============
  118. */
  119. void idMsgQueue::CopyToBuffer( byte *buf ) const {
  120. if ( startIndex <= endIndex ) {
  121. memcpy( buf, buffer + startIndex, endIndex - startIndex );
  122. } else {
  123. memcpy( buf, buffer + startIndex, sizeof( buffer ) - startIndex );
  124. memcpy( buf + sizeof( buffer ) - startIndex, buffer, endIndex );
  125. }
  126. }
  127. /*
  128. ===============
  129. idMsgQueue::WriteByte
  130. ===============
  131. */
  132. void idMsgQueue::WriteByte( byte b ) {
  133. buffer[endIndex] = b;
  134. endIndex = ( endIndex + 1 ) & ( MAX_MSG_QUEUE_SIZE - 1 );
  135. }
  136. /*
  137. ===============
  138. idMsgQueue::ReadByte
  139. ===============
  140. */
  141. byte idMsgQueue::ReadByte( void ) {
  142. byte b = buffer[startIndex];
  143. startIndex = ( startIndex + 1 ) & ( MAX_MSG_QUEUE_SIZE - 1 );
  144. return b;
  145. }
  146. /*
  147. ===============
  148. idMsgQueue::WriteShort
  149. ===============
  150. */
  151. void idMsgQueue::WriteShort( int s ) {
  152. WriteByte( ( s >> 0 ) & 255 );
  153. WriteByte( ( s >> 8 ) & 255 );
  154. }
  155. /*
  156. ===============
  157. idMsgQueue::ReadShort
  158. ===============
  159. */
  160. int idMsgQueue::ReadShort( void ) {
  161. return ReadByte() | ( ReadByte() << 8 );
  162. }
  163. /*
  164. ===============
  165. idMsgQueue::WriteLong
  166. ===============
  167. */
  168. void idMsgQueue::WriteLong( int l ) {
  169. WriteByte( ( l >> 0 ) & 255 );
  170. WriteByte( ( l >> 8 ) & 255 );
  171. WriteByte( ( l >> 16 ) & 255 );
  172. WriteByte( ( l >> 24 ) & 255 );
  173. }
  174. /*
  175. ===============
  176. idMsgQueue::ReadLong
  177. ===============
  178. */
  179. int idMsgQueue::ReadLong( void ) {
  180. return ReadByte() | ( ReadByte() << 8 ) | ( ReadByte() << 16 ) | ( ReadByte() << 24 );
  181. }
  182. /*
  183. ===============
  184. idMsgQueue::WriteData
  185. ===============
  186. */
  187. void idMsgQueue::WriteData( const byte *data, const int size ) {
  188. for ( int i = 0; i < size; i++ ) {
  189. WriteByte( data[i] );
  190. }
  191. }
  192. /*
  193. ===============
  194. idMsgQueue::ReadData
  195. ===============
  196. */
  197. void idMsgQueue::ReadData( byte *data, const int size ) {
  198. if ( data ) {
  199. for ( int i = 0; i < size; i++ ) {
  200. data[i] = ReadByte();
  201. }
  202. } else {
  203. for ( int i = 0; i < size; i++ ) {
  204. ReadByte();
  205. }
  206. }
  207. }
  208. /*
  209. ===============
  210. idMsgChannel::idMsgChannel
  211. ===============
  212. */
  213. idMsgChannel::idMsgChannel() {
  214. id = -1;
  215. }
  216. /*
  217. ==============
  218. idMsgChannel::Init
  219. Opens a channel to a remote system.
  220. ==============
  221. */
  222. void idMsgChannel::Init( const netadr_t adr, const int id ) {
  223. this->remoteAddress = adr;
  224. this->id = id;
  225. this->maxRate = 50000;
  226. this->compressor = idCompressor::AllocRunLength_ZeroBased();
  227. lastSendTime = 0;
  228. lastDataBytes = 0;
  229. outgoingRateTime = 0;
  230. outgoingRateBytes = 0;
  231. incomingRateTime = 0;
  232. incomingRateBytes = 0;
  233. incomingReceivedPackets = 0.0f;
  234. incomingDroppedPackets = 0.0f;
  235. incomingPacketLossTime = 0;
  236. outgoingCompression = 0.0f;
  237. incomingCompression = 0.0f;
  238. outgoingSequence = 1;
  239. incomingSequence = 0;
  240. unsentFragments = false;
  241. unsentFragmentStart = 0;
  242. fragmentSequence = 0;
  243. fragmentLength = 0;
  244. reliableSend.Init( 1 );
  245. reliableReceive.Init( 0 );
  246. }
  247. /*
  248. ===============
  249. idMsgChannel::Shutdown
  250. ================
  251. */
  252. void idMsgChannel::Shutdown( void ) {
  253. delete compressor;
  254. compressor = NULL;
  255. }
  256. /*
  257. =================
  258. idMsgChannel::ResetRate
  259. =================
  260. */
  261. void idMsgChannel::ResetRate( void ) {
  262. lastSendTime = 0;
  263. lastDataBytes = 0;
  264. outgoingRateTime = 0;
  265. outgoingRateBytes = 0;
  266. incomingRateTime = 0;
  267. incomingRateBytes = 0;
  268. }
  269. /*
  270. =================
  271. idMsgChannel::ReadyToSend
  272. =================
  273. */
  274. bool idMsgChannel::ReadyToSend( const int time ) const {
  275. int deltaTime;
  276. if ( !maxRate ) {
  277. return true;
  278. }
  279. deltaTime = time - lastSendTime;
  280. if ( deltaTime > 1000 ) {
  281. return true;
  282. }
  283. return ( ( lastDataBytes - ( deltaTime * maxRate ) / 1000 ) <= 0 );
  284. }
  285. /*
  286. ===============
  287. idMsgChannel::WriteMessageData
  288. ================
  289. */
  290. void idMsgChannel::WriteMessageData( idBitMsg &out, const idBitMsg &msg ) {
  291. idBitMsg tmp;
  292. byte tmpBuf[MAX_MESSAGE_SIZE];
  293. tmp.Init( tmpBuf, sizeof( tmpBuf ) );
  294. // write acknowledgement of last received reliable message
  295. tmp.WriteLong( reliableReceive.GetLast() );
  296. // write reliable messages
  297. reliableSend.CopyToBuffer( tmp.GetData() + tmp.GetSize() );
  298. tmp.SetSize( tmp.GetSize() + reliableSend.GetTotalSize() );
  299. tmp.WriteShort( 0 );
  300. // write data
  301. tmp.WriteData( msg.GetData(), msg.GetSize() );
  302. // write message size
  303. out.WriteShort( tmp.GetSize() );
  304. // compress message
  305. idFile_BitMsg file( out );
  306. compressor->Init( &file, true, 3 );
  307. compressor->Write( tmp.GetData(), tmp.GetSize() );
  308. compressor->FinishCompress();
  309. outgoingCompression = compressor->GetCompressionRatio();
  310. }
  311. /*
  312. ===============
  313. idMsgChannel::ReadMessageData
  314. ================
  315. */
  316. bool idMsgChannel::ReadMessageData( idBitMsg &out, const idBitMsg &msg ) {
  317. int reliableAcknowledge, reliableMessageSize, reliableSequence;
  318. // read message size
  319. out.SetSize( msg.ReadShort() );
  320. // decompress message
  321. idFile_BitMsg file( msg );
  322. compressor->Init( &file, false, 3 );
  323. compressor->Read( out.GetData(), out.GetSize() );
  324. incomingCompression = compressor->GetCompressionRatio();
  325. out.BeginReading();
  326. // read acknowledgement of sent reliable messages
  327. reliableAcknowledge = out.ReadLong();
  328. // remove acknowledged reliable messages
  329. while( reliableSend.GetFirst() <= reliableAcknowledge ) {
  330. if ( !reliableSend.Get( NULL, reliableMessageSize ) ) {
  331. break;
  332. }
  333. }
  334. // read reliable messages
  335. reliableMessageSize = out.ReadShort();
  336. while( reliableMessageSize != 0 ) {
  337. if ( reliableMessageSize <= 0 || reliableMessageSize > out.GetSize() - out.GetReadCount() ) {
  338. common->Printf( "%s: bad reliable message\n", Sys_NetAdrToString( remoteAddress ) );
  339. return false;
  340. }
  341. reliableSequence = out.ReadLong();
  342. if ( reliableSequence == reliableReceive.GetLast() + 1 ) {
  343. reliableReceive.Add( out.GetData() + out.GetReadCount(), reliableMessageSize );
  344. }
  345. out.ReadData( NULL, reliableMessageSize );
  346. reliableMessageSize = out.ReadShort();
  347. }
  348. return true;
  349. }
  350. /*
  351. =================
  352. idMsgChannel::SendNextFragment
  353. Sends one fragment of the current message.
  354. =================
  355. */
  356. void idMsgChannel::SendNextFragment( idPort &port, const int time ) {
  357. idBitMsg msg;
  358. byte msgBuf[MAX_PACKETLEN];
  359. int fragLength;
  360. if ( remoteAddress.type == NA_BAD ) {
  361. return;
  362. }
  363. if ( !unsentFragments ) {
  364. return;
  365. }
  366. // write the packet
  367. msg.Init( msgBuf, sizeof( msgBuf ) );
  368. msg.WriteShort( id );
  369. msg.WriteLong( outgoingSequence | FRAGMENT_BIT );
  370. fragLength = FRAGMENT_SIZE;
  371. if ( unsentFragmentStart + fragLength > unsentMsg.GetSize() ) {
  372. fragLength = unsentMsg.GetSize() - unsentFragmentStart;
  373. }
  374. msg.WriteShort( unsentFragmentStart );
  375. msg.WriteShort( fragLength );
  376. msg.WriteData( unsentMsg.GetData() + unsentFragmentStart, fragLength );
  377. // send the packet
  378. port.SendPacket( remoteAddress, msg.GetData(), msg.GetSize() );
  379. // update rate control variables
  380. UpdateOutgoingRate( time, msg.GetSize() );
  381. if ( net_channelShowPackets.GetBool() ) {
  382. common->Printf( "%d send %4i : s = %i fragment = %i,%i\n", id, msg.GetSize(), outgoingSequence - 1, unsentFragmentStart, fragLength );
  383. }
  384. unsentFragmentStart += fragLength;
  385. // this exit condition is a little tricky, because a packet
  386. // that is exactly the fragment length still needs to send
  387. // a second packet of zero length so that the other side
  388. // can tell there aren't more to follow
  389. if ( unsentFragmentStart == unsentMsg.GetSize() && fragLength != FRAGMENT_SIZE ) {
  390. outgoingSequence++;
  391. unsentFragments = false;
  392. }
  393. }
  394. /*
  395. ===============
  396. idMsgChannel::SendMessage
  397. Sends a message to a connection, fragmenting if necessary
  398. A 0 length will still generate a packet.
  399. ================
  400. */
  401. int idMsgChannel::SendMessage( idPort &port, const int time, const idBitMsg &msg ) {
  402. int totalLength;
  403. if ( remoteAddress.type == NA_BAD ) {
  404. return -1;
  405. }
  406. if ( unsentFragments ) {
  407. common->Error( "idMsgChannel::SendMessage: called with unsent fragments left" );
  408. return -1;
  409. }
  410. totalLength = 4 + reliableSend.GetTotalSize() + 4 + msg.GetSize();
  411. if ( totalLength > MAX_MESSAGE_SIZE ) {
  412. common->Printf( "idMsgChannel::SendMessage: message too large, length = %i\n", totalLength );
  413. return -1;
  414. }
  415. unsentMsg.Init( unsentBuffer, sizeof( unsentBuffer ) );
  416. unsentMsg.BeginWriting();
  417. // fragment large messages
  418. if ( totalLength >= FRAGMENT_SIZE ) {
  419. unsentFragments = true;
  420. unsentFragmentStart = 0;
  421. // write out the message data
  422. WriteMessageData( unsentMsg, msg );
  423. // send the first fragment now
  424. SendNextFragment( port, time );
  425. return outgoingSequence;
  426. }
  427. // write the header
  428. unsentMsg.WriteShort( id );
  429. unsentMsg.WriteLong( outgoingSequence );
  430. // write out the message data
  431. WriteMessageData( unsentMsg, msg );
  432. // send the packet
  433. port.SendPacket( remoteAddress, unsentMsg.GetData(), unsentMsg.GetSize() );
  434. // update rate control variables
  435. UpdateOutgoingRate( time, unsentMsg.GetSize() );
  436. if ( net_channelShowPackets.GetBool() ) {
  437. common->Printf( "%d send %4i : s = %i ack = %i\n", id, unsentMsg.GetSize(), outgoingSequence - 1, incomingSequence );
  438. }
  439. outgoingSequence++;
  440. return ( outgoingSequence - 1 );
  441. }
  442. /*
  443. =================
  444. idMsgChannel::Process
  445. Returns false if the message should not be processed due to being out of order or a fragment.
  446. msg must be large enough to hold MAX_MESSAGE_SIZE, because if this is the final
  447. fragment of a multi-part message, the entire thing will be copied out.
  448. =================
  449. */
  450. bool idMsgChannel::Process( const netadr_t from, int time, idBitMsg &msg, int &sequence ) {
  451. int fragStart, fragLength, dropped;
  452. bool fragmented;
  453. idBitMsg fragMsg;
  454. // the IP port can't be used to differentiate them, because
  455. // some address translating routers periodically change UDP
  456. // port assignments
  457. if ( remoteAddress.port != from.port ) {
  458. common->Printf( "idMsgChannel::Process: fixing up a translated port\n" );
  459. remoteAddress.port = from.port;
  460. }
  461. // update incoming rate
  462. UpdateIncomingRate( time, msg.GetSize() );
  463. // get sequence numbers
  464. sequence = msg.ReadLong();
  465. // check for fragment information
  466. if ( sequence & FRAGMENT_BIT ) {
  467. sequence &= ~FRAGMENT_BIT;
  468. fragmented = true;
  469. } else {
  470. fragmented = false;
  471. }
  472. // read the fragment information
  473. if ( fragmented ) {
  474. fragStart = msg.ReadShort();
  475. fragLength = msg.ReadShort();
  476. } else {
  477. fragStart = 0; // stop warning message
  478. fragLength = 0;
  479. }
  480. if ( net_channelShowPackets.GetBool() ) {
  481. if ( fragmented ) {
  482. common->Printf( "%d recv %4i : s = %i fragment = %i,%i\n", id, msg.GetSize(), sequence, fragStart, fragLength );
  483. } else {
  484. common->Printf( "%d recv %4i : s = %i\n", id, msg.GetSize(), sequence );
  485. }
  486. }
  487. //
  488. // discard out of order or duplicated packets
  489. //
  490. if ( sequence <= incomingSequence ) {
  491. if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
  492. common->Printf( "%s: out of order packet %i at %i\n", Sys_NetAdrToString( remoteAddress ), sequence, incomingSequence );
  493. }
  494. return false;
  495. }
  496. //
  497. // dropped packets don't keep this message from being used
  498. //
  499. dropped = sequence - (incomingSequence+1);
  500. if ( dropped > 0 ) {
  501. if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
  502. common->Printf( "%s: dropped %i packets at %i\n", Sys_NetAdrToString( remoteAddress ), dropped, sequence );
  503. }
  504. UpdatePacketLoss( time, 0, dropped );
  505. }
  506. //
  507. // if the message is fragmented
  508. //
  509. if ( fragmented ) {
  510. // make sure we have the correct sequence number
  511. if ( sequence != fragmentSequence ) {
  512. fragmentSequence = sequence;
  513. fragmentLength = 0;
  514. }
  515. // if we missed a fragment, dump the message
  516. if ( fragStart != fragmentLength ) {
  517. if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
  518. common->Printf( "%s: dropped a message fragment at seq %d\n", Sys_NetAdrToString( remoteAddress ), sequence );
  519. }
  520. // we can still keep the part that we have so far,
  521. // so we don't need to clear fragmentLength
  522. UpdatePacketLoss( time, 0, 1 );
  523. return false;
  524. }
  525. // copy the fragment to the fragment buffer
  526. if ( fragLength < 0 || fragLength > msg.GetRemaingData() || fragmentLength + fragLength > sizeof( fragmentBuffer ) ) {
  527. if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
  528. common->Printf( "%s: illegal fragment length\n", Sys_NetAdrToString( remoteAddress ) );
  529. }
  530. UpdatePacketLoss( time, 0, 1 );
  531. return false;
  532. }
  533. memcpy( fragmentBuffer + fragmentLength, msg.GetData() + msg.GetReadCount(), fragLength );
  534. fragmentLength += fragLength;
  535. UpdatePacketLoss( time, 1, 0 );
  536. // if this wasn't the last fragment, don't process anything
  537. if ( fragLength == FRAGMENT_SIZE ) {
  538. return false;
  539. }
  540. } else {
  541. memcpy( fragmentBuffer, msg.GetData() + msg.GetReadCount(), msg.GetRemaingData() );
  542. fragmentLength = msg.GetRemaingData();
  543. UpdatePacketLoss( time, 1, 0 );
  544. }
  545. fragMsg.Init( fragmentBuffer, fragmentLength );
  546. fragMsg.SetSize( fragmentLength );
  547. fragMsg.BeginReading();
  548. incomingSequence = sequence;
  549. // read the message data
  550. if ( !ReadMessageData( msg, fragMsg ) ) {
  551. return false;
  552. }
  553. return true;
  554. }
  555. /*
  556. =================
  557. idMsgChannel::SendReliableMessage
  558. =================
  559. */
  560. bool idMsgChannel::SendReliableMessage( const idBitMsg &msg ) {
  561. bool result;
  562. assert( remoteAddress.type != NA_BAD );
  563. if ( remoteAddress.type == NA_BAD ) {
  564. return false;
  565. }
  566. result = reliableSend.Add( msg.GetData(), msg.GetSize() );
  567. if ( !result ) {
  568. common->Warning( "idMsgChannel::SendReliableMessage: overflowed" );
  569. return false;
  570. }
  571. return result;
  572. }
  573. /*
  574. =================
  575. idMsgChannel::GetReliableMessage
  576. =================
  577. */
  578. bool idMsgChannel::GetReliableMessage( idBitMsg &msg ) {
  579. int size;
  580. bool result;
  581. result = reliableReceive.Get( msg.GetData(), size );
  582. msg.SetSize( size );
  583. msg.BeginReading();
  584. return result;
  585. }
  586. /*
  587. ===============
  588. idMsgChannel::ClearReliableMessages
  589. ================
  590. */
  591. void idMsgChannel::ClearReliableMessages( void ) {
  592. reliableSend.Init( 1 );
  593. reliableReceive.Init( 0 );
  594. }
  595. /*
  596. =================
  597. idMsgChannel::UpdateOutgoingRate
  598. =================
  599. */
  600. void idMsgChannel::UpdateOutgoingRate( const int time, const int size ) {
  601. // update the outgoing rate control variables
  602. int deltaTime = time - lastSendTime;
  603. if ( deltaTime > 1000 ) {
  604. lastDataBytes = 0;
  605. } else {
  606. lastDataBytes -= ( deltaTime * maxRate ) / 1000;
  607. if ( lastDataBytes < 0 ) {
  608. lastDataBytes = 0;
  609. }
  610. }
  611. lastDataBytes += size;
  612. lastSendTime = time;
  613. // update outgoing rate variables
  614. if ( time - outgoingRateTime > 1000 ) {
  615. outgoingRateBytes -= outgoingRateBytes * ( time - outgoingRateTime - 1000 ) / 1000;
  616. if ( outgoingRateBytes < 0 ) {
  617. outgoingRateBytes = 0;
  618. }
  619. }
  620. outgoingRateTime = time - 1000;
  621. outgoingRateBytes += size;
  622. }
  623. /*
  624. =================
  625. idMsgChannel::UpdateIncomingRate
  626. =================
  627. */
  628. void idMsgChannel::UpdateIncomingRate( const int time, const int size ) {
  629. // update incoming rate variables
  630. if ( time - incomingRateTime > 1000 ) {
  631. incomingRateBytes -= incomingRateBytes * ( time - incomingRateTime - 1000 ) / 1000;
  632. if ( incomingRateBytes < 0 ) {
  633. incomingRateBytes = 0;
  634. }
  635. }
  636. incomingRateTime = time - 1000;
  637. incomingRateBytes += size;
  638. }
  639. /*
  640. =================
  641. idMsgChannel::UpdatePacketLoss
  642. =================
  643. */
  644. void idMsgChannel::UpdatePacketLoss( const int time, const int numReceived, const int numDropped ) {
  645. // update incoming packet loss variables
  646. if ( time - incomingPacketLossTime > 5000 ) {
  647. float scale = ( time - incomingPacketLossTime - 5000 ) * ( 1.0f / 5000.0f );
  648. incomingReceivedPackets -= incomingReceivedPackets * scale;
  649. if ( incomingReceivedPackets < 0.0f ) {
  650. incomingReceivedPackets = 0.0f;
  651. }
  652. incomingDroppedPackets -= incomingDroppedPackets * scale;
  653. if ( incomingDroppedPackets < 0.0f ) {
  654. incomingDroppedPackets = 0.0f;
  655. }
  656. }
  657. incomingPacketLossTime = time - 5000;
  658. incomingReceivedPackets += numReceived;
  659. incomingDroppedPackets += numDropped;
  660. }
  661. /*
  662. =================
  663. idMsgChannel::GetIncomingPacketLoss
  664. =================
  665. */
  666. float idMsgChannel::GetIncomingPacketLoss( void ) const {
  667. if ( incomingReceivedPackets == 0.0f && incomingDroppedPackets == 0.0f ) {
  668. return 0.0f;
  669. }
  670. return incomingDroppedPackets * 100.0f / ( incomingReceivedPackets + incomingDroppedPackets );
  671. }