Counter Strike : Global Offensive Source Code
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.

3797 lines
94 KiB

  1. //==== Copyright (c) 1996-2010, 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 "replay.h"
  18. #include "datacache/imdlcache.h"
  19. #include "tier0/vprof.h"
  20. #if defined( _X360 )
  21. #include "xbox/xbox_console.h"
  22. #endif
  23. #ifdef POSIX
  24. #include "net_ws_headers.h" // need SOCKET
  25. #endif
  26. #include "net_ws_queued_packet_sender.h"
  27. #include "download.h"
  28. #include "filesystem_init.h"
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include "tier0/memdbgon.h"
  31. //////////////////////////////////////////////////////////////////////
  32. // Construction/Destruction
  33. //////////////////////////////////////////////////////////////////////
  34. ConVar net_showudp( "net_showudp", "0", FCVAR_RELEASE, "Dump UDP packets summary to console" );
  35. ConVar net_showudp_oob( "net_showudp_oob", "0", FCVAR_RELEASE, "Dump OOB UDP packets summary to console" );
  36. ConVar net_showudp_remoteonly( "net_showudp_remoteonly", "0", FCVAR_RELEASE, "Dump non-loopback udp only" );
  37. ConVar net_showtcp( "net_showtcp", "0", 0, "Dump TCP stream summary to console" );
  38. ConVar net_blocksize( "net_maxfragments", NETSTRING( MAX_ROUTABLE_PAYLOAD ), 0, "Max fragment bytes per packet", true, FRAGMENT_SIZE, true, MAX_ROUTABLE_PAYLOAD );
  39. static ConVar net_showmsg( "net_showmsg", "0", FCVAR_DEVELOPMENTONLY, "Show incoming message: <0|1|name>" );
  40. static ConVar net_showfragments( "net_showfragments", "0", 0, "Show netchannel fragments" );
  41. static ConVar net_showpeaks( "net_showpeaks", "0", 0, "Show messages for large packets only: <size>" );
  42. static ConVar net_blockmsg( "net_blockmsg", "0", FCVAR_CHEAT, "Discards incoming message: <0|1|name>" ); // "none" here is bad, causes superfluous strcmp on every net message
  43. static ConVar net_showdrop( "net_showdrop", "0", FCVAR_DEVELOPMENTONLY, "Show dropped packets in console" );
  44. static ConVar net_drawslider( "net_drawslider", "0", 0, "Draw completion slider during signon" );
  45. static ConVar net_chokeloopback( "net_chokeloop", "0", FCVAR_DEVELOPMENTONLY, "Apply bandwidth choke to loopback packets" );
  46. static ConVar net_maxfilesize( "net_maxfilesize", "16", 0, "Maximum allowed file size for uploading in MB", true, 0, true, 64 );
  47. static ConVar net_compresspackets( "net_compresspackets", "1", FCVAR_DEVELOPMENTONLY, "Use lz compression on game packets." );
  48. static ConVar net_compresspackets_minsize( "net_compresspackets_minsize", "1000", FCVAR_DEVELOPMENTONLY, "Don't bother compressing packets below this size." );
  49. 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)." );
  50. static ConVar net_droponsendoverflow( "net_droponsendoverflow", "0", FCVAR_RELEASE, "If enabled, channel will drop client when sending too much data causes buffer overrun" );
  51. extern ConVar net_maxroutable;
  52. extern int NET_ConnectSocket( int nSock, const netadr_t &addr );
  53. extern void NET_CloseSocket( int hSocket, int sock = -1 );
  54. extern int NET_SendStream( int nSock, const char * buf, int len, int flags );
  55. extern int NET_ReceiveStream( int nSock, char * buf, int len, int flags );
  56. // If the network connection hasn't been active in this many seconds, display some warning text.
  57. #define CONNECTION_PROBLEM_TIME 4.0f // assume network problem after this time
  58. #define BYTES2FRAGMENTS(i) ((i+FRAGMENT_SIZE-1)/FRAGMENT_SIZE)
  59. #define FLIPBIT(v,b) if (v&b) v &= ~b; else v |= b;
  60. static const char HEX[] = "0123456789abcdef";
  61. void LogMultiline(bool input, char const *label, const char * data, size_t len) {
  62. const char * direction = (input ? " << " : " >> ");
  63. const size_t LINE_SIZE = 24;
  64. char hex_line[LINE_SIZE * 9 / 4 + 2], asc_line[LINE_SIZE + 1];
  65. while (len > 0)
  66. {
  67. memset(asc_line, ' ', sizeof(asc_line));
  68. memset(hex_line, ' ', sizeof(hex_line));
  69. size_t line_len = MIN(len, LINE_SIZE);
  70. for (size_t i=0; i<line_len; ++i) {
  71. unsigned char ch = static_cast<unsigned char>(data[i]);
  72. asc_line[i] = ( V_isprint(ch) && !V_iscntrl(ch) ) ? data[i] : '.';
  73. hex_line[i*2 + i/4] = HEX[ch >> 4];
  74. hex_line[i*2 + i/4 + 1] = HEX[ch & 0xf];
  75. }
  76. asc_line[sizeof(asc_line)-1] = 0;
  77. hex_line[sizeof(hex_line)-1] = 0;
  78. Msg( "%s %s %s %s \n", label, direction, asc_line, hex_line );
  79. data += line_len;
  80. len -= line_len;
  81. }
  82. }
  83. // Want this on PC and non-cert builds
  84. #if !defined( _GAMECONSOLE ) || !defined( _CERT )
  85. #define NET_PARANOID_DUMPS
  86. #endif
  87. #if defined( NET_PARANOID_DUMPS )
  88. class CNetchanParanoidMode
  89. {
  90. public:
  91. CNetchanParanoidMode();
  92. ~CNetchanParanoidMode();
  93. void Init();
  94. void StartPacket( bf_read &fullbuf );
  95. void NoteHeaderSize( bf_read &buf, int flags );
  96. void AddMessage( INetMessage *msg, int nStartBit );
  97. // Message has been parsed, update raw data
  98. void UpdateMessage( INetMessage *msg, int nEndBit );
  99. void AddControlMessage( int m_nType, int nStartBit, char const *name, char const *desc );
  100. // Called if processing failes for some reason
  101. void Dump( CNetChan *channel, char const *pchReason );
  102. private:
  103. bool IsEnabled();
  104. bool m_bInitialized;
  105. int m_nRawDataSize;
  106. byte *m_pRawData;
  107. int m_nHeaderBits;
  108. int m_nFlags;
  109. struct MessageItem_t
  110. {
  111. MessageItem_t() :
  112. m_pMsg( NULL ),
  113. m_nMessageSize( 0 ),
  114. m_nType( 0 ),
  115. m_nGroup( 0 ),
  116. m_nStartBit( 0 ),
  117. m_nEndBit( -1 )
  118. {
  119. m_szName[ 0 ] = 0;
  120. m_szDesc[ 0 ] = 0;
  121. Q_memset( m_Message, 0, sizeof( m_Message ) );
  122. }
  123. void Init( INetMessage *msg, int nStartBit )
  124. {
  125. m_pMsg = msg;
  126. m_nMessageSize = msg->GetSize();
  127. m_nType = msg->GetType();
  128. m_nGroup = msg->GetGroup();
  129. Q_strncpy( m_szName, msg->GetName(), sizeof( m_szName ) );
  130. //Q_strncpy( m_szDesc, msg->ToString(), sizeof( m_szDesc ) );
  131. m_szDesc[ 0 ] = 0; // Don't call ToString until after message parses
  132. m_nStartBit = nStartBit;
  133. m_nEndBit = -1;
  134. }
  135. void InitControlMessage( int nType, int nStartBit, char const *pchName, char const *pchDesc )
  136. {
  137. m_pMsg = NULL;
  138. m_nMessageSize = 0;
  139. m_nType = nType;
  140. m_nGroup = 0;
  141. Q_strncpy( m_szName, pchName, sizeof( m_szName ) );
  142. Q_strncpy( m_szDesc, pchDesc, sizeof( m_szDesc ) );
  143. m_nStartBit = nStartBit;
  144. m_nEndBit = -1;
  145. }
  146. void UpdateRaw( INetMessage *msg, int nEndBit )
  147. {
  148. Q_memcpy( m_Message, (const byte *)msg, MIN( msg->GetSize(), sizeof( m_Message ) ) );
  149. m_nEndBit = nEndBit;
  150. Q_strncpy( m_szDesc, msg->ToString(), sizeof( m_szDesc ) );
  151. }
  152. void Dump()
  153. {
  154. if ( m_pMsg && m_nEndBit == -1 )
  155. {
  156. Msg( "---> DIDN'T FINISH PARSING %s\n", m_szName );
  157. }
  158. Msg( "%s: type( %d ) group ( %d ) size ( %d bytes ), startbit %d end bit %d\n", m_szName, m_nType, m_nGroup, m_nMessageSize, m_nStartBit, m_nEndBit );
  159. Msg( " %s\n", m_szDesc );
  160. // Raw contents
  161. if ( m_pMsg )
  162. {
  163. Msg( "RAW(%s) start\n", m_szName );
  164. LogMultiline( false, m_szName, (const char *)m_pMsg, m_nMessageSize );
  165. Msg( "RAW(%s) end\n", m_szName );
  166. }
  167. else
  168. {
  169. Msg( " %s Control message\n", m_szName );
  170. }
  171. }
  172. INetMessage *m_pMsg;
  173. size_t m_nMessageSize;
  174. int m_nType;
  175. int m_nGroup;
  176. int m_nStartBit;
  177. int m_nEndBit;
  178. byte m_Message[ 128 ];;
  179. char m_szName[ 32 ];
  180. char m_szDesc[ 128 ]; // m_pMsg->ToString()
  181. };
  182. enum
  183. {
  184. MAX_MESSAGES_IN_PACKET = 256,
  185. };
  186. MessageItem_t *m_pPacketMessages;
  187. int m_nPacketMessageCount;
  188. };
  189. static ConVar net_dumptest( "net_dumptest", "0" );
  190. static ConVar net_paranoid( "net_paranoid", "1" );
  191. static CNetchanParanoidMode g_NetParanoid;
  192. void NET_InitParanoidMode()
  193. {
  194. g_NetParanoid.Init();
  195. }
  196. CNetchanParanoidMode::CNetchanParanoidMode() :
  197. m_bInitialized( false ),
  198. m_nRawDataSize( 0 ),
  199. m_pRawData( NULL ),
  200. m_nHeaderBits( 0 ),
  201. m_nFlags( 0 ),
  202. m_pPacketMessages( NULL ),
  203. m_nPacketMessageCount( 0 )
  204. {
  205. }
  206. CNetchanParanoidMode::~CNetchanParanoidMode()
  207. {
  208. delete[] m_pPacketMessages;
  209. delete[] m_pRawData;
  210. }
  211. bool CNetchanParanoidMode::IsEnabled()
  212. {
  213. if ( !m_bInitialized )
  214. return false;
  215. return net_paranoid.GetBool();
  216. }
  217. void CNetchanParanoidMode::Init()
  218. {
  219. m_bInitialized = true;
  220. m_pRawData = new byte[ NET_MAX_PAYLOAD ];
  221. m_pPacketMessages = new MessageItem_t[ MAX_MESSAGES_IN_PACKET ];
  222. }
  223. void CNetchanParanoidMode::StartPacket( bf_read &fullbuf )
  224. {
  225. if ( !IsEnabled() )
  226. return;
  227. m_nRawDataSize = MIN( fullbuf.TotalBytesAvailable(), NET_MAX_PAYLOAD );
  228. Q_memcpy( m_pRawData, fullbuf.GetBasePointer(), m_nRawDataSize );
  229. // Reset counter
  230. m_nPacketMessageCount = 0;
  231. m_nHeaderBits = 0;
  232. m_nFlags = 0;
  233. }
  234. void CNetchanParanoidMode::NoteHeaderSize( bf_read &msg, int flags )
  235. {
  236. if ( !IsEnabled() )
  237. return;
  238. m_nHeaderBits = msg.GetNumBitsRead();
  239. m_nFlags = flags;
  240. }
  241. void CNetchanParanoidMode::AddMessage( INetMessage *msg, int nStartBit )
  242. {
  243. if ( !IsEnabled() )
  244. return;
  245. if ( m_nPacketMessageCount >= MAX_MESSAGES_IN_PACKET - 1 )
  246. return;
  247. MessageItem_t &item = m_pPacketMessages[ m_nPacketMessageCount++ ];
  248. item.Init( msg, nStartBit );
  249. }
  250. void CNetchanParanoidMode::UpdateMessage( INetMessage *msg, int nEndBit )
  251. {
  252. if ( !IsEnabled() )
  253. return;
  254. if ( m_nPacketMessageCount <= 0 )
  255. return;
  256. MessageItem_t &item = m_pPacketMessages[ m_nPacketMessageCount - 1 ];
  257. if ( item.m_pMsg != msg )
  258. return;
  259. item.UpdateRaw( msg, nEndBit );
  260. }
  261. void CNetchanParanoidMode::AddControlMessage( int m_nType, int nStartBit, char const *name, char const *desc )
  262. {
  263. if ( !IsEnabled() )
  264. return;
  265. if ( m_nPacketMessageCount >= MAX_MESSAGES_IN_PACKET - 1 )
  266. return;
  267. MessageItem_t &item = m_pPacketMessages[ m_nPacketMessageCount++ ];
  268. item.InitControlMessage( m_nType, nStartBit, name, desc );
  269. }
  270. void CNetchanParanoidMode::Dump( CNetChan *channel, char const *pchReason )
  271. {
  272. if ( !IsEnabled() )
  273. return;
  274. Msg( "%s\n ", pchReason );
  275. Msg( "Dumping messages for channel %s(%s) 0x%p\n",
  276. channel->GetName(), channel->GetAddress(), channel );
  277. Msg( "Header bits %d, flags == %d\n", m_nHeaderBits, m_nFlags );
  278. Msg( "%d messages\n", m_nPacketMessageCount );
  279. for ( int i = 0; i < m_nPacketMessageCount; ++i )
  280. {
  281. MessageItem_t &item = m_pPacketMessages[ i ];
  282. Msg( "%d -----------------------\n", i );
  283. item.Dump();
  284. }
  285. // Dump raw memory, too
  286. Msg( "Raw\n" );
  287. LogMultiline( false, "PKT", (const char *)m_pRawData, m_nRawDataSize );
  288. }
  289. #else
  290. void NET_InitParanoidMode()
  291. {
  292. // NOTHING!!!
  293. }
  294. #endif
  295. // We only need to checksum packets on the PC and only when we're actually sending them over the network.
  296. bool ShouldChecksumPackets()
  297. {
  298. return NET_IsMultiplayer();
  299. }
  300. bool CNetChan::IsLoopback() const
  301. {
  302. return remote_address.IsLoopback();
  303. }
  304. bool CNetChan::IsNull() const
  305. {
  306. return remote_address.IsNull();
  307. }
  308. /*
  309. ==============================
  310. CNetChan::Clear
  311. ==============================
  312. */
  313. void CNetChan::Clear()
  314. {
  315. int i;
  316. // clear waiting lists
  317. for ( i=0; i<MAX_STREAMS; i++ )
  318. {
  319. while ( m_WaitingList[i].Count() )
  320. RemoveHeadInWaitingList( i );
  321. if ( m_ReceiveList[i].buffer )
  322. {
  323. delete[] m_ReceiveList[i].buffer;
  324. m_ReceiveList[i].buffer = NULL;
  325. }
  326. }
  327. for( i=0; i<MAX_SUBCHANNELS; i++ )
  328. {
  329. if ( m_SubChannels[i].state == SUBCHANNEL_TOSEND )
  330. {
  331. int bit = 1<<i; // flip bit back since data was send yet
  332. FLIPBIT(m_nOutReliableState, bit);
  333. m_SubChannels[i].Free();
  334. }
  335. else if ( m_SubChannels[i].state == SUBCHANNEL_WAITING )
  336. {
  337. // data is already out, mark channel as dirty
  338. m_SubChannels[i].state = SUBCHANNEL_DIRTY;
  339. }
  340. }
  341. m_bStopProcessing = true;
  342. Reset();
  343. }
  344. void CNetChan::CompressFragments()
  345. {
  346. // We don't want this to go in the VCR file, because the compressed size can be different. The reason is
  347. // that the bf_writes that contributed to this message may have uninitialized bits at the end of the buffer
  348. // (for example if it uses only the first couple bits of the last byte in the message). If the
  349. // last few bits are different, it can produce a different compressed size.
  350. if ( !m_bUseCompression || !net_compresspackets.GetBool() )
  351. return;
  352. // write fragemnts for both streams
  353. for ( int i=0; i<MAX_STREAMS; i++ )
  354. {
  355. if ( m_WaitingList[i].Count() == 0 )
  356. continue;
  357. // get the first fragments block which is send next
  358. dataFragments_t *data = m_WaitingList[i][0];
  359. // if data is already compressed or too small, skip it
  360. if ( data->isCompressed || data->bytes < 512 )
  361. continue;
  362. // if we already started sending this block, we can't compress it anymore
  363. if ( data->ackedFragments > 0 || data->pendingFragments > 0 )
  364. continue;
  365. //ok, compress it.
  366. if ( data->buffer )
  367. {
  368. // fragments data is in memory
  369. unsigned int compressedSize = data->bytes;
  370. char * compressedData = new char[data->bytes];
  371. if ( NET_BufferToBufferCompress( compressedData , &compressedSize, data->buffer, data->bytes ) )
  372. {
  373. const char *name = GetName();
  374. const char *address = GetAddress();
  375. DevMsg("Compressing fragments for %s(%s) (%d -> %d bytes)\n", name, address, data->bytes, compressedSize );
  376. // copy compressed data but dont reallocate memory
  377. Q_memcpy( data->buffer, compressedData, compressedSize );
  378. data->nUncompressedSize = data->bytes;
  379. data->bytes = compressedSize;
  380. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  381. data->isCompressed = true;
  382. }
  383. delete [] compressedData; // free temp buffer
  384. }
  385. else // it's a file
  386. {
  387. Assert( data->file != FILESYSTEM_INVALID_HANDLE );
  388. char compressedfilename[ MAX_OSPATH ];
  389. int compressedFileSize = -1;
  390. FileHandle_t hZipFile = FILESYSTEM_INVALID_HANDLE;
  391. // check to see if there is a compressed version of the file
  392. Q_snprintf( compressedfilename, sizeof(compressedfilename), "%s.ztmp", data->filename);
  393. // check the timestamps
  394. int compressedFileTime = g_pFileSystem->GetFileTime( compressedfilename );
  395. int fileTime = g_pFileSystem->GetFileTime( data->filename );
  396. if ( compressedFileTime >= fileTime )
  397. {
  398. // compressed file is newer than uncompressed file, use this one
  399. hZipFile = g_pFileSystem->Open( compressedfilename, "rb", NULL );
  400. }
  401. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  402. {
  403. // use the existing compressed file
  404. compressedFileSize = g_pFileSystem->Size( hZipFile );
  405. }
  406. else
  407. {
  408. // create compressed version of source file
  409. char *uncompressed = new char[data->bytes];
  410. char *compressed = new char[data->bytes];
  411. unsigned int compressedSize = data->bytes;
  412. unsigned int uncompressedSize = data->bytes;
  413. // read in source file
  414. g_pFileSystem->Read( uncompressed, data->bytes, data->file );
  415. // compress into buffer
  416. if ( NET_BufferToBufferCompress( compressed, &compressedSize, uncompressed, uncompressedSize ) )
  417. {
  418. // write out to disk compressed version
  419. hZipFile = g_pFileSystem->Open( compressedfilename, "wb", NULL );
  420. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  421. {
  422. DevMsg("Creating compressed version of file %s (%d -> %d)\n", data->filename, data->bytes, compressedSize);
  423. g_pFileSystem->Write( compressed, compressedSize, hZipFile );
  424. g_pFileSystem->Close( hZipFile );
  425. // and open zip file it again for reading
  426. hZipFile = g_pFileSystem->Open( compressedfilename, "rb", NULL );
  427. if ( hZipFile != FILESYSTEM_INVALID_HANDLE )
  428. {
  429. // ok, now everything if fine
  430. compressedFileSize = compressedSize;
  431. }
  432. }
  433. }
  434. delete [] uncompressed;
  435. delete [] compressed;
  436. }
  437. if ( compressedFileSize > 0 )
  438. {
  439. // use compressed file handle instead of original file
  440. g_pFileSystem->Close( data->file );
  441. data->file = hZipFile;
  442. data->nUncompressedSize = data->bytes;
  443. data->bytes = compressedFileSize;
  444. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  445. data->isCompressed = true;
  446. }
  447. }
  448. }
  449. }
  450. void CNetChan::UncompressFragments( dataFragments_t *data )
  451. {
  452. if ( !data->isCompressed )
  453. return;
  454. VPROF( "UncompressFragments" );
  455. // allocate buffer for uncompressed data, align to 4 bytes boundary
  456. char *newbuffer = new char[PAD_NUMBER( data->nUncompressedSize, 4 )];
  457. unsigned int uncompressedSize = data->nUncompressedSize;
  458. // uncompress data
  459. NET_BufferToBufferDecompress( newbuffer, &uncompressedSize, data->buffer, data->bytes );
  460. Assert( uncompressedSize == data->nUncompressedSize );
  461. // free old buffer and set new buffer
  462. delete [] data->buffer;
  463. data->buffer = newbuffer;
  464. data->bytes = uncompressedSize;
  465. data->isCompressed = false;
  466. }
  467. unsigned int CNetChan::RequestFile(const char *filename, bool bIsReplayDemoFile )
  468. {
  469. m_FileRequestCounter++;
  470. if ( net_showfragments.GetInt() == 2 )
  471. {
  472. DevMsg("RequestFile: %s (ID %i)\n", filename, m_FileRequestCounter );
  473. }
  474. CNETMsg_File_t file;
  475. file.set_transfer_id( m_FileRequestCounter );
  476. file.set_file_name( filename );
  477. file.set_is_replay_demo_file( bIsReplayDemoFile );
  478. file.set_deny( 0 );
  479. file.WriteToBuffer( m_StreamReliable );
  480. return m_FileRequestCounter;
  481. }
  482. void CNetChan::RequestFile_OLD(const char *filename, unsigned int transferID)
  483. {
  484. Error( "Called RequestFile_OLD" );
  485. }
  486. void CNetChan::DenyFile(const char *filename, unsigned int transferID, bool bIsReplayDemoFile )
  487. {
  488. if ( net_showfragments.GetInt() == 2 )
  489. {
  490. DevMsg("DenyFile: %s (ID %i)\n", filename, transferID );
  491. }
  492. CNETMsg_File_t file;
  493. file.set_transfer_id( transferID );
  494. file.set_file_name( filename );
  495. file.set_is_replay_demo_file( bIsReplayDemoFile );
  496. file.set_deny( 1 );
  497. file.WriteToBuffer( m_StreamReliable );
  498. }
  499. bool CNetChan::SendFile(const char *filename, unsigned int transferID, bool bIsReplayDemoFile )
  500. {
  501. // add file to waiting list
  502. if ( IsNull() )
  503. return true;
  504. if ( !filename )
  505. return false;
  506. const char *sendfile = filename;
  507. while( sendfile[0] && PATHSEPARATOR( sendfile[0] ) )
  508. {
  509. sendfile = sendfile + 1;
  510. }
  511. // Don't transfer exe, vbs, com, bat-type files.
  512. if ( !IsValidFileForTransfer( sendfile ) )
  513. return false;
  514. if ( !CreateFragmentsFromFile( sendfile, FRAG_FILE_STREAM, transferID, bIsReplayDemoFile ) )
  515. {
  516. DenyFile( sendfile, transferID, bIsReplayDemoFile ); // send host a deny message
  517. return false;
  518. }
  519. if ( net_showfragments.GetInt() == 2 )
  520. {
  521. DevMsg("SendFile: %s (ID %i)\n", sendfile, transferID );
  522. }
  523. return true;
  524. }
  525. bool CNetChan::EnqueueVeryLargeAsyncTransfer( INetMessage &msg )
  526. {
  527. if ( IsNull() )
  528. return true;
  529. char chStackBuffer[ NET_MAX_PAYLOAD ];
  530. bf_write bufWrite;
  531. bufWrite.StartWriting( chStackBuffer, NET_MAX_PAYLOAD );
  532. bool bResult = msg.WriteToBuffer( bufWrite );
  533. if ( !bResult )
  534. {
  535. Warning( "EnqueueVeryLargeAsyncTransfer %s: buffer overflow (maxsize = %d)!\n", GetAddress(), NET_MAX_PAYLOAD );
  536. Assert( 0 );
  537. if ( net_droponsendoverflow.GetBool() )
  538. {
  539. m_MessageHandler->ConnectionCrashed( "Buffer overflow in EnqueueVeryLargeAsyncTransfer" );
  540. }
  541. return false;
  542. }
  543. if ( !bufWrite.GetNumBytesWritten() )
  544. return false;
  545. //////////////////////////////////////////////////////////////////////////
  546. dataFragments_t *data = new dataFragments_t;
  547. data->bytes = bufWrite.GetNumBytesWritten();
  548. data->bits = data->bytes * 8;
  549. data->buffer = new char[ bufWrite.GetNumBytesWritten() ];
  550. V_memcpy( data->buffer, chStackBuffer, bufWrite.GetNumBytesWritten() );
  551. data->isCompressed = false;
  552. data->isReplayDemo = false;
  553. data->nUncompressedSize = 0;
  554. data->file = FILESYSTEM_INVALID_HANDLE;
  555. m_FileRequestCounter++;
  556. data->transferID = m_FileRequestCounter;
  557. V_memset( data->filename, 0, sizeof( data->filename ) );
  558. m_WaitingList[ FRAG_FILE_STREAM ].AddToTail( data ); // that's it for now
  559. // check if send as stream or with snapshot
  560. data->asTCP = false; // m_StreamActive && ( Bits2Bytes(data->length) > m_MaxReliablePayloadSize );
  561. // calc number of fragments needed
  562. data->numFragments = BYTES2FRAGMENTS( data->bytes );
  563. data->ackedFragments = 0;
  564. data->pendingFragments = 0;
  565. if ( net_showfragments.GetInt() == 2 )
  566. {
  567. DevMsg( "EnqueueVeryLargeAsyncTransfer: %s (%d bytes, ID %i)\n", msg.GetName(), data->bytes, data->transferID );
  568. }
  569. return true;
  570. }
  571. void CNetChan::Shutdown(const char *pReason)
  572. {
  573. // send discconect
  574. if ( m_Socket < 0 )
  575. return;
  576. Clear(); // free all buffers (reliable & unreliable)
  577. if ( pReason )
  578. {
  579. // send disconnect message
  580. CNETMsg_Disconnect_t disconnect;
  581. disconnect.set_text( pReason );
  582. disconnect.WriteToBuffer( m_StreamUnreliable );
  583. Transmit(); // push message out
  584. }
  585. if ( m_StreamSocket )
  586. {
  587. NET_CloseSocket( m_StreamSocket, m_Socket );
  588. m_StreamSocket = 0;
  589. m_StreamActive = false;
  590. }
  591. NET_TerminateConnection( m_Socket, remote_address );
  592. // signals that netchannel isn't valid anymore
  593. m_Socket = -1;
  594. remote_address.Clear();
  595. m_szRemoteAddressName[0] = '\0';
  596. if ( m_MessageHandler )
  597. {
  598. m_MessageHandler->ConnectionClosing( pReason );
  599. m_MessageHandler = NULL;
  600. }
  601. // free net messages
  602. for ( int i = 0; i < m_NetMessages.Count(); i++ )
  603. {
  604. CUtlVector< INetMessageBinder * >& Messages = m_NetMessages[ i ];
  605. for( int j = Messages.Count() - 1; j >= 0; j-- )
  606. {
  607. Messages[ j ]->SetNetChannel( NULL );
  608. }
  609. }
  610. m_NetMessages.Purge();
  611. m_DemoRecorder = NULL;
  612. if ( m_bProcessingMessages )
  613. {
  614. NET_RemoveNetChannel( this, false ); // Delay the deletion or it'll crash in the message-processing loop.
  615. m_bShouldDelete = true;
  616. }
  617. else
  618. {
  619. NET_RemoveNetChannel( this, true );
  620. }
  621. }
  622. CNetChan::CNetChan() : m_SplitPlayers( 0, 0, SplitPlayer_t::Less )
  623. {
  624. m_pActiveChannel = this;
  625. m_nSplitPacketSequence = 1;
  626. m_nMaxRoutablePayloadSize = MAX_ROUTABLE_PAYLOAD;
  627. m_bProcessingMessages = false;
  628. m_bShouldDelete = false;
  629. m_bStopProcessing = false;
  630. m_Socket = -1; // invalid
  631. remote_address.Clear();
  632. m_szRemoteAddressName[0] = '\0';
  633. last_received = 0;
  634. connect_time = 0;
  635. Q_strncpy( m_Name, "", sizeof(m_Name) );
  636. m_MessageHandler = NULL;
  637. m_DemoRecorder = NULL;
  638. m_StreamUnreliable.SetDebugName( "netchan_t::unreliabledata" );
  639. m_StreamReliable.SetDebugName( "netchan_t::reliabledata" );
  640. m_Rate = DEFAULT_RATE;
  641. m_Timeout = SIGNON_TIME_OUT;
  642. // Prevent the first message from getting dropped after connection is set up.
  643. m_nOutSequenceNr = 1; // otherwise it looks like a
  644. m_nInSequenceNr = 0;
  645. m_nOutSequenceNrAck = 0;
  646. m_nOutReliableState = 0; // our current reliable state
  647. m_nInReliableState = 0; // last remote reliable state
  648. // m_nLostPackets = 0;
  649. m_ChallengeNr = 0;
  650. m_StreamSocket = 0;
  651. m_StreamActive = false;
  652. ResetStreaming();
  653. m_MaxReliablePayloadSize = NET_MAX_PAYLOAD;
  654. m_FileRequestCounter = 0;
  655. m_bFileBackgroundTranmission = true;
  656. m_bUseCompression = false;
  657. m_nQueuedPackets = 0;
  658. m_flRemoteFrameTime = 0;
  659. m_flRemoteFrameTimeStdDeviation = 0;
  660. m_flRemoteFrameStartTimeStdDeviation = 0;
  661. m_bWasLastMessageReliable = false;
  662. FlowReset();
  663. }
  664. CNetChan::~CNetChan()
  665. {
  666. Shutdown("NetChannel removed.");
  667. }
  668. /*
  669. ==============
  670. CNetChan::Setup
  671. called to open a channel to a remote system
  672. ==============
  673. */
  674. void CNetChan::Setup( int sock, const ns_address &adr, const char * name, INetChannelHandler * handler, const byte *pbEncryptionKey )
  675. {
  676. Assert( name );
  677. Assert ( handler );
  678. m_Socket = sock;
  679. if ( m_StreamSocket )
  680. {
  681. NET_CloseSocket( m_StreamSocket );
  682. m_StreamSocket = 0;
  683. }
  684. remote_address = adr;
  685. V_strcpy_safe( m_szRemoteAddressName, ns_address_render( remote_address ).String() );
  686. last_received = net_time;
  687. connect_time = net_time;
  688. Q_strncpy( m_Name, name, sizeof(m_Name) );
  689. m_MessageHandler = handler;
  690. m_DemoRecorder = NULL;
  691. MEM_ALLOC_CREDIT();
  692. SetMaxBufferSize( false, NET_MAX_DATAGRAM_PAYLOAD );
  693. SetMaxBufferSize( false, NET_MAX_DATAGRAM_PAYLOAD, true ); //Set up voice buffer
  694. SetMaxBufferSize( true, NET_MAX_PAYLOAD );
  695. m_Rate = DEFAULT_RATE;
  696. m_Timeout = SIGNON_TIME_OUT;
  697. // Prevent the first message from getting dropped after connection is set up.
  698. m_nOutSequenceNr = 1; // otherwise it looks like a
  699. m_nInSequenceNr = 0;
  700. m_nOutSequenceNrAck = 0;
  701. m_nOutReliableState = 0; // our current reliable state
  702. m_nInReliableState = 0; // last remote reliable state
  703. m_nChokedPackets = 0;
  704. m_fClearTime = 0.0;
  705. m_ChallengeNr = 0;
  706. m_StreamSocket = 0;
  707. m_StreamActive = false;
  708. m_ReceiveList[FRAG_NORMAL_STREAM].buffer = NULL;
  709. m_ReceiveList[FRAG_FILE_STREAM].buffer = NULL;
  710. // init 8 subchannels
  711. for ( int i=0; i<MAX_SUBCHANNELS; i++ )
  712. {
  713. m_SubChannels[i].index = i; // set index once
  714. m_SubChannels[i].Free();
  715. }
  716. ResetStreaming();
  717. if ( NET_IsMultiplayer() )
  718. {
  719. m_MaxReliablePayloadSize = net_blocksize.GetInt();
  720. }
  721. else
  722. {
  723. m_MaxReliablePayloadSize = NET_MAX_PAYLOAD;
  724. }
  725. FlowReset();
  726. // Set our encryption key
  727. m_EncryptionKey.Purge();
  728. if ( pbEncryptionKey )
  729. {
  730. m_EncryptionKey.EnsureCapacity( NET_CRYPT_KEY_LENGTH );
  731. Q_memcpy( m_EncryptionKey.Base(), pbEncryptionKey, NET_CRYPT_KEY_LENGTH );
  732. }
  733. m_NETMsgNOP.Bind< CNETMsg_NOP_t >( this, UtlMakeDelegate( this, &CNetChan::NETMsg_NOP ) );
  734. m_NETMsgDisconnect.Bind< CNETMsg_Disconnect_t >( this, UtlMakeDelegate( this, &CNetChan::NETMsg_Disconnect ) );
  735. m_NETMsgFile.Bind< CNETMsg_File_t >( this, UtlMakeDelegate( this, &CNetChan::NETMsg_File ) );
  736. m_NETMsgSplitScreenUser.Bind< CNETMsg_SplitScreenUser_t >( this, UtlMakeDelegate( this, &CNetChan::NETMsg_SplitScreenUser ) );
  737. // tell message handler to register known netmessages
  738. m_MessageHandler->ConnectionStart( this );
  739. }
  740. void CNetChan::ResetStreaming( void )
  741. {
  742. m_SteamType = STREAM_CMD_NONE;
  743. m_StreamLength = 0;
  744. m_StreamReceived = 0;
  745. m_StreamSeqNr = 0;
  746. m_SteamFile[0] = 0;
  747. }
  748. bool CNetChan::StartStreaming( unsigned int challengeNr )
  749. {
  750. // reset stream state machine
  751. ResetStreaming();
  752. m_ChallengeNr = challengeNr;
  753. if ( !NET_IsMultiplayer() )
  754. {
  755. m_StreamSocket = 0;
  756. return true; // streaming is done via loopback buffers in SP mode
  757. }
  758. // Stream sockets only supported to ordinary IP address
  759. if ( !remote_address.IsType<netadr_t>() )
  760. {
  761. extern bool net_notcp;
  762. if ( !net_notcp )
  763. Warning( "Attempt to open streaming socket to remote host '%s'. Stream sockets only supported to ordinary IPv4 addresses\n", ns_address_render( remote_address ).String() );
  764. return false;
  765. }
  766. MEM_ALLOC_CREDIT();
  767. m_StreamSocket = NET_ConnectSocket( m_Socket, remote_address.AsType<netadr_t>() );
  768. m_StreamData.EnsureCapacity( NET_MAX_PAYLOAD );
  769. return (m_StreamSocket != 0);
  770. }
  771. void CNetChan::SetChallengeNr(unsigned int chnr)
  772. {
  773. m_ChallengeNr = chnr;
  774. }
  775. unsigned int CNetChan::GetChallengeNr( void ) const
  776. {
  777. return m_ChallengeNr;
  778. }
  779. void CNetChan::GetSequenceData( int &nOutSequenceNr, int &nInSequenceNr, int &nOutSequenceNrAck )
  780. {
  781. nOutSequenceNr = m_nOutSequenceNr;
  782. nInSequenceNr = m_nInSequenceNr;
  783. nOutSequenceNrAck = m_nOutSequenceNrAck;
  784. }
  785. void CNetChan::SetSequenceData( int nOutSequenceNr, int nInSequenceNr, int nOutSequenceNrAck )
  786. {
  787. Assert( IsPlayback() );
  788. m_nOutSequenceNr = nOutSequenceNr;
  789. m_nInSequenceNr = nInSequenceNr;
  790. m_nOutSequenceNrAck = nOutSequenceNrAck;
  791. }
  792. void CNetChan::SetDemoRecorder(IDemoRecorder * recorder)
  793. {
  794. m_DemoRecorder = recorder;
  795. }
  796. void CNetChan::SetTimeout(float seconds, bool bForceExact /*= false*/)
  797. {
  798. m_Timeout = seconds;
  799. // Exact setting doesn't require validation
  800. if ( bForceExact )
  801. return;
  802. if ( m_Timeout > 3600.0f )
  803. {
  804. m_Timeout = 3600.0f; // 1 hour maximum
  805. }
  806. else if ( m_Timeout <= 0.0f )
  807. {
  808. m_Timeout = -1.0f; // never time out (demo files)
  809. }
  810. else if ( m_Timeout < CONNECTION_PROBLEM_TIME )
  811. {
  812. m_Timeout = CONNECTION_PROBLEM_TIME; // allow at least this minimum
  813. }
  814. }
  815. void CNetChan::SetMaxBufferSize(bool bReliable, int nBytes, bool bVoice )
  816. {
  817. // force min/max sizes 4-96kB
  818. nBytes = clamp( nBytes, NET_MAX_DATAGRAM_PAYLOAD, NET_MAX_PAYLOAD );
  819. bf_write *stream;
  820. CUtlMemory<byte> *buffer;
  821. if ( bReliable )
  822. {
  823. stream = &m_StreamReliable;
  824. buffer = &m_ReliableDataBuffer;
  825. }
  826. else if ( bVoice == true )
  827. {
  828. stream = &m_StreamVoice;
  829. buffer = &m_VoiceDataBuffer;
  830. }
  831. else
  832. {
  833. stream = &m_StreamUnreliable;
  834. buffer = &m_UnreliableDataBuffer;
  835. }
  836. if ( buffer->Count() == nBytes )
  837. return;
  838. byte *copybuf = NULL;
  839. int copybits = stream->GetNumBitsWritten();
  840. int copybytes = Bits2Bytes( copybits );
  841. if ( copybytes >= nBytes )
  842. {
  843. ConMsg("CNetChan::SetMaxBufferSize: cant preserve exiting data %i>%i.\n", copybytes, nBytes );
  844. return;
  845. }
  846. if ( copybits > 0 )
  847. {
  848. copybuf = new byte[ copybytes ];
  849. Q_memcpy( copybuf, buffer->Base(), copybytes );
  850. }
  851. buffer->Purge();
  852. MEM_ALLOC_CREDIT();
  853. buffer->EnsureCapacity( nBytes );
  854. if ( copybits > 0 )
  855. {
  856. Q_memcpy( buffer->Base(), copybuf, copybytes );
  857. delete [] copybuf;
  858. copybuf = NULL;
  859. }
  860. stream->StartWriting( buffer->Base(), nBytes, copybits );
  861. }
  862. void CNetChan::SetFileTransmissionMode( bool bBackgroundMode )
  863. {
  864. m_bFileBackgroundTranmission = bBackgroundMode;
  865. }
  866. void CNetChan::SetCompressionMode( bool bUseCompression )
  867. {
  868. m_bUseCompression = bUseCompression;
  869. }
  870. void CNetChan::SetDataRate(float rate)
  871. {
  872. m_Rate = clamp( rate, MIN_RATE, MAX_RATE );
  873. }
  874. const char * CNetChan::GetName() const
  875. {
  876. return m_Name;
  877. }
  878. const char * CNetChan::GetAddress() const
  879. {
  880. return m_szRemoteAddressName;
  881. }
  882. int CNetChan::GetDropNumber() const
  883. {
  884. return m_PacketDrop;
  885. }
  886. /*
  887. ===============
  888. CNetChan::CanPacket
  889. Returns true if the bandwidth choke isn't active
  890. ================
  891. */
  892. bool CNetChan::CanPacket () const
  893. {
  894. // Never choke loopback packets.
  895. if ( !net_chokeloopback.GetInt() && remote_address.IsLoopback() )
  896. {
  897. return true;
  898. }
  899. if ( HasQueuedPackets() )
  900. {
  901. return false;
  902. }
  903. return m_fClearTime < net_time;
  904. }
  905. bool CNetChan::IsPlayback( void ) const
  906. {
  907. #if !defined(DEDICATED)
  908. return demoplayer->IsPlayingBack();
  909. #else
  910. return false;
  911. #endif
  912. }
  913. void CNetChan::FlowReset( void )
  914. {
  915. Q_memset( m_DataFlow, 0, sizeof( m_DataFlow ) );
  916. Q_memset( m_MsgStats, 0, sizeof( m_MsgStats ) );
  917. }
  918. void CNetChan::FlowNewPacket(int flow, int seqnr, int acknr, int nChoked, int nDropped, int nSize )
  919. {
  920. netflow_t * pflow = &m_DataFlow[ flow ];
  921. // if frame_number != ( current + 1 ) mark frames between as invalid
  922. netframe_header_t *pframeheader = NULL;
  923. netframe_t *pframe = NULL;
  924. if ( seqnr > pflow->currentindex )
  925. {
  926. //
  927. // The following loop must execute no more than NET_FRAMES_BACKUP times
  928. // since that's the amount of storage in frame_headers & frames arrays,
  929. // a malformed client packet pushing "seqnr" by 1,000,000 can cause this
  930. // loop to watchdog.
  931. //
  932. for ( int i = pflow->currentindex + 1, numPacketFramesOverflow = 0;
  933. ( i <= seqnr ) && ( numPacketFramesOverflow < NET_FRAMES_BACKUP );
  934. ++ i, ++ numPacketFramesOverflow )
  935. {
  936. int nBackTrack = seqnr - i;
  937. pframeheader = &pflow->frame_headers[ i & NET_FRAMES_MASK ];
  938. pframe = &pflow->frames[ i & NET_FRAMES_MASK ];
  939. pframeheader->time = net_time; // now
  940. pframeheader->valid = false;
  941. pframeheader->size = 0;
  942. pframeheader->latency = -1.0f; // not acknowledged yet
  943. pframe->avg_latency = GetAvgLatency( FLOW_OUTGOING );
  944. pframeheader->choked = 0; // not acknowledged yet
  945. pframe->dropped = 0;
  946. pframe->m_flInterpolationAmount = 0.0f;
  947. Q_memset( &pframe->msggroups, 0, sizeof(pframe->msggroups) );
  948. if ( nBackTrack < ( nChoked + nDropped ) )
  949. {
  950. if ( nBackTrack < nChoked )
  951. {
  952. pframeheader->choked = 1;
  953. }
  954. else
  955. {
  956. pframe->dropped = 1;
  957. }
  958. }
  959. }
  960. pframe->dropped = nDropped;
  961. pframeheader->choked = nChoked;
  962. pframeheader->size = nSize;
  963. pframeheader->valid = true;
  964. pframe->avg_latency = GetAvgLatency( FLOW_OUTGOING );
  965. pframe->m_flInterpolationAmount = m_flInterpolationAmount;
  966. }
  967. else
  968. {
  969. #ifdef DEDICATED
  970. Assert( seqnr > pflow->currentindex );
  971. #else
  972. Assert( demoplayer->IsPlayingBack() || seqnr > pflow->currentindex );
  973. #endif
  974. }
  975. pflow->totalpackets++;
  976. pflow->currentindex = seqnr;
  977. pflow->currentframe = pframe;
  978. // updated ping for acknowledged packet
  979. int aflow = (flow==FLOW_OUTGOING) ? FLOW_INCOMING : FLOW_OUTGOING;
  980. if ( acknr <= (m_DataFlow[aflow].currentindex - NET_FRAMES_BACKUP) )
  981. return; // acknowledged packet isn't in backup buffer anymore
  982. netframe_header_t * aframe = &m_DataFlow[aflow].frame_headers[ acknr & NET_FRAMES_MASK ];
  983. if ( aframe->valid && aframe->latency == -1.0f )
  984. {
  985. // update ping for acknowledged packet, if not already acknowledged before
  986. aframe->latency = net_time - aframe->time;
  987. if ( aframe->latency < 0.0f )
  988. aframe->latency = 0.0f;
  989. }
  990. }
  991. void CNetChan::FlowUpdate(int flow, int addbytes)
  992. {
  993. netflow_t * pflow = &m_DataFlow[ flow ];
  994. pflow->totalbytes += addbytes;
  995. if ( pflow->nextcompute > net_time )
  996. return;
  997. pflow->nextcompute = net_time + FLOW_INTERVAL;
  998. int totalvalid = 0;
  999. int totalinvalid = 0;
  1000. int totalbytes = 0;
  1001. float totallatency = 0.0f;
  1002. int totallatencycount = 0;
  1003. int totalchoked = 0;
  1004. float starttime = FLT_MAX;
  1005. float endtime = 0.0f;
  1006. netframe_header_t * pcurr;
  1007. for ( int i = 0; i < NET_FRAMES_BACKUP; i++ )
  1008. {
  1009. // Most recent message then backward from there
  1010. pcurr = &pflow->frame_headers[ i ];
  1011. if ( pcurr->valid )
  1012. {
  1013. if ( pcurr->time < starttime )
  1014. starttime = pcurr->time;
  1015. if ( pcurr->time > endtime )
  1016. endtime = pcurr->time;
  1017. totalvalid++;
  1018. totalchoked += pcurr->choked;
  1019. totalbytes += pcurr->size;
  1020. if ( pcurr->latency > -1.0f )
  1021. {
  1022. totallatency += pcurr->latency;
  1023. totallatencycount++;
  1024. }
  1025. }
  1026. else
  1027. {
  1028. totalinvalid++;
  1029. }
  1030. }
  1031. float totaltime = endtime - starttime;
  1032. if ( totaltime > 0.0f )
  1033. {
  1034. pflow->avgbytespersec *= FLOW_AVG;
  1035. pflow->avgbytespersec += ( 1.0f - FLOW_AVG ) * ((float)totalbytes / totaltime);
  1036. pflow->avgpacketspersec *= FLOW_AVG;
  1037. pflow->avgpacketspersec += ( 1.0f - FLOW_AVG ) * ((float)totalvalid / totaltime);
  1038. }
  1039. int totalPackets = totalvalid + totalinvalid;
  1040. if ( totalPackets > 0 )
  1041. {
  1042. pflow->avgloss *= FLOW_AVG;
  1043. pflow->avgloss += ( 1.0f - FLOW_AVG ) * ((float)(totalinvalid-totalchoked)/totalPackets);
  1044. if ( totalinvalid-totalchoked <= 0 )
  1045. pflow->avgloss = 0; // snap loss to zero if nothing lost over last 128 ticks
  1046. pflow->avgchoke *= FLOW_AVG;
  1047. pflow->avgchoke += ( 1.0f - FLOW_AVG ) * ((float)totalchoked/totalPackets);
  1048. if ( totalchoked <= 0 )
  1049. pflow->avgchoke = 0; // snap choke to zero if nothing lost over last 128 ticks
  1050. }
  1051. else
  1052. {
  1053. pflow->avgloss = 0;
  1054. pflow->avgchoke = 0;
  1055. }
  1056. if ( totallatencycount>0 )
  1057. {
  1058. float newping = totallatency / totallatencycount ;
  1059. pflow->latency = newping;
  1060. pflow->avglatency*= FLOW_AVG;
  1061. pflow->avglatency += ( 1.0f - FLOW_AVG ) * newping;
  1062. }
  1063. }
  1064. void CNetChan::SetChoked( void )
  1065. {
  1066. m_nOutSequenceNr++; // sends to be done since move command use sequence number
  1067. m_nChokedPackets++;
  1068. }
  1069. bool CNetChan::Transmit(bool onlyReliable )
  1070. {
  1071. if ( onlyReliable )
  1072. m_StreamUnreliable.Reset();
  1073. return (SendDatagram( NULL ) != 0);
  1074. }
  1075. bool CNetChan::IsFileInWaitingList( const char *filename )
  1076. {
  1077. if ( !filename || !filename[0] )
  1078. return true;
  1079. for ( int stream=0; stream<MAX_STREAMS; stream++)
  1080. {
  1081. for ( int i = 0; i < m_WaitingList[stream].Count(); i++ )
  1082. {
  1083. dataFragments_t * data = m_WaitingList[stream][i];
  1084. if ( !Q_strcmp( data->filename, filename ) )
  1085. return true; // alread in list
  1086. }
  1087. }
  1088. return false; // file not found
  1089. }
  1090. void CNetChan::RemoveHeadInWaitingList( int nList )
  1091. {
  1092. Assert( m_WaitingList[nList].Count() );
  1093. dataFragments_t * data = m_WaitingList[nList][0]; // get head
  1094. if ( data->buffer )
  1095. delete [] data->buffer; // free data buffer
  1096. if ( data->file != FILESYSTEM_INVALID_HANDLE )
  1097. {
  1098. g_pFileSystem->Close( data->file );
  1099. data->file = FILESYSTEM_INVALID_HANDLE;
  1100. }
  1101. // data->fragments.Purge();
  1102. m_WaitingList[nList].FindAndRemove( data ); // remove from list
  1103. delete data; //free structure itself
  1104. }
  1105. bool CNetChan::CreateFragmentsFromBuffer( bf_write *buffer, int stream )
  1106. {
  1107. bf_write bfwrite;
  1108. dataFragments_t *data = NULL;
  1109. // if we have more than one item in the waiting list, try to add the
  1110. // reliable data to the last item. that doesn't work with the first item
  1111. // since it may have been already send and is waiting for acknowledge
  1112. int count = m_WaitingList[stream].Count();
  1113. if ( count > 1 )
  1114. {
  1115. // get last item in waiting list
  1116. data = m_WaitingList[stream][count-1];
  1117. int totalBytes = Bits2Bytes( data->bits + buffer->GetNumBitsWritten() );
  1118. totalBytes = PAD_NUMBER( totalBytes, 4 ); // align to 4 bytes boundary
  1119. if ( totalBytes < NET_MAX_PAYLOAD && data->buffer )
  1120. {
  1121. // we have enough space for it, create new larger mem buffer
  1122. char *newBuf = new char[totalBytes];
  1123. Q_memcpy( newBuf, data->buffer, data->bytes );
  1124. delete [] data->buffer; // free old buffer
  1125. data->buffer = newBuf; // set new buffer
  1126. bfwrite.StartWriting( newBuf, totalBytes, data->bits );
  1127. }
  1128. else
  1129. {
  1130. data = NULL; // reset to NULL
  1131. }
  1132. }
  1133. // if not added to existing item, create a new reliable data waiting buffer
  1134. if ( !data )
  1135. {
  1136. int totalBytes = Bits2Bytes( buffer->GetNumBitsWritten());
  1137. totalBytes = PAD_NUMBER( totalBytes, 4 ); // align to 4 bytes boundary
  1138. data = new dataFragments_t;
  1139. data->bytes = 0; // not filled yet
  1140. data->bits = 0;
  1141. data->buffer = new char[ totalBytes ];
  1142. data->isCompressed = false;
  1143. data->isReplayDemo = false;
  1144. data->nUncompressedSize = 0;
  1145. data->file = FILESYSTEM_INVALID_HANDLE;
  1146. data->filename[0] = 0;
  1147. bfwrite.StartWriting( data->buffer, totalBytes );
  1148. m_WaitingList[stream].AddToTail( data ); // that's it for now
  1149. }
  1150. // write new reliable data to buffer
  1151. bfwrite.WriteBits( buffer->GetData(), buffer->GetNumBitsWritten() );
  1152. // fill last bits in last byte with NOP if necessary
  1153. int nRemainingBits = bfwrite.GetNumBitsWritten() % 8;
  1154. if ( nRemainingBits > 0 && nRemainingBits <= (8-NETMSG_TYPE_BITS) )
  1155. {
  1156. CNETMsg_NOP_t nop;
  1157. nop.WriteToBuffer( bfwrite );
  1158. }
  1159. // update bit length
  1160. data->bits += buffer->GetNumBitsWritten();
  1161. data->bytes = Bits2Bytes(data->bits);
  1162. // check if send as stream or with snapshot
  1163. data->asTCP = m_StreamActive && ( data->bytes > m_MaxReliablePayloadSize );
  1164. // calc number of fragments needed
  1165. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  1166. data->ackedFragments = 0;
  1167. data->pendingFragments = 0;
  1168. return true;
  1169. }
  1170. bool CNetChan::CreateFragmentsFromFile( const char *filename, int stream, unsigned int transferID, bool bIsReplayDemoFile )
  1171. {
  1172. if ( IsFileInWaitingList( filename ) )
  1173. return true; // already scheduled for upload
  1174. const char *pPathID = "GAME";
  1175. if ( !g_pFileSystem->FileExists( filename, pPathID ) )
  1176. {
  1177. ConMsg( "CreateFragmentsFromFile: '%s' doesn't exist.\n", filename );
  1178. return false;
  1179. }
  1180. int totalBytes = g_pFileSystem->Size( filename, pPathID );
  1181. if ( totalBytes >= (net_maxfilesize.GetInt()*1024*1024) )
  1182. {
  1183. ConMsg( "CreateFragmentsFromFile: '%s' size exceeds net_maxfilesize limit (%i MB).\n", filename, net_maxfilesize.GetInt() );
  1184. return false;
  1185. }
  1186. if ( totalBytes >= MAX_FILE_SIZE )
  1187. {
  1188. ConMsg( "CreateFragmentsFromFile: '%s' too big (max %i bytes).\n", filename, MAX_FILE_SIZE );
  1189. return false;
  1190. }
  1191. dataFragments_t *data = new dataFragments_t;
  1192. data->bytes = totalBytes;
  1193. data->bits = data->bytes * 8;
  1194. data->buffer = NULL;
  1195. data->isCompressed = false;
  1196. data->isReplayDemo = bIsReplayDemoFile;
  1197. data->nUncompressedSize = 0;
  1198. data->file = g_pFileSystem->Open( filename, "rb", pPathID );
  1199. if ( data->file == FILESYSTEM_INVALID_HANDLE )
  1200. {
  1201. ConMsg( "CreateFragmentsFromFile: couldn't open '%s'.\n", filename );
  1202. delete data;
  1203. return false;
  1204. }
  1205. data->transferID = transferID;
  1206. Q_strncpy( data->filename, filename, sizeof(data->filename) );
  1207. m_WaitingList[stream].AddToTail( data ); // that's it for now
  1208. // check if send as stream or with snapshot
  1209. data->asTCP = false; // m_StreamActive && ( Bits2Bytes(data->length) > m_MaxReliablePayloadSize );
  1210. // calc number of fragments needed
  1211. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  1212. data->ackedFragments = 0;
  1213. data->pendingFragments = 0;
  1214. return true;
  1215. }
  1216. void CNetChan::SendTCPData( void )
  1217. {
  1218. if ( m_WaitingList[FRAG_NORMAL_STREAM].Count() == 0 )
  1219. return; // nothing in line
  1220. dataFragments_t *data = m_WaitingList[FRAG_NORMAL_STREAM][0];
  1221. if ( !data->asTCP )
  1222. return; // not as TCP
  1223. if ( data->pendingFragments > 0 )
  1224. return; // already send, wait for ACK
  1225. // OK send it now
  1226. SendReliableViaStream( data );
  1227. }
  1228. bool CNetChan::SendSubChannelData( bf_write &buf )
  1229. {
  1230. subChannel_s *subChan = NULL;
  1231. int i;
  1232. CompressFragments();
  1233. SendTCPData();
  1234. UpdateSubChannels();
  1235. // find subchannl with data to send/resend:
  1236. for ( i=0; i<MAX_SUBCHANNELS; i++ )
  1237. {
  1238. subChan = &m_SubChannels[i];
  1239. if ( subChan->state == SUBCHANNEL_TOSEND )
  1240. break;
  1241. }
  1242. if ( i == MAX_SUBCHANNELS )
  1243. return false; // no data to send in any subchannel
  1244. // first write subchannel index
  1245. buf.WriteUBitLong( i, 3 );
  1246. // write fragemnts for both streams
  1247. for ( i=0; i<MAX_STREAMS; i++ )
  1248. {
  1249. if ( subChan->numFragments[i] == 0 )
  1250. {
  1251. buf.WriteOneBit( 0 ); // no data for this stream
  1252. continue;
  1253. }
  1254. dataFragments_t *data = m_WaitingList[i][0];
  1255. buf.WriteOneBit( 1 ); // data follows:
  1256. unsigned int offset = subChan->startFraggment[i]*FRAGMENT_SIZE;
  1257. unsigned int length = subChan->numFragments[i]*FRAGMENT_SIZE;
  1258. if ( (subChan->startFraggment[i]+subChan->numFragments[i]) == data->numFragments )
  1259. {
  1260. // we are sending the last fragment, adjust length
  1261. int rest = FRAGMENT_SIZE - ( data->bytes % FRAGMENT_SIZE );
  1262. if ( rest < FRAGMENT_SIZE )
  1263. length -= rest;
  1264. }
  1265. // if all fragments can be send within a single packet, avoid overhead (if not a file)
  1266. bool bSingleBlock = (subChan->numFragments[i] == data->numFragments) &&
  1267. ( data->file == FILESYSTEM_INVALID_HANDLE );
  1268. if ( bSingleBlock )
  1269. {
  1270. Assert( length == data->bytes );
  1271. Assert( length < NET_MAX_PAYLOAD );
  1272. Assert( offset == 0 );
  1273. buf.WriteOneBit( 0 ); // single block bit
  1274. // data compressed ?
  1275. if ( data->isCompressed )
  1276. {
  1277. buf.WriteOneBit( 1 );
  1278. buf.WriteUBitLong( data->nUncompressedSize, MAX_FILE_SIZE_BITS );
  1279. }
  1280. else
  1281. {
  1282. buf.WriteOneBit( 0 );
  1283. }
  1284. buf.WriteUBitLong( data->bytes, NET_MAX_PAYLOAD_BITS );
  1285. }
  1286. else
  1287. {
  1288. buf.WriteOneBit( 1 ); // uses fragments with start fragment offset byte
  1289. buf.WriteUBitLong( subChan->startFraggment[i], (MAX_FILE_SIZE_BITS-FRAGMENT_BITS) );
  1290. buf.WriteUBitLong( subChan->numFragments[i], 3 );
  1291. if ( offset == 0 )
  1292. {
  1293. // this is the first fragment, write header info
  1294. if ( data->file != FILESYSTEM_INVALID_HANDLE )
  1295. {
  1296. buf.WriteOneBit( 1 ); // file transmission net message stream
  1297. buf.WriteUBitLong( data->transferID, 32 );
  1298. buf.WriteString( data->filename );
  1299. if ( data->isReplayDemo )
  1300. {
  1301. buf.WriteOneBit( 1 );
  1302. }
  1303. else
  1304. {
  1305. buf.WriteOneBit( 0 );
  1306. }
  1307. }
  1308. else
  1309. {
  1310. buf.WriteOneBit( 0 ); // normal net message stream
  1311. }
  1312. // data compressed ?
  1313. if ( data->isCompressed )
  1314. {
  1315. buf.WriteOneBit( 1 );
  1316. buf.WriteUBitLong( data->nUncompressedSize, MAX_FILE_SIZE_BITS );
  1317. }
  1318. else
  1319. {
  1320. buf.WriteOneBit( 0 );
  1321. }
  1322. buf.WriteUBitLong( data->bytes, MAX_FILE_SIZE_BITS ); // 4MB max for files
  1323. }
  1324. }
  1325. // write fragments to buffer
  1326. if ( data->buffer )
  1327. {
  1328. Assert( data->file == FILESYSTEM_INVALID_HANDLE );
  1329. // send from memory block
  1330. buf.WriteBytes( data->buffer+offset, length );
  1331. }
  1332. else // if ( data->file != FILESYSTEM_INVALID_HANDLE )
  1333. {
  1334. // send from file
  1335. Assert( data->file != FILESYSTEM_INVALID_HANDLE );
  1336. char *tmpbuf = new char[ MAX( length, 1 ) ]; // alloc on stack
  1337. g_pFileSystem->Seek( data->file, offset, FILESYSTEM_SEEK_HEAD );
  1338. g_pFileSystem->Read( tmpbuf, length, data->file );
  1339. buf.WriteBytes( tmpbuf, length );
  1340. delete[] tmpbuf;
  1341. }
  1342. if ( net_showfragments.GetBool() )
  1343. {
  1344. ConMsg("Sending subchan %i: start %i, num %i\n", subChan->index, subChan->startFraggment[i], subChan->numFragments[i] );
  1345. }
  1346. subChan->sendSeqNr = m_nOutSequenceNr;
  1347. subChan->state = SUBCHANNEL_WAITING;
  1348. }
  1349. return true;
  1350. }
  1351. bool CNetChan::ReadSubChannelData( bf_read &buf, int stream )
  1352. {
  1353. dataFragments_t * data = &m_ReceiveList[stream]; // get list
  1354. int startFragment = 0;
  1355. int numFragments = 0;
  1356. unsigned int offset = 0;
  1357. unsigned int length = 0;
  1358. bool bSingleBlock = buf.ReadOneBit() == 0; // is single block ?
  1359. if ( !bSingleBlock )
  1360. {
  1361. startFragment = buf.ReadUBitLong( MAX_FILE_SIZE_BITS-FRAGMENT_BITS ); // 16 MB max
  1362. numFragments = buf.ReadUBitLong( 3 ); // 8 fragments per packet max
  1363. offset = startFragment * FRAGMENT_SIZE;
  1364. length = numFragments * FRAGMENT_SIZE;
  1365. }
  1366. if ( offset == 0 ) // first fragment, read header info
  1367. {
  1368. data->filename[0] = 0;
  1369. data->isCompressed = false;
  1370. data->isReplayDemo = false;
  1371. data->transferID = 0;
  1372. if ( bSingleBlock )
  1373. {
  1374. // data compressed ?
  1375. if ( buf.ReadOneBit() )
  1376. {
  1377. data->isCompressed = true;
  1378. data->nUncompressedSize = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1379. }
  1380. else
  1381. {
  1382. data->isCompressed = false;
  1383. }
  1384. data->bytes = buf.ReadUBitLong( NET_MAX_PAYLOAD_BITS );
  1385. }
  1386. else
  1387. {
  1388. if ( buf.ReadOneBit() ) // is it a file ?
  1389. {
  1390. data->transferID = buf.ReadUBitLong( 32 );
  1391. buf.ReadString( data->filename, MAX_OSPATH );
  1392. // replay demo?
  1393. if ( buf.ReadOneBit() )
  1394. {
  1395. data->isReplayDemo = true;
  1396. }
  1397. }
  1398. // data compressed ?
  1399. if ( buf.ReadOneBit() )
  1400. {
  1401. data->isCompressed = true;
  1402. data->nUncompressedSize = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1403. }
  1404. else
  1405. {
  1406. data->isCompressed = false;
  1407. }
  1408. data->bytes = buf.ReadUBitLong( MAX_FILE_SIZE_BITS );
  1409. }
  1410. if ( data->buffer )
  1411. {
  1412. // last transmission was aborted, free data
  1413. delete [] data->buffer;
  1414. data->buffer = NULL;
  1415. ConDMsg("Fragment transmission aborted at %i/%i from %s.\n", data->ackedFragments, data->numFragments, GetAddress() );
  1416. }
  1417. data->bits = data->bytes * 8;
  1418. data->asTCP = false;
  1419. data->numFragments = BYTES2FRAGMENTS(data->bytes);
  1420. data->ackedFragments = 0;
  1421. data->file = FILESYSTEM_INVALID_HANDLE;
  1422. if ( bSingleBlock )
  1423. {
  1424. numFragments = data->numFragments;
  1425. length = numFragments * FRAGMENT_SIZE;
  1426. }
  1427. if ( data->bytes > MAX_FILE_SIZE )
  1428. {
  1429. // This can happen with the compressed path above, which uses VarInt32 rather than MAX_FILE_SIZE_BITS
  1430. Warning( "Net message exceeds max size (%u / %u)\n", MAX_FILE_SIZE, data->bytes );
  1431. // Subsequent packets for this transfer will treated as invalid since we never setup a buffer.
  1432. return false;
  1433. }
  1434. if ( data->isCompressed && data->nUncompressedSize > MAX_FILE_SIZE )
  1435. {
  1436. // This can happen with the compressed path above, which uses VarInt32 rather than MAX_FILE_SIZE_BITS
  1437. Warning( "Net message uncompressed size exceeds max size (%u / compressed %u / uncompressed %u)\n", MAX_FILE_SIZE, data->bytes, data->nUncompressedSize );
  1438. // Subsequent packets for this transfer will treated as invalid since we never setup a buffer.
  1439. return false;
  1440. }
  1441. data->buffer = new char[ PAD_NUMBER( data->bytes, 4 ) ];
  1442. }
  1443. else
  1444. {
  1445. if ( data->buffer == NULL )
  1446. {
  1447. // This can occur if the packet containing the "header" (offset == 0) is dropped. Since we need the header to arrive we'll just wait
  1448. // for a retry
  1449. // ConDMsg("Received fragment out of order: %i/%i\n", startFragment, numFragments );
  1450. return false;
  1451. }
  1452. }
  1453. if ( (startFragment+numFragments) == data->numFragments )
  1454. {
  1455. // we are receiving the last fragment, adjust length
  1456. int rest = FRAGMENT_SIZE - ( data->bytes % FRAGMENT_SIZE );
  1457. if ( rest < FRAGMENT_SIZE )
  1458. length -= rest;
  1459. }
  1460. else if ( (startFragment+numFragments) > data->numFragments )
  1461. {
  1462. // a malicious client can send a fragment beyond what was arranged in fragment#0 header
  1463. // old code will overrun the allocated buffer and likely cause a server crash
  1464. // it could also cause a client memory overrun because the offset can be anywhere from 0 to 16MB range
  1465. // drop the packet and wait for client to retry
  1466. ConDMsg("Received fragment chunk out of bounds: %i+%i>%i from %s\n", startFragment, numFragments, data->numFragments, GetAddress() );
  1467. return false;
  1468. }
  1469. Assert ( (offset + length) <= data->bytes );
  1470. buf.ReadBytes( data->buffer + offset, length ); // read data
  1471. data->ackedFragments+= numFragments;
  1472. if ( net_showfragments.GetBool() )
  1473. ConMsg("Received fragments: start %i, num %i\n", startFragment, numFragments );
  1474. return true;
  1475. }
  1476. void CNetChan::UpdateSubChannels()
  1477. {
  1478. // first check if there is a free subchannel
  1479. subChannel_s * freeSubChan = GetFreeSubChannel();
  1480. if ( freeSubChan == NULL )
  1481. return; //all subchannels in use right now
  1482. int i, nSendMaxFragments = m_MaxReliablePayloadSize / FRAGMENT_SIZE;
  1483. bool bSendData = false;
  1484. for ( i = 0; i < MAX_STREAMS; i++ )
  1485. {
  1486. if ( m_WaitingList[i].Count() <= 0 )
  1487. continue;
  1488. dataFragments_s *data = m_WaitingList[i][0]; // get head
  1489. if ( data->asTCP )
  1490. continue;
  1491. int nSentFragments = data->ackedFragments + data->pendingFragments;
  1492. Assert( nSentFragments <= data->numFragments );
  1493. if ( nSentFragments == data->numFragments )
  1494. continue; // all fragments already send
  1495. // how many fragments can we send ?
  1496. int numFragments = MIN( nSendMaxFragments, data->numFragments - nSentFragments );
  1497. // if we are in file background transmission mode, just send one fragment per packet
  1498. if ( i == FRAG_FILE_STREAM && m_bFileBackgroundTranmission )
  1499. numFragments = MIN( 1, numFragments );
  1500. // copy fragment data into subchannel
  1501. freeSubChan->startFraggment[i] = nSentFragments;
  1502. freeSubChan->numFragments[i] = numFragments;
  1503. data->pendingFragments += numFragments;
  1504. bSendData = true;
  1505. nSendMaxFragments -= numFragments;
  1506. if ( nSendMaxFragments <= 0 )
  1507. break;
  1508. }
  1509. if ( bSendData )
  1510. {
  1511. // flip channel bit
  1512. int bit = 1<<freeSubChan->index;
  1513. FLIPBIT(m_nOutReliableState, bit);
  1514. freeSubChan->state = SUBCHANNEL_TOSEND;
  1515. freeSubChan->sendSeqNr = 0;
  1516. }
  1517. }
  1518. #if 1
  1519. unsigned short BufferToShortChecksum( const void *pvData, size_t nLength )
  1520. {
  1521. CRC32_t crc = CRC32_ProcessSingleBuffer( pvData, nLength );
  1522. unsigned short lowpart = ( crc & 0xffff );
  1523. unsigned short highpart = ( ( crc >> 16 ) & 0xffff );
  1524. return (unsigned short)( lowpart ^ highpart );
  1525. }
  1526. #else
  1527. // If the CRC version ever is deemed to expensive, here's a quick xor version.
  1528. // It's probably not super robust.
  1529. inline unsigned short BufferToShortChecksum( const void *pvData, size_t nSize )
  1530. {
  1531. const uint32 *pData = (const uint32 *)pvData;
  1532. unsigned short us = 0;
  1533. while ( nSize >= sizeof( uint32 ) )
  1534. {
  1535. us ^= ( *pData & 0xffff );
  1536. us ^= ( ( *pData >> 16 ) & 0xffff );
  1537. nSize -= sizeof( uint32 );
  1538. pData += sizeof( uint32 );
  1539. }
  1540. const byte *pbData = (const byte *)pData;
  1541. while ( nSize > 0 )
  1542. {
  1543. us ^= *pbData;
  1544. ++pbData;
  1545. --nSize;
  1546. }
  1547. return us;
  1548. }
  1549. #endif
  1550. #define MIN_ROUTABLE_TESTING
  1551. #if defined( _DEBUG ) || defined( MIN_ROUTABLE_TESTING )
  1552. static ConVar net_minroutable( "net_minroutable", "16", FCVAR_DEVELOPMENTONLY, "Forces larger payloads." );
  1553. #endif
  1554. // XBox live requires appending voice data in the clear after game payload
  1555. static bool ShouldSendVoiceInTheClear()
  1556. {
  1557. if ( IsX360() )
  1558. return true;
  1559. if ( NET_IsDedicatedForXbox() )
  1560. return true;
  1561. return false;
  1562. }
  1563. /*
  1564. ===============
  1565. CNetChan::TransmitBits
  1566. tries to send an unreliable message to a connection, and handles the
  1567. transmition / retransmition of the reliable messages.
  1568. A 0 length will still generate a packet and deal with the reliable messages.
  1569. ================
  1570. */
  1571. int CNetChan::SendDatagram(bf_write *datagram)
  1572. {
  1573. VPROF( "CNetChan::SendDatagram" );
  1574. byte send_buf[ NET_MAX_MESSAGE ];
  1575. // Make sure for the client that the max routable payload size is up to date
  1576. if ( m_Socket == NS_CLIENT )
  1577. {
  1578. if ( net_maxroutable.GetInt() != GetMaxRoutablePayloadSize() )
  1579. {
  1580. SetMaxRoutablePayloadSize( net_maxroutable.GetInt() );
  1581. }
  1582. }
  1583. // first increase out sequence number
  1584. // check, if fake client, then fake send also
  1585. if ( remote_address.IsNull() )
  1586. {
  1587. // this is a demo channel, fake sending all data
  1588. m_fClearTime = 0.0; // no bandwidth delay
  1589. m_nChokedPackets = 0; // Reset choke state
  1590. m_StreamReliable.Reset(); // clear current reliable buffer
  1591. m_StreamUnreliable.Reset(); // clear current unrelaible buffer
  1592. m_nOutSequenceNr++;
  1593. return m_nOutSequenceNr-1;
  1594. }
  1595. // If we have "split" users hanging off of us, we need to merge their data in now
  1596. SplitUserCombineForSending();
  1597. // process all new and pending reliable data, return true if reliable data should
  1598. // been send with this packet
  1599. if ( m_StreamReliable.IsOverflowed() )
  1600. {
  1601. ConMsg ("%s:send reliable stream overflow\n" , GetAddress() );
  1602. return 0;
  1603. }
  1604. else if ( m_StreamReliable.GetNumBitsWritten() > 0 )
  1605. {
  1606. CreateFragmentsFromBuffer( &m_StreamReliable, FRAG_NORMAL_STREAM );
  1607. m_StreamReliable.Reset();
  1608. }
  1609. bf_write send( "CNetChan_TransmitBits->send", send_buf, sizeof(send_buf) );
  1610. // Prepare the packet header
  1611. // build packet flags
  1612. unsigned char flags = 0;
  1613. // start writing packet
  1614. send.WriteLong ( m_nOutSequenceNr );
  1615. send.WriteLong ( m_nInSequenceNr );
  1616. bf_write flagsPos = send; // remember flags byte position
  1617. send.WriteByte ( 0 ); // write correct flags value later
  1618. if ( ShouldChecksumPackets() )
  1619. {
  1620. send.WriteShort( 0 ); // write correct checksum later
  1621. Assert( !(send.GetNumBitsWritten() % 8 ) );
  1622. }
  1623. // Note, this only matters on the PC
  1624. int nCheckSumStart = send.GetNumBytesWritten();
  1625. send.WriteByte ( m_nInReliableState );
  1626. if ( m_nChokedPackets > 0 )
  1627. {
  1628. flags |= PACKET_FLAG_CHOKED;
  1629. send.WriteByte ( m_nChokedPackets & 0xFF ); // send number of choked packets
  1630. }
  1631. if ( SendSubChannelData( send ) )
  1632. {
  1633. flags |= PACKET_FLAG_RELIABLE;
  1634. }
  1635. // Is there room for given datagram data. the datagram data
  1636. // is somewhat more important than the normal unreliable data
  1637. // this is done to allow some kind of snapshot behavior
  1638. // weather all data in datagram is transmitted or none.
  1639. if ( datagram )
  1640. {
  1641. if( datagram->GetNumBitsWritten() < send.GetNumBitsLeft() )
  1642. {
  1643. send.WriteBits( datagram->GetData(), datagram->GetNumBitsWritten() );
  1644. }
  1645. else
  1646. {
  1647. ConDMsg("CNetChan::SendDatagram: data would overfow, ignoring\n");
  1648. }
  1649. }
  1650. // Is there room for the unreliable payload?
  1651. if ( m_StreamUnreliable.GetNumBitsWritten() < send.GetNumBitsLeft() )
  1652. {
  1653. send.WriteBits(m_StreamUnreliable.GetData(), m_StreamUnreliable.GetNumBitsWritten() );
  1654. }
  1655. else
  1656. {
  1657. ConDMsg("CNetChan::SendDatagram: Unreliable would overfow, ignoring\n");
  1658. }
  1659. m_StreamUnreliable.Reset(); // clear unreliable data buffer
  1660. // On the PC the voice data is in the main packet
  1661. if ( !ShouldSendVoiceInTheClear() &&
  1662. m_StreamVoice.GetNumBitsWritten() > 0 && m_StreamVoice.GetNumBitsWritten() < send.GetNumBitsLeft() )
  1663. {
  1664. send.WriteBits(m_StreamVoice.GetData(), m_StreamVoice.GetNumBitsWritten() );
  1665. m_StreamVoice.Reset();
  1666. }
  1667. int nMinRoutablePayload = MIN_ROUTABLE_PAYLOAD;
  1668. #if defined( _DEBUG ) || defined( MIN_ROUTABLE_TESTING )
  1669. if ( m_Socket == NS_SERVER )
  1670. {
  1671. nMinRoutablePayload = net_minroutable.GetInt();
  1672. }
  1673. #endif
  1674. // Deal with packets that are too small for some networks
  1675. while ( send.GetNumBytesWritten() < nMinRoutablePayload )
  1676. {
  1677. // Go ahead and pad some bits as long as needed
  1678. CNETMsg_NOP_t nop;
  1679. nop.WriteToBuffer( send );
  1680. }
  1681. // Make sure we have enough bits to read a final net_NOP opcode before compressing
  1682. int nRemainingBits = send.GetNumBitsWritten() % 8;
  1683. if ( nRemainingBits > 0 && nRemainingBits <= (8-NETMSG_TYPE_BITS) )
  1684. {
  1685. CNETMsg_NOP_t nop;
  1686. nop.WriteToBuffer( send );
  1687. }
  1688. // if ( IsX360() )
  1689. {
  1690. // Now round up to byte boundary
  1691. nRemainingBits = send.GetNumBitsWritten() % 8;
  1692. if ( nRemainingBits > 0 )
  1693. {
  1694. int nPadBits = 8 - nRemainingBits;
  1695. flags |= ENCODE_PAD_BITS( nPadBits );
  1696. // Pad with ones
  1697. if ( nPadBits > 0 )
  1698. {
  1699. unsigned int unOnes = GetBitForBitnum( nPadBits ) - 1;
  1700. send.WriteUBitLong( unOnes, nPadBits );
  1701. }
  1702. }
  1703. }
  1704. int nBitsPerPayload = net_blocksize.GetInt() * 8;
  1705. // FIXME: This isn't actually correct since compression might make the main payload usage a bit smaller
  1706. // On 360, only add voice data if the packet isn't going to be split
  1707. bool bSendVoice = ShouldSendVoiceInTheClear() && ( m_StreamVoice.GetNumBitsWritten() > 0 && m_StreamVoice.GetNumBitsWritten() + send.GetNumBitsWritten() < nBitsPerPayload );
  1708. bool bClearVoice = ( bSendVoice || m_StreamVoice.GetNumBitsWritten() >= nBitsPerPayload );
  1709. bool bCompress = false;
  1710. if ( net_compresspackets.GetBool() )
  1711. {
  1712. if ( send.GetNumBytesWritten() >= net_compresspackets_minsize.GetInt() )
  1713. {
  1714. bCompress = true;
  1715. }
  1716. }
  1717. // write correct flags value and the checksum
  1718. flagsPos.WriteByte( flags );
  1719. // Compute checksum (must be aligned to a byte boundary!!)
  1720. if ( ShouldChecksumPackets() )
  1721. {
  1722. const void *pvData = send.GetData() + nCheckSumStart;
  1723. Assert( !(send.GetNumBitsWritten() % 8 ) );
  1724. int nCheckSumBytes = send.GetNumBytesWritten() - nCheckSumStart;
  1725. unsigned short usCheckSum = BufferToShortChecksum( pvData, nCheckSumBytes );
  1726. flagsPos.WriteUBitLong( usCheckSum, 16 );
  1727. }
  1728. // Send the datagram
  1729. int bytesSent = NET_SendPacket ( this, m_Socket, remote_address, send.GetData(), send.GetNumBytesWritten(), bSendVoice ? &m_StreamVoice : 0, bCompress );
  1730. if ( bClearVoice || !ShouldSendVoiceInTheClear() )
  1731. {
  1732. m_StreamVoice.Reset();
  1733. }
  1734. if ( net_showudp.GetInt() && net_showudp.GetInt() != 2 &&
  1735. ( !net_showudp_remoteonly.GetBool() || !( remote_address.IsLocalhost() || remote_address.IsLoopback() ) ) )
  1736. {
  1737. int mask = 63;
  1738. char comp[ 64 ] = { 0 };
  1739. if ( net_compresspackets.GetBool() &&
  1740. bytesSent &&
  1741. ( bytesSent < send.GetNumBytesWritten() ) )
  1742. {
  1743. Q_snprintf( comp, sizeof( comp ), " compression=%5u [%5.2f %%]", bytesSent, 100.0f * float( bytesSent ) / float( send.GetNumBytesWritten() ) );
  1744. }
  1745. char desc[ 128 ];
  1746. uint64 steamID = g_pSteamSocketMgr->GetSteamIDForRemote( remote_address );
  1747. Color clr( 0, 200, 255, 255 );
  1748. if ( steamID != 0ull )
  1749. {
  1750. clr = Color( 255, 255, 100, 255 );
  1751. Q_snprintf( desc, sizeof( desc ), "%12.12s %21.21s s(%llx)", GetName(), GetAddress(), steamID );
  1752. }
  1753. else
  1754. {
  1755. Q_snprintf( desc, sizeof( desc ), "%12.12s %21.21s", GetName(), GetAddress() );
  1756. }
  1757. ConColorMsg ( clr, "UDP -> %s: sz=%5i seq=%5i ack=%5i rel=%1i tm=%8.3f%s\n"
  1758. , desc
  1759. , send.GetNumBytesWritten()
  1760. , ( m_nOutSequenceNr ) & mask
  1761. , m_nInSequenceNr & mask
  1762. , (flags & PACKET_FLAG_RELIABLE) ? 1 : 0
  1763. , (float)net_time
  1764. , comp );
  1765. }
  1766. // update stats
  1767. int nTotalSize = bytesSent + UDP_HEADER_SIZE;
  1768. FlowNewPacket( FLOW_OUTGOING, m_nOutSequenceNr, m_nInSequenceNr, m_nChokedPackets, 0, nTotalSize );
  1769. FlowUpdate( FLOW_OUTGOING, nTotalSize );
  1770. if ( m_fClearTime < net_time )
  1771. {
  1772. m_fClearTime = net_time;
  1773. }
  1774. // calculate net_time when channel will be ready for next packet (throttling)
  1775. // TODO: This doesn't exactly match size sent when packet is a "split" packet (actual bytes sent is higher, etc.)
  1776. double fAddTime = (float)nTotalSize / (float)m_Rate;
  1777. m_fClearTime += fAddTime;
  1778. if ( net_maxcleartime.GetFloat() > 0.0f )
  1779. {
  1780. double m_flLatestClearTime = net_time + net_maxcleartime.GetFloat();
  1781. if ( m_fClearTime > m_flLatestClearTime )
  1782. {
  1783. m_fClearTime = m_flLatestClearTime;
  1784. }
  1785. }
  1786. m_nChokedPackets = 0;
  1787. m_nOutSequenceNr++;
  1788. return m_nOutSequenceNr-1; // return send seq nr
  1789. }
  1790. bool CNetChan::NETMsg_NOP( const CNETMsg_NOP& msg )
  1791. {
  1792. return true;
  1793. }
  1794. bool CNetChan::NETMsg_Disconnect( const CNETMsg_Disconnect& msg )
  1795. {
  1796. #ifdef DEDICATED
  1797. m_MessageHandler->ConnectionClosing( "Disconnect" );
  1798. #else
  1799. m_MessageHandler->ConnectionClosing( msg.text().c_str() );
  1800. #endif
  1801. return false;
  1802. }
  1803. bool CNetChan::NETMsg_File( const CNETMsg_File& msg )
  1804. {
  1805. const char *string = msg.file_name().c_str();
  1806. if ( !msg.deny() && IsValidFileForTransfer( string ) )
  1807. {
  1808. m_MessageHandler->FileRequested( string, msg.transfer_id(), msg.is_replay_demo_file() );
  1809. }
  1810. else
  1811. {
  1812. m_MessageHandler->FileDenied( string, msg.transfer_id(), msg.is_replay_demo_file() );
  1813. }
  1814. return true;
  1815. }
  1816. bool CNetChan::NETMsg_SplitScreenUser( const CNETMsg_SplitScreenUser& msg )
  1817. {
  1818. return m_MessageHandler->ChangeSplitscreenUser( msg.slot() );
  1819. }
  1820. bool CNetChan::WasLastMessageReliable() const
  1821. {
  1822. return m_bWasLastMessageReliable;
  1823. }
  1824. const unsigned char * CNetChan::GetChannelEncryptionKey() const
  1825. {
  1826. extern int32 GetHostVersion();
  1827. static const uint32 unHostVersion = GetHostVersion();
  1828. static const byte ubDefaultEncryptionKey[ NET_CRYPT_KEY_LENGTH ] = {
  1829. 'C', 'S', 'G', 'O',
  1830. byte( ( unHostVersion >> 0 ) & 0xFF ), byte( ( unHostVersion >> 8 ) & 0xFF ), byte( ( unHostVersion >> 16 ) & 0xFF ), byte( ( unHostVersion >> 24 ) & 0xFF ),
  1831. byte( ( unHostVersion >> 2 ) & 0xFF ), byte( ( unHostVersion >> 10 ) & 0xFF ), byte( ( unHostVersion >> 18 ) & 0xFF ), byte( ( unHostVersion >> 26 ) & 0xFF ),
  1832. byte( ( unHostVersion >> 4 ) & 0xFF ), byte( ( unHostVersion >> 12 ) & 0xFF ), byte( ( unHostVersion >> 20 ) & 0xFF ), byte( ( unHostVersion >> 28 ) & 0xFF ),
  1833. };
  1834. return m_EncryptionKey.NumAllocated() ? m_EncryptionKey.Base() : ubDefaultEncryptionKey;
  1835. }
  1836. bool CNetChan::ProcessMessages( bf_read &buf, bool wasReliable )
  1837. {
  1838. MDLCACHE_CRITICAL_SECTION( );
  1839. // For split screen support
  1840. m_pActiveChannel = this;
  1841. return _ProcessMessages( buf, wasReliable );
  1842. // Can't safely put code here because delete this could have occurred!!!
  1843. }
  1844. bool CNetChan::_ProcessMessages( bf_read &buf, bool wasReliable )
  1845. {
  1846. VPROF( "CNetChan::ProcessMessages" );
  1847. #if defined( NET_PARANOID_DUMPS )
  1848. CNetchanParanoidMode *pParanoid = &g_NetParanoid;
  1849. #endif
  1850. m_bStopProcessing = false;
  1851. const char * showmsgname = net_showmsg.GetString();
  1852. const char * blockmsgname = net_blockmsg.GetString();
  1853. if ( showmsgname[ 0 ] == '0' )
  1854. {
  1855. showmsgname = NULL; // dont do strcmp all the time
  1856. }
  1857. if ( blockmsgname[ 0 ] == '0' )
  1858. {
  1859. blockmsgname = NULL; // dont do strcmp all the time
  1860. }
  1861. if ( net_showpeaks.GetInt() > 0 && net_showpeaks.GetInt() < buf.GetNumBytesLeft() )
  1862. {
  1863. showmsgname = "1"; // show messages for this packet only
  1864. }
  1865. bf_read democopy = buf; // create a copy of reading buffer state for demo recording
  1866. m_bWasLastMessageReliable = wasReliable;
  1867. int startbit = buf.GetNumBitsRead();
  1868. while ( true )
  1869. {
  1870. if ( buf.IsOverflowed() )
  1871. {
  1872. Warning( "ProcessMessages %s: incoming buffer overflow!\n", GetAddress() );
  1873. m_MessageHandler->ConnectionCrashed( "Buffer overflow in net message" );
  1874. return false;
  1875. }
  1876. // Are we at the end?
  1877. if ( buf.GetNumBitsLeft() < 8 ) // Minimum bits for message header encoded using VarInt32
  1878. {
  1879. break;
  1880. }
  1881. unsigned char cmd = buf.ReadVarInt32();
  1882. // see if we have a registered message object for this type
  1883. INetMessageBinder *pMsgBind = ((CNetChan *)m_pActiveChannel)->FindMessageBinder( cmd, 0 );
  1884. if ( pMsgBind )
  1885. {
  1886. int startbit = buf.GetNumBitsRead();
  1887. INetMessage * netmsg = pMsgBind->CreateFromBuffer( buf );
  1888. if ( !netmsg )
  1889. {
  1890. Msg( "Netchannel: failed reading message %d from %s.\n", cmd, GetAddress() );
  1891. Assert ( 0 );
  1892. return false;
  1893. }
  1894. netmsg->SetReliable( wasReliable );
  1895. UpdateMessageStats( netmsg->GetGroup(), buf.GetNumBitsRead() - startbit );
  1896. if ( showmsgname )
  1897. {
  1898. if ( (*showmsgname == '1') || !Q_stricmp(showmsgname, netmsg->GetName() ) )
  1899. {
  1900. Msg("Msg from %s: %s\n", GetAddress(), netmsg->GetName() );
  1901. Msg("%s\n", netmsg->ToString() );
  1902. }
  1903. }
  1904. if ( blockmsgname )
  1905. {
  1906. if ( (*blockmsgname== '1') || !Q_stricmp(blockmsgname, netmsg->GetName() ) )
  1907. {
  1908. Msg("Blocking message %s\n", netmsg->ToString() );
  1909. continue;
  1910. }
  1911. }
  1912. int iMsgHandler = 1;
  1913. do
  1914. {
  1915. // netmessage calls the Process function that was registered by it's MessageHandler
  1916. m_bProcessingMessages = true;
  1917. bool bRet = pMsgBind->Process( *netmsg );
  1918. m_bProcessingMessages = false;
  1919. // This means we were deleted during the processing of that message.
  1920. if ( m_bShouldDelete )
  1921. {
  1922. delete netmsg;
  1923. delete this;
  1924. return false;
  1925. }
  1926. // This means our message buffer was freed or invalidated during the processing of that message.
  1927. if ( m_bStopProcessing )
  1928. {
  1929. delete netmsg;
  1930. return false;
  1931. }
  1932. if ( !bRet )
  1933. {
  1934. ConDMsg( "Netchannel: failed processing message %s.\n", netmsg->GetName() );
  1935. Assert ( 0 );
  1936. delete netmsg;
  1937. return false;
  1938. }
  1939. if ( IsOverflowed() )
  1940. {
  1941. delete netmsg;
  1942. return false;
  1943. }
  1944. // Because we are moving to another net message, we have to clone it
  1945. pMsgBind = ( ( CNetChan * )m_pActiveChannel )->FindMessageBinder( cmd, iMsgHandler++ );
  1946. } while( pMsgBind );
  1947. delete netmsg;
  1948. }
  1949. else
  1950. {
  1951. ConMsg( "Netchannel: unknown net message (%i) from %s.\n", cmd, GetAddress() );
  1952. Assert ( 0 );
  1953. #if defined( NET_PARANOID_DUMPS )
  1954. pParanoid->Dump( this, "unknown message" );
  1955. #endif
  1956. return false;
  1957. }
  1958. }
  1959. #if !defined(DEDICATED)
  1960. // all messages could be parsed, write packet to demo file
  1961. if ( m_DemoRecorder && !demoplayer->IsPlayingBack() )
  1962. {
  1963. // only record if any message was paresd
  1964. m_DemoRecorder->RecordMessages( democopy, buf.GetNumBitsRead() - startbit );
  1965. }
  1966. #endif
  1967. #if defined( NET_PARANOID_DUMPS )
  1968. int level = net_dumptest.GetInt();
  1969. if ( level > 0 )
  1970. {
  1971. if (level == 2 )
  1972. {
  1973. // Crash
  1974. #if defined( _X360 )
  1975. XBX_CrashDump( false );
  1976. #else
  1977. byte *p = 0;
  1978. *p = 0x1;
  1979. #endif
  1980. }
  1981. else
  1982. {
  1983. net_dumptest.SetValue( 0 );
  1984. pParanoid->Dump( this, "requested from console" );
  1985. }
  1986. }
  1987. #endif
  1988. return true; // ok fine
  1989. }
  1990. bool CNetChan::SetActiveChannel( INetChannel *pNewChannel )
  1991. {
  1992. m_pActiveChannel = static_cast< CNetChan * >( pNewChannel );
  1993. Assert( m_pActiveChannel );
  1994. return m_pActiveChannel ? true : false;
  1995. }
  1996. void CNetChan::ProcessPlayback( void )
  1997. {
  1998. #if !defined(DEDICATED)
  1999. netpacket_t * packet;
  2000. while ( ( packet = demoplayer->ReadPacket() ) != NULL )
  2001. {
  2002. // Update data flow stats
  2003. FlowNewPacket( FLOW_INCOMING, m_nInSequenceNr, m_nOutSequenceNrAck, 0, 0, packet->wiresize );
  2004. last_received = net_time;
  2005. m_MessageHandler->PacketStart( m_nInSequenceNr, m_nOutSequenceNrAck );
  2006. if ( ProcessMessages( packet->message, true ) )
  2007. {
  2008. m_MessageHandler->PacketEnd();
  2009. }
  2010. else
  2011. {
  2012. break;
  2013. }
  2014. }
  2015. #endif
  2016. }
  2017. CNetChan::subChannel_s *CNetChan::GetFreeSubChannel()
  2018. {
  2019. for ( int i=0; i<MAX_SUBCHANNELS; i++ )
  2020. {
  2021. if ( m_SubChannels[i].state == SUBCHANNEL_FREE )
  2022. return &m_SubChannels[i];
  2023. }
  2024. return NULL;
  2025. }
  2026. void CNetChan::CheckWaitingList(int nList)
  2027. {
  2028. // go thru waiting lists and mark fragments send with this seqnr packet
  2029. if ( m_WaitingList[nList].Count() == 0 || m_nOutSequenceNrAck <= 0 )
  2030. return; // no data in list
  2031. dataFragments_t *data = m_WaitingList[nList][0]; // get head
  2032. if ( data->ackedFragments == data->numFragments )
  2033. {
  2034. // all fragmenst were send successfully
  2035. if ( net_showfragments.GetBool() )
  2036. ConMsg("Sending complete: %i fragments, %i bytes.\n", data->numFragments, data->bytes );
  2037. #if defined( REPLAY_ENABLED )
  2038. // if it's a replay demo, notify the replay system
  2039. if ( data->isReplayDemo )
  2040. {
  2041. Replay_OnFileSendComplete( data->filename, data->bytes );
  2042. }
  2043. #endif
  2044. RemoveHeadInWaitingList( nList );
  2045. return;
  2046. }
  2047. else if ( data->ackedFragments > data->numFragments )
  2048. {
  2049. //ConMsg("CheckWaitingList: invalid acknowledge fragments %i/%i.\n", data->ackedFragments, data->numFragments );
  2050. }
  2051. // else: still pending fragments
  2052. }
  2053. bool CNetChan::CheckReceivingList(int nList)
  2054. {
  2055. dataFragments_t * data = &m_ReceiveList[nList]; // get list
  2056. if ( data->buffer == NULL )
  2057. return true;
  2058. if ( data->ackedFragments < data->numFragments )
  2059. return true;
  2060. if ( data->ackedFragments > data->numFragments )
  2061. {
  2062. ConMsg("Receiving failed: too many fragments %i/%i from %s\n", data->ackedFragments, data->numFragments, GetAddress() );
  2063. return false;
  2064. }
  2065. // got all fragments
  2066. if ( net_showfragments.GetBool() )
  2067. ConMsg("Receiving complete: %i fragments, %i bytes\n", data->numFragments, data->bytes );
  2068. if ( data->isCompressed )
  2069. {
  2070. UncompressFragments( data );
  2071. }
  2072. if ( !data->filename[0] )
  2073. {
  2074. bf_read buffer( data->buffer, data->bytes );
  2075. if ( !ProcessMessages( buffer, true ) ) // parse net message
  2076. {
  2077. return false; // stop reading any further
  2078. }
  2079. }
  2080. else
  2081. {
  2082. static ConVar *s_pAllowUpload = NULL;
  2083. if ( !s_pAllowUpload )
  2084. {
  2085. s_pAllowUpload = g_pCVar->FindVar( "sv_allowupload" );
  2086. }
  2087. if ( s_pAllowUpload && s_pAllowUpload->GetBool() )
  2088. {
  2089. // Make sure that this file is not being written to a location above the current directory, isn't in
  2090. // writing to any locations we don't want, isn't an unsupported
  2091. if ( CNetChan::IsValidFileForTransfer( data->filename ) )
  2092. {
  2093. // CSGO: FileExists will fail with an invalid write path, but writing files will default to the game dir, which
  2094. // lets servers stomp existing files. Use default write path for the below calls (this is the same as the fastdl path done in
  2095. // download.h/cpp
  2096. const char *pszPathID = NULL;
  2097. // we received a file, write it to disk and notify host
  2098. if ( !g_pFileSystem->FileExists( data->filename, pszPathID ) )
  2099. {
  2100. // Make sure path exists
  2101. char szParentDir[ MAX_PATH ];
  2102. if ( !V_ExtractFilePath( data->filename, szParentDir, sizeof(szParentDir) ) )
  2103. {
  2104. szParentDir[0] = '\0';
  2105. }
  2106. g_pFileSystem->CreateDirHierarchy( szParentDir, pszPathID );
  2107. // open new file for write binary
  2108. data->file = g_pFileSystem->Open( data->filename, "wb", pszPathID );
  2109. if ( FILESYSTEM_INVALID_HANDLE != data->file )
  2110. {
  2111. g_pFileSystem->Write( data->buffer, data->bytes, data->file );
  2112. g_pFileSystem->Close( data->file );
  2113. if ( net_showfragments.GetInt() == 2 )
  2114. {
  2115. DevMsg("FileReceived: %s, %i bytes (ID %i)\n", data->filename, data->bytes, data->transferID );
  2116. }
  2117. m_MessageHandler->FileReceived( data->filename, data->transferID, data->isReplayDemo );
  2118. }
  2119. else
  2120. {
  2121. ConMsg("Failed to write received file '%s'!\n", data->filename );
  2122. }
  2123. }
  2124. else
  2125. {
  2126. // don't overwrite existing files
  2127. ConMsg("Download file '%s' already exists!\n", data->filename );
  2128. }
  2129. }
  2130. else
  2131. {
  2132. // Something about the path or extension was unnaceptable
  2133. ConMsg("Download file '%s' has invalid path or extension!\n", data->filename );
  2134. }
  2135. }
  2136. else
  2137. {
  2138. // We won't create the file if 'sv_allowupload' is not enabled
  2139. ConMsg("Download file '%s' ignored. File uploads are disabled!\n", data->filename );
  2140. }
  2141. }
  2142. // clear receiveList
  2143. if ( data->buffer )
  2144. {
  2145. delete [] data->buffer;
  2146. data->buffer = NULL;
  2147. }
  2148. return true;
  2149. }
  2150. int CNetChan::ProcessPacketHeader( netpacket_t * packet )
  2151. {
  2152. // get sequence numbers
  2153. int sequence = packet->message.ReadLong();
  2154. int sequence_ack= packet->message.ReadLong();
  2155. int flags = packet->message.ReadByte();
  2156. if ( ShouldChecksumPackets() )
  2157. {
  2158. unsigned short usCheckSum = (unsigned short)packet->message.ReadUBitLong( 16 );
  2159. // Checksum applies to rest of packet
  2160. Assert( !( packet->message.GetNumBitsRead() % 8 ) );
  2161. int nOffset = packet->message.GetNumBitsRead() >> 3;
  2162. int nCheckSumBytes = packet->message.TotalBytesAvailable() - nOffset;
  2163. const void *pvData = packet->message.GetBasePointer() + nOffset;
  2164. unsigned short usDataCheckSum = BufferToShortChecksum( pvData, nCheckSumBytes );
  2165. if ( usDataCheckSum != usCheckSum )
  2166. {
  2167. ConMsg ("%s:corrupted packet %i at %i\n"
  2168. , GetAddress()
  2169. , sequence
  2170. , m_nInSequenceNr);
  2171. return -1;
  2172. }
  2173. }
  2174. int relState = packet->message.ReadByte(); // reliable state of 8 subchannels
  2175. int nChoked = 0; // read later if choked flag is set
  2176. int i,j;
  2177. if ( flags & PACKET_FLAG_CHOKED )
  2178. nChoked = packet->message.ReadByte();
  2179. // discard stale or duplicated packets
  2180. if (sequence <= m_nInSequenceNr )
  2181. {
  2182. if ( net_showdrop.GetInt() )
  2183. {
  2184. if ( sequence == m_nInSequenceNr )
  2185. {
  2186. ConMsg ("%s:duplicate packet %i at %i\n"
  2187. , GetAddress()
  2188. , sequence
  2189. , m_nInSequenceNr);
  2190. }
  2191. else
  2192. {
  2193. ConMsg ("%s:out of order packet %i at %i\n"
  2194. , GetAddress()
  2195. , sequence
  2196. , m_nInSequenceNr);
  2197. }
  2198. }
  2199. return -1;
  2200. }
  2201. //
  2202. // dropped packets don't keep the message from being used
  2203. //
  2204. m_PacketDrop = sequence - (m_nInSequenceNr + nChoked + 1);
  2205. if ( m_PacketDrop > 0 )
  2206. {
  2207. if ( net_showdrop.GetInt() )
  2208. {
  2209. ConMsg ("%s:Dropped %i packets at %i\n"
  2210. ,GetAddress(), m_PacketDrop, sequence );
  2211. }
  2212. }
  2213. for ( i = 0; i<MAX_SUBCHANNELS; i++ )
  2214. {
  2215. int bitmask = (1<<i);
  2216. // data of channel i has been acknowledged
  2217. subChannel_s * subchan = &m_SubChannels[i];
  2218. Assert( subchan->index == i);
  2219. if ( (m_nOutReliableState & bitmask) == (relState & bitmask) )
  2220. {
  2221. if ( subchan->state == SUBCHANNEL_DIRTY )
  2222. {
  2223. // subchannel was marked dirty during changelevel, waiting list is already cleared
  2224. subchan->Free();
  2225. }
  2226. else if ( subchan->sendSeqNr > sequence_ack )
  2227. {
  2228. ConMsg ("%s:reliable state invalid (%i).\n" ,GetAddress(), i );
  2229. Assert( 0 );
  2230. return -1;
  2231. }
  2232. else if ( subchan->state == SUBCHANNEL_WAITING )
  2233. {
  2234. for ( j=0; j<MAX_STREAMS; j++ )
  2235. {
  2236. if ( subchan->numFragments[j] == 0 )
  2237. continue;
  2238. Assert( m_WaitingList[j].Count() > 0 );
  2239. dataFragments_t * data = m_WaitingList[j][0];
  2240. // tell waiting list, that we received the acknowledge
  2241. data->ackedFragments += subchan->numFragments[j];
  2242. data->pendingFragments -= subchan->numFragments[j];
  2243. }
  2244. subchan->Free(); // mark subchannel as free again
  2245. }
  2246. }
  2247. else // subchannel doesn't match
  2248. {
  2249. if ( subchan->sendSeqNr <= sequence_ack )
  2250. {
  2251. Assert( subchan->state != SUBCHANNEL_FREE );
  2252. if ( subchan->state == SUBCHANNEL_WAITING )
  2253. {
  2254. if ( net_showfragments.GetBool() )
  2255. {
  2256. ConMsg("Resending subchan %i: start %i, num %i\n", subchan->index, subchan->startFraggment[0], subchan->numFragments[0] );
  2257. }
  2258. subchan->state = SUBCHANNEL_TOSEND; // schedule for resend
  2259. }
  2260. else if ( subchan->state == SUBCHANNEL_DIRTY )
  2261. {
  2262. // remote host lost dirty channel data, flip bit back
  2263. int bit = 1<<subchan->index; // flip bit back since data was send yet
  2264. FLIPBIT(m_nOutReliableState, bit);
  2265. subchan->Free();
  2266. }
  2267. }
  2268. }
  2269. }
  2270. m_nInSequenceNr = sequence;
  2271. m_nOutSequenceNrAck = sequence_ack;
  2272. // Update waiting list status
  2273. for( i=0; i<MAX_STREAMS;i++)
  2274. CheckWaitingList( i );
  2275. // Update data flow stats (use wiresize (compressed))
  2276. FlowNewPacket( FLOW_INCOMING, m_nInSequenceNr, m_nOutSequenceNrAck, nChoked, m_PacketDrop, packet->wiresize + UDP_HEADER_SIZE );
  2277. return flags;
  2278. }
  2279. /*
  2280. =================
  2281. CNetChan::ProcessPacket
  2282. called when a new packet has arrived for this netchannel
  2283. sequence numbers are extracted, fragments/file streams stripped
  2284. and then the netmessages processed
  2285. =================
  2286. */
  2287. void CNetChan::ProcessPacket( netpacket_t * packet, bool bHasHeader )
  2288. {
  2289. VPROF( "CNetChan::ProcessPacket" );
  2290. Assert( packet );
  2291. bf_read &msg = packet->message; // handy shortcut
  2292. msg.Seek( 0 );
  2293. if ( remote_address.IsValid() && !packet->from.CompareAdr ( remote_address ) )
  2294. {
  2295. return;
  2296. }
  2297. #if defined( NET_PARANOID_DUMPS )
  2298. g_NetParanoid.StartPacket( msg );
  2299. #endif
  2300. // Update data flow stats
  2301. FlowUpdate( FLOW_INCOMING, packet->wiresize + UDP_HEADER_SIZE );
  2302. int flags = 0;
  2303. if ( bHasHeader )
  2304. {
  2305. flags = ProcessPacketHeader( packet );
  2306. }
  2307. if ( flags == -1 )
  2308. return; // invalid header/packet
  2309. #if defined( NET_PARANOID_DUMPS )
  2310. g_NetParanoid.NoteHeaderSize( msg, flags );
  2311. #endif
  2312. if ( net_showudp.GetInt() && net_showudp.GetInt() != 3 &&
  2313. ( !net_showudp_remoteonly.GetBool() || !( remote_address.IsLocalhost() || remote_address.IsLoopback() ) ) )
  2314. {
  2315. char desc[ 128 ];
  2316. uint64 steamID = g_pSteamSocketMgr->GetSteamIDForRemote( remote_address );
  2317. Color clr( 0, 200, 255, 255 );
  2318. if ( steamID != 0ull )
  2319. {
  2320. clr = Color( 255, 255, 100, 255 );
  2321. Q_snprintf( desc, sizeof( desc ), "%12.12s %21.21s s(%llx)", GetName(), GetAddress(), steamID );
  2322. }
  2323. else
  2324. {
  2325. Q_snprintf( desc, sizeof( desc ), "%12.12s %21.21s", GetName(), GetAddress() );
  2326. }
  2327. ConColorMsg( clr, "UDP <- %s: sz=%5i seq=%5i ack=%5i rel=%1i tm=%8.3f wire=%i\n"
  2328. , desc
  2329. , packet->size
  2330. , m_nInSequenceNr & 63
  2331. , m_nOutSequenceNrAck & 63
  2332. , flags & PACKET_FLAG_RELIABLE ? 1 : 0
  2333. , net_time
  2334. , packet->wiresize );
  2335. }
  2336. last_received = net_time;
  2337. // tell message handler that a new packet has arrived
  2338. m_MessageHandler->PacketStart( m_nInSequenceNr, m_nOutSequenceNrAck );
  2339. if ( flags & PACKET_FLAG_RELIABLE )
  2340. {
  2341. int i, bit = 1<<msg.ReadUBitLong( 3 );
  2342. for ( i=0; i<MAX_STREAMS; i++ )
  2343. {
  2344. if ( msg.ReadOneBit() != 0 )
  2345. {
  2346. if ( !ReadSubChannelData( msg, i ) )
  2347. return; // error while reading fragments, drop whole packet
  2348. }
  2349. }
  2350. // flip subChannel bit to signal successfull receiving
  2351. FLIPBIT(m_nInReliableState, bit);
  2352. for ( i=0; i<MAX_STREAMS; i++ )
  2353. {
  2354. if ( !CheckReceivingList( i ) )
  2355. return; // error while processing
  2356. }
  2357. }
  2358. // Is there anything left to process?
  2359. if ( msg.GetNumBitsLeft() > 0 )
  2360. {
  2361. // parse and handle all messeges
  2362. if ( !ProcessMessages( msg, false ) )
  2363. {
  2364. return; // disconnect or error
  2365. }
  2366. }
  2367. // tell message handler that packet is completely parsed
  2368. m_MessageHandler->PacketEnd();
  2369. #if !defined(DEDICATED)
  2370. // tell demo system that packet is completely parsed
  2371. if ( m_DemoRecorder && !demoplayer->IsPlayingBack() )
  2372. {
  2373. m_DemoRecorder->RecordPacket();
  2374. }
  2375. #endif
  2376. }
  2377. int CNetChan::GetNumBitsWritten( bool bReliable )
  2378. {
  2379. bf_write *pStream = &m_StreamUnreliable;
  2380. if ( bReliable )
  2381. {
  2382. pStream = &m_StreamReliable;
  2383. }
  2384. return pStream->GetNumBitsWritten();
  2385. }
  2386. bool CNetChan::SendNetMsg( INetMessage &msg, bool bForceReliable, bool bVoice )
  2387. {
  2388. if ( remote_address.IsNull() )
  2389. return true;
  2390. bf_write *pStream = &m_StreamUnreliable;
  2391. if ( msg.IsReliable() || bForceReliable )
  2392. {
  2393. pStream = &m_StreamReliable;
  2394. }
  2395. if ( bVoice )
  2396. {
  2397. pStream = &m_StreamVoice;
  2398. }
  2399. bool bResult = msg.WriteToBuffer( *pStream );
  2400. if ( !bResult )
  2401. {
  2402. Warning( "SendNetMsg %s: stream[%s] buffer overflow (maxsize = %d)!\n", GetAddress(), pStream->GetDebugName(), (pStream->GetMaxNumBits()+7)/8 );
  2403. Assert( 0 );
  2404. if ( net_droponsendoverflow.GetBool() )
  2405. {
  2406. m_MessageHandler->ConnectionCrashed( "Buffer overflow in send net message" );
  2407. return false;
  2408. }
  2409. }
  2410. return bResult;
  2411. }
  2412. INetMessageBinder *CNetChan::FindMessageBinder( int type, int index )
  2413. {
  2414. if ( !m_NetMessages.IsValidIndex( type ) )
  2415. {
  2416. return NULL;
  2417. }
  2418. if( index < m_NetMessages[ type ].Count() )
  2419. {
  2420. return m_NetMessages[ type ][ index ];
  2421. }
  2422. return NULL;
  2423. }
  2424. bool CNetChan::RegisterMessage(INetMessageBinder *msg)
  2425. {
  2426. int Type = msg->GetType();
  2427. Assert( Type <= SVC_Messages_MAX || Type <= CLC_Messages_MAX || Type <= NET_Messages_MAX );
  2428. m_NetMessages.EnsureCount( Type + 1 );
  2429. m_NetMessages[ Type ].AddToTail( msg );
  2430. msg->SetNetChannel( this );
  2431. return true;
  2432. }
  2433. bool CNetChan::UnregisterMessage(INetMessageBinder *msg)
  2434. {
  2435. CUtlVector< INetMessageBinder * >& Messages = m_NetMessages[ msg->GetType() ];
  2436. int numtypes = Messages.Count();
  2437. for( int i = 0; i < numtypes; i++ )
  2438. {
  2439. if ( Messages[ i ] == msg )
  2440. {
  2441. Messages.Remove( i );
  2442. return true;
  2443. }
  2444. }
  2445. return false;
  2446. }
  2447. bool CNetChan::SendData( bf_write &msg, bool bReliable )
  2448. {
  2449. // Always queue any pending reliable data ahead of the fragmentation buffer
  2450. if ( remote_address.IsNull() )
  2451. return true;
  2452. if ( msg.GetNumBitsWritten() <= 0 )
  2453. return true;
  2454. if ( msg.IsOverflowed() && !bReliable )
  2455. return true;
  2456. bf_write * buf = bReliable ? &m_StreamReliable : &m_StreamUnreliable;
  2457. if ( msg.GetNumBitsWritten() > buf->GetNumBitsLeft() )
  2458. {
  2459. if ( bReliable )
  2460. {
  2461. ConMsg( "ERROR! SendData reliabe data too big (%i)", msg.GetNumBytesWritten() );
  2462. }
  2463. return false;
  2464. }
  2465. return buf->WriteBits( msg.GetData(), msg.GetNumBitsWritten() );
  2466. }
  2467. bool CNetChan::SendReliableViaStream( dataFragments_t *data)
  2468. {
  2469. // Always queue any pending reliable data ahead of the fragmentation buffer
  2470. char headerBuf[32];
  2471. bf_write header( "outDataHeader", headerBuf, sizeof(headerBuf) );
  2472. data->transferID = m_nOutSequenceNr; // used for acknowledging
  2473. data->pendingFragments = data->numFragments; // send, but not ACKed yet
  2474. header.WriteByte( STREAM_CMD_DATA );
  2475. header.WriteWord( data->bytes ); // bytes
  2476. header.WriteLong( data->transferID );
  2477. if ( net_showtcp.GetInt() )
  2478. {
  2479. ConMsg ("TCP -> %s: sz=%i seq=%i\n", GetAddress(), data->bytes, m_nOutSequenceNr );
  2480. }
  2481. NET_SendStream( m_StreamSocket, (char*)header.GetData(), header.GetNumBytesWritten(), 0 );
  2482. return NET_SendStream( m_StreamSocket, data->buffer, data->bytes, 0 ) != -1;
  2483. }
  2484. bool CNetChan::SendReliableAcknowledge(int seqnr)
  2485. {
  2486. // Always queue any pending reliable data ahead of the fragmentation buffer
  2487. char headerBuf[32];
  2488. bf_write header( "outAcknHeader", headerBuf, sizeof(headerBuf) );
  2489. header.WriteByte( STREAM_CMD_ACKN );
  2490. header.WriteLong( seqnr ); // used for acknowledging
  2491. if ( net_showtcp.GetInt() )
  2492. {
  2493. ConMsg ("TCP -> %s: ACKN seq=%i\n", GetAddress(), seqnr );
  2494. }
  2495. return NET_SendStream( m_StreamSocket, (char*)header.GetData(), header.GetNumBytesWritten(), 0 ) > 0;
  2496. }
  2497. bool CNetChan::ProcessStream( void )
  2498. {
  2499. char cmd;
  2500. ALIGN4 char headerBuf[512] ALIGN4_POST;
  2501. if ( !m_StreamSocket )
  2502. return true;
  2503. if ( m_SteamType == STREAM_CMD_NONE )
  2504. {
  2505. // read command byte
  2506. int ret = NET_ReceiveStream( m_StreamSocket, &cmd, 1, 0 );
  2507. if ( ret == 0)
  2508. {
  2509. // nothing received, but ok
  2510. return true;
  2511. }
  2512. else if ( ret == -1 )
  2513. {
  2514. // something failed with the TCP connection
  2515. return false;
  2516. }
  2517. ResetStreaming(); // clear all state values
  2518. m_SteamType = cmd;
  2519. }
  2520. bf_read header( "inDataHeader", headerBuf, sizeof(headerBuf) );
  2521. // now check command type
  2522. if ( m_SteamType==STREAM_CMD_AUTH )
  2523. {
  2524. // server accpeted connection, send challenge nr
  2525. m_StreamActive = true;
  2526. ResetStreaming();
  2527. return SendReliableAcknowledge( m_ChallengeNr );
  2528. }
  2529. if ( (m_SteamType==STREAM_CMD_DATA) && (m_StreamLength==0) )
  2530. {
  2531. int ret = NET_ReceiveStream( m_StreamSocket, (char*)&headerBuf, 6, 0 ) ;
  2532. if ( ret == 0)
  2533. {
  2534. // nothing received, but ok
  2535. return true;
  2536. }
  2537. else if ( ret == -1 )
  2538. {
  2539. // something failed with the TCP connection
  2540. return false;
  2541. }
  2542. m_StreamLength = header.ReadWord();
  2543. m_StreamSeqNr = header.ReadLong();
  2544. if ( m_StreamLength > NET_MAX_PAYLOAD )
  2545. {
  2546. ConMsg( "ERROR! Stream indata too big (%i)", m_StreamLength );
  2547. return false;
  2548. }
  2549. }
  2550. if ( (m_SteamType==STREAM_CMD_FILE) && (m_SteamFile[0]==0) )
  2551. {
  2552. Assert ( 0 );
  2553. return false;
  2554. }
  2555. if ( (m_SteamType==STREAM_CMD_ACKN) && (m_StreamSeqNr==0) )
  2556. {
  2557. int ret = NET_ReceiveStream( m_StreamSocket, (char*)&headerBuf, 4, 0 );
  2558. if ( ret == 0)
  2559. {
  2560. // nothing received, but ok
  2561. return true;
  2562. }
  2563. else if ( ret == -1 )
  2564. {
  2565. // something failed with the TCP connection
  2566. return false;
  2567. }
  2568. m_StreamSeqNr = header.ReadLong();
  2569. dataFragments_t * data = m_WaitingList[FRAG_NORMAL_STREAM][0];
  2570. if ( data->transferID == (unsigned)m_StreamSeqNr )
  2571. {
  2572. if ( net_showtcp.GetInt() )
  2573. {
  2574. ConMsg ("TCP <- %s: ACKN seq=%i\n", GetAddress(), m_StreamSeqNr );
  2575. }
  2576. Assert( data->pendingFragments == data->numFragments );
  2577. RemoveHeadInWaitingList( FRAG_NORMAL_STREAM );
  2578. }
  2579. else
  2580. {
  2581. ConMsg ("TCP <- %s: invalid ACKN streamlen %d seqnr %i\n", GetAddress(), m_StreamLength, m_StreamSeqNr );
  2582. }
  2583. ResetStreaming();
  2584. return true;
  2585. }
  2586. if ( m_StreamReceived < m_StreamLength )
  2587. {
  2588. // read in 4kB chuncks
  2589. int bytesLeft = ( m_StreamLength - m_StreamReceived );
  2590. int bytesRecv = NET_ReceiveStream( m_StreamSocket, (char*)m_StreamData.Base() + m_StreamReceived, bytesLeft, 0 );
  2591. if ( bytesRecv == 0 )
  2592. {
  2593. return true;
  2594. }
  2595. else if ( bytesRecv == -1 )
  2596. {
  2597. return false;
  2598. }
  2599. m_StreamReceived+= bytesRecv;
  2600. if ( m_StreamReceived > m_StreamLength )
  2601. {
  2602. ConMsg( "ERROR! Stream indata oversize." );
  2603. return false;
  2604. }
  2605. if ( m_StreamReceived == m_StreamLength )
  2606. {
  2607. int ackseqnr =m_StreamSeqNr;
  2608. bf_read buffer( m_StreamData.Base(), m_StreamLength );
  2609. ProcessMessages( buffer, true );
  2610. // reset stream state
  2611. ResetStreaming();
  2612. return SendReliableAcknowledge( ackseqnr ); // tell sender that we have it
  2613. }
  2614. }
  2615. return true;
  2616. }
  2617. int CNetChan::GetDataRate() const
  2618. {
  2619. return m_Rate;
  2620. }
  2621. bool CNetChan::HasPendingReliableData( void )
  2622. {
  2623. return (m_StreamReliable.GetNumBitsWritten() > 0) ||
  2624. (m_WaitingList[FRAG_NORMAL_STREAM].Count() > 0) ||
  2625. (m_WaitingList[FRAG_FILE_STREAM].Count() > 0);
  2626. }
  2627. float CNetChan::GetTimeConnected() const
  2628. {
  2629. float t = net_time - connect_time;
  2630. return (t>0.0f) ? t : 0.0f ;
  2631. }
  2632. const ns_address &CNetChan::GetRemoteAddress() const
  2633. {
  2634. return remote_address;
  2635. }
  2636. INetChannelHandler * CNetChan::GetMsgHandler( void ) const
  2637. {
  2638. return m_MessageHandler;
  2639. }
  2640. bool CNetChan::IsTimedOut() const
  2641. {
  2642. if ( m_Timeout == -1.0f )
  2643. return false;
  2644. else
  2645. return (last_received + m_Timeout) < net_time;
  2646. }
  2647. bool CNetChan::IsTimingOut() const
  2648. {
  2649. if ( m_Timeout == -1.0f )
  2650. return false;
  2651. else
  2652. return (last_received + CONNECTION_PROBLEM_TIME) < net_time;
  2653. }
  2654. float CNetChan::GetTimeoutSeconds() const
  2655. {
  2656. return m_Timeout;
  2657. }
  2658. float CNetChan::GetTimeSinceLastReceived() const
  2659. {
  2660. float t = net_time - last_received;
  2661. return (t>0.0f) ? t : 0.0f ;
  2662. }
  2663. bool CNetChan::IsOverflowed() const
  2664. {
  2665. return m_StreamReliable.IsOverflowed();
  2666. }
  2667. void CNetChan::Reset()
  2668. {
  2669. // FlowReset();
  2670. m_StreamUnreliable.Reset(); // clear any pending unreliable data messages
  2671. m_StreamReliable.Reset(); // clear any pending reliable data messages
  2672. m_fClearTime = 0.0; // ready to send
  2673. m_nChokedPackets = 0;
  2674. m_nSplitPacketSequence = 1;
  2675. }
  2676. int CNetChan::GetSocket() const
  2677. {
  2678. return m_Socket;
  2679. }
  2680. float CNetChan::GetAvgData( int flow ) const
  2681. {
  2682. return m_DataFlow[flow].avgbytespersec;
  2683. }
  2684. float CNetChan::GetAvgPackets( int flow ) const
  2685. {
  2686. return m_DataFlow[flow].avgpacketspersec;
  2687. }
  2688. //-----------------------------------------------------------------------------
  2689. // Purpose:
  2690. // Input : *chan -
  2691. //-----------------------------------------------------------------------------
  2692. int CNetChan::GetTotalData(int flow ) const
  2693. {
  2694. return m_DataFlow[flow].totalbytes;
  2695. }
  2696. int CNetChan::GetTotalPackets( int flow ) const
  2697. {
  2698. return m_DataFlow[flow].totalpackets;
  2699. }
  2700. int CNetChan::GetSequenceNr( int flow ) const
  2701. {
  2702. if ( flow == FLOW_OUTGOING )
  2703. {
  2704. return m_nOutSequenceNr;
  2705. }
  2706. else if ( flow == FLOW_INCOMING )
  2707. {
  2708. return m_nInSequenceNr;
  2709. }
  2710. return 0;
  2711. }
  2712. int CNetChan::GetBufferSize( void ) const
  2713. {
  2714. return NET_FRAMES_BACKUP;
  2715. }
  2716. bool CNetChan::IsValidPacket( int flow, int frame_number ) const
  2717. {
  2718. return m_DataFlow[flow].frame_headers[ frame_number & NET_FRAMES_MASK ].valid;
  2719. }
  2720. float CNetChan::GetPacketTime( int flow, int frame_number ) const
  2721. {
  2722. return m_DataFlow[flow].frame_headers[ frame_number & NET_FRAMES_MASK ].time;
  2723. }
  2724. void CNetChan::GetPacketResponseLatency( int flow, int frame_number, int *pnLatencyMsecs, int *pnChoke ) const
  2725. {
  2726. const netframe_header_t &nfh = m_DataFlow[flow].frame_headers[ frame_number & NET_FRAMES_MASK ];
  2727. const netframe_t &nf = m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ];
  2728. if ( pnLatencyMsecs )
  2729. {
  2730. if ( nf.dropped )
  2731. {
  2732. *pnLatencyMsecs = 9999;
  2733. }
  2734. else
  2735. {
  2736. *pnLatencyMsecs = (int)( 1000.0f * nf.avg_latency );
  2737. }
  2738. }
  2739. if ( pnChoke )
  2740. {
  2741. *pnChoke = nfh.choked;
  2742. }
  2743. }
  2744. void CNetChan::GetRemoteFramerate( float *pflFrameTime, float *pflRemoteFrameTimeStdDeviation, float *pflFrameStartTimeStdDeviation ) const
  2745. {
  2746. if ( pflFrameTime )
  2747. {
  2748. *pflFrameTime = m_flRemoteFrameTime;
  2749. }
  2750. if ( pflRemoteFrameTimeStdDeviation )
  2751. {
  2752. *pflRemoteFrameTimeStdDeviation = m_flRemoteFrameTimeStdDeviation;
  2753. }
  2754. if ( pflFrameStartTimeStdDeviation )
  2755. {
  2756. *pflFrameStartTimeStdDeviation = m_flRemoteFrameStartTimeStdDeviation;
  2757. }
  2758. }
  2759. float CNetChan::GetLatency( int flow ) const
  2760. {
  2761. return m_DataFlow[flow].latency;
  2762. }
  2763. float CNetChan::GetAvgChoke( int flow ) const
  2764. {
  2765. return m_DataFlow[flow].avgchoke;
  2766. }
  2767. float CNetChan::GetAvgLatency( int flow ) const
  2768. {
  2769. return m_DataFlow[flow].avglatency;
  2770. }
  2771. float CNetChan::GetAvgLoss( int flow ) const
  2772. {
  2773. return m_DataFlow[flow].avgloss;
  2774. }
  2775. float CNetChan::GetTime( void ) const
  2776. {
  2777. return net_time;
  2778. }
  2779. bool CNetChan::GetStreamProgress( int flow, int *received, int *total ) const
  2780. {
  2781. (*total) = 0;
  2782. (*received) = 0;
  2783. if ( flow == FLOW_INCOMING )
  2784. {
  2785. for ( int i = 0; i<MAX_STREAMS; i++ )
  2786. {
  2787. if ( m_ReceiveList[i].buffer != NULL )
  2788. {
  2789. (*total) += m_ReceiveList[i].numFragments * FRAGMENT_SIZE;
  2790. (*received) += m_ReceiveList[i].ackedFragments * FRAGMENT_SIZE;
  2791. }
  2792. }
  2793. return ((*total)>0);
  2794. }
  2795. if ( flow == FLOW_OUTGOING )
  2796. {
  2797. for ( int i = 0; i<MAX_STREAMS; i++ )
  2798. {
  2799. if ( m_WaitingList[i].Count() > 0 )
  2800. {
  2801. (*total) += m_WaitingList[i][0]->numFragments * FRAGMENT_SIZE;
  2802. (*received) += m_WaitingList[i][0]->ackedFragments * FRAGMENT_SIZE;
  2803. }
  2804. }
  2805. return ((*total)>0);
  2806. }
  2807. return false; // TODO TCP progress
  2808. }
  2809. float CNetChan::GetCommandInterpolationAmount( int flow, int frame_number ) const
  2810. {
  2811. return m_DataFlow[ flow ].frames[ frame_number & NET_FRAMES_MASK ].m_flInterpolationAmount;
  2812. }
  2813. int CNetChan::GetPacketBytes( int flow, int frame_number, int group ) const
  2814. {
  2815. if ( group >= INetChannelInfo::TOTAL )
  2816. {
  2817. return m_DataFlow[flow].frame_headers[ frame_number & NET_FRAMES_MASK ].size;
  2818. }
  2819. else
  2820. {
  2821. return Bits2Bytes( m_DataFlow[flow].frames[ frame_number & NET_FRAMES_MASK ].msggroups[group] );
  2822. }
  2823. }
  2824. void CNetChan::UpdateMessageStats( int msggroup, int bits)
  2825. {
  2826. netflow_t * pflow = &m_DataFlow[ FLOW_INCOMING ];
  2827. netframe_t *pframe = pflow->currentframe;
  2828. Assert( (msggroup >= INetChannelInfo::GENERIC) && (msggroup < INetChannelInfo::TOTAL) );
  2829. m_MsgStats[msggroup] += bits;
  2830. if ( pframe )
  2831. pframe->msggroups[msggroup] +=bits;
  2832. }
  2833. void CNetChan::IncrementQueuedPackets()
  2834. {
  2835. ++m_nQueuedPackets;
  2836. }
  2837. void CNetChan::DecrementQueuedPackets()
  2838. {
  2839. --m_nQueuedPackets;
  2840. Assert( m_nQueuedPackets >= 0 );
  2841. if ( m_nQueuedPackets < 0 )
  2842. m_nQueuedPackets = 0;
  2843. }
  2844. bool CNetChan::HasQueuedPackets() const
  2845. {
  2846. if ( g_pQueuedPackedSender->HasQueuedPackets( this ) )
  2847. {
  2848. return true;
  2849. }
  2850. return m_nQueuedPackets > 0;
  2851. }
  2852. void CNetChan::SetInterpolationAmount( float flInterpolationAmount )
  2853. {
  2854. m_flInterpolationAmount = flInterpolationAmount;
  2855. }
  2856. void CNetChan::SetRemoteFramerate( float flFrameTime, float flFrameTimeStdDeviation, float flFrameStartTimeStdDeviation )
  2857. {
  2858. m_flRemoteFrameTime = flFrameTime;
  2859. m_flRemoteFrameTimeStdDeviation = flFrameTimeStdDeviation;
  2860. m_flRemoteFrameStartTimeStdDeviation = flFrameStartTimeStdDeviation;
  2861. }
  2862. // Max # of payload bytes before we must split/fragment the packet
  2863. void CNetChan::SetMaxRoutablePayloadSize( int nSplitSize )
  2864. {
  2865. if ( m_nMaxRoutablePayloadSize != nSplitSize )
  2866. {
  2867. DevMsg( "Setting max routable payload size from %d to %d for %s\n",
  2868. m_nMaxRoutablePayloadSize, nSplitSize, GetName() );
  2869. }
  2870. m_nMaxRoutablePayloadSize = nSplitSize;
  2871. }
  2872. int CNetChan::GetMaxRoutablePayloadSize()
  2873. {
  2874. return m_nMaxRoutablePayloadSize;
  2875. }
  2876. int CNetChan::IncrementSplitPacketSequence()
  2877. {
  2878. return ++m_nSplitPacketSequence;
  2879. }
  2880. bool CNetChan::IsValidFileForTransfer( const char *pszFilename )
  2881. {
  2882. if ( !pszFilename || !pszFilename[0] )
  2883. return false;
  2884. // No absolute paths or weaseling up the tree with ".." allowed.
  2885. if ( !COM_IsValidPath( pszFilename ) || V_IsAbsolutePath( pszFilename ) )
  2886. return false;
  2887. char szTemp[MAX_PATH];
  2888. int l = V_strlen( pszFilename );
  2889. if ( l >= sizeof(szTemp) )
  2890. return false;
  2891. V_strcpy_safe( szTemp, pszFilename );
  2892. V_FixSlashes( szTemp, '/' );
  2893. if ( szTemp[l-1] == '/' )
  2894. return false;
  2895. if (
  2896. V_stristr( pszFilename, "lua/" )
  2897. || V_stristr( pszFilename, "gamemodes/" )
  2898. || V_stristr( pszFilename, "scripts/" )
  2899. || V_stristr( pszFilename, "addons/" )
  2900. || V_stristr( pszFilename, "cfg/" )
  2901. || V_stristr( pszFilename, "~/" )
  2902. || V_stristr( pszFilename, "gamemodes.txt" )
  2903. )
  2904. return false;
  2905. // Allow only bsp and nav file transfers to not overwrite any assets in maps directory
  2906. if ( V_stristr( pszFilename, "maps/" ) &&
  2907. !V_stristr( pszFilename, ".bsp" ) &&
  2908. !V_stristr( pszFilename, ".ain" ) &&
  2909. !V_stristr( pszFilename, ".nav" ) )
  2910. return false;
  2911. const char *extension = V_strrchr( pszFilename, '.' );
  2912. if ( !extension )
  2913. return false;
  2914. int baseLen = V_strlen( extension );
  2915. if ( baseLen > 4 || baseLen < 3 )
  2916. return false;
  2917. // are there any spaces in the extension? (windows exploit)
  2918. const char *pChar = extension;
  2919. while ( *pChar )
  2920. {
  2921. if ( V_isspace( *pChar ) )
  2922. {
  2923. return false;
  2924. }
  2925. ++pChar;
  2926. }
  2927. if ( !Q_strcasecmp( extension, ".cfg" ) ||
  2928. !Q_strcasecmp( extension, ".lst" ) ||
  2929. !Q_strcasecmp( extension, ".lmp" ) ||
  2930. !Q_strcasecmp( extension, ".exe" ) ||
  2931. !Q_strcasecmp( extension, ".vbs" ) ||
  2932. !Q_strcasecmp( extension, ".com" ) ||
  2933. !Q_strcasecmp( extension, ".bat" ) ||
  2934. !Q_strcasecmp( extension, ".dll" ) ||
  2935. !Q_strcasecmp( extension, ".ini" ) ||
  2936. !Q_strcasecmp( extension, ".log" ) ||
  2937. !Q_strcasecmp( extension, ".lua" ) ||
  2938. !Q_strcasecmp( extension, ".nut" ) ||
  2939. !Q_strcasecmp( extension, ".vdf" ) ||
  2940. !Q_strcasecmp( extension, ".smx" ) ||
  2941. !Q_strcasecmp( extension, ".gcf" ) ||
  2942. !Q_strcasecmp( extension, ".sys" ) )
  2943. {
  2944. return false;
  2945. }
  2946. return true;
  2947. }
  2948. void CNetChan::AttachSplitPlayer( int nSplitPlayerSlot, INetChannel *pChannel )
  2949. {
  2950. SplitPlayer_t search;
  2951. search.m_nSlot = nSplitPlayerSlot;
  2952. search.m_pChannel = pChannel;
  2953. int idx = m_SplitPlayers.Find( search );
  2954. if ( idx == m_SplitPlayers.InvalidIndex() )
  2955. {
  2956. m_SplitPlayers.Insert( search );
  2957. }
  2958. }
  2959. void CNetChan::DetachSplitPlayer( int nSplitPlayerSlot )
  2960. {
  2961. SplitPlayer_t search;
  2962. search.m_nSlot = nSplitPlayerSlot;
  2963. int idx = m_SplitPlayers.Find( search );
  2964. if ( idx != m_SplitPlayers.InvalidIndex() )
  2965. {
  2966. m_SplitPlayers.RemoveAt( idx );
  2967. }
  2968. }
  2969. void CNetChan::ChangeSplitUser( bf_write &out, int slot )
  2970. {
  2971. // Msg( "Changing to slot %d on %s\n", slot, GetName() );
  2972. CNETMsg_SplitScreenUser_t SplitScreenUser;
  2973. SplitScreenUser.set_slot( slot );
  2974. SplitScreenUser.WriteToBuffer( out );
  2975. }
  2976. void CNetChan::MaybeAppendBuffer( EBufType eBufType, bf_write &out, SplitPlayer_t &sp, bf_write &src, int *pnCurrentSlot )
  2977. {
  2978. if ( src.GetNumBitsWritten() <= 0 )
  2979. return;
  2980. if ( sp.m_nSlot != *pnCurrentSlot )
  2981. {
  2982. *pnCurrentSlot = sp.m_nSlot;
  2983. ChangeSplitUser( out, sp.m_nSlot );
  2984. }
  2985. out.WriteBits( src.GetData(), src.GetNumBitsWritten() );
  2986. //Msg( "Wrote %d [%.3f] bits to buffer %s\n",
  2987. // src.GetNumBitsWritten(), (float)src.GetNumBitsWritten() / 8.0f, GetBufferDebugName( eBufType ) );
  2988. src.Reset();
  2989. }
  2990. bf_write &CNetChan::GetBuffer( EBufType eBufType )
  2991. {
  2992. switch ( eBufType )
  2993. {
  2994. default:
  2995. break;
  2996. case BUF_RELIABLE:
  2997. return m_StreamReliable;
  2998. case BUF_UNRELIABLE:
  2999. return m_StreamUnreliable;
  3000. case BUF_VOICE:
  3001. return m_StreamVoice;
  3002. }
  3003. Assert( 0 );
  3004. return m_StreamReliable;
  3005. }
  3006. char const *CNetChan::GetBufferDebugName( EBufType eBufType )
  3007. {
  3008. switch ( eBufType )
  3009. {
  3010. default:
  3011. break;
  3012. case BUF_RELIABLE:
  3013. return "m_StreamReliable";
  3014. case BUF_UNRELIABLE:
  3015. return "m_StreamUnreliable";
  3016. case BUF_VOICE:
  3017. return "m_StreamVoice";
  3018. }
  3019. Assert( 0 );
  3020. return "???";
  3021. }
  3022. void CNetChan::MergeSplitUserBuffers( EBufType eBufType, bf_write &outbuf )
  3023. {
  3024. int nCurrentSlot = 0;
  3025. for ( int user = m_SplitPlayers.FirstInorder(); user != m_SplitPlayers.InvalidIndex(); user = m_SplitPlayers.NextInorder( user ) )
  3026. {
  3027. SplitPlayer_t &sp = m_SplitPlayers[ user ];
  3028. CNetChan *chan = static_cast< CNetChan * >( sp.m_pChannel );
  3029. if ( !chan )
  3030. continue;
  3031. bf_write &src = chan->GetBuffer( eBufType );
  3032. // This might change the user
  3033. MaybeAppendBuffer( eBufType, outbuf, sp, src, &nCurrentSlot );
  3034. }
  3035. if ( nCurrentSlot != 0 )
  3036. {
  3037. ChangeSplitUser( outbuf, 0 );
  3038. }
  3039. }
  3040. void CNetChan::SplitUserCombineForSending()
  3041. {
  3042. // Nothing to do?
  3043. if ( m_SplitPlayers.Count() == 0 )
  3044. return;
  3045. MergeSplitUserBuffers( BUF_RELIABLE, m_StreamReliable );
  3046. // FIXME: datagram payload?
  3047. MergeSplitUserBuffers( BUF_UNRELIABLE, m_StreamUnreliable );
  3048. MergeSplitUserBuffers( BUF_VOICE, m_StreamVoice );
  3049. }
  3050. bool CNetChan::IsRemoteDisconnected() const
  3051. {
  3052. // See if we think remote side is using Steam sockets
  3053. if ( remote_address.IsValid() && // was connected
  3054. remote_address.GetPort() == (unsigned short)ISteamSocketMgr::STEAM_CNX_PORT && // was using the "steam" pseudo port #
  3055. g_pSteamSocketMgr->GetSteamIDForRemote( remote_address ) == 0ull ) // no longer have an association for the remote side by steamid (socket died)
  3056. {
  3057. return true;
  3058. }
  3059. // Regular case never signals this way.
  3060. return false;
  3061. }