Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3232 lines
79 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: net_chan.cpp: implementation of the CNetChan_t struct.
  4. //
  5. //=============================================================================//
  6. #include "../utils/bzip2/bzlib.h"
  7. #include "net_chan.h"
  8. #include "tier1/strtools.h"
  9. #include "filesystem_engine.h"
  10. #include "demo.h"
  11. #include "convar.h"
  12. #include "mathlib/mathlib.h"
  13. #include "protocol.h"
  14. #include "inetmsghandler.h"
  15. #include "host.h"
  16. #include "netmessages.h"
  17. #include "tier0/vcrmode.h"
  18. #include "tier0/etwprof.h"
  19. #include "tier0/vprof.h"
  20. #include "net_ws_headers.h"
  21. #include "net_ws_queued_packet_sender.h"
  22. #include "filesystem_init.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. //////////////////////////////////////////////////////////////////////
  26. // Construction/Destruction
  27. //////////////////////////////////////////////////////////////////////
  28. ConVar net_showudp( "net_showudp", "0", 0, "Dump UDP packets summary to console" );
  29. ConVar net_showtcp( "net_showtcp", "0", 0, "Dump TCP stream summary to console" );
  30. ConVar net_blocksize( "net_maxfragments", NETSTRING( MAX_ROUTABLE_PAYLOAD ), 0, "Max fragment bytes per packet", true, FRAGMENT_SIZE, true, MAX_ROUTABLE_PAYLOAD );
  31. static ConVar net_showmsg( "net_showmsg", "0", 0, "Show incoming message: <0|1|name>" );
  32. static ConVar net_showfragments( "net_showfragments", "0", 0, "Show netchannel fragments" );
  33. static ConVar net_showpeaks( "net_showpeaks", "0", 0, "Show messages for large packets only: <size>" );
  34. static ConVar net_blockmsg( "net_blockmsg", "none", FCVAR_CHEAT, "Discards incoming message: <0|1|name>" );
  35. static ConVar net_showdrop( "net_showdrop", "0", 0, "Show dropped packets in console" );
  36. static ConVar net_drawslider( "net_drawslider", "0", 0, "Draw completion slider during signon" );
  37. static ConVar net_chokeloopback( "net_chokeloop", "0", 0, "Apply bandwidth choke to loopback packets" );
  38. static ConVar net_maxfilesize( "net_maxfilesize", "16", 0, "Maximum allowed file size for uploading in MB", true, 0, true, 64 );
  39. static ConVar net_compresspackets( "net_compresspackets", "1", 0, "Use compression on game packets." );
  40. static ConVar net_compresspackets_minsize( "net_compresspackets_minsize", "1024", 0, "Don't bother compressing packets below this size." );
  41. static ConVar net_maxcleartime( "net_maxcleartime", "4.0", 0, "Max # of seconds we can wait for next packets to be sent based on rate setting (0 == no limit)." );
  42. static ConVar net_maxpacketdrop( "net_maxpacketdrop", "5000", 0, "Ignore any packets with the sequence number more than this ahead (0 == no limit)" );
  43. extern ConVar net_maxroutable;
  44. extern int NET_ConnectSocket( int nSock, const netadr_t &addr );
  45. extern void NET_CloseSocket( int hSocket, int sock = -1 );
  46. extern int NET_SendStream( int nSock, const char * buf, int len, int flags );
  47. extern int NET_ReceiveStream( int nSock, char * buf, int len, int flags );
  48. // If the network connection hasn't been active in this many seconds, display some warning text.
  49. #define CONNECTION_PROBLEM_TIME 4.0f // assume network problem after this time
  50. #define BYTES2FRAGMENTS(i) ((i+FRAGMENT_SIZE-1)/FRAGMENT_SIZE)
  51. #define FLIPBIT(v,b) if (v&b) v &= ~b; else v |= b;
  52. // We only need to checksum packets on the PC and only when we're actually sending them over the network.
  53. static bool ShouldChecksumPackets()
  54. {
  55. if ( !IsPC() )
  56. return false;
  57. return NET_IsMultiplayer();
  58. }
  59. bool CNetChan::IsLoopback() const
  60. {
  61. return remote_address.IsLoopback();
  62. }
  63. bool CNetChan::IsNull() const
  64. {
  65. return remote_address.GetType() == NA_NULL ? true : false;
  66. }
  67. /*
  68. ==============================
  69. CNetChan::Clear
  70. ==============================
  71. */
  72. void CNetChan::Clear()
  73. {
  74. int i;
  75. // clear waiting lists
  76. for ( i=0; i<MAX_STREAMS; i++ )
  77. {
  78. while ( m_WaitingList[i].Count() )
  79. RemoveHeadInWaitingList( i );
  80. if ( m_ReceiveList[i].buffer )
  81. {
  82. delete[] m_ReceiveList[i].buffer;
  83. m_ReceiveList[i].buffer = NULL;
  84. }
  85. }
  86. for( i=0; i<MAX_SUBCHANNELS; i++ )
  87. {
  88. if ( m_SubChannels[i].state == SUBCHANNEL_TOSEND )
  89. {
  90. int bit = 1<<i; // flip bit back since data was send yet
  91. FLIPBIT(m_nOutReliableState, bit);
  92. m_SubChannels[i].Free();
  93. }
  94. else if ( m_SubChannels[i].state == SUBCHANNEL_WAITING )
  95. {
  96. // data is already out, mark channel as dirty
  97. m_SubChannels[i].state = SUBCHANNEL_DIRTY;
  98. }
  99. }
  100. if ( m_bProcessingMessages )
  101. {
  102. // ProcessMessages() needs to know we just nuked the receive list from under it or bad things ensue.
  103. m_bClearedDuringProcessing = true;
  104. }
  105. Reset();
  106. }
  107. void CNetChan::CompressFragments()
  108. {
  109. // We don't want this to go in the VCR file, because the compressed size can be different. The reason is
  110. // that the bf_writes that contributed to this message may have uninitialized bits at the end of the buffer
  111. // (for example if it uses only the first couple bits of the last byte in the message). If the
  112. // last few bits are different, it can produce a different compressed size.
  113. if ( !m_bUseCompression )
  114. return;
  115. if ( VCRGetMode() != VCR_Disabled )
  116. return;
  117. VPROF_BUDGET( "CNetChan::CompressFragments", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  118. // write fragemnts for both streams
  119. for ( int i=0; i<MAX_STREAMS; i++ )
  120. {
  121. if ( m_WaitingList[i].Count() == 0 )
  122. continue;
  123. // get the first fragments block which is send next
  124. dataFragments_t *data = m_WaitingList[i][0];
  125. // if data is already compressed or too small, skip it
  126. if ( data->isCompressed || (int)data->bytes < net_compresspackets_minsize.GetInt() )
  127. continue;
  128. // if we already started sending this block, we can't compress it anymore
  129. if ( data->ackedFragments > 0 || data->pendingFragments > 0 )
  130. continue;
  131. //ok, compress it.
  132. if ( data->buffer )
  133. {
  134. CFastTimer compressTimer;
  135. compressTimer.Start();
  136. // fragments data is in memory
  137. unsigned int compressedSize = COM_GetIdealDestinationCompressionBufferSize_Snappy( data->bytes );
  138. char * compressedData = new char[ compressedSize ];
  139. if ( COM_BufferToBufferCompress_Snappy( compressedData, &compressedSize, data->buffer, data->bytes ) &&
  140. ( compressedSize < data->bytes ) )
  141. {
  142. compressTimer.End();
  143. DevMsg("Compressing fragments (%d -> %d bytes): %.2fms\n",
  144. data->bytes, compressedSize, compressTimer.GetDuration().GetMillisecondsF() );
  145. // copy compressed data but dont reallocate memory
  146. Q_memcpy( data->buffer, compressedData, compressedSize );
  147. data->nUncompressedSize = data->bytes;
  148. data->bytes = compressedSize;
  149. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  150. data->isCompressed = true;
  151. }
  152. delete [] compressedData; // free temp buffer
  153. }
  154. else // it's a file
  155. {
  156. Assert( data->file != FILESYSTEM_INVALID_HANDLE );
  157. char compressedfilename[ MAX_OSPATH ];
  158. int compressedFileSize = -1;
  159. FileHandle_t hZipFile = FILESYSTEM_INVALID_HANDLE;
  160. // check to see if there is a compressed version of the file
  161. Q_snprintf( compressedfilename, sizeof(compressedfilename), "%s.ztmp", data->filename);
  162. // check the timestamps
  163. int compressedFileTime = g_pFileSystem->GetFileTime( compressedfilename );
  164. int fileTime = g_pFileSystem->GetFileTime( data->filename );
  165. if ( compressedFileTime >= fileTime )
  166. {
  167. // compressed file is newer than uncompressed file, use this one
  168. hZipFile = g_pFileSystem->Open( compressedfilename, "rb", NULL );
  169. }
  170. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  171. {
  172. // use the existing compressed file
  173. compressedFileSize = g_pFileSystem->Size( hZipFile );
  174. }
  175. else
  176. {
  177. // create compressed version of source file
  178. unsigned int uncompressedSize = data->bytes;
  179. unsigned int compressedSize = COM_GetIdealDestinationCompressionBufferSize_Snappy( uncompressedSize );
  180. char *uncompressed = new char[uncompressedSize];
  181. char *compressed = new char[compressedSize];
  182. // read in source file
  183. g_pFileSystem->Read( uncompressed, data->bytes, data->file );
  184. // compress into buffer
  185. if ( COM_BufferToBufferCompress_Snappy( compressed, &compressedSize, uncompressed, uncompressedSize ) )
  186. {
  187. // write out to disk compressed version
  188. hZipFile = g_pFileSystem->Open( compressedfilename, "wb", NULL );
  189. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  190. {
  191. DevMsg("Creating compressed version of file %s (%d -> %d)\n", data->filename, data->bytes, compressedSize);
  192. g_pFileSystem->Write( compressed, compressedSize, hZipFile );
  193. g_pFileSystem->Close( hZipFile );
  194. // and open zip file it again for reading
  195. hZipFile = g_pFileSystem->Open( compressedfilename, "rb", NULL );
  196. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  197. {
  198. // ok, now everything if fine
  199. compressedFileSize = compressedSize;
  200. }
  201. }
  202. }
  203. delete [] uncompressed;
  204. delete [] compressed;
  205. }
  206. if ( compressedFileSize > 0 )
  207. {
  208. // use compressed file handle instead of original file
  209. g_pFileSystem->Close( data->file );
  210. data->file = hZipFile;
  211. data->nUncompressedSize = data->bytes;
  212. data->bytes = compressedFileSize;
  213. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  214. data->isCompressed = true;
  215. }
  216. }
  217. }
  218. }
  219. void CNetChan::UncompressFragments( dataFragments_t *data )
  220. {
  221. if ( !data->isCompressed )
  222. return;
  223. // allocate buffer for uncompressed data, align to 4 bytes boundary
  224. char *newbuffer = new char[PAD_NUMBER( data->nUncompressedSize, 4 )];
  225. unsigned int uncompressedSize = data->nUncompressedSize;
  226. // uncompress data
  227. COM_BufferToBufferDecompress( newbuffer, &uncompressedSize, data->buffer, data->bytes );
  228. Assert( uncompressedSize == data->nUncompressedSize );
  229. // free old buffer and set new buffer
  230. delete [] data->buffer;
  231. data->buffer = newbuffer;
  232. data->bytes = uncompressedSize;
  233. data->isCompressed = false;
  234. }
  235. unsigned int CNetChan::RequestFile(const char *filename)
  236. {
  237. m_FileRequestCounter++;
  238. if ( net_showfragments.GetInt() == 2 )
  239. {
  240. DevMsg("RequestFile: %s (ID %i)\n", filename, m_FileRequestCounter );
  241. }
  242. m_StreamReliable.WriteUBitLong( net_File, NETMSG_TYPE_BITS );
  243. m_StreamReliable.WriteUBitLong( m_FileRequestCounter, 32 );
  244. m_StreamReliable.WriteString( filename );
  245. m_StreamReliable.WriteOneBit( 1 ); // reqest this file
  246. return m_FileRequestCounter;
  247. }
  248. void CNetChan::RequestFile_OLD(const char *filename, unsigned int transferID)
  249. {
  250. Error( "Called RequestFile_OLD" );
  251. }
  252. void CNetChan::DenyFile(const char *filename, unsigned int transferID)
  253. {
  254. if ( net_showfragments.GetInt() == 2 )
  255. {
  256. DevMsg("DenyFile: %s (ID %i)\n", filename, transferID );
  257. }
  258. m_StreamReliable.WriteUBitLong( net_File, NETMSG_TYPE_BITS );
  259. m_StreamReliable.WriteUBitLong( transferID, 32 );
  260. m_StreamReliable.WriteString( filename );
  261. m_StreamReliable.WriteOneBit( 0 ); // deny this file
  262. }
  263. bool CNetChan::SendFile(const char *filename, unsigned int transferID)
  264. {
  265. // add file to waiting list
  266. if ( remote_address.GetType() == NA_NULL )
  267. return true;
  268. if ( !filename )
  269. return false;
  270. const char *sendfile = filename;
  271. while( sendfile[0] && PATHSEPARATOR( sendfile[0] ) )
  272. {
  273. sendfile = sendfile + 1;
  274. }
  275. // Don't transfer exe, vbs, com, bat-type files.
  276. if ( !IsValidFileForTransfer( sendfile ) )
  277. return false;
  278. if ( !CreateFragmentsFromFile( sendfile, FRAG_FILE_STREAM, transferID ) )
  279. {
  280. DenyFile( sendfile, transferID ); // send host a deny message
  281. return false;
  282. }
  283. if ( net_showfragments.GetInt() == 2 )
  284. {
  285. DevMsg("SendFile: %s (ID %i)\n", sendfile, transferID );
  286. }
  287. return true;
  288. }
  289. void CNetChan::Shutdown(const char *pReason)
  290. {
  291. // send discconect
  292. if ( m_Socket < 0 )
  293. return;
  294. Clear(); // free all buffers (reliable & unreliable)
  295. if ( pReason )
  296. {
  297. // send disconnect message
  298. m_StreamUnreliable.WriteUBitLong( net_Disconnect, NETMSG_TYPE_BITS );
  299. m_StreamUnreliable.WriteString( pReason );
  300. Transmit(); // push message out
  301. }
  302. if ( m_StreamSocket )
  303. {
  304. NET_CloseSocket( m_StreamSocket, m_Socket );
  305. m_StreamSocket = 0;
  306. m_StreamActive = false;
  307. }
  308. m_Socket = -1; // signals that netchannel isn't valid anymore
  309. remote_address.Clear();
  310. if ( m_MessageHandler )
  311. {
  312. m_MessageHandler->ConnectionClosing( pReason );
  313. m_MessageHandler = NULL;
  314. }
  315. // free new messages
  316. for (int i=0; i<m_NetMessages.Count(); i++ )
  317. {
  318. Assert( m_NetMessages[i] );
  319. delete m_NetMessages[i];
  320. }
  321. m_NetMessages.Purge();
  322. m_DemoRecorder = NULL;
  323. if ( m_bProcessingMessages )
  324. {
  325. NET_RemoveNetChannel( this, false ); // Delay the deletion or it'll crash in the message-processing loop.
  326. m_bShouldDelete = true;
  327. }
  328. else
  329. {
  330. NET_RemoveNetChannel( this, true );
  331. }
  332. }
  333. CNetChan::CNetChan()
  334. {
  335. m_nSplitPacketSequence = 1;
  336. m_nMaxRoutablePayloadSize = MAX_ROUTABLE_PAYLOAD;
  337. m_bProcessingMessages = false;
  338. m_bShouldDelete = false;
  339. m_bClearedDuringProcessing = false;
  340. m_bStreamContainsChallenge = false;
  341. m_Socket = -1; // invalid
  342. remote_address.Clear();
  343. last_received = 0;
  344. connect_time = 0;
  345. m_nProtocolVersion = -1; // invalid
  346. Q_strncpy( m_Name, "", sizeof(m_Name) );
  347. m_MessageHandler = NULL;
  348. m_DemoRecorder = NULL;
  349. m_StreamUnreliable.SetDebugName( "netchan_t::unreliabledata" );
  350. m_StreamReliable.SetDebugName( "netchan_t::reliabledata" );
  351. m_Rate = DEFAULT_RATE;
  352. m_Timeout = SIGNON_TIME_OUT;
  353. // Prevent the first message from getting dropped after connection is set up.
  354. m_nOutSequenceNr = 1; // otherwise it looks like a
  355. m_nInSequenceNr = 0;
  356. m_nOutSequenceNrAck = 0;
  357. m_nOutReliableState = 0; // our current reliable state
  358. m_nInReliableState = 0; // last remote reliable state
  359. // m_nLostPackets = 0;
  360. m_ChallengeNr = 0;
  361. m_StreamSocket = 0;
  362. m_StreamActive = false;
  363. ResetStreaming();
  364. m_MaxReliablePayloadSize = NET_MAX_PAYLOAD;
  365. m_FileRequestCounter = 0;
  366. m_bFileBackgroundTranmission = true;
  367. m_bUseCompression = false;
  368. m_nQueuedPackets = 0;
  369. m_flRemoteFrameTime = 0;
  370. m_flRemoteFrameTimeStdDeviation = 0;
  371. FlowReset();
  372. }
  373. CNetChan::~CNetChan()
  374. {
  375. Shutdown("NetChannel removed.");
  376. }
  377. /*
  378. ==============
  379. CNetChan::Setup
  380. called to open a channel to a remote system
  381. ==============
  382. */
  383. void CNetChan::Setup(int sock, netadr_t *adr, const char * name, INetChannelHandler * handler,
  384. int nProtocolVersion )
  385. {
  386. Assert( name );
  387. Assert ( handler );
  388. m_Socket = sock;
  389. if ( m_StreamSocket )
  390. {
  391. NET_CloseSocket( m_StreamSocket );
  392. m_StreamSocket = 0;
  393. }
  394. // remote_address may be NULL for fake channels (demo playback etc)
  395. if ( adr )
  396. {
  397. remote_address = *adr;
  398. }
  399. else
  400. {
  401. remote_address.Clear(); // it's a demo fake channel
  402. remote_address.SetType( NA_NULL );
  403. }
  404. last_received = net_time;
  405. connect_time = net_time;
  406. Q_strncpy( m_Name, name, sizeof(m_Name) );
  407. m_MessageHandler = handler;
  408. m_nProtocolVersion = nProtocolVersion;
  409. m_DemoRecorder = NULL;
  410. MEM_ALLOC_CREDIT();
  411. SetMaxBufferSize( false, NET_MAX_DATAGRAM_PAYLOAD );
  412. SetMaxBufferSize( false, NET_MAX_DATAGRAM_PAYLOAD, true ); //Set up voice buffer
  413. SetMaxBufferSize( true, NET_MAX_PAYLOAD );
  414. m_Rate = DEFAULT_RATE;
  415. m_Timeout = SIGNON_TIME_OUT;
  416. // Prevent the first message from getting dropped after connection is set up.
  417. m_nOutSequenceNr = 1; // otherwise it looks like a
  418. m_nInSequenceNr = 0;
  419. m_nOutSequenceNrAck = 0;
  420. m_nOutReliableState = 0; // our current reliable state
  421. m_nInReliableState = 0; // last remote reliable state
  422. m_nChokedPackets = 0;
  423. m_fClearTime = 0.0;
  424. m_ChallengeNr = 0;
  425. m_StreamSocket = 0;
  426. m_StreamActive = false;
  427. m_ReceiveList[FRAG_NORMAL_STREAM].buffer = NULL;
  428. m_ReceiveList[FRAG_FILE_STREAM].buffer = NULL;
  429. // init 8 subchannels
  430. for ( int i=0; i<MAX_SUBCHANNELS; i++ )
  431. {
  432. m_SubChannels[i].index = i; // set index once
  433. m_SubChannels[i].Free();
  434. }
  435. ResetStreaming();
  436. if ( NET_IsMultiplayer() )
  437. {
  438. m_MaxReliablePayloadSize = net_blocksize.GetInt();
  439. }
  440. else
  441. {
  442. m_MaxReliablePayloadSize = NET_MAX_PAYLOAD;
  443. }
  444. FlowReset();
  445. // tell message handler to register known netmessages
  446. m_MessageHandler->ConnectionStart( this );
  447. }
  448. void CNetChan::ResetStreaming( void )
  449. {
  450. m_SteamType = STREAM_CMD_NONE;
  451. m_StreamLength = 0;
  452. m_StreamReceived = 0;
  453. m_StreamSeqNr = 0;
  454. m_SteamFile[0] = 0;
  455. }
  456. bool CNetChan::StartStreaming( unsigned int challengeNr )
  457. {
  458. // reset stream state maschine
  459. ResetStreaming();
  460. m_ChallengeNr = challengeNr;
  461. if ( !NET_IsMultiplayer() )
  462. {
  463. m_StreamSocket = 0;
  464. return true; // streaming is done via loopback buffers in SP mode
  465. }
  466. #ifdef _XBOX
  467. // We don't want to go into here because it'll eat up 192k extra memory in the client and server's m_StreamData.
  468. Error( "StartStreaming not allowed on XBOX." );
  469. #endif
  470. MEM_ALLOC_CREDIT();
  471. m_StreamSocket = NET_ConnectSocket( m_Socket, remote_address );
  472. m_StreamData.EnsureCapacity( NET_MAX_PAYLOAD );
  473. return (m_StreamSocket != 0);
  474. }
  475. void CNetChan::SetChallengeNr(unsigned int chnr)
  476. {
  477. m_ChallengeNr = chnr;
  478. }
  479. unsigned int CNetChan::GetChallengeNr( void ) const
  480. {
  481. return m_ChallengeNr;
  482. }
  483. void CNetChan::GetSequenceData( int &nOutSequenceNr, int &nInSequenceNr, int &nOutSequenceNrAck )
  484. {
  485. nOutSequenceNr = m_nOutSequenceNr;
  486. nInSequenceNr = m_nInSequenceNr;
  487. nOutSequenceNrAck = m_nOutSequenceNrAck;
  488. }
  489. void CNetChan::SetSequenceData( int nOutSequenceNr, int nInSequenceNr, int nOutSequenceNrAck )
  490. {
  491. Assert( IsPlayback() );
  492. m_nOutSequenceNr = nOutSequenceNr;
  493. m_nInSequenceNr = nInSequenceNr;
  494. m_nOutSequenceNrAck = nOutSequenceNrAck;
  495. }
  496. void CNetChan::SetDemoRecorder(IDemoRecorder * recorder)
  497. {
  498. m_DemoRecorder = recorder;
  499. }
  500. void CNetChan::SetTimeout(float seconds)
  501. {
  502. m_Timeout = seconds;
  503. if ( m_Timeout > 3600.0f )
  504. {
  505. m_Timeout = 3600.0f; // 1 hour maximum
  506. }
  507. else if ( m_Timeout <= 0.0f )
  508. {
  509. m_Timeout = -1.0f; // never time out (demo files)
  510. }
  511. else if ( m_Timeout < CONNECTION_PROBLEM_TIME )
  512. {
  513. m_Timeout = CONNECTION_PROBLEM_TIME; // allow at least this minimum
  514. }
  515. }
  516. void CNetChan::SetMaxBufferSize(bool bReliable, int nBytes, bool bVoice )
  517. {
  518. // force min/max sizes 4-96kB
  519. nBytes = clamp( nBytes, NET_MAX_DATAGRAM_PAYLOAD, NET_MAX_PAYLOAD );
  520. bf_write *stream;
  521. CUtlMemory<byte> *buffer;
  522. if ( bReliable )
  523. {
  524. stream = &m_StreamReliable;
  525. buffer = &m_ReliableDataBuffer;
  526. }
  527. else if ( bVoice == true )
  528. {
  529. stream = &m_StreamVoice;
  530. buffer = &m_VoiceDataBuffer;
  531. }
  532. else
  533. {
  534. stream = &m_StreamUnreliable;
  535. buffer = &m_UnreliableDataBuffer;
  536. }
  537. if ( buffer->Count() == nBytes )
  538. return;
  539. byte copybuf[NET_MAX_DATAGRAM_PAYLOAD];
  540. int copybits = stream->GetNumBitsWritten();
  541. int copybytes = Bits2Bytes( copybits );
  542. if ( copybytes >= nBytes )
  543. {
  544. ConMsg("CNetChan::SetMaxBufferSize: cant preserve exiting data %i>%i.\n", copybytes, nBytes );
  545. return;
  546. }
  547. if ( copybits > 0 )
  548. {
  549. Q_memcpy( copybuf, buffer->Base(), copybytes );
  550. }
  551. buffer->Purge();
  552. MEM_ALLOC_CREDIT();
  553. buffer->EnsureCapacity( nBytes );
  554. if ( copybits > 0 )
  555. {
  556. Q_memcpy( buffer->Base(), copybuf, copybytes );
  557. }
  558. stream->StartWriting( buffer->Base(), nBytes, copybits );
  559. }
  560. void CNetChan::SetFileTransmissionMode( bool bBackgroundMode )
  561. {
  562. m_bFileBackgroundTranmission = bBackgroundMode;
  563. }
  564. void CNetChan::SetCompressionMode( bool bUseCompression )
  565. {
  566. m_bUseCompression = bUseCompression;
  567. }
  568. void CNetChan::SetDataRate(float rate)
  569. {
  570. m_Rate = clamp( rate, (float) MIN_RATE, (float) MAX_RATE );
  571. }
  572. const char * CNetChan::GetName() const
  573. {
  574. return m_Name;
  575. }
  576. const char * CNetChan::GetAddress() const
  577. {
  578. return remote_address.ToString();
  579. }
  580. int CNetChan::GetDropNumber() const
  581. {
  582. return m_PacketDrop;
  583. }
  584. /*
  585. ===============
  586. CNetChan::CanPacket
  587. Returns true if the bandwidth choke isn't active
  588. ================
  589. */
  590. bool CNetChan::CanPacket () const
  591. {
  592. // Never choke loopback packets.
  593. if ( !net_chokeloopback.GetInt() && remote_address.IsLoopback() )
  594. {
  595. return true;
  596. }
  597. if ( HasQueuedPackets() )
  598. {
  599. return false;
  600. }
  601. return m_fClearTime < net_time;
  602. }
  603. bool CNetChan::IsPlayback( void ) const
  604. {
  605. #if !defined(SWDS) && !defined(_XBOX)
  606. return demoplayer->IsPlayingBack();
  607. #else
  608. return false;
  609. #endif
  610. }
  611. void CNetChan::FlowReset( void )
  612. {
  613. Q_memset( m_DataFlow, 0, sizeof( m_DataFlow ) );
  614. Q_memset( m_MsgStats, 0, sizeof( m_MsgStats ) );
  615. }
  616. void CNetChan::FlowNewPacket(int flow, int seqnr, int acknr, int nChoked, int nDropped, int nSize )
  617. {
  618. netflow_t * pflow = &m_DataFlow[ flow ];
  619. // if frame_number != ( current + 1 ) mark frames between as invalid
  620. netframe_t *pframe = NULL;
  621. if ( seqnr > pflow->currentindex )
  622. {
  623. //
  624. // The following loop must execute no more than NET_FRAMES_BACKUP times
  625. // since that's the amount of storage in frame_headers & frames arrays,
  626. // a malformed client packet pushing "seqnr" by 1,000,000 can cause this
  627. // loop to watchdog.
  628. //
  629. for ( int i = pflow->currentindex + 1, numPacketFramesOverflow = 0;
  630. ( i <= seqnr ) && ( numPacketFramesOverflow < NET_FRAMES_BACKUP );
  631. ++ i, ++ numPacketFramesOverflow )
  632. {
  633. int nBackTrack = seqnr - i;
  634. pframe = &pflow->frames[ i & NET_FRAMES_MASK ];
  635. pframe->time = net_time; // now
  636. pframe->valid = false;
  637. pframe->size = 0;
  638. pframe->latency = -1.0f; // not acknowledged yet
  639. pframe->avg_latency = GetAvgLatency( FLOW_OUTGOING );
  640. pframe->choked = 0; // not acknowledged yet
  641. pframe->dropped = 0;
  642. pframe->m_flInterpolationAmount = 0.0f;
  643. Q_memset( &pframe->msggroups, 0, sizeof(pframe->msggroups) );
  644. if ( nBackTrack < ( nChoked + nDropped ) )
  645. {
  646. if ( nBackTrack < nChoked )
  647. {
  648. pframe->choked = 1;
  649. }
  650. else
  651. {
  652. pframe->dropped = 1;
  653. }
  654. }
  655. }
  656. pframe->dropped = nDropped;
  657. pframe->choked = nChoked;
  658. pframe->size = nSize;
  659. pframe->valid = true;
  660. pframe->avg_latency = GetAvgLatency( FLOW_OUTGOING );
  661. pframe->m_flInterpolationAmount = m_flInterpolationAmount;
  662. }
  663. else
  664. {
  665. #if !defined( SWDS )
  666. Assert( demoplayer->IsPlayingBack() || seqnr > pflow->currentindex );
  667. #endif
  668. }
  669. pflow->totalpackets++;
  670. pflow->currentindex = seqnr;
  671. pflow->currentframe = pframe;
  672. // updated ping for acknowledged packet
  673. int aflow = (flow==FLOW_OUTGOING) ? FLOW_INCOMING : FLOW_OUTGOING;
  674. if ( acknr <= (m_DataFlow[aflow].currentindex - NET_FRAMES_BACKUP) )
  675. return; // acknowledged packet isn't in backup buffer anymore
  676. netframe_t * aframe = &m_DataFlow[aflow].frames[ acknr & NET_FRAMES_MASK ];
  677. if ( aframe->valid && aframe->latency == -1.0f )
  678. {
  679. // update ping for acknowledged packet, if not already acknowledged before
  680. aframe->latency = net_time - aframe->time;
  681. if ( aframe->latency < 0.0f )
  682. aframe->latency = 0.0f;
  683. }
  684. }
  685. void CNetChan::FlowUpdate(int flow, int addbytes)
  686. {
  687. netflow_t * pflow = &m_DataFlow[ flow ];
  688. pflow->totalbytes += addbytes;
  689. if ( pflow->nextcompute > net_time )
  690. return;
  691. pflow->nextcompute = net_time + FLOW_INTERVAL;
  692. int totalvalid = 0;
  693. int totalinvalid = 0;
  694. int totalbytes = 0;
  695. float totallatency = 0.0f;
  696. int totallatencycount = 0;
  697. int totalchoked = 0;
  698. float starttime = FLT_MAX;
  699. float endtime = 0.0f;
  700. netframe_t *pprev = &pflow->frames[ NET_FRAMES_BACKUP-1 ];
  701. for ( int i = 0; i < NET_FRAMES_BACKUP; i++ )
  702. {
  703. // Most recent message then backward from there
  704. netframe_t * pcurr = &pflow->frames[ i ];
  705. if ( pcurr->valid )
  706. {
  707. if ( pcurr->time < starttime )
  708. starttime = pcurr->time;
  709. if ( pcurr->time > endtime )
  710. endtime = pcurr->time;
  711. totalvalid++;
  712. totalchoked += pcurr->choked;
  713. totalbytes += pcurr->size;
  714. if ( pcurr->latency > -1.0f )
  715. {
  716. totallatency += pcurr->latency;
  717. totallatencycount++;
  718. }
  719. }
  720. else
  721. {
  722. totalinvalid++;
  723. }
  724. pprev = pcurr;
  725. }
  726. float totaltime = endtime - starttime;
  727. if ( totaltime > 0.0f )
  728. {
  729. pflow->avgbytespersec *= FLOW_AVG;
  730. pflow->avgbytespersec += ( 1.0f - FLOW_AVG ) * ((float)totalbytes / totaltime);
  731. pflow->avgpacketspersec *= FLOW_AVG;
  732. pflow->avgpacketspersec += ( 1.0f - FLOW_AVG ) * ((float)totalvalid / totaltime);
  733. }
  734. int totalPackets = totalvalid + totalinvalid;
  735. if ( totalPackets > 0 )
  736. {
  737. pflow->avgloss *= FLOW_AVG;
  738. pflow->avgloss += ( 1.0f - FLOW_AVG ) * ((float)(totalinvalid-totalchoked)/totalPackets);
  739. if ( pflow->avgloss < 0 )
  740. pflow->avgloss = 0;
  741. pflow->avgchoke *= FLOW_AVG;
  742. pflow->avgchoke += ( 1.0f - FLOW_AVG ) * ((float)totalchoked/totalPackets);
  743. }
  744. if ( totallatencycount>0 )
  745. {
  746. float newping = totallatency / totallatencycount ;
  747. pflow->latency = newping;
  748. pflow->avglatency*= FLOW_AVG;
  749. pflow->avglatency += ( 1.0f - FLOW_AVG ) * newping;
  750. }
  751. }
  752. void CNetChan::SetChoked( void )
  753. {
  754. m_nOutSequenceNr++; // sends to be done since move command use sequence number
  755. m_nChokedPackets++;
  756. }
  757. bool CNetChan::Transmit(bool onlyReliable )
  758. {
  759. if ( onlyReliable )
  760. m_StreamUnreliable.Reset();
  761. return (SendDatagram( NULL ) != 0);
  762. }
  763. bool CNetChan::IsFileInWaitingList( const char *filename )
  764. {
  765. if ( !filename || !filename[0] )
  766. return true;
  767. for ( int stream=0; stream<MAX_STREAMS; stream++)
  768. {
  769. for ( int i = 0; i < m_WaitingList[stream].Count(); i++ )
  770. {
  771. dataFragments_t * data = m_WaitingList[stream][i];
  772. if ( !Q_strcmp( data->filename, filename ) )
  773. return true; // alread in list
  774. }
  775. }
  776. return false; // file not found
  777. }
  778. void CNetChan::RemoveHeadInWaitingList( int nList )
  779. {
  780. Assert( m_WaitingList[nList].Count() );
  781. dataFragments_t * data = m_WaitingList[nList][0]; // get head
  782. if ( data->buffer )
  783. delete [] data->buffer; // free data buffer
  784. if ( data->file != FILESYSTEM_INVALID_HANDLE )
  785. {
  786. g_pFileSystem->Close( data->file );
  787. data->file = FILESYSTEM_INVALID_HANDLE;
  788. }
  789. // data->fragments.Purge();
  790. m_WaitingList[nList].FindAndRemove( data ); // remove from list
  791. delete data; //free structure itself
  792. }
  793. bool CNetChan::CreateFragmentsFromBuffer( bf_write *buffer, int stream )
  794. {
  795. VPROF_BUDGET( "CNetChan::CreateFragmentsFromBuffer", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  796. bf_write bfwrite;
  797. dataFragments_t *data = NULL;
  798. // if we have more than one item in the waiting list, try to add the
  799. // reliable data to the last item. that doesn't work with the first item
  800. // since it may have been already send and is waiting for acknowledge
  801. int count = m_WaitingList[stream].Count();
  802. if ( count > 1 )
  803. {
  804. // get last item in waiting list
  805. data = m_WaitingList[stream][count-1];
  806. int totalBytes = Bits2Bytes( data->bits + buffer->GetNumBitsWritten() );
  807. totalBytes = PAD_NUMBER( totalBytes, 4 ); // align to 4 bytes boundary
  808. if ( totalBytes < NET_MAX_PAYLOAD && data->buffer )
  809. {
  810. // we have enough space for it, create new larger mem buffer
  811. char *newBuf = new char[totalBytes];
  812. Q_memcpy( newBuf, data->buffer, data->bytes );
  813. delete [] data->buffer; // free old buffer
  814. data->buffer = newBuf; // set new buffer
  815. bfwrite.StartWriting( newBuf, totalBytes, data->bits );
  816. }
  817. else
  818. {
  819. data = NULL; // reset to NULL
  820. }
  821. }
  822. // if not added to existing item, create a new reliable data waiting buffer
  823. if ( !data )
  824. {
  825. int totalBytes = Bits2Bytes( buffer->GetNumBitsWritten());
  826. totalBytes = PAD_NUMBER( totalBytes, 4 ); // align to 4 bytes boundary
  827. data = new dataFragments_t;
  828. data->bytes = 0; // not filled yet
  829. data->bits = 0;
  830. data->buffer = new char[ totalBytes ];
  831. data->isCompressed = false;
  832. data->nUncompressedSize = 0;
  833. data->file = FILESYSTEM_INVALID_HANDLE;
  834. data->filename[0] = 0;
  835. bfwrite.StartWriting( data->buffer, totalBytes );
  836. m_WaitingList[stream].AddToTail( data ); // that's it for now
  837. }
  838. // write new reliable data to buffer
  839. bfwrite.WriteBits( buffer->GetData(), buffer->GetNumBitsWritten() );
  840. // fill last bits in last byte with NOP if necessary
  841. int nRemainingBits = bfwrite.GetNumBitsWritten() % 8;
  842. if ( nRemainingBits > 0 && nRemainingBits <= (8-NETMSG_TYPE_BITS) )
  843. {
  844. bfwrite.WriteUBitLong( net_NOP, NETMSG_TYPE_BITS );
  845. }
  846. // update bit length
  847. data->bits += buffer->GetNumBitsWritten();
  848. data->bytes = Bits2Bytes(data->bits);
  849. // check if send as stream or with snapshot
  850. data->asTCP = m_StreamActive && ( data->bytes > m_MaxReliablePayloadSize );
  851. // calc number of fragments needed
  852. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  853. data->ackedFragments = 0;
  854. data->pendingFragments = 0;
  855. return true;
  856. }
  857. bool CNetChan::CreateFragmentsFromFile( const char *filename, int stream, unsigned int transferID )
  858. {
  859. if ( IsFileInWaitingList( filename ) )
  860. return true; // already scheduled for upload
  861. const char *pPathID = "GAME";
  862. if ( !g_pFileSystem->FileExists( filename, pPathID ) )
  863. {
  864. ConMsg( "CreateFragmentsFromFile: '%s' doesn't exist.\n", filename );
  865. return false;
  866. }
  867. int totalBytes = g_pFileSystem->Size( filename, pPathID );
  868. if ( totalBytes >= (net_maxfilesize.GetInt()*1024*1024) )
  869. {
  870. ConMsg( "CreateFragmentsFromFile: '%s' size exceeds net_maxfilesize limit (%i MB).\n", filename, net_maxfilesize.GetInt() );
  871. return false;
  872. }
  873. if ( totalBytes >= MAX_FILE_SIZE )
  874. {
  875. ConMsg( "CreateFragmentsFromFile: '%s' too big (max %i bytes).\n", filename, MAX_FILE_SIZE );
  876. return false;
  877. }
  878. dataFragments_t *data = new dataFragments_t;
  879. data->bytes = totalBytes;
  880. data->bits = data->bytes * 8;
  881. data->buffer = NULL;
  882. data->isCompressed = false;
  883. data->nUncompressedSize = 0;
  884. data->file = g_pFileSystem->Open( filename, "rb", pPathID );
  885. if ( data->file == FILESYSTEM_INVALID_HANDLE )
  886. {
  887. ConMsg( "CreateFragmentsFromFile: couldn't open '%s'.\n", filename );
  888. delete data;
  889. return false;
  890. }
  891. data->transferID = transferID;
  892. Q_strncpy( data->filename, filename, sizeof(data->filename) );
  893. m_WaitingList[stream].AddToTail( data ); // that's it for now
  894. // check if send as stream or with snapshot
  895. data->asTCP = false; // m_StreamActive && ( Bits2Bytes(data->length) > m_MaxReliablePayloadSize );
  896. // calc number of fragments needed
  897. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  898. data->ackedFragments = 0;
  899. data->pendingFragments = 0;
  900. return true;
  901. }
  902. void CNetChan::SendTCPData( void )
  903. {
  904. if ( m_WaitingList[FRAG_NORMAL_STREAM].Count() == 0 )
  905. return; // nothing in line
  906. dataFragments_t *data = m_WaitingList[FRAG_NORMAL_STREAM][0];
  907. if ( !data->asTCP )
  908. return; // not as TCP
  909. if ( data->pendingFragments > 0 )
  910. return; // already send, wait for ACK
  911. // OK send it now
  912. SendReliableViaStream( data );
  913. }
  914. bool CNetChan::SendSubChannelData( bf_write &buf )
  915. {
  916. VPROF_BUDGET( "CNetChan::SendSubChannelData", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  917. subChannel_s *subChan = NULL;
  918. int i;
  919. CompressFragments();
  920. SendTCPData();
  921. UpdateSubChannels();
  922. // find subchannl with data to send/resend:
  923. for ( i=0; i<MAX_SUBCHANNELS; i++ )
  924. {
  925. subChan = &m_SubChannels[i];
  926. if ( subChan->state == SUBCHANNEL_TOSEND )
  927. break;
  928. }
  929. if ( i == MAX_SUBCHANNELS )
  930. return false; // no data to send in any subchannel
  931. // first write subchannel index
  932. buf.WriteUBitLong( i, 3 );
  933. // write fragemnts for both streams
  934. for ( i=0; i<MAX_STREAMS; i++ )
  935. {
  936. if ( subChan->numFragments[i] == 0 )
  937. {
  938. buf.WriteOneBit( 0 ); // no data for this stream
  939. continue;
  940. }
  941. dataFragments_t *data = m_WaitingList[i][0];
  942. buf.WriteOneBit( 1 ); // data follows:
  943. unsigned int offset = subChan->startFraggment[i]*FRAGMENT_SIZE;
  944. unsigned int length = subChan->numFragments[i]*FRAGMENT_SIZE;
  945. if ( (subChan->startFraggment[i]+subChan->numFragments[i]) == data->numFragments )
  946. {
  947. // we are sending the last fragment, adjust length
  948. int rest = FRAGMENT_SIZE - ( data->bytes % FRAGMENT_SIZE );
  949. if ( rest < FRAGMENT_SIZE )
  950. length -= rest;
  951. }
  952. // if all fragments can be send within a single packet, avoid overhead (if not a file)
  953. bool bSingleBlock = (subChan->numFragments[i] == data->numFragments) &&
  954. ( data->file == FILESYSTEM_INVALID_HANDLE );
  955. if ( bSingleBlock )
  956. {
  957. Assert( length == data->bytes );
  958. Assert( length < NET_MAX_PAYLOAD );
  959. Assert( offset == 0 );
  960. buf.WriteOneBit( 0 ); // single block bit
  961. // data compressed ?
  962. if ( data->isCompressed )
  963. {
  964. buf.WriteOneBit( 1 );
  965. buf.WriteUBitLong( data->nUncompressedSize, MAX_FILE_SIZE_BITS );
  966. }
  967. else
  968. {
  969. buf.WriteOneBit( 0 );
  970. }
  971. buf.WriteVarInt32( data->bytes );
  972. }
  973. else
  974. {
  975. buf.WriteOneBit( 1 ); // uses fragments with start fragment offset byte
  976. buf.WriteUBitLong( subChan->startFraggment[i], (MAX_FILE_SIZE_BITS-FRAGMENT_BITS) );
  977. buf.WriteUBitLong( subChan->numFragments[i], 3 );
  978. if ( offset == 0 )
  979. {
  980. // this is the first fragment, write header info
  981. if ( data->file != FILESYSTEM_INVALID_HANDLE )
  982. {
  983. buf.WriteOneBit( 1 ); // file transmission net message stream
  984. buf.WriteUBitLong( data->transferID, 32 );
  985. buf.WriteString( data->filename );
  986. }
  987. else
  988. {
  989. buf.WriteOneBit( 0 ); // normal net message stream
  990. }
  991. // data compressed ?
  992. if ( data->isCompressed )
  993. {
  994. buf.WriteOneBit( 1 );
  995. buf.WriteUBitLong( data->nUncompressedSize, MAX_FILE_SIZE_BITS );
  996. }
  997. else
  998. {
  999. buf.WriteOneBit( 0 );
  1000. }
  1001. buf.WriteUBitLong( data->bytes, MAX_FILE_SIZE_BITS ); // 4MB max for files
  1002. }
  1003. }
  1004. // write fragments to buffer
  1005. if ( data->buffer )
  1006. {
  1007. Assert( data->file == FILESYSTEM_INVALID_HANDLE );
  1008. // send from memory block
  1009. buf.WriteBytes( data->buffer+offset, length );
  1010. }
  1011. else // if ( data->file != FILESYSTEM_INVALID_HANDLE )
  1012. {
  1013. // send from file
  1014. Assert( data->file != FILESYSTEM_INVALID_HANDLE );
  1015. char * tmpbuf = (char*)_alloca( length ); // alloc on stack
  1016. g_pFileSystem->Seek( data->file, offset, FILESYSTEM_SEEK_HEAD );
  1017. g_pFileSystem->Read( tmpbuf, length, data->file );
  1018. buf.WriteBytes( tmpbuf, length );
  1019. }
  1020. if ( net_showfragments.GetBool() )
  1021. {
  1022. ConMsg("Sending subchan %i: start %i, num %i\n", subChan->index, subChan->startFraggment[i], subChan->numFragments[i] );
  1023. }
  1024. subChan->sendSeqNr = m_nOutSequenceNr;
  1025. subChan->state = SUBCHANNEL_WAITING;
  1026. }
  1027. return true;
  1028. }
  1029. bool CNetChan::ReadSubChannelData( bf_read &buf, int stream )
  1030. {
  1031. dataFragments_t * data = &m_ReceiveList[stream]; // get list
  1032. int startFragment = 0;
  1033. int numFragments = 0;
  1034. unsigned int offset = 0;
  1035. unsigned int length = 0;
  1036. bool bSingleBlock = buf.ReadOneBit() == 0; // is single block ?
  1037. if ( !bSingleBlock )
  1038. {
  1039. startFragment = buf.ReadUBitLong( MAX_FILE_SIZE_BITS-FRAGMENT_BITS ); // 16 MB max
  1040. numFragments = buf.ReadUBitLong( 3 ); // 8 fragments per packet max
  1041. offset = startFragment * FRAGMENT_SIZE;
  1042. length = numFragments * FRAGMENT_SIZE;
  1043. }
  1044. if ( offset == 0 ) // first fragment, read header info
  1045. {
  1046. data->filename[0] = 0;
  1047. data->isCompressed = false;
  1048. data->transferID = 0;
  1049. if ( bSingleBlock )
  1050. {
  1051. // data compressed ?
  1052. if ( buf.ReadOneBit() )
  1053. {
  1054. data->isCompressed = true;
  1055. data->nUncompressedSize = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1056. }
  1057. else
  1058. {
  1059. data->isCompressed = false;
  1060. }
  1061. data->bytes = buf.ReadVarInt32();
  1062. }
  1063. else
  1064. {
  1065. if ( buf.ReadOneBit() ) // is it a file ?
  1066. {
  1067. data->transferID = buf.ReadUBitLong( 32 );
  1068. buf.ReadString( data->filename, MAX_OSPATH );
  1069. }
  1070. // data compressed ?
  1071. if ( buf.ReadOneBit() )
  1072. {
  1073. data->isCompressed = true;
  1074. data->nUncompressedSize = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1075. }
  1076. else
  1077. {
  1078. data->isCompressed = false;
  1079. }
  1080. data->bytes = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1081. }
  1082. if ( data->buffer )
  1083. {
  1084. // last transmission was aborted, free data
  1085. delete [] data->buffer;
  1086. data->buffer = NULL;
  1087. ConDMsg( "Fragment transmission aborted at %i/%i from %s.\n", data->ackedFragments, data->numFragments, GetAddress() );
  1088. }
  1089. data->bits = data->bytes * 8;
  1090. data->asTCP = false;
  1091. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  1092. data->ackedFragments = 0;
  1093. data->file = FILESYSTEM_INVALID_HANDLE;
  1094. if ( bSingleBlock )
  1095. {
  1096. numFragments = data->numFragments;
  1097. length = numFragments * FRAGMENT_SIZE;
  1098. }
  1099. if ( data->bytes > MAX_FILE_SIZE )
  1100. {
  1101. // This can happen with the compressed path above, which uses VarInt32 rather than MAX_FILE_SIZE_BITS
  1102. Warning( "Net message exceeds max size (%u / %u)\n", MAX_FILE_SIZE, data->bytes );
  1103. // Subsequent packets for this transfer will treated as invalid since we never setup a buffer.
  1104. return false;
  1105. }
  1106. data->buffer = new char[PAD_NUMBER(data->bytes, 4)];
  1107. }
  1108. else
  1109. {
  1110. if ( data->buffer == NULL )
  1111. {
  1112. // This can occur if the packet containing the "header" (offset == 0) is dropped. Since we need the header to arrive we'll just wait
  1113. // for a retry
  1114. // ConDMsg("Received fragment out of order: %i/%i\n", startFragment, numFragments );
  1115. return false;
  1116. }
  1117. }
  1118. if ( (startFragment+numFragments) == data->numFragments )
  1119. {
  1120. // we are receiving the last fragment, adjust length
  1121. int rest = FRAGMENT_SIZE - ( data->bytes % FRAGMENT_SIZE );
  1122. if ( rest < FRAGMENT_SIZE )
  1123. length -= rest;
  1124. }
  1125. else if ( ( startFragment + numFragments ) > data->numFragments )
  1126. {
  1127. // a malicious client can send a fragment beyond what was arranged in fragment#0 header
  1128. // old code will overrun the allocated buffer and likely cause a server crash
  1129. // it could also cause a client memory overrun because the offset can be anywhere from 0 to 16MB range
  1130. // drop the packet and wait for client to retry
  1131. ConDMsg( "Received fragment chunk out of bounds: %i+%i>%i from %s\n", startFragment, numFragments, data->numFragments, GetAddress() );
  1132. return false;
  1133. }
  1134. Assert ( (offset + length) <= data->bytes );
  1135. if ( length == 0 || ( offset + length > data->bytes ) )
  1136. {
  1137. delete[] data->buffer;
  1138. data->buffer = NULL;
  1139. ConMsg("Malformed fragment ofs %i len %d, buffer size %d from %s\n", offset, length, PAD_NUMBER(data->bytes, 4), remote_address.ToString() );
  1140. return false;
  1141. }
  1142. buf.ReadBytes( data->buffer + offset, length ); // read data
  1143. data->ackedFragments+= numFragments;
  1144. if ( net_showfragments.GetBool() )
  1145. ConMsg("Received fragments: start %i, num %i\n", startFragment, numFragments );
  1146. return true;
  1147. }
  1148. void CNetChan::UpdateSubChannels()
  1149. {
  1150. // first check if there is a free subchannel
  1151. subChannel_s * freeSubChan = GetFreeSubChannel();
  1152. if ( freeSubChan == NULL )
  1153. return; //all subchannels in use right now
  1154. int i, nSendMaxFragments = m_MaxReliablePayloadSize / FRAGMENT_SIZE;
  1155. bool bSendData = false;
  1156. for ( i = 0; i < MAX_STREAMS; i++ )
  1157. {
  1158. if ( m_WaitingList[i].Count() <= 0 )
  1159. continue;
  1160. dataFragments_s *data = m_WaitingList[i][0]; // get head
  1161. if ( data->asTCP )
  1162. continue;
  1163. int nSentFragments = data->ackedFragments + data->pendingFragments;
  1164. Assert( nSentFragments <= data->numFragments );
  1165. if ( nSentFragments == data->numFragments )
  1166. continue; // all fragments already send
  1167. // how many fragments can we send ?
  1168. int numFragments = min( nSendMaxFragments, data->numFragments - nSentFragments );
  1169. // if we are in file background transmission mode, just send one fragment per packet
  1170. if ( i == FRAG_FILE_STREAM && m_bFileBackgroundTranmission )
  1171. numFragments = min( 1, numFragments );
  1172. // copy fragment data into subchannel
  1173. freeSubChan->startFraggment[i] = nSentFragments;
  1174. freeSubChan->numFragments[i] = numFragments;
  1175. data->pendingFragments += numFragments;
  1176. bSendData = true;
  1177. nSendMaxFragments -= numFragments;
  1178. if ( nSendMaxFragments <= 0 )
  1179. break;
  1180. }
  1181. if ( bSendData )
  1182. {
  1183. // flip channel bit
  1184. int bit = 1<<freeSubChan->index;
  1185. FLIPBIT(m_nOutReliableState, bit);
  1186. freeSubChan->state = SUBCHANNEL_TOSEND;
  1187. freeSubChan->sendSeqNr = 0;
  1188. }
  1189. }
  1190. #if 1
  1191. inline unsigned short BufferToShortChecksum( const void *pvData, size_t nLength )
  1192. {
  1193. CRC32_t crc = CRC32_ProcessSingleBuffer( pvData, nLength );
  1194. unsigned short lowpart = ( crc & 0xffff );
  1195. unsigned short highpart = ( ( crc >> 16 ) & 0xffff );
  1196. return (unsigned short)( lowpart ^ highpart );
  1197. }
  1198. #else
  1199. // If the CRC version ever is deemed to expensive, here's a quick xor version.
  1200. // It's probably not super robust.
  1201. inline unsigned short BufferToShortChecksum( const void *pvData, size_t nSize )
  1202. {
  1203. const uint32 *pData = (const uint32 *)pvData;
  1204. unsigned short us = 0;
  1205. while ( nSize >= sizeof( uint32 ) )
  1206. {
  1207. us ^= ( *pData & 0xffff );
  1208. us ^= ( ( *pData >> 16 ) & 0xffff );
  1209. nSize -= sizeof( uint32 );
  1210. pData += sizeof( uint32 );
  1211. }
  1212. const byte *pbData = (const byte *)pData;
  1213. while ( nSize > 0 )
  1214. {
  1215. us ^= *pbData;
  1216. ++pbData;
  1217. --nSize;
  1218. }
  1219. return us;
  1220. }
  1221. #endif
  1222. // #define MIN_ROUTABLE_TESTING
  1223. #if defined( _DEBUG ) || defined( MIN_ROUTABLE_TESTING )
  1224. static ConVar net_minroutable( "net_minroutable", "16", 0, "Forces larger payloads." );
  1225. #endif
  1226. /*
  1227. ===============
  1228. CNetChan::TransmitBits
  1229. tries to send an unreliable message to a connection, and handles the
  1230. transmition / retransmition of the reliable messages.
  1231. A 0 length will still generate a packet and deal with the reliable messages.
  1232. ================
  1233. */
  1234. int CNetChan::SendDatagram(bf_write *datagram)
  1235. {
  1236. ALIGN4 byte send_buf[ NET_MAX_MESSAGE ] ALIGN4_POST;
  1237. #ifndef NO_VCR
  1238. if ( vcr_verbose.GetInt() && datagram && datagram->GetNumBytesWritten() > 0 )
  1239. VCRGenericValueVerify( "datagram", datagram->GetBasePointer(), datagram->GetNumBytesWritten()-1 );
  1240. #endif
  1241. // Make sure for the client that the max routable payload size is up to date
  1242. if ( m_Socket == NS_CLIENT )
  1243. {
  1244. if ( net_maxroutable.GetInt() != GetMaxRoutablePayloadSize() )
  1245. {
  1246. SetMaxRoutablePayloadSize( net_maxroutable.GetInt() );
  1247. }
  1248. }
  1249. // first increase out sequence number
  1250. // check, if fake client, then fake send also
  1251. if ( remote_address.GetType() == NA_NULL )
  1252. {
  1253. // this is a demo channel, fake sending all data
  1254. m_fClearTime = 0.0; // no bandwidth delay
  1255. m_nChokedPackets = 0; // Reset choke state
  1256. m_StreamReliable.Reset(); // clear current reliable buffer
  1257. m_StreamUnreliable.Reset(); // clear current unrelaible buffer
  1258. m_nOutSequenceNr++;
  1259. return m_nOutSequenceNr-1;
  1260. }
  1261. // process all new and pending reliable data, return true if reliable data should
  1262. // been send with this packet
  1263. if ( m_StreamReliable.IsOverflowed() )
  1264. {
  1265. ConMsg ("%s:send reliable stream overflow\n" ,remote_address.ToString());
  1266. return 0;
  1267. }
  1268. else if ( m_StreamReliable.GetNumBitsWritten() > 0 )
  1269. {
  1270. CreateFragmentsFromBuffer( &m_StreamReliable, FRAG_NORMAL_STREAM );
  1271. m_StreamReliable.Reset();
  1272. }
  1273. bf_write send( "CNetChan_TransmitBits->send", send_buf, sizeof(send_buf) );
  1274. // Prepare the packet header
  1275. // build packet flags
  1276. unsigned char flags = 0;
  1277. // start writing packet
  1278. send.WriteLong ( m_nOutSequenceNr );
  1279. send.WriteLong ( m_nInSequenceNr );
  1280. bf_write flagsPos = send; // remember flags byte position
  1281. send.WriteByte ( 0 ); // write correct flags value later
  1282. if ( ShouldChecksumPackets() )
  1283. {
  1284. send.WriteShort( 0 ); // write correct checksum later
  1285. Assert( !(send.GetNumBitsWritten() % 8 ) );
  1286. }
  1287. // Note, this only matters on the PC
  1288. int nCheckSumStart = send.GetNumBytesWritten();
  1289. send.WriteByte ( m_nInReliableState );
  1290. if ( m_nChokedPackets > 0 )
  1291. {
  1292. flags |= PACKET_FLAG_CHOKED;
  1293. send.WriteByte ( m_nChokedPackets & 0xFF ); // send number of choked packets
  1294. }
  1295. // always append a challenge number
  1296. flags |= PACKET_FLAG_CHALLENGE ;
  1297. // append the challenge number itself right on the end
  1298. send.WriteLong( m_ChallengeNr );
  1299. if ( SendSubChannelData( send ) )
  1300. {
  1301. flags |= PACKET_FLAG_RELIABLE;
  1302. }
  1303. // Is there room for given datagram data. the datagram data
  1304. // is somewhat more important than the normal unreliable data
  1305. // this is done to allow some kind of snapshot behavior
  1306. // weather all data in datagram is transmitted or none.
  1307. if ( datagram )
  1308. {
  1309. if( datagram->GetNumBitsWritten() < send.GetNumBitsLeft() )
  1310. {
  1311. send.WriteBits( datagram->GetData(), datagram->GetNumBitsWritten() );
  1312. }
  1313. else
  1314. {
  1315. ConDMsg("CNetChan::SendDatagram: data would overfow, ignoring\n");
  1316. }
  1317. }
  1318. // Is there room for the unreliable payload?
  1319. if ( m_StreamUnreliable.GetNumBitsWritten() < send.GetNumBitsLeft() )
  1320. {
  1321. send.WriteBits(m_StreamUnreliable.GetData(), m_StreamUnreliable.GetNumBitsWritten() );
  1322. }
  1323. else
  1324. {
  1325. ConDMsg("CNetChan::SendDatagram: Unreliable would overfow, ignoring\n");
  1326. }
  1327. m_StreamUnreliable.Reset(); // clear unreliable data buffer
  1328. // On the PC the voice data is in the main packet
  1329. if ( !IsX360() &&
  1330. m_StreamVoice.GetNumBitsWritten() > 0 && m_StreamVoice.GetNumBitsWritten() < send.GetNumBitsLeft() )
  1331. {
  1332. send.WriteBits(m_StreamVoice.GetData(), m_StreamVoice.GetNumBitsWritten() );
  1333. m_StreamVoice.Reset();
  1334. }
  1335. int nMinRoutablePayload = MIN_ROUTABLE_PAYLOAD;
  1336. #if defined( _DEBUG ) || defined( MIN_ROUTABLE_TESTING )
  1337. if ( m_Socket == NS_SERVER )
  1338. {
  1339. nMinRoutablePayload = net_minroutable.GetInt();
  1340. }
  1341. #endif
  1342. // Deal with packets that are too small for some networks
  1343. while ( send.GetNumBytesWritten() < nMinRoutablePayload )
  1344. {
  1345. // Go ahead and pad some bits as long as needed
  1346. send.WriteUBitLong( net_NOP, NETMSG_TYPE_BITS );
  1347. }
  1348. // Make sure we have enough bits to read a final net_NOP opcode before compressing
  1349. int nRemainingBits = send.GetNumBitsWritten() % 8;
  1350. if ( nRemainingBits > 0 && nRemainingBits <= (8-NETMSG_TYPE_BITS) )
  1351. {
  1352. send.WriteUBitLong( net_NOP, NETMSG_TYPE_BITS );
  1353. }
  1354. // if ( IsX360() )
  1355. {
  1356. // Now round up to byte boundary
  1357. nRemainingBits = send.GetNumBitsWritten() % 8;
  1358. if ( nRemainingBits > 0 )
  1359. {
  1360. int nPadBits = 8 - nRemainingBits;
  1361. flags |= ENCODE_PAD_BITS( nPadBits );
  1362. // Pad with ones
  1363. if ( nPadBits > 0 )
  1364. {
  1365. unsigned int unOnes = GetBitForBitnum( nPadBits ) - 1;
  1366. send.WriteUBitLong( unOnes, nPadBits );
  1367. }
  1368. }
  1369. }
  1370. // FIXME: This isn't actually correct since compression might make the main payload usage a bit smaller
  1371. bool bSendVoice = IsX360() && ( m_StreamVoice.GetNumBitsWritten() > 0 && m_StreamVoice.GetNumBitsWritten() < send.GetNumBitsLeft() );
  1372. bool bCompress = false;
  1373. if ( net_compresspackets.GetBool() )
  1374. {
  1375. if ( send.GetNumBytesWritten() >= net_compresspackets_minsize.GetInt() )
  1376. {
  1377. bCompress = true;
  1378. }
  1379. }
  1380. // write correct flags value and the checksum
  1381. flagsPos.WriteByte( flags );
  1382. // Compute checksum (must be aligned to a byte boundary!!)
  1383. if ( ShouldChecksumPackets() )
  1384. {
  1385. const void *pvData = send.GetData() + nCheckSumStart;
  1386. Assert( !(send.GetNumBitsWritten() % 8 ) );
  1387. int nCheckSumBytes = send.GetNumBytesWritten() - nCheckSumStart;
  1388. unsigned short usCheckSum = BufferToShortChecksum( pvData, nCheckSumBytes );
  1389. flagsPos.WriteUBitLong( usCheckSum, 16 );
  1390. }
  1391. // Send the datagram
  1392. int bytesSent = NET_SendPacket ( this, m_Socket, remote_address, send.GetData(), send.GetNumBytesWritten(), bSendVoice ? &m_StreamVoice : 0, bCompress );
  1393. if ( bSendVoice || !IsX360() )
  1394. {
  1395. m_StreamVoice.Reset();
  1396. }
  1397. if ( net_showudp.GetInt() && net_showudp.GetInt() != 2 )
  1398. {
  1399. int mask = 63;
  1400. char comp[ 64 ] = { 0 };
  1401. if ( net_compresspackets.GetBool() &&
  1402. bytesSent &&
  1403. ( bytesSent < send.GetNumBytesWritten() ) )
  1404. {
  1405. Q_snprintf( comp, sizeof( comp ), " compression=%5u [%5.2f %%]", bytesSent, 100.0f * float( bytesSent ) / float( send.GetNumBytesWritten() ) );
  1406. }
  1407. ConMsg ("UDP -> %12.12s: sz=%5i seq=%5i ack=%5i rel=%1i ch=%1i tm=%f rt=%f%s\n"
  1408. , GetName()
  1409. , send.GetNumBytesWritten()
  1410. , ( m_nOutSequenceNr ) & mask
  1411. , m_nInSequenceNr & mask
  1412. , (flags & PACKET_FLAG_RELIABLE) ? 1 : 0
  1413. , flags & PACKET_FLAG_CHALLENGE ? 1 : 0
  1414. , (float)net_time
  1415. , (float)Plat_FloatTime()
  1416. , comp );
  1417. }
  1418. // update stats
  1419. int nTotalSize = bytesSent + UDP_HEADER_SIZE;
  1420. FlowNewPacket( FLOW_OUTGOING, m_nOutSequenceNr, m_nInSequenceNr, m_nChokedPackets, 0, nTotalSize );
  1421. FlowUpdate( FLOW_OUTGOING, nTotalSize );
  1422. if ( m_fClearTime < net_time )
  1423. {
  1424. m_fClearTime = net_time;
  1425. }
  1426. // calculate net_time when channel will be ready for next packet (throttling)
  1427. // TODO: This doesn't exactly match size sent when packet is a "split" packet (actual bytes sent is higher, etc.)
  1428. double fAddTime = (float)nTotalSize / (float)m_Rate;
  1429. m_fClearTime += fAddTime;
  1430. if ( net_maxcleartime.GetFloat() > 0.0f )
  1431. {
  1432. double m_flLatestClearTime = net_time + net_maxcleartime.GetFloat();
  1433. if ( m_fClearTime > m_flLatestClearTime )
  1434. {
  1435. m_fClearTime = m_flLatestClearTime;
  1436. }
  1437. }
  1438. m_nChokedPackets = 0;
  1439. m_nOutSequenceNr++;
  1440. return m_nOutSequenceNr-1; // return send seq nr
  1441. }
  1442. bool CNetChan::ProcessControlMessage( int cmd, bf_read &buf)
  1443. {
  1444. char string[1024];
  1445. if ( cmd == net_NOP )
  1446. {
  1447. return true;
  1448. }
  1449. if ( cmd == net_Disconnect )
  1450. {
  1451. buf.ReadString( string, sizeof(string) );
  1452. m_MessageHandler->ConnectionClosing( string );
  1453. return false;
  1454. }
  1455. if ( cmd == net_File )
  1456. {
  1457. unsigned int transferID = buf.ReadUBitLong( 32 );
  1458. buf.ReadString( string, sizeof(string) );
  1459. if ( buf.ReadOneBit() != 0 && IsValidFileForTransfer( string ) )
  1460. {
  1461. m_MessageHandler->FileRequested( string, transferID );
  1462. }
  1463. else
  1464. {
  1465. m_MessageHandler->FileDenied( string, transferID );
  1466. }
  1467. return true;
  1468. }
  1469. ConMsg( "Netchannel: received bad control cmd %i from %s.\n", cmd, remote_address.ToString() );
  1470. return false;
  1471. }
  1472. bool CNetChan::ProcessMessages( bf_read &buf )
  1473. {
  1474. VPROF( "CNetChan::ProcessMessages" );
  1475. const char * showmsgname = net_showmsg.GetString();
  1476. const char * blockmsgname = net_blockmsg.GetString();
  1477. if ( !Q_strcmp(showmsgname, "0") )
  1478. {
  1479. showmsgname = NULL; // dont do strcmp all the time
  1480. }
  1481. if ( !Q_strcmp(blockmsgname, "0") )
  1482. {
  1483. blockmsgname = NULL; // dont do strcmp all the time
  1484. }
  1485. if ( net_showpeaks.GetInt() > 0 && net_showpeaks.GetInt() < buf.GetNumBytesLeft() )
  1486. {
  1487. showmsgname = "1"; // show messages for this packet only
  1488. }
  1489. bf_read democopy = buf; // create a copy of reading buffer state for demo recording
  1490. int startbit = buf.GetNumBitsRead();
  1491. while ( true )
  1492. {
  1493. if ( buf.IsOverflowed() )
  1494. {
  1495. m_MessageHandler->ConnectionCrashed( "Buffer overflow in net message" );
  1496. return false;
  1497. }
  1498. // Are we at the end?
  1499. if ( buf.GetNumBitsLeft() < NETMSG_TYPE_BITS )
  1500. {
  1501. break;
  1502. }
  1503. unsigned char cmd = buf.ReadUBitLong( NETMSG_TYPE_BITS );
  1504. if ( cmd <= net_File )
  1505. {
  1506. if ( !ProcessControlMessage( cmd, buf ) )
  1507. {
  1508. return false; // disconnect or error
  1509. }
  1510. continue;
  1511. }
  1512. // see if we have a registered message object for this type
  1513. INetMessage * netmsg = FindMessage( cmd );
  1514. if ( netmsg )
  1515. {
  1516. // let message parse itself from buffe
  1517. const char *msgname = netmsg->GetName();
  1518. int nMsgStartBit = buf.GetNumBitsRead();
  1519. if ( !netmsg->ReadFromBuffer( buf ) )
  1520. {
  1521. ConMsg( "Netchannel: failed reading message %s from %s.\n", msgname, remote_address.ToString() );
  1522. Assert ( 0 );
  1523. return false;
  1524. }
  1525. UpdateMessageStats( netmsg->GetGroup(), buf.GetNumBitsRead() - nMsgStartBit );
  1526. if ( showmsgname )
  1527. {
  1528. if ( (*showmsgname == '1') || !Q_stricmp(showmsgname, netmsg->GetName() ) )
  1529. {
  1530. ConMsg("Msg from %s: %s\n", remote_address.ToString(), netmsg->ToString() );
  1531. }
  1532. }
  1533. if ( blockmsgname )
  1534. {
  1535. if ( (*blockmsgname== '1') || !Q_stricmp(blockmsgname, netmsg->GetName() ) )
  1536. {
  1537. ConMsg("Blocking message %s\n", netmsg->ToString() );
  1538. continue;
  1539. }
  1540. }
  1541. // netmessage calls the Process function that was registered by it's MessageHandler
  1542. m_bProcessingMessages = true;
  1543. bool bRet = netmsg->Process();
  1544. m_bProcessingMessages = false;
  1545. // This means we were deleted during the processing of that message.
  1546. if ( m_bShouldDelete )
  1547. {
  1548. delete this;
  1549. return false;
  1550. }
  1551. if ( m_bClearedDuringProcessing )
  1552. {
  1553. // Clear() was called during processing, our buffer is no longer valid
  1554. m_bClearedDuringProcessing = false;
  1555. return false;
  1556. }
  1557. if ( !bRet )
  1558. {
  1559. ConDMsg( "Netchannel: failed processing message %s.\n", msgname );
  1560. Assert ( 0 );
  1561. return false;
  1562. }
  1563. if ( IsOverflowed() )
  1564. return false;
  1565. }
  1566. else
  1567. {
  1568. ConMsg( "Netchannel: unknown net message (%i) from %s.\n", cmd, remote_address.ToString() );
  1569. Assert ( 0 );
  1570. return false;
  1571. }
  1572. }
  1573. #if !defined(SWDS) && !defined(_XBOX)
  1574. // all messages could be parsed, write packet to demo file
  1575. if ( m_DemoRecorder && !demoplayer->IsPlayingBack() )
  1576. {
  1577. // only record if any message was paresd
  1578. m_DemoRecorder->RecordMessages( democopy, buf.GetNumBitsRead() - startbit );
  1579. }
  1580. #endif
  1581. return true; // ok fine
  1582. }
  1583. void CNetChan::ProcessPlayback( void )
  1584. {
  1585. #if !defined(SWDS) && !defined(_XBOX)
  1586. netpacket_t * packet;
  1587. while ( ( packet = demoplayer->ReadPacket() ) != NULL )
  1588. {
  1589. // Update data flow stats
  1590. FlowNewPacket( FLOW_INCOMING, m_nInSequenceNr, m_nOutSequenceNrAck, 0, 0, packet->wiresize );
  1591. last_received = net_time;
  1592. m_MessageHandler->PacketStart( m_nInSequenceNr, m_nOutSequenceNrAck );
  1593. if ( ProcessMessages( packet->message ) )
  1594. {
  1595. m_MessageHandler->PacketEnd();
  1596. }
  1597. else
  1598. {
  1599. break;
  1600. }
  1601. }
  1602. #endif
  1603. }
  1604. CNetChan::subChannel_s *CNetChan::GetFreeSubChannel()
  1605. {
  1606. for ( int i=0; i<MAX_SUBCHANNELS; i++ )
  1607. {
  1608. if ( m_SubChannels[i].state == SUBCHANNEL_FREE )
  1609. return &m_SubChannels[i];
  1610. }
  1611. return NULL;
  1612. }
  1613. void CNetChan::CheckWaitingList(int nList)
  1614. {
  1615. // go thru waiting lists and mark fragments send with this seqnr packet
  1616. if ( m_WaitingList[nList].Count() == 0 || m_nOutSequenceNrAck <= 0 )
  1617. return; // no data in list
  1618. dataFragments_t *data = m_WaitingList[nList][0]; // get head
  1619. if ( data->ackedFragments == data->numFragments )
  1620. {
  1621. // all fragmenst were send successfully
  1622. if ( net_showfragments.GetBool() )
  1623. ConMsg("Sending complete: %i fragments, %i bytes.\n", data->numFragments, data->bytes );
  1624. RemoveHeadInWaitingList( nList );
  1625. return;
  1626. }
  1627. else if ( data->ackedFragments > data->numFragments )
  1628. {
  1629. //ConMsg("CheckWaitingList: invalid acknowledge fragments %i/%i.\n", data->ackedFragments, data->numFragments );
  1630. }
  1631. // else: still pending fragments
  1632. }
  1633. #ifdef STAGING_ONLY
  1634. CON_COMMAND( netchan_test_upload, "[filename]: Uploads a file to server." )
  1635. {
  1636. if ( args.ArgC() != 2 )
  1637. {
  1638. Msg( "Usage: netchan_test_upload [filename]\n" );
  1639. return;
  1640. }
  1641. //$ TODO: the con command system is truncating the filenames we're passing in. Need to workaround this...
  1642. const char *filename = args.GetCommandString() + V_strlen( "netchan_test_upload " );
  1643. Msg( "Sending '%s'\n", filename );
  1644. bool bRet = CNetChan::TestUpload( filename );
  1645. Msg( "%s returned %d\n", __FUNCTION__, bRet );
  1646. }
  1647. bool CNetChan::TestUpload( const char *filename )
  1648. {
  1649. dataFragments_t data;
  1650. static char s_buf[] = "The quick brown\nfox\n";
  1651. data.file = FILESYSTEM_INVALID_HANDLE; // open file handle
  1652. V_strcpy_safe( data.filename, filename ); // filename
  1653. data.buffer = s_buf; // if NULL it's a file
  1654. data.bytes = sizeof( s_buf ) - 1; // size in bytes
  1655. data.bits = data.bytes * 8; // size in bits
  1656. data.transferID = 123; // only for files
  1657. data.isCompressed = false; // true if data is bzip compressed
  1658. data.nUncompressedSize = data.bytes; // full size in bytes
  1659. data.asTCP = 0; // send as TCP stream
  1660. data.numFragments = 0; // number of total fragments
  1661. data.ackedFragments = 0; // number of fragments send & acknowledged
  1662. data.pendingFragments = 0; // number of fragments send, but not acknowledged yet
  1663. return HandleUpload( &data, NULL );
  1664. }
  1665. #endif // STAGING_ONLY
  1666. bool CNetChan::HandleUpload( dataFragments_t *data, INetChannelHandler *MessageHandler )
  1667. {
  1668. const char *szErrorStr = NULL;
  1669. static ConVar *s_pAllowUpload = g_pCVar->FindVar( "sv_allowupload" );
  1670. if ( !s_pAllowUpload || !s_pAllowUpload->GetBool() )
  1671. {
  1672. szErrorStr = "ignored. File uploads are disabled!";
  1673. }
  1674. else
  1675. {
  1676. // Make sure that this file is not being written to a location above the current directory, isn't in
  1677. // writing to any locations we don't want, isn't an unsupported
  1678. if ( !CNetChan::IsValidFileForTransfer( data->filename ) )
  1679. {
  1680. szErrorStr = "has invalid path or extension!";
  1681. }
  1682. else
  1683. {
  1684. // There's a special write path for this stuff
  1685. const char *pszPathID = "download";
  1686. // we received a file, write it to disk and notify host
  1687. if ( g_pFileSystem->FileExists( data->filename, pszPathID ) )
  1688. {
  1689. szErrorStr = "already exists!";
  1690. }
  1691. else
  1692. {
  1693. // Make sure path exists
  1694. char szParentDir[ MAX_PATH ];
  1695. if ( !V_ExtractFilePath( data->filename, szParentDir, sizeof( szParentDir ) ) )
  1696. szParentDir[0] = '\0';
  1697. g_pFileSystem->CreateDirHierarchy( szParentDir, pszPathID );
  1698. // Open new file for write binary.
  1699. data->file = g_pFileSystem->Open( data->filename, "wb", pszPathID );
  1700. if ( FILESYSTEM_INVALID_HANDLE == data->file )
  1701. {
  1702. szErrorStr = "failed to write!";
  1703. }
  1704. else
  1705. {
  1706. g_pFileSystem->Write( data->buffer, data->bytes, data->file );
  1707. g_pFileSystem->Close( data->file );
  1708. if ( net_showfragments.GetInt() == 2 )
  1709. {
  1710. DevMsg( "FileReceived: %s, %i bytes (ID %i)\n", data->filename, data->bytes, data->transferID );
  1711. }
  1712. if ( MessageHandler )
  1713. {
  1714. MessageHandler->FileReceived( data->filename, data->transferID );
  1715. }
  1716. }
  1717. }
  1718. }
  1719. }
  1720. if ( szErrorStr )
  1721. {
  1722. ConMsg( "Download file '%s' %s\n", data->filename, szErrorStr );
  1723. }
  1724. return true;
  1725. }
  1726. bool CNetChan::CheckReceivingList(int nList)
  1727. {
  1728. dataFragments_t * data = &m_ReceiveList[nList]; // get list
  1729. if ( data->buffer == NULL )
  1730. return true;
  1731. if ( data->ackedFragments < data->numFragments )
  1732. return true;
  1733. if ( data->ackedFragments > data->numFragments )
  1734. {
  1735. ConMsg( "Receiving failed: too many fragments %i/%i from %s\n", data->ackedFragments, data->numFragments, GetAddress() );
  1736. return false;
  1737. }
  1738. // Got all fragments.
  1739. if ( net_showfragments.GetBool() )
  1740. ConMsg("Receiving complete: %i fragments, %i bytes\n", data->numFragments, data->bytes );
  1741. if ( data->isCompressed )
  1742. {
  1743. UncompressFragments( data );
  1744. }
  1745. if ( !data->filename[0] )
  1746. {
  1747. bf_read buffer( data->buffer, data->bytes );
  1748. if ( !ProcessMessages( buffer ) ) // parse net message
  1749. {
  1750. return false; // stop reading any further
  1751. }
  1752. }
  1753. else
  1754. {
  1755. HandleUpload( data, m_MessageHandler );
  1756. }
  1757. // clear receiveList
  1758. if ( data->buffer )
  1759. {
  1760. delete [] data->buffer;
  1761. data->buffer = NULL;
  1762. }
  1763. return true;
  1764. }
  1765. int CNetChan::ProcessPacketHeader( netpacket_t * packet )
  1766. {
  1767. // get sequence numbers
  1768. int sequence = packet->message.ReadLong();
  1769. int sequence_ack= packet->message.ReadLong();
  1770. int flags = packet->message.ReadByte();
  1771. if ( ShouldChecksumPackets() )
  1772. {
  1773. unsigned short usCheckSum = (unsigned short)packet->message.ReadUBitLong( 16 );
  1774. // Checksum applies to rest of packet
  1775. Assert( !( packet->message.GetNumBitsRead() % 8 ) );
  1776. int nOffset = packet->message.GetNumBitsRead() >> 3;
  1777. int nCheckSumBytes = packet->message.TotalBytesAvailable() - nOffset;
  1778. const void *pvData = packet->message.GetBasePointer() + nOffset;
  1779. unsigned short usDataCheckSum = BufferToShortChecksum( pvData, nCheckSumBytes );
  1780. if ( usDataCheckSum != usCheckSum )
  1781. {
  1782. ConMsg ("%s:corrupted packet %i at %i\n"
  1783. , remote_address.ToString ()
  1784. , sequence
  1785. , m_nInSequenceNr);
  1786. return -1;
  1787. }
  1788. }
  1789. int relState = packet->message.ReadByte(); // reliable state of 8 subchannels
  1790. int nChoked = 0; // read later if choked flag is set
  1791. int i,j;
  1792. if ( flags & PACKET_FLAG_CHOKED )
  1793. nChoked = packet->message.ReadByte();
  1794. if ( flags & PACKET_FLAG_CHALLENGE )
  1795. {
  1796. unsigned int nChallenge = packet->message.ReadLong();
  1797. if ( nChallenge != m_ChallengeNr )
  1798. return -1;
  1799. // challenge was good, latch we saw a good one
  1800. m_bStreamContainsChallenge = true;
  1801. }
  1802. else if ( m_bStreamContainsChallenge )
  1803. return -1; // what, no challenge in this packet but we got them before?
  1804. // discard stale or duplicated packets
  1805. if (sequence <= m_nInSequenceNr )
  1806. {
  1807. if ( net_showdrop.GetInt() )
  1808. {
  1809. if ( sequence == m_nInSequenceNr )
  1810. {
  1811. ConMsg ("%s:duplicate packet %i at %i\n"
  1812. , remote_address.ToString ()
  1813. , sequence
  1814. , m_nInSequenceNr);
  1815. }
  1816. else
  1817. {
  1818. ConMsg ("%s:out of order packet %i at %i\n"
  1819. , remote_address.ToString ()
  1820. , sequence
  1821. , m_nInSequenceNr);
  1822. }
  1823. }
  1824. return -1;
  1825. }
  1826. //
  1827. // dropped packets don't keep the message from being used
  1828. //
  1829. m_PacketDrop = sequence - (m_nInSequenceNr + nChoked + 1);
  1830. if ( m_PacketDrop > 0 )
  1831. {
  1832. if ( net_showdrop.GetInt() )
  1833. {
  1834. ConMsg ("%s:Dropped %i packets at %i\n"
  1835. ,remote_address.ToString(), m_PacketDrop, sequence );
  1836. }
  1837. }
  1838. if ( net_maxpacketdrop.GetInt() > 0 && m_PacketDrop > net_maxpacketdrop.GetInt() )
  1839. {
  1840. if ( net_showdrop.GetInt() )
  1841. {
  1842. ConMsg ("%s:Too many dropped packets (%i) at %i\n"
  1843. ,remote_address.ToString(), m_PacketDrop, sequence );
  1844. }
  1845. return -1;
  1846. }
  1847. for ( i = 0; i<MAX_SUBCHANNELS; i++ )
  1848. {
  1849. int bitmask = (1<<i);
  1850. // data of channel i has been acknowledged
  1851. subChannel_s * subchan = &m_SubChannels[i];
  1852. Assert( subchan->index == i);
  1853. if ( (m_nOutReliableState & bitmask) == (relState & bitmask) )
  1854. {
  1855. if ( subchan->state == SUBCHANNEL_DIRTY )
  1856. {
  1857. // subchannel was marked dirty during changelevel, waiting list is already cleared
  1858. subchan->Free();
  1859. }
  1860. else if ( subchan->sendSeqNr > sequence_ack )
  1861. {
  1862. ConMsg ("%s:reliable state invalid (%i).\n" ,remote_address.ToString(), i );
  1863. Assert( 0 );
  1864. return -1;
  1865. }
  1866. else if ( subchan->state == SUBCHANNEL_WAITING )
  1867. {
  1868. for ( j=0; j<MAX_STREAMS; j++ )
  1869. {
  1870. if ( subchan->numFragments[j] == 0 )
  1871. continue;
  1872. Assert( m_WaitingList[j].Count() > 0 );
  1873. dataFragments_t * data = m_WaitingList[j][0];
  1874. // tell waiting list, that we received the acknowledge
  1875. data->ackedFragments += subchan->numFragments[j];
  1876. data->pendingFragments -= subchan->numFragments[j];
  1877. }
  1878. subchan->Free(); // mark subchannel as free again
  1879. }
  1880. }
  1881. else // subchannel doesn't match
  1882. {
  1883. if ( subchan->sendSeqNr <= sequence_ack )
  1884. {
  1885. Assert( subchan->state != SUBCHANNEL_FREE );
  1886. if ( subchan->state == SUBCHANNEL_WAITING )
  1887. {
  1888. if ( net_showfragments.GetBool() )
  1889. {
  1890. ConMsg("Resending subchan %i: start %i, num %i\n", subchan->index, subchan->startFraggment[0], subchan->numFragments[0] );
  1891. }
  1892. subchan->state = SUBCHANNEL_TOSEND; // schedule for resend
  1893. }
  1894. else if ( subchan->state == SUBCHANNEL_DIRTY )
  1895. {
  1896. // remote host lost dirty channel data, flip bit back
  1897. int bit = 1<<subchan->index; // flip bit back since data was send yet
  1898. FLIPBIT(m_nOutReliableState, bit);
  1899. subchan->Free();
  1900. }
  1901. }
  1902. }
  1903. }
  1904. m_nInSequenceNr = sequence;
  1905. m_nOutSequenceNrAck = sequence_ack;
  1906. ETWReadPacket( packet->from.ToString(), packet->wiresize, m_nInSequenceNr, m_nOutSequenceNr );
  1907. // Update waiting list status
  1908. for( i=0; i<MAX_STREAMS;i++)
  1909. CheckWaitingList( i );
  1910. // Update data flow stats (use wiresize (compressed))
  1911. FlowNewPacket( FLOW_INCOMING, m_nInSequenceNr, m_nOutSequenceNrAck, nChoked, m_PacketDrop, packet->wiresize + UDP_HEADER_SIZE );
  1912. return flags;
  1913. }
  1914. /*
  1915. =================
  1916. CNetChan::ProcessPacket
  1917. called when a new packet has arrived for this netchannel
  1918. sequence numbers are extracted, fragments/file streams stripped
  1919. and then the netmessages processed
  1920. =================
  1921. */
  1922. void CNetChan::ProcessPacket( netpacket_t * packet, bool bHasHeader )
  1923. {
  1924. VPROF( "CNetChan::ProcessPacket" );
  1925. Assert( packet );
  1926. bf_read &msg = packet->message; // handy shortcut
  1927. if ( remote_address.IsValid() && !packet->from.CompareAdr ( remote_address ) )
  1928. {
  1929. return;
  1930. }
  1931. // Update data flow stats
  1932. FlowUpdate( FLOW_INCOMING, packet->wiresize + UDP_HEADER_SIZE );
  1933. int flags = 0;
  1934. if ( bHasHeader )
  1935. {
  1936. flags = ProcessPacketHeader( packet );
  1937. }
  1938. if ( flags == -1 )
  1939. return; // invalid header/packet
  1940. if ( net_showudp.GetInt() && net_showudp.GetInt() != 3 )
  1941. {
  1942. ConMsg ("UDP <- %s: sz=%i seq=%i ack=%i rel=%i ch=%d, tm=%f rt=%f wire=%i\n"
  1943. , GetName()
  1944. , packet->size
  1945. , m_nInSequenceNr & 63
  1946. , m_nOutSequenceNrAck & 63
  1947. , flags & PACKET_FLAG_RELIABLE ? 1 : 0
  1948. , flags & PACKET_FLAG_CHALLENGE ? 1 : 0
  1949. , net_time
  1950. , (float)Plat_FloatTime()
  1951. , packet->wiresize );
  1952. }
  1953. last_received = net_time;
  1954. // tell message handler that a new packet has arrived
  1955. m_MessageHandler->PacketStart( m_nInSequenceNr, m_nOutSequenceNrAck );
  1956. if ( flags & PACKET_FLAG_RELIABLE )
  1957. {
  1958. int i, bit = 1<<msg.ReadUBitLong( 3 );
  1959. for ( i=0; i<MAX_STREAMS; i++ )
  1960. {
  1961. if ( msg.ReadOneBit() != 0 )
  1962. {
  1963. if ( !ReadSubChannelData( msg, i ) )
  1964. return; // error while reading fragments, drop whole packet
  1965. }
  1966. }
  1967. // flip subChannel bit to signal successful receiving
  1968. FLIPBIT(m_nInReliableState, bit);
  1969. for ( i=0; i<MAX_STREAMS; i++ )
  1970. {
  1971. if ( !CheckReceivingList( i ) )
  1972. return; // error while processing
  1973. }
  1974. }
  1975. // Is there anything left to process?
  1976. if ( msg.GetNumBitsLeft() > 0 )
  1977. {
  1978. // parse and handle all messeges
  1979. if ( !ProcessMessages( msg ) )
  1980. {
  1981. return; // disconnect or error
  1982. }
  1983. }
  1984. // tell message handler that packet is completely parsed
  1985. m_MessageHandler->PacketEnd();
  1986. #if !defined(SWDS) && !defined(_XBOX)
  1987. // tell demo system that packet is completely parsed
  1988. if ( m_DemoRecorder && !demoplayer->IsPlayingBack() )
  1989. {
  1990. m_DemoRecorder->RecordPacket();
  1991. }
  1992. #endif
  1993. }
  1994. int CNetChan::GetNumBitsWritten( bool bReliable )
  1995. {
  1996. bf_write *pStream = &m_StreamUnreliable;
  1997. if ( bReliable )
  1998. {
  1999. pStream = &m_StreamReliable;
  2000. }
  2001. return pStream->GetNumBitsWritten();
  2002. }
  2003. bool CNetChan::SendNetMsg( INetMessage &msg, bool bForceReliable, bool bVoice )
  2004. {
  2005. if ( remote_address.GetType() == NA_NULL )
  2006. return true;
  2007. bf_write *pStream = &m_StreamUnreliable;
  2008. if ( msg.IsReliable() || bForceReliable )
  2009. {
  2010. pStream = &m_StreamReliable;
  2011. }
  2012. if ( bVoice )
  2013. {
  2014. pStream = &m_StreamVoice;
  2015. }
  2016. if ( vcr_verbose.GetInt() )
  2017. {
  2018. bool bRet = false;
  2019. #ifndef NO_VCR
  2020. int nOldBytes = pStream->GetNumBytesWritten();
  2021. bRet = msg.WriteToBuffer( *pStream );
  2022. int nNewBytes = pStream->GetNumBytesWritten();
  2023. if ( nNewBytes > nOldBytes )
  2024. {
  2025. VCRGenericValueVerify( "NetMsg", &pStream->GetBasePointer()[nOldBytes], nNewBytes-nOldBytes-1 );
  2026. }
  2027. #endif
  2028. return bRet;
  2029. }
  2030. else
  2031. {
  2032. return msg.WriteToBuffer( *pStream );
  2033. }
  2034. }
  2035. INetMessage *CNetChan::FindMessage(int type)
  2036. {
  2037. int numtypes = m_NetMessages.Count();
  2038. for (int i=0; i<numtypes; i++ )
  2039. {
  2040. if ( m_NetMessages[i]->GetType() == type )
  2041. return m_NetMessages[i];
  2042. }
  2043. return NULL;
  2044. }
  2045. bool CNetChan::RegisterMessage(INetMessage *msg)
  2046. {
  2047. Assert( msg );
  2048. if ( FindMessage( msg->GetType() ) )
  2049. {
  2050. return false;
  2051. }
  2052. m_NetMessages.AddToTail( msg );
  2053. msg->SetNetChannel( this );
  2054. return true;
  2055. }
  2056. bool CNetChan::SendData( bf_write &msg, bool bReliable )
  2057. {
  2058. // Always queue any pending reliable data ahead of the fragmentation buffer
  2059. if ( remote_address.GetType() == NA_NULL )
  2060. return true;
  2061. if ( msg.GetNumBitsWritten() <= 0 )
  2062. return true;
  2063. if ( msg.IsOverflowed() && !bReliable )
  2064. return true;
  2065. bf_write * buf = bReliable ? &m_StreamReliable : &m_StreamUnreliable;
  2066. if ( msg.GetNumBitsWritten() > buf->GetNumBitsLeft() )
  2067. {
  2068. if ( bReliable )
  2069. {
  2070. ConMsg( "ERROR! SendData reliabe data too big (%i)", msg.GetNumBytesWritten() );
  2071. }
  2072. return false;
  2073. }
  2074. return buf->WriteBits( msg.GetData(), msg.GetNumBitsWritten() );
  2075. }
  2076. bool CNetChan::SendReliableViaStream( dataFragments_t *data)
  2077. {
  2078. // Always queue any pending reliable data ahead of the fragmentation buffer
  2079. ALIGN4 char headerBuf[32] ALIGN4_POST;
  2080. bf_write header( "outDataHeader", headerBuf, sizeof(headerBuf) );
  2081. data->transferID = m_nOutSequenceNr; // used for acknowledging
  2082. data->pendingFragments = data->numFragments; // send, but not ACKed yet
  2083. header.WriteByte( STREAM_CMD_DATA );
  2084. header.WriteWord( data->bytes ); // bytes
  2085. header.WriteLong( data->transferID );
  2086. if ( net_showtcp.GetInt() )
  2087. {
  2088. ConMsg ("TCP -> %s: sz=%i seq=%i\n", remote_address.ToString(), data->bytes, m_nOutSequenceNr );
  2089. }
  2090. NET_SendStream( m_StreamSocket, (char*)header.GetData(), header.GetNumBytesWritten(), 0 );
  2091. return NET_SendStream( m_StreamSocket, data->buffer, data->bytes, 0 ) != -1;
  2092. }
  2093. bool CNetChan::SendReliableAcknowledge(int seqnr)
  2094. {
  2095. // Always queue any pending reliable data ahead of the fragmentation buffer
  2096. ALIGN4 char headerBuf[32] ALIGN4_POST;
  2097. bf_write header( "outAcknHeader", headerBuf, sizeof(headerBuf) );
  2098. header.WriteByte( STREAM_CMD_ACKN );
  2099. header.WriteLong( seqnr ); // used for acknowledging
  2100. if ( net_showtcp.GetInt() )
  2101. {
  2102. ConMsg ("TCP -> %s: ACKN seq=%i\n", remote_address.ToString(), seqnr );
  2103. }
  2104. return NET_SendStream( m_StreamSocket, (char*)header.GetData(), header.GetNumBytesWritten(), 0 ) > 0;
  2105. }
  2106. bool CNetChan::ProcessStream( void )
  2107. {
  2108. char cmd;
  2109. ALIGN4 char headerBuf[512] ALIGN4_POST;
  2110. if ( !m_StreamSocket )
  2111. return true;
  2112. if ( m_SteamType == STREAM_CMD_NONE )
  2113. {
  2114. // read command byte
  2115. int ret = NET_ReceiveStream( m_StreamSocket, &cmd, 1, 0 );
  2116. if ( ret == 0)
  2117. {
  2118. // nothing received, but ok
  2119. return true;
  2120. }
  2121. else if ( ret == -1 )
  2122. {
  2123. // something failed with the TCP connection
  2124. return false;
  2125. }
  2126. ResetStreaming(); // clear all state values
  2127. m_SteamType = cmd;
  2128. }
  2129. bf_read header( "inDataHeader", headerBuf, sizeof(headerBuf) );
  2130. // now check command type
  2131. if ( m_SteamType==STREAM_CMD_AUTH )
  2132. {
  2133. // server accpeted connection, send challenge nr
  2134. m_StreamActive = true;
  2135. ResetStreaming();
  2136. return SendReliableAcknowledge( m_ChallengeNr );
  2137. }
  2138. if ( (m_SteamType==STREAM_CMD_DATA) && (m_StreamLength==0) )
  2139. {
  2140. int ret = NET_ReceiveStream( m_StreamSocket, (char*)&headerBuf, 6, 0 ) ;
  2141. if ( ret == 0)
  2142. {
  2143. // nothing received, but ok
  2144. return true;
  2145. }
  2146. else if ( ret == -1 )
  2147. {
  2148. // something failed with the TCP connection
  2149. return false;
  2150. }
  2151. m_StreamLength = header.ReadWord();
  2152. m_StreamSeqNr = header.ReadLong();
  2153. const int cMaxPayload = GetProtocolVersion() > PROTOCOL_VERSION_23 ? NET_MAX_PAYLOAD : NET_MAX_PAYLOAD_V23;
  2154. if ( m_StreamLength > cMaxPayload )
  2155. {
  2156. ConMsg( "ERROR! Stream indata too big (%i)", m_StreamLength );
  2157. return false;
  2158. }
  2159. }
  2160. if ( (m_SteamType==STREAM_CMD_FILE) && (m_SteamFile[0]==0) )
  2161. {
  2162. Assert ( 0 );
  2163. return false;
  2164. }
  2165. if ( (m_SteamType==STREAM_CMD_ACKN) && (m_StreamSeqNr==0) )
  2166. {
  2167. int ret = NET_ReceiveStream( m_StreamSocket, (char*)&headerBuf, 4, 0 );
  2168. if ( ret == 0)
  2169. {
  2170. // nothing received, but ok
  2171. return true;
  2172. }
  2173. else if ( ret == -1 )
  2174. {
  2175. // something failed with the TCP connection
  2176. return false;
  2177. }
  2178. m_StreamSeqNr = header.ReadLong();
  2179. dataFragments_t * data = m_WaitingList[FRAG_NORMAL_STREAM][0];
  2180. if ( data->transferID == (unsigned)m_StreamSeqNr )
  2181. {
  2182. if ( net_showtcp.GetInt() )
  2183. {
  2184. ConMsg ("TCP <- %s: ACKN seqnr=%i\n", remote_address.ToString(), m_StreamSeqNr );
  2185. }
  2186. Assert( data->pendingFragments == data->numFragments );
  2187. RemoveHeadInWaitingList( FRAG_NORMAL_STREAM );
  2188. }
  2189. else
  2190. {
  2191. ConMsg ("TCP <- %s: invalid ACKN seqnr=%i\n", remote_address.ToString(), m_StreamSeqNr );
  2192. }
  2193. ResetStreaming();
  2194. return true;
  2195. }
  2196. if ( m_StreamReceived < m_StreamLength )
  2197. {
  2198. // read in 4kB chuncks
  2199. int bytesLeft = ( m_StreamLength - m_StreamReceived );
  2200. int bytesRecv = NET_ReceiveStream( m_StreamSocket, (char*)m_StreamData.Base() + m_StreamReceived, bytesLeft, 0 );
  2201. if ( bytesRecv == 0 )
  2202. {
  2203. return true;
  2204. }
  2205. else if ( bytesRecv == -1 )
  2206. {
  2207. return false;
  2208. }
  2209. m_StreamReceived+= bytesRecv;
  2210. if ( m_StreamReceived > m_StreamLength )
  2211. {
  2212. ConMsg( "ERROR! Stream indata oversize." );
  2213. return false;
  2214. }
  2215. if ( m_StreamReceived == m_StreamLength )
  2216. {
  2217. int ackseqnr =m_StreamSeqNr;
  2218. bf_read buffer( m_StreamData.Base(), m_StreamLength );
  2219. ProcessMessages( buffer );
  2220. // reset stream state
  2221. ResetStreaming();
  2222. return SendReliableAcknowledge( ackseqnr ); // tell sender that we have it
  2223. }
  2224. }
  2225. return true;
  2226. }
  2227. int CNetChan::GetDataRate() const
  2228. {
  2229. return m_Rate;
  2230. }
  2231. bool CNetChan::HasPendingReliableData( void )
  2232. {
  2233. return (m_StreamReliable.GetNumBitsWritten() > 0) ||
  2234. (m_WaitingList[FRAG_NORMAL_STREAM].Count() > 0) ||
  2235. (m_WaitingList[FRAG_FILE_STREAM].Count() > 0);
  2236. }
  2237. float CNetChan::GetTimeConnected() const
  2238. {
  2239. float t = net_time - connect_time;
  2240. return (t>0.0f) ? t : 0.0f ;
  2241. }
  2242. const netadr_t & CNetChan::GetRemoteAddress() const
  2243. {
  2244. return remote_address;
  2245. }
  2246. INetChannelHandler * CNetChan::GetMsgHandler( void ) const
  2247. {
  2248. return m_MessageHandler;
  2249. }
  2250. bool CNetChan::IsTimedOut() const
  2251. {
  2252. if ( m_Timeout == -1.0f )
  2253. return false;
  2254. else
  2255. return (last_received + m_Timeout) < net_time;
  2256. }
  2257. bool CNetChan::IsTimingOut() const
  2258. {
  2259. if ( m_Timeout == -1.0f )
  2260. return false;
  2261. else
  2262. return (last_received + CONNECTION_PROBLEM_TIME) < net_time;
  2263. }
  2264. float CNetChan::GetTimeoutSeconds() const
  2265. {
  2266. return m_Timeout;
  2267. }
  2268. float CNetChan::GetTimeSinceLastReceived() const
  2269. {
  2270. float t = net_time - last_received;
  2271. return (t>0.0f) ? t : 0.0f ;
  2272. }
  2273. bool CNetChan::IsOverflowed() const
  2274. {
  2275. return m_StreamReliable.IsOverflowed();
  2276. }
  2277. void CNetChan::Reset()
  2278. {
  2279. // FlowReset();
  2280. m_StreamUnreliable.Reset(); // clear any pending unreliable data messages
  2281. m_StreamReliable.Reset(); // clear any pending reliable data messages
  2282. m_fClearTime = 0.0; // ready to send
  2283. m_nChokedPackets = 0;
  2284. m_nSplitPacketSequence = 1;
  2285. }
  2286. int CNetChan::GetSocket() const
  2287. {
  2288. return m_Socket;
  2289. }
  2290. float CNetChan::GetAvgData( int flow ) const
  2291. {
  2292. return m_DataFlow[flow].avgbytespersec;
  2293. }
  2294. float CNetChan::GetAvgPackets( int flow ) const
  2295. {
  2296. return m_DataFlow[flow].avgpacketspersec;
  2297. }
  2298. //-----------------------------------------------------------------------------
  2299. // Purpose:
  2300. // Input : *chan -
  2301. //-----------------------------------------------------------------------------
  2302. int CNetChan::GetTotalData(int flow ) const
  2303. {
  2304. return m_DataFlow[flow].totalbytes;
  2305. }
  2306. int CNetChan::GetSequenceNr( int flow ) const
  2307. {
  2308. if ( flow == FLOW_OUTGOING )
  2309. {
  2310. return m_nOutSequenceNr;
  2311. }
  2312. else if ( flow == FLOW_INCOMING )
  2313. {
  2314. return m_nInSequenceNr;
  2315. }
  2316. return 0;
  2317. }
  2318. int CNetChan::GetBufferSize( void ) const
  2319. {
  2320. return NET_FRAMES_BACKUP;
  2321. }
  2322. bool CNetChan::IsValidPacket( int flow, int frame_number ) const
  2323. {
  2324. return m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ].valid;
  2325. }
  2326. float CNetChan::GetPacketTime( int flow, int frame_number ) const
  2327. {
  2328. return m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ].time;
  2329. }
  2330. void CNetChan::GetPacketResponseLatency( int flow, int frame_number, int *pnLatencyMsecs, int *pnChoke ) const
  2331. {
  2332. const netframe_t &nf = m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ];
  2333. if ( pnLatencyMsecs )
  2334. {
  2335. if ( nf.dropped )
  2336. {
  2337. *pnLatencyMsecs = 9999;
  2338. }
  2339. else
  2340. {
  2341. *pnLatencyMsecs = (int)( 1000.0f * nf.avg_latency );
  2342. }
  2343. }
  2344. if ( pnChoke )
  2345. {
  2346. *pnChoke = nf.choked;
  2347. }
  2348. }
  2349. void CNetChan::GetRemoteFramerate( float *pflFrameTime, float *pflRemoteFrameTimeStdDeviation ) const
  2350. {
  2351. if ( pflFrameTime )
  2352. {
  2353. *pflFrameTime = m_flRemoteFrameTime;
  2354. }
  2355. if ( pflRemoteFrameTimeStdDeviation )
  2356. {
  2357. *pflRemoteFrameTimeStdDeviation = m_flRemoteFrameTimeStdDeviation;
  2358. }
  2359. }
  2360. float CNetChan::GetLatency( int flow ) const
  2361. {
  2362. return m_DataFlow[flow].latency;
  2363. }
  2364. float CNetChan::GetAvgChoke( int flow ) const
  2365. {
  2366. return m_DataFlow[flow].avgchoke;
  2367. }
  2368. float CNetChan::GetAvgLatency( int flow ) const
  2369. {
  2370. return m_DataFlow[flow].avglatency;
  2371. }
  2372. float CNetChan::GetAvgLoss( int flow ) const
  2373. {
  2374. return m_DataFlow[flow].avgloss;
  2375. }
  2376. float CNetChan::GetTime( void ) const
  2377. {
  2378. return net_time;
  2379. }
  2380. bool CNetChan::GetStreamProgress( int flow, int *received, int *total ) const
  2381. {
  2382. (*total) = 0;
  2383. (*received) = 0;
  2384. if ( flow == FLOW_INCOMING )
  2385. {
  2386. for ( int i = 0; i<MAX_STREAMS; i++ )
  2387. {
  2388. if ( m_ReceiveList[i].buffer != NULL )
  2389. {
  2390. (*total) += m_ReceiveList[i].numFragments * FRAGMENT_SIZE;
  2391. (*received) += m_ReceiveList[i].ackedFragments * FRAGMENT_SIZE;
  2392. }
  2393. }
  2394. return ((*total)>0);
  2395. }
  2396. if ( flow == FLOW_OUTGOING )
  2397. {
  2398. for ( int i = 0; i<MAX_STREAMS; i++ )
  2399. {
  2400. if ( m_WaitingList[i].Count() > 0 )
  2401. {
  2402. (*total) += m_WaitingList[i][0]->numFragments * FRAGMENT_SIZE;
  2403. (*received) += m_WaitingList[i][0]->ackedFragments * FRAGMENT_SIZE;
  2404. }
  2405. }
  2406. return ((*total)>0);
  2407. }
  2408. return false; // TODO TCP progress
  2409. }
  2410. float CNetChan::GetCommandInterpolationAmount( int flow, int frame_number ) const
  2411. {
  2412. return m_DataFlow[ flow ].frames[ frame_number & NET_FRAMES_MASK ].m_flInterpolationAmount;
  2413. }
  2414. int CNetChan::GetPacketBytes( int flow, int frame_number, int group ) const
  2415. {
  2416. if ( group >= INetChannelInfo::TOTAL )
  2417. {
  2418. return m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ].size;
  2419. }
  2420. else
  2421. {
  2422. return Bits2Bytes( m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ].msggroups[group] );
  2423. }
  2424. }
  2425. void CNetChan::UpdateMessageStats( int msggroup, int bits)
  2426. {
  2427. netflow_t * pflow = &m_DataFlow[ FLOW_INCOMING ];
  2428. netframe_t *pframe = pflow->currentframe;
  2429. Assert( (msggroup >= INetChannelInfo::GENERIC) && (msggroup < INetChannelInfo::TOTAL) );
  2430. m_MsgStats[msggroup] += bits;
  2431. if ( pframe )
  2432. pframe->msggroups[msggroup] +=bits;
  2433. }
  2434. void CNetChan::IncrementQueuedPackets()
  2435. {
  2436. ++m_nQueuedPackets;
  2437. }
  2438. void CNetChan::DecrementQueuedPackets()
  2439. {
  2440. --m_nQueuedPackets;
  2441. Assert( m_nQueuedPackets >= 0 );
  2442. if ( m_nQueuedPackets < 0 )
  2443. m_nQueuedPackets = 0;
  2444. }
  2445. bool CNetChan::HasQueuedPackets() const
  2446. {
  2447. if ( g_pQueuedPackedSender->HasQueuedPackets( this ) )
  2448. {
  2449. return true;
  2450. }
  2451. return m_nQueuedPackets > 0;
  2452. }
  2453. void CNetChan::SetInterpolationAmount( float flInterpolationAmount )
  2454. {
  2455. m_flInterpolationAmount = flInterpolationAmount;
  2456. }
  2457. void CNetChan::SetRemoteFramerate( float flFrameTime, float flFrameTimeStdDeviation )
  2458. {
  2459. m_flRemoteFrameTime = flFrameTime;
  2460. m_flRemoteFrameTimeStdDeviation = flFrameTimeStdDeviation;
  2461. }
  2462. // Max # of payload bytes before we must split/fragment the packet
  2463. void CNetChan::SetMaxRoutablePayloadSize( int nSplitSize )
  2464. {
  2465. if ( m_nMaxRoutablePayloadSize != nSplitSize )
  2466. {
  2467. DevMsg( "Setting max routable payload size from %d to %d for %s\n",
  2468. m_nMaxRoutablePayloadSize, nSplitSize, GetName() );
  2469. }
  2470. m_nMaxRoutablePayloadSize = nSplitSize;
  2471. }
  2472. int CNetChan::GetMaxRoutablePayloadSize()
  2473. {
  2474. return m_nMaxRoutablePayloadSize;
  2475. }
  2476. int CNetChan::GetProtocolVersion()
  2477. {
  2478. AssertMsg(
  2479. m_nProtocolVersion >= 0 && m_nProtocolVersion <= PROTOCOL_VERSION,
  2480. "This is probably not being initialized somewhere"
  2481. );
  2482. return m_nProtocolVersion;
  2483. }
  2484. int CNetChan::IncrementSplitPacketSequence()
  2485. {
  2486. return ++m_nSplitPacketSequence;
  2487. }
  2488. bool CNetChan::IsValidFileForTransfer( const char *pszFilename )
  2489. {
  2490. if ( !pszFilename || !pszFilename[ 0 ] )
  2491. return false;
  2492. // No absolute paths or weaseling up the tree with ".." allowed.
  2493. if ( !COM_IsValidPath( pszFilename ) || V_IsAbsolutePath( pszFilename ) )
  2494. return false;
  2495. int len = V_strlen( pszFilename );
  2496. if ( len >= MAX_PATH )
  2497. return false;
  2498. char szTemp[ MAX_PATH ];
  2499. V_strcpy_safe( szTemp, pszFilename );
  2500. // Convert so we've got all forward slashes in the path.
  2501. V_FixSlashes( szTemp, '/' );
  2502. V_FixDoubleSlashes( szTemp );
  2503. if ( szTemp[ len - 1 ] == '/' )
  2504. return false;
  2505. int slash_count = 0;
  2506. for ( const char *psz = szTemp; *psz; psz++ )
  2507. {
  2508. if ( *psz == '/' )
  2509. slash_count++;
  2510. }
  2511. // Really no reason to have deeper directory than this?
  2512. if ( slash_count >= 32 )
  2513. return false;
  2514. // Don't allow filenames with unicode whitespace in them.
  2515. if ( Q_RemoveAllEvilCharacters( szTemp ) )
  2516. return false;
  2517. if ( V_stristr( szTemp, "lua/" ) ||
  2518. V_stristr( szTemp, "gamemodes/" ) ||
  2519. V_stristr( szTemp, "addons/" ) ||
  2520. V_stristr( szTemp, "~/" ) ||
  2521. // V_stristr( szTemp, "//" ) || // Don't allow '//'. TODO: Is this check ok?
  2522. V_stristr( szTemp, "./././" ) || // Don't allow folks to make crazy long paths with ././././ stuff.
  2523. V_stristr( szTemp, " " ) || // Don't allow multiple spaces or tab (was being used for an exploit).
  2524. V_stristr( szTemp, "\t" ) )
  2525. {
  2526. return false;
  2527. }
  2528. // If .exe or .EXE or these other strings exist _anywhere_ in the filename, reject it.
  2529. if ( V_stristr( szTemp, ".cfg" ) ||
  2530. V_stristr( szTemp, ".lst" ) ||
  2531. V_stristr( szTemp, ".exe" ) ||
  2532. V_stristr( szTemp, ".vbs" ) ||
  2533. V_stristr( szTemp, ".com" ) ||
  2534. V_stristr( szTemp, ".bat" ) ||
  2535. V_stristr( szTemp, ".cmd" ) ||
  2536. V_stristr( szTemp, ".dll" ) ||
  2537. V_stristr( szTemp, ".so" ) ||
  2538. V_stristr( szTemp, ".dylib" ) ||
  2539. V_stristr( szTemp, ".ini" ) ||
  2540. V_stristr( szTemp, ".log" ) ||
  2541. V_stristr( szTemp, ".lua" ) ||
  2542. V_stristr( szTemp, ".vdf" ) ||
  2543. V_stristr( szTemp, ".smx" ) ||
  2544. V_stristr( szTemp, ".gcf" ) ||
  2545. V_stristr( szTemp, ".lmp" ) ||
  2546. V_stristr( szTemp, ".sys" ) )
  2547. {
  2548. return false;
  2549. }
  2550. // Search for the first . in the base filename, and bail if not found.
  2551. // We don't want people passing in things like 'cfg/.wp.so'...
  2552. const char *basename = strrchr( szTemp, '/' );
  2553. if ( !basename )
  2554. basename = szTemp;
  2555. const char *extension = strchr( basename, '.' );
  2556. if ( !extension )
  2557. return false;
  2558. // If the extension is not exactly 3 or 4 characters, bail.
  2559. int extension_len = V_strlen( extension );
  2560. if ( ( extension_len != 3 ) &&
  2561. ( extension_len != 4 ) &&
  2562. V_stricmp( extension, ".bsp.bz2" ) &&
  2563. V_stricmp( extension, ".xbox.vtx" ) &&
  2564. V_stricmp( extension, ".dx80.vtx" ) &&
  2565. V_stricmp( extension, ".dx90.vtx" ) &&
  2566. V_stricmp( extension, ".sw.vtx" ) )
  2567. {
  2568. return false;
  2569. }
  2570. // If there are any spaces in the extension, bail. (Windows exploit).
  2571. if ( strchr( extension, ' ' ) )
  2572. return false;
  2573. return true;
  2574. }