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

1735 lines
43 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: baseclient.cpp: implementation of the CBaseClient class.
  4. //
  5. //===========================================================================//
  6. #include "client_pch.h"
  7. #include "tier0/etwprof.h"
  8. #include "eiface.h"
  9. #include "baseclient.h"
  10. #include "server.h"
  11. #include "host.h"
  12. #include "networkstringtable.h"
  13. #include "framesnapshot.h"
  14. #include "GameEventManager.h"
  15. #include "LocalNetworkBackdoor.h"
  16. #include "dt_send_eng.h"
  17. #ifndef SWDS
  18. #include "vgui_baseui_interface.h"
  19. #endif
  20. #include "sv_remoteaccess.h" // NotifyDedicatedServerUI()
  21. #include "MapReslistGenerator.h"
  22. #include "sv_steamauth.h"
  23. #include "matchmaking.h"
  24. #include "iregistry.h"
  25. #include "sv_main.h"
  26. #include "hltvserver.h"
  27. #include <ctype.h>
  28. #if defined( REPLAY_ENABLED )
  29. #include "replay_internal.h"
  30. #endif
  31. // memdbgon must be the last include file in a .cpp file!!!
  32. #include "tier0/memdbgon.h"
  33. extern IServerGameDLL *serverGameDLL;
  34. extern ConVar tv_enable;
  35. ConVar sv_namechange_cooldown_seconds( "sv_namechange_cooldown_seconds", "30.0", FCVAR_NONE, "When a client name change is received, wait N seconds before allowing another name change" );
  36. ConVar sv_netspike_on_reliable_snapshot_overflow( "sv_netspike_on_reliable_snapshot_overflow", "0", FCVAR_NONE, "If nonzero, the server will dump a netspike trace if a client is dropped due to reliable snapshot overflow" );
  37. ConVar sv_netspike_sendtime_ms( "sv_netspike_sendtime_ms", "0", FCVAR_NONE, "If nonzero, the server will dump a netspike trace if it takes more than N ms to prepare a snapshot to a single client. This feature does take some CPU cycles, so it should be left off when not in use." );
  38. ConVar sv_netspike_output( "sv_netspike_output", "1", FCVAR_NONE, "Where the netspike data be written? Sum of the following values: 1=netspike.txt, 2=ordinary server log" );
  39. //////////////////////////////////////////////////////////////////////
  40. // Construction/Destruction
  41. //////////////////////////////////////////////////////////////////////
  42. CBaseClient::CBaseClient()
  43. {
  44. // init all pointers
  45. m_NetChannel = NULL;
  46. m_ConVars = NULL;
  47. m_Server = NULL;
  48. m_pBaseline = NULL;
  49. m_bIsHLTV = false;
  50. #if defined( REPLAY_ENABLED )
  51. m_bIsReplay = false;
  52. #endif
  53. m_bConVarsChanged = false;
  54. m_bInitialConVarsSet = false;
  55. m_bSendServerInfo = false;
  56. m_bFullyAuthenticated = false;
  57. m_fTimeLastNameChange = 0.0;
  58. m_szPendingNameChange[0] = '\0';
  59. m_bReportFakeClient = true;
  60. m_iTracing = 0;
  61. m_bPlayerNameLocked = false;
  62. }
  63. CBaseClient::~CBaseClient()
  64. {
  65. }
  66. void CBaseClient::SetRate(int nRate, bool bForce )
  67. {
  68. if ( m_NetChannel )
  69. m_NetChannel->SetDataRate( nRate );
  70. }
  71. int CBaseClient::GetRate( void ) const
  72. {
  73. if ( m_NetChannel )
  74. {
  75. return m_NetChannel->GetDataRate();
  76. }
  77. else
  78. {
  79. return 0;
  80. }
  81. }
  82. bool CBaseClient::FillUserInfo( player_info_s &userInfo )
  83. {
  84. Q_memset( &userInfo, 0, sizeof(userInfo) );
  85. if ( !m_Name[0] || !IsConnected() )
  86. return false; // inactive user, no more data available
  87. Q_strncpy( userInfo.name, GetClientName(), MAX_PLAYER_NAME_LENGTH );
  88. V_strcpy_safe( userInfo.guid, GetNetworkIDString() );
  89. userInfo.friendsID = m_nFriendsID;
  90. Q_strncpy( userInfo.friendsName, m_FriendsName, sizeof(m_FriendsName) );
  91. userInfo.userID = GetUserID();
  92. userInfo.fakeplayer = IsFakeClient();
  93. userInfo.ishltv = IsHLTV();
  94. #if defined( REPLAY_ENABLED )
  95. userInfo.isreplay = IsReplay();
  96. #endif
  97. for( int i=0; i< MAX_CUSTOM_FILES; i++ )
  98. userInfo.customFiles[i] = m_nCustomFiles[i].crc;
  99. userInfo.filesDownloaded = m_nFilesDownloaded;
  100. return true;
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: Send text to client
  104. // Input : *fmt -
  105. // ... -
  106. //-----------------------------------------------------------------------------
  107. void CBaseClient::ClientPrintf (const char *fmt, ...)
  108. {
  109. if ( !m_NetChannel )
  110. {
  111. return;
  112. }
  113. va_list argptr;
  114. char string[1024];
  115. va_start (argptr,fmt);
  116. Q_vsnprintf (string, sizeof( string ), fmt,argptr);
  117. va_end (argptr);
  118. SVC_Print print(string);
  119. m_NetChannel->SendNetMsg( print );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose: Send text to client
  123. // Input : *fmt -
  124. // ... -
  125. //-----------------------------------------------------------------------------
  126. bool CBaseClient::SendNetMsg(INetMessage &msg, bool bForceReliable)
  127. {
  128. if ( !m_NetChannel )
  129. {
  130. return true;
  131. }
  132. int nStartBit = m_NetChannel->GetNumBitsWritten( msg.IsReliable() || bForceReliable );
  133. bool bret = m_NetChannel->SendNetMsg( msg, bForceReliable );
  134. if ( IsTracing() )
  135. {
  136. int nBits = m_NetChannel->GetNumBitsWritten( msg.IsReliable() || bForceReliable ) - nStartBit;
  137. TraceNetworkMsg( nBits, "NetMessage %s", msg.GetName() );
  138. }
  139. return bret;
  140. }
  141. char const *CBaseClient::GetUserSetting(char const *pchCvar) const
  142. {
  143. if ( !m_ConVars || !pchCvar || !pchCvar[0] )
  144. {
  145. return "";
  146. }
  147. const char * value = m_ConVars->GetString( pchCvar, "" );
  148. if ( value[0]==0 )
  149. {
  150. // check if this var even existed
  151. if ( m_ConVars->GetDataType( pchCvar ) == KeyValues::TYPE_NONE )
  152. {
  153. DevMsg( "GetUserSetting: cvar '%s' unknown.\n", pchCvar );
  154. }
  155. }
  156. return value;
  157. }
  158. void CBaseClient::SetUserCVar( const char *pchCvar, const char *value)
  159. {
  160. if ( !pchCvar || !value )
  161. return;
  162. // Name is handled differently
  163. if ( !Q_stricmp( pchCvar, "name") )
  164. {
  165. //Msg("CBaseClient::SetUserCVar[index=%d]('name', '%s')\n", m_nClientSlot, value );
  166. ClientRequestNameChange( value );
  167. return;
  168. }
  169. m_ConVars->SetString( pchCvar, value );
  170. }
  171. void CBaseClient::SetUpdateRate(int udpaterate, bool bForce)
  172. {
  173. udpaterate = clamp( udpaterate, 1, 100 );
  174. m_fSnapshotInterval = 1.0f / udpaterate;
  175. }
  176. int CBaseClient::GetUpdateRate(void) const
  177. {
  178. if ( m_fSnapshotInterval > 0 )
  179. return (int)(1.0f/m_fSnapshotInterval);
  180. else
  181. return 0;
  182. }
  183. void CBaseClient::FreeBaselines()
  184. {
  185. if ( m_pBaseline )
  186. {
  187. m_pBaseline->ReleaseReference();
  188. m_pBaseline = NULL;
  189. }
  190. m_nBaselineUpdateTick = -1;
  191. m_nBaselineUsed = 0;
  192. m_BaselinesSent.ClearAll();
  193. }
  194. void CBaseClient::Clear()
  195. {
  196. // Throw away any residual garbage in the channel.
  197. if ( m_NetChannel )
  198. {
  199. m_NetChannel->Shutdown("Disconnect by server.\n");
  200. m_NetChannel = NULL;
  201. }
  202. if ( m_ConVars )
  203. {
  204. m_ConVars->deleteThis();
  205. m_ConVars = NULL;
  206. }
  207. FreeBaselines();
  208. // This used to be a memset, but memset will screw up any embedded classes
  209. // and we want to preserve some things like index.
  210. m_nSignonState = SIGNONSTATE_NONE;
  211. m_nDeltaTick = -1;
  212. m_nSignonTick = 0;
  213. m_nStringTableAckTick = 0;
  214. m_pLastSnapshot = NULL;
  215. m_nForceWaitForTick = -1;
  216. m_bFakePlayer = false;
  217. m_bIsHLTV = false;
  218. #if defined( REPLAY_ENABLED )
  219. m_bIsReplay = false;
  220. #endif
  221. m_fNextMessageTime = 0;
  222. m_fSnapshotInterval = 0;
  223. m_bReceivedPacket = false;
  224. m_UserID = 0;
  225. m_Name[0] = 0;
  226. m_nFriendsID = 0;
  227. m_FriendsName[0] = 0;
  228. m_nSendtableCRC = 0;
  229. m_nBaselineUpdateTick = -1;
  230. m_nBaselineUsed = 0;
  231. m_nFilesDownloaded = 0;
  232. m_bConVarsChanged = false;
  233. m_bSendServerInfo = false;
  234. m_bFullyAuthenticated = false;
  235. m_fTimeLastNameChange = 0.0;
  236. m_szPendingNameChange[0] = '\0';
  237. Q_memset( m_nCustomFiles, 0, sizeof(m_nCustomFiles) );
  238. }
  239. bool CBaseClient::SetSignonState(int state, int spawncount)
  240. {
  241. MDLCACHE_COARSE_LOCK_(g_pMDLCache);
  242. switch( m_nSignonState )
  243. {
  244. case SIGNONSTATE_CONNECTED : // client is connected, leave client in this state and let SendPendingSignonData do the rest
  245. m_bSendServerInfo = true;
  246. break;
  247. case SIGNONSTATE_NEW : // client got server info, send prespawn datam_Client->SendServerInfo()
  248. if ( !SendSignonData() )
  249. return false;
  250. break;
  251. case SIGNONSTATE_PRESPAWN : SpawnPlayer();
  252. break;
  253. case SIGNONSTATE_SPAWN : ActivatePlayer();
  254. break;
  255. case SIGNONSTATE_FULL : OnSignonStateFull();
  256. break;
  257. case SIGNONSTATE_CHANGELEVEL: break;
  258. }
  259. return true;
  260. }
  261. void CBaseClient::Reconnect( void )
  262. {
  263. ConMsg("Forcing client reconnect (%i)\n", m_nSignonState );
  264. m_NetChannel->Clear();
  265. m_nSignonState = SIGNONSTATE_CONNECTED;
  266. NET_SignonState signon( m_nSignonState, -1 );
  267. m_NetChannel->SendNetMsg( signon );
  268. }
  269. void CBaseClient::Inactivate( void )
  270. {
  271. FreeBaselines();
  272. m_nDeltaTick = -1;
  273. m_nSignonTick = 0;
  274. m_nStringTableAckTick = 0;
  275. m_pLastSnapshot = NULL;
  276. m_nForceWaitForTick = -1;
  277. m_nSignonState = SIGNONSTATE_CHANGELEVEL;
  278. if ( m_NetChannel )
  279. {
  280. // don't do that for fakeclients
  281. m_NetChannel->Clear();
  282. if ( NET_IsMultiplayer() )
  283. {
  284. NET_SignonState signon( m_nSignonState, m_Server->GetSpawnCount() );
  285. SendNetMsg( signon );
  286. // force sending message now
  287. m_NetChannel->Transmit();
  288. }
  289. }
  290. // don't receive event messages anymore
  291. g_GameEventManager.RemoveListener( this );
  292. }
  293. //---------------------------------------------------------------------------
  294. // Purpose: Determine whether or not a character should be ignored in a player's name.
  295. //---------------------------------------------------------------------------
  296. inline bool BIgnoreCharInName ( unsigned char cChar, bool bIsFirstCharacter )
  297. {
  298. // Don't copy '%' or '~' chars across
  299. // Don't copy '#' chars across if they would go into the first position in the name
  300. // Don't allow color codes ( less than COLOR_MAX )
  301. return cChar == '%' || cChar == '~' || cChar < 0x09 || ( bIsFirstCharacter && cChar == '#' );
  302. }
  303. void ValidateName( char *pszName, int nBuffSize )
  304. {
  305. if ( !pszName )
  306. return;
  307. // did we get an empty string for the name?
  308. if ( Q_strlen( pszName ) <= 0 )
  309. {
  310. Q_snprintf( pszName, nBuffSize, "unnamed" );
  311. }
  312. else
  313. {
  314. Q_RemoveAllEvilCharacters( pszName );
  315. const unsigned char *pChar = (unsigned char *)pszName;
  316. // also skip characters we're going to ignore
  317. while ( *pChar && ( isspace(*pChar) || BIgnoreCharInName( *pChar, true ) ) )
  318. {
  319. ++pChar;
  320. }
  321. // did we get all the way to the end of the name without a non-whitespace character?
  322. if ( *pChar == '\0' )
  323. {
  324. Q_snprintf( pszName, nBuffSize, "unnamed" );
  325. }
  326. }
  327. }
  328. void CBaseClient::SetName(const char * playerName)
  329. {
  330. char name[MAX_PLAYER_NAME_LENGTH];
  331. Q_strncpy( name, playerName, sizeof(name) );
  332. // Clear any pending name change
  333. m_szPendingNameChange[0] = '\0';
  334. // quick check to make sure the name isn't empty or full of whitespace
  335. ValidateName( name, sizeof(name) );
  336. if ( Q_strncmp( name, m_Name, sizeof(m_Name) ) == 0 )
  337. return; // didn't change
  338. int i;
  339. int dupc = 1;
  340. char *p, *val;
  341. char newname[MAX_PLAYER_NAME_LENGTH];
  342. // remove evil char '%'
  343. char *pFrom = (char *)name;
  344. char *pTo = m_Name;
  345. char *pLimit = &m_Name[sizeof(m_Name)-1];
  346. while ( *pFrom && pTo < pLimit )
  347. {
  348. // Don't copy '%' or '~' chars across
  349. // Don't copy '#' chars across if they would go into the first position in the name
  350. // Don't allow color codes ( less than COLOR_MAX )
  351. if ( !BIgnoreCharInName( *pFrom, pTo == &m_Name[0] ) )
  352. {
  353. *pTo++ = *pFrom;
  354. }
  355. pFrom++;
  356. }
  357. *pTo = 0;
  358. Assert( m_Name[ 0 ] != '\0' ); // this should've been caught by ValidateName
  359. if ( m_Name[ 0 ] == '\0' )
  360. {
  361. V_strncpy( m_Name, "unnamed", sizeof(m_Name) );
  362. }
  363. val = m_Name;
  364. // Don't care about duplicate names on the xbox. It can only occur when a player
  365. // is reconnecting after crashing, and we don't want to ever show the (X) then.
  366. if ( !IsX360() )
  367. {
  368. // Check to see if another user by the same name exists
  369. while ( true )
  370. {
  371. for ( i = 0; i < m_Server->GetClientCount(); i++ )
  372. {
  373. IClient *client = m_Server->GetClient( i );
  374. if( !client->IsConnected() || client == this )
  375. continue;
  376. // If it's 2 bots they're allowed to have matching names, otherwise there's a conflict
  377. if( !Q_stricmp( client->GetClientName(), val ) && !( IsFakeClient() && client->IsFakeClient() ) )
  378. {
  379. CBaseClient *pClient = dynamic_cast< CBaseClient* >( client );
  380. if ( IsFakeClient() && pClient )
  381. {
  382. // We're a bot so we get to keep the name... change the other guy
  383. pClient->m_Name[ 0 ] = '\0';
  384. pClient->SetName( val );
  385. }
  386. else
  387. {
  388. break;
  389. }
  390. }
  391. }
  392. if (i >= m_Server->GetClientCount())
  393. break;
  394. p = val;
  395. if (val[0] == '(')
  396. {
  397. if (val[2] == ')')
  398. {
  399. p = val + 3;
  400. }
  401. else if (val[3] == ')') //assumes max players is < 100
  402. {
  403. p = val + 4;
  404. }
  405. }
  406. Q_snprintf(newname, sizeof(newname), "(%d)%-.*s", dupc++, MAX_PLAYER_NAME_LENGTH - 4, p );
  407. Q_strncpy(m_Name, newname, sizeof(m_Name));
  408. val = m_Name;
  409. }
  410. }
  411. m_ConVars->SetString( "name", m_Name );
  412. m_bConVarsChanged = true;
  413. m_Server->UserInfoChanged( m_nClientSlot );
  414. }
  415. void CBaseClient::ActivatePlayer()
  416. {
  417. COM_TimestampedLog( "CBaseClient::ActivatePlayer" );
  418. // tell server to update the user info table (if not already done)
  419. m_Server->UserInfoChanged( m_nClientSlot );
  420. m_nSignonState = SIGNONSTATE_FULL;
  421. MapReslistGenerator().OnPlayerSpawn();
  422. #ifndef _XBOX
  423. // update the UI
  424. NotifyDedicatedServerUI("UpdatePlayers");
  425. #endif
  426. }
  427. void CBaseClient::SpawnPlayer( void )
  428. {
  429. COM_TimestampedLog( "CBaseClient::SpawnPlayer" );
  430. if ( !IsFakeClient() )
  431. {
  432. // free old baseline snapshot
  433. FreeBaselines();
  434. // create baseline snapshot for real clients
  435. m_pBaseline = framesnapshotmanager->CreateEmptySnapshot( 0, MAX_EDICTS );
  436. }
  437. // Set client clock to match server's
  438. NET_Tick tick( m_Server->GetTick(), host_frametime_unbounded, host_frametime_stddeviation );
  439. SendNetMsg( tick, true );
  440. // Spawned into server, not fully active, though
  441. m_nSignonState = SIGNONSTATE_SPAWN;
  442. NET_SignonState signonState (m_nSignonState, m_Server->GetSpawnCount() );
  443. SendNetMsg( signonState );
  444. }
  445. bool CBaseClient::SendSignonData( void )
  446. {
  447. COM_TimestampedLog( " CBaseClient::SendSignonData" );
  448. #ifndef SWDS
  449. EngineVGui()->UpdateProgressBar(PROGRESS_SENDSIGNONDATA);
  450. #endif
  451. if ( m_Server->m_Signon.IsOverflowed() )
  452. {
  453. Host_Error( "Signon buffer overflowed %i bytes!!!\n", m_Server->m_Signon.GetNumBytesWritten() );
  454. return false;
  455. }
  456. m_NetChannel->SendData( m_Server->m_Signon );
  457. m_nSignonState = SIGNONSTATE_PRESPAWN;
  458. NET_SignonState signonState( m_nSignonState, m_Server->GetSpawnCount() );
  459. return m_NetChannel->SendNetMsg( signonState );
  460. }
  461. void CBaseClient::Connect( const char * szName, int nUserID, INetChannel *pNetChannel, bool bFakePlayer, int clientChallenge )
  462. {
  463. COM_TimestampedLog( "CBaseClient::Connect" );
  464. #ifndef SWDS
  465. EngineVGui()->UpdateProgressBar(PROGRESS_SIGNONCONNECT);
  466. #endif
  467. Clear();
  468. m_ConVars = new KeyValues("userinfo");
  469. m_bInitialConVarsSet = false;
  470. m_UserID = nUserID;
  471. SetName( szName );
  472. m_fTimeLastNameChange = 0.0;
  473. m_bFakePlayer = bFakePlayer;
  474. m_NetChannel = pNetChannel;
  475. if ( m_NetChannel && m_Server && m_Server->IsMultiplayer() )
  476. {
  477. m_NetChannel->SetCompressionMode( true );
  478. }
  479. m_clientChallenge = clientChallenge;
  480. m_nSignonState = SIGNONSTATE_CONNECTED;
  481. if ( bFakePlayer )
  482. {
  483. // Hidden fake players and the HLTV/Replay bot will get removed by CSteam3Server::SendUpdatedServerDetails.
  484. Steam3Server().NotifyLocalClientConnect( this );
  485. }
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Purpose: Drops client from server, with explanation
  489. // Input : *cl -
  490. // crash -
  491. // *fmt -
  492. // ... -
  493. //-----------------------------------------------------------------------------
  494. void CBaseClient::Disconnect( const char *fmt, ... )
  495. {
  496. va_list argptr;
  497. char string[1024];
  498. if ( m_nSignonState == SIGNONSTATE_NONE )
  499. return; // no recursion
  500. #if !defined( SWDS ) && defined( ENABLE_RPT )
  501. SV_NotifyRPTOfDisconnect( m_nClientSlot );
  502. #endif
  503. #ifndef _XBOX
  504. Steam3Server().NotifyClientDisconnect( this );
  505. #endif
  506. m_nSignonState = SIGNONSTATE_NONE;
  507. // clear user info
  508. m_Server->UserInfoChanged( m_nClientSlot );
  509. va_start (argptr,fmt);
  510. Q_vsnprintf (string, sizeof( string ), fmt,argptr);
  511. va_end (argptr);
  512. ConMsg("Dropped %s from server (%s)\n", GetClientName(), string );
  513. // remove the client as listener
  514. g_GameEventManager.RemoveListener( this );
  515. // Send the remaining reliable buffer so the client finds out the server is shutting down.
  516. if ( m_NetChannel )
  517. {
  518. m_NetChannel->Shutdown( string ) ;
  519. m_NetChannel = NULL;
  520. }
  521. Clear(); // clear state
  522. #ifndef _XBOX
  523. NotifyDedicatedServerUI("UpdatePlayers");
  524. #endif
  525. Steam3Server().SendUpdatedServerDetails(); // Update the master server.
  526. }
  527. void CBaseClient::FireGameEvent( IGameEvent *event )
  528. {
  529. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  530. char buffer_data[MAX_EVENT_BYTES];
  531. SVC_GameEvent eventMsg;
  532. eventMsg.m_DataOut.StartWriting( buffer_data, sizeof(buffer_data) );
  533. // create bitstream from KeyValues
  534. if ( g_GameEventManager.SerializeEvent( event, &eventMsg.m_DataOut ) )
  535. {
  536. if ( m_NetChannel )
  537. {
  538. bool bSent = m_NetChannel->SendNetMsg( eventMsg );
  539. if ( !bSent )
  540. DevMsg("GameEventManager: failed to send event '%s'.\n", event->GetName() );
  541. }
  542. }
  543. else
  544. {
  545. DevMsg("GameEventManager: failed to serialize event '%s'.\n", event->GetName() );
  546. }
  547. }
  548. bool CBaseClient::SendServerInfo( void )
  549. {
  550. COM_TimestampedLog( " CBaseClient::SendServerInfo" );
  551. // supporting smaller stack
  552. byte *buffer = (byte *)MemAllocScratch( NET_MAX_PAYLOAD );
  553. bf_write msg( "SV_SendServerinfo->msg", buffer, NET_MAX_PAYLOAD );
  554. // Only send this message to developer console, or multiplayer clients.
  555. if ( developer.GetBool() || m_Server->IsMultiplayer() )
  556. {
  557. char devtext[ 2048 ];
  558. int curplayers = m_Server->GetNumClients();
  559. Q_snprintf( devtext, sizeof( devtext ),
  560. "\n%s\nMap: %s\nPlayers: %i / %i\nBuild: %d\nServer Number: %i\n\n",
  561. serverGameDLL->GetGameDescription(),
  562. m_Server->GetMapName(),
  563. curplayers, m_Server->GetMaxClients(),
  564. build_number(),
  565. m_Server->GetSpawnCount() );
  566. SVC_Print printMsg( devtext );
  567. printMsg.WriteToBuffer( msg );
  568. }
  569. SVC_ServerInfo serverinfo; // create serverinfo message
  570. serverinfo.m_nPlayerSlot = m_nClientSlot; // own slot number
  571. m_Server->FillServerInfo( serverinfo ); // fill rest of info message
  572. serverinfo.WriteToBuffer( msg );
  573. if ( IsX360() && serverinfo.m_nMaxClients > 1 )
  574. {
  575. Msg( "Telling clients to connect" );
  576. g_pMatchmaking->TellClientsToConnect();
  577. }
  578. // send first tick
  579. m_nSignonTick = m_Server->m_nTickCount;
  580. NET_Tick signonTick( m_nSignonTick, 0, 0 );
  581. signonTick.WriteToBuffer( msg );
  582. // write stringtable baselines
  583. #ifndef SHARED_NET_STRING_TABLES
  584. m_Server->m_StringTables->WriteBaselines( msg );
  585. #endif
  586. // Write replicated ConVars to non-listen server clients only
  587. if ( !m_NetChannel->IsLoopback() )
  588. {
  589. NET_SetConVar convars;
  590. Host_BuildConVarUpdateMessage( &convars, FCVAR_REPLICATED, true );
  591. convars.WriteToBuffer( msg );
  592. }
  593. m_bSendServerInfo = false;
  594. // send signon state
  595. m_nSignonState = SIGNONSTATE_NEW;
  596. NET_SignonState signonMsg( m_nSignonState, m_Server->GetSpawnCount() );
  597. signonMsg.WriteToBuffer( msg );
  598. // send server info as one data block
  599. if ( !m_NetChannel->SendData( msg ) )
  600. {
  601. MemFreeScratch();
  602. Disconnect("Server info data overflow");
  603. return false;
  604. }
  605. COM_TimestampedLog( " CBaseClient::SendServerInfo(finished)" );
  606. MemFreeScratch();
  607. return true;
  608. }
  609. CClientFrame *CBaseClient::GetDeltaFrame( int nTick )
  610. {
  611. Assert( 0 ); // derive moe
  612. return NULL; // CBaseClient has no delta frames
  613. }
  614. void CBaseClient::WriteGameSounds(bf_write &buf)
  615. {
  616. // CBaseClient has no events
  617. }
  618. void CBaseClient::ConnectionStart(INetChannel *chan)
  619. {
  620. REGISTER_NET_MSG( Tick );
  621. REGISTER_NET_MSG( StringCmd );
  622. REGISTER_NET_MSG( SetConVar );
  623. REGISTER_NET_MSG( SignonState );
  624. REGISTER_CLC_MSG( ClientInfo );
  625. REGISTER_CLC_MSG( Move );
  626. REGISTER_CLC_MSG( VoiceData );
  627. REGISTER_CLC_MSG( BaselineAck );
  628. REGISTER_CLC_MSG( ListenEvents );
  629. REGISTER_CLC_MSG( RespondCvarValue );
  630. REGISTER_CLC_MSG( FileCRCCheck );
  631. REGISTER_CLC_MSG( FileMD5Check );
  632. #if defined( REPLAY_ENABLED )
  633. REGISTER_CLC_MSG( SaveReplay );
  634. #endif
  635. REGISTER_CLC_MSG( CmdKeyValues );
  636. }
  637. bool CBaseClient::ProcessTick( NET_Tick *msg )
  638. {
  639. m_NetChannel->SetRemoteFramerate( msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation );
  640. return UpdateAcknowledgedFramecount( msg->m_nTick );
  641. }
  642. bool CBaseClient::ProcessStringCmd( NET_StringCmd *msg )
  643. {
  644. ExecuteStringCommand( msg->m_szCommand );
  645. return true;
  646. }
  647. bool CBaseClient::ProcessSetConVar( NET_SetConVar *msg )
  648. {
  649. for ( int i=0; i<msg->m_ConVars.Count(); i++ )
  650. {
  651. const char *name = msg->m_ConVars[i].name;
  652. const char *value = msg->m_ConVars[i].value;
  653. // Discard any convar change request if contains funky characters
  654. bool bFunky = false;
  655. for (const char *s = name ; *s != '\0' ; ++s )
  656. {
  657. if ( !V_isalnum(*s) && *s != '_' )
  658. {
  659. bFunky = true;
  660. break;
  661. }
  662. }
  663. if ( bFunky )
  664. {
  665. Msg( "Ignoring convar change request for variable '%s' from client %s; invalid characters in the variable name\n", name, GetClientName() );
  666. continue;
  667. }
  668. // "name" convar is handled differently
  669. if ( V_stricmp( name, "name" ) == 0 )
  670. {
  671. ClientRequestNameChange( value );
  672. continue;
  673. }
  674. // The initial set of convars must contain all client convars that are flagged userinfo. This is a simple fix to
  675. // exploits that send bogus data later, and catches bugs (why are new userinfo convars appearing later?)
  676. if ( m_bInitialConVarsSet && !m_ConVars->FindKey( name ) )
  677. {
  678. #ifndef _DEBUG // warn all the time in debug build
  679. static double s_dblLastWarned = 0.0;
  680. double dblTimeNow = Plat_FloatTime();
  681. if ( dblTimeNow - s_dblLastWarned > 10 )
  682. #endif
  683. {
  684. #ifndef _DEBUG
  685. s_dblLastWarned = dblTimeNow;
  686. #endif
  687. Warning( "Client \"%s\" userinfo ignored: \"%s\" = \"%s\"\n",
  688. this->GetClientName(), name, value );
  689. }
  690. continue;
  691. }
  692. m_ConVars->SetString( name, value );
  693. // DevMsg( 1, " UserInfo update %s: %s = %s\n", m_Client->m_Name, name, value );
  694. }
  695. m_bConVarsChanged = true;
  696. m_bInitialConVarsSet = true;
  697. return true;
  698. }
  699. bool CBaseClient::ProcessSignonState( NET_SignonState *msg)
  700. {
  701. if ( msg->m_nSignonState == SIGNONSTATE_CHANGELEVEL )
  702. {
  703. return true; // ignore this message
  704. }
  705. if ( msg->m_nSignonState > SIGNONSTATE_CONNECTED )
  706. {
  707. if ( msg->m_nSpawnCount != m_Server->GetSpawnCount() )
  708. {
  709. Reconnect();
  710. return true;
  711. }
  712. }
  713. // client must acknowledge our current state, otherwise start again
  714. if ( msg->m_nSignonState != m_nSignonState )
  715. {
  716. Reconnect();
  717. return true;
  718. }
  719. return SetSignonState( msg->m_nSignonState, msg->m_nSpawnCount );
  720. }
  721. bool CBaseClient::ProcessClientInfo( CLC_ClientInfo *msg )
  722. {
  723. if ( m_nSignonState != SIGNONSTATE_NEW )
  724. {
  725. Warning( "Dropping ClientInfo packet from client not in appropriate state\n" );
  726. return false;
  727. }
  728. m_nSendtableCRC = msg->m_nSendTableCRC;
  729. // Protect against spoofed packets claiming to be HLTV clients
  730. if ( ( hltv && hltv->IsTVRelay() ) || tv_enable.GetBool() )
  731. {
  732. m_bIsHLTV = msg->m_bIsHLTV;
  733. }
  734. else
  735. {
  736. m_bIsHLTV = false;
  737. }
  738. #if defined( REPLAY_ENABLED )
  739. m_bIsReplay = msg->m_bIsReplay;
  740. #endif
  741. m_nFilesDownloaded = 0;
  742. m_nFriendsID = msg->m_nFriendsID;
  743. Q_strncpy( m_FriendsName, msg->m_FriendsName, sizeof(m_FriendsName) );
  744. for ( int i=0; i<MAX_CUSTOM_FILES; i++ )
  745. {
  746. m_nCustomFiles[i].crc = msg->m_nCustomFiles[i];
  747. m_nCustomFiles[i].reqID = 0;
  748. }
  749. if ( msg->m_nServerCount != m_Server->GetSpawnCount() )
  750. {
  751. Reconnect(); // client still in old game, reconnect
  752. }
  753. return true;
  754. }
  755. bool CBaseClient::ProcessBaselineAck( CLC_BaselineAck *msg )
  756. {
  757. if ( msg->m_nBaselineTick != m_nBaselineUpdateTick )
  758. {
  759. // This occurs when there are multiple ack's queued up for processing from a client.
  760. return true;
  761. }
  762. if ( msg->m_nBaselineNr != m_nBaselineUsed )
  763. {
  764. DevMsg("CBaseClient::ProcessBaselineAck: wrong baseline nr received (%i)\n", msg->m_nBaselineTick );
  765. return true;
  766. }
  767. Assert( m_pBaseline );
  768. // copy ents send as full updates this frame into baseline stuff
  769. CClientFrame *frame = GetDeltaFrame( m_nBaselineUpdateTick );
  770. if ( frame == NULL )
  771. {
  772. // Will get here if we have a lot of packet loss and finally receive a stale ack from
  773. // remote client. Our "window" could be well beyond what it's acking, so just ignore the ack.
  774. return true;
  775. }
  776. CFrameSnapshot *pSnapshot = frame->GetSnapshot();
  777. if ( pSnapshot == NULL )
  778. {
  779. // TODO if client lags for a couple of seconds the snapshot is lost
  780. // fix: don't remove snapshots that are labled a possible basline candidates
  781. // or: send full update
  782. DevMsg("CBaseClient::ProcessBaselineAck: invalid frame snapshot (%i)\n", m_nBaselineUpdateTick );
  783. return false;
  784. }
  785. int index = m_BaselinesSent.FindNextSetBit( 0 );
  786. while ( index >= 0 )
  787. {
  788. // get new entity
  789. PackedEntityHandle_t hNewEntity = pSnapshot->m_pEntities[index].m_pPackedData;
  790. if ( hNewEntity == INVALID_PACKED_ENTITY_HANDLE )
  791. {
  792. DevMsg("CBaseClient::ProcessBaselineAck: invalid packet handle (%i)\n", index );
  793. return false;
  794. }
  795. PackedEntityHandle_t hOldEntity = m_pBaseline->m_pEntities[index].m_pPackedData;
  796. if ( hOldEntity != INVALID_PACKED_ENTITY_HANDLE )
  797. {
  798. // remove reference before overwriting packed entity
  799. framesnapshotmanager->RemoveEntityReference( hOldEntity );
  800. }
  801. // increase reference
  802. framesnapshotmanager->AddEntityReference( hNewEntity );
  803. // copy entity handle, class & serial number to
  804. m_pBaseline->m_pEntities[index] = pSnapshot->m_pEntities[index];
  805. // go to next entity
  806. index = m_BaselinesSent.FindNextSetBit( index + 1 );
  807. }
  808. m_pBaseline->m_nTickCount = m_nBaselineUpdateTick;
  809. // flip used baseline flag
  810. m_nBaselineUsed = (m_nBaselineUsed==1)?0:1;
  811. m_nBaselineUpdateTick = -1; // ready to update baselines again
  812. return true;
  813. }
  814. bool CBaseClient::ProcessListenEvents( CLC_ListenEvents *msg )
  815. {
  816. // first remove the client as listener
  817. g_GameEventManager.RemoveListener( this );
  818. for ( int i=0; i < MAX_EVENT_NUMBER; i++ )
  819. {
  820. if ( msg->m_EventArray.Get(i) )
  821. {
  822. CGameEventDescriptor *descriptor = g_GameEventManager.GetEventDescriptor( i );
  823. if ( descriptor )
  824. {
  825. g_GameEventManager.AddListener( this, descriptor, CGameEventManager::CLIENTSTUB );
  826. }
  827. else
  828. {
  829. DevMsg("ProcessListenEvents: game event %i not found.\n", i );
  830. return false;
  831. }
  832. }
  833. }
  834. return true;
  835. }
  836. extern int GetNetSpikeValue();
  837. void CBaseClient::StartTrace( bf_write &msg )
  838. {
  839. // Should we be tracing?
  840. m_Trace.m_nMinWarningBytes = 0;
  841. if ( !IsHLTV() && !IsReplay() && !IsFakeClient() )
  842. m_Trace.m_nMinWarningBytes = GetNetSpikeValue();
  843. if ( m_iTracing < 2 )
  844. {
  845. if ( m_Trace.m_nMinWarningBytes <= 0 && sv_netspike_sendtime_ms.GetFloat() <= 0.0f )
  846. {
  847. m_iTracing = 0;
  848. return;
  849. }
  850. m_iTracing = 1;
  851. }
  852. m_Trace.m_nStartBit = msg.GetNumBitsWritten();
  853. m_Trace.m_nCurBit = m_Trace.m_nStartBit;
  854. m_Trace.m_StartSendTime = Plat_FloatTime();
  855. }
  856. #define SERVER_PACKETS_LOG "netspike.txt"
  857. void CBaseClient::EndTrace( bf_write &msg )
  858. {
  859. if ( m_iTracing == 0 )
  860. return;
  861. VPROF_BUDGET( "CBaseClient::EndTrace", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  862. int bits = m_Trace.m_nCurBit - m_Trace.m_nStartBit;
  863. float flElapsedMs = ( Plat_FloatTime() - m_Trace.m_StartSendTime ) * 1000.0;
  864. int nBitThreshold = m_Trace.m_nMinWarningBytes << 3;
  865. if ( m_iTracing < 2 // not forced
  866. && ( nBitThreshold <= 0 || bits < nBitThreshold ) // didn't exceed data threshold
  867. && ( sv_netspike_sendtime_ms.GetFloat() <= 0.0f || flElapsedMs < sv_netspike_sendtime_ms.GetFloat() ) ) // didn't exceed time threshold
  868. {
  869. m_Trace.m_Records.RemoveAll();
  870. m_iTracing = 0;
  871. return;
  872. }
  873. CUtlBuffer logData( 0, 0, CUtlBuffer::TEXT_BUFFER );
  874. logData.Printf( "%f/%d Player [%s][%d][adr:%s] was sent a datagram %d bits (%8.3f bytes), took %.2fms\n",
  875. realtime,
  876. host_tickcount,
  877. GetClientName(),
  878. GetPlayerSlot(),
  879. GetNetChannel()->GetAddress(),
  880. bits, (float)bits / 8.0f,
  881. flElapsedMs
  882. );
  883. // Write header line to the log if we aren't writing the whole thing
  884. if ( ( sv_netspike_output.GetInt() & 2 ) == 0 )
  885. Log("netspike: %s", logData.String() );
  886. for ( int i = 0 ; i < m_Trace.m_Records.Count() ; ++i )
  887. {
  888. Spike_t &sp = m_Trace.m_Records[ i ];
  889. logData.Printf( "%64.64s : %8d bits (%8.3f bytes)\n", sp.m_szDesc, sp.m_nBits, (float)sp.m_nBits / 8.0f );
  890. }
  891. if ( sv_netspike_output.GetInt() & 1 )
  892. COM_LogString( SERVER_PACKETS_LOG, logData.String() );
  893. if ( sv_netspike_output.GetInt() & 2 )
  894. Log( "%s", logData.String() );
  895. ETWMark1S( "netspike", logData.String() );
  896. m_Trace.m_Records.RemoveAll();
  897. m_iTracing = 0;
  898. }
  899. void CBaseClient::TraceNetworkData( bf_write &msg, char const *fmt, ... )
  900. {
  901. if ( !IsTracing() )
  902. return;
  903. VPROF_BUDGET( "CBaseClient::TraceNetworkData", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  904. char buf[ 64 ];
  905. va_list argptr;
  906. va_start( argptr, fmt );
  907. Q_vsnprintf( buf, sizeof( buf ), fmt, argptr );
  908. va_end( argptr );
  909. Spike_t t;
  910. Q_strncpy( t.m_szDesc, buf, sizeof( t.m_szDesc ) );
  911. t.m_nBits = msg.GetNumBitsWritten() - m_Trace.m_nCurBit;
  912. m_Trace.m_Records.AddToTail( t );
  913. m_Trace.m_nCurBit = msg.GetNumBitsWritten();
  914. }
  915. void CBaseClient::TraceNetworkMsg( int nBits, char const *fmt, ... )
  916. {
  917. if ( !IsTracing() )
  918. return;
  919. VPROF_BUDGET( "CBaseClient::TraceNetworkMsg", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  920. char buf[ 64 ];
  921. va_list argptr;
  922. va_start( argptr, fmt );
  923. Q_vsnprintf( buf, sizeof( buf ), fmt, argptr );
  924. va_end( argptr );
  925. Spike_t t;
  926. Q_strncpy( t.m_szDesc, buf, sizeof( t.m_szDesc ) );
  927. t.m_nBits = nBits;
  928. m_Trace.m_Records.AddToTail( t );
  929. }
  930. void CBaseClient::SendSnapshot( CClientFrame *pFrame )
  931. {
  932. // never send the same snapshot twice
  933. if ( m_pLastSnapshot == pFrame->GetSnapshot() )
  934. {
  935. m_NetChannel->Transmit();
  936. return;
  937. }
  938. // if we send a full snapshot (no delta-compression) before, wait until client
  939. // received and acknowledge that update. don't spam client with full updates
  940. if ( m_nForceWaitForTick > 0 )
  941. {
  942. // just continue transmitting reliable data
  943. m_NetChannel->Transmit();
  944. return;
  945. }
  946. VPROF_BUDGET( "SendSnapshot", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  947. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  948. bool bFailedOnce = false;
  949. write_again:
  950. bf_write msg( "CBaseClient::SendSnapshot", m_SnapshotScratchBuffer, sizeof( m_SnapshotScratchBuffer ) );
  951. TRACE_PACKET( ( "SendSnapshot(%d)\n", pFrame->tick_count ) );
  952. // now create client snapshot packet
  953. CClientFrame *deltaFrame = GetDeltaFrame( m_nDeltaTick ); // NULL if delta_tick is not found
  954. if ( !deltaFrame )
  955. {
  956. // We need to send a full update and reset the instanced baselines
  957. OnRequestFullUpdate();
  958. }
  959. // send tick time
  960. NET_Tick tickmsg( pFrame->tick_count, host_frametime_unbounded, host_frametime_stddeviation );
  961. StartTrace( msg );
  962. tickmsg.WriteToBuffer( msg );
  963. if ( IsTracing() )
  964. {
  965. TraceNetworkData( msg, "NET_Tick" );
  966. }
  967. #ifndef SHARED_NET_STRING_TABLES
  968. // in LocalNetworkBackdoor mode we updated the stringtables already in SV_ComputeClientPacks()
  969. if ( !g_pLocalNetworkBackdoor )
  970. {
  971. // Update shared client/server string tables. Must be done before sending entities
  972. m_Server->m_StringTables->WriteUpdateMessage( this, GetMaxAckTickCount(), msg );
  973. }
  974. #endif
  975. int nDeltaStartBit = 0;
  976. if ( IsTracing() )
  977. {
  978. nDeltaStartBit = msg.GetNumBitsWritten();
  979. }
  980. // send entity update, delta compressed if deltaFrame != NULL
  981. m_Server->WriteDeltaEntities( this, pFrame, deltaFrame, msg );
  982. if ( IsTracing() )
  983. {
  984. int nBits = msg.GetNumBitsWritten() - nDeltaStartBit;
  985. TraceNetworkMsg( nBits, "Total Delta" );
  986. }
  987. // send all unreliable temp entities between last and current frame
  988. // send max 64 events in multi player, 255 in SP
  989. int nMaxTempEnts = m_Server->IsMultiplayer() ? 64 : 255;
  990. m_Server->WriteTempEntities( this, pFrame->GetSnapshot(), m_pLastSnapshot.GetObject(), msg, nMaxTempEnts );
  991. if ( IsTracing() )
  992. {
  993. TraceNetworkData( msg, "Temp Entities" );
  994. }
  995. WriteGameSounds( msg );
  996. // write message to packet and check for overflow
  997. if ( msg.IsOverflowed() )
  998. {
  999. bool bWasTracing = IsTracing();
  1000. if ( bWasTracing )
  1001. {
  1002. TraceNetworkMsg( 0, "Finished [delta %s]", deltaFrame ? "yes" : "no" );
  1003. EndTrace( msg );
  1004. }
  1005. if ( !deltaFrame )
  1006. {
  1007. if ( !bWasTracing )
  1008. {
  1009. // Check for debugging by dumping a snapshot
  1010. if ( sv_netspike_on_reliable_snapshot_overflow.GetBool() )
  1011. {
  1012. if ( !bFailedOnce ) // shouldn't be necessary, but just in case
  1013. {
  1014. Warning(" RELIABLE SNAPSHOT OVERFLOW! Triggering trace to see what is so large\n" );
  1015. bFailedOnce = true;
  1016. m_iTracing = 2;
  1017. goto write_again;
  1018. }
  1019. m_iTracing = 0;
  1020. }
  1021. }
  1022. // if this is a reliable snapshot, drop the client
  1023. Disconnect( "ERROR! Reliable snapshot overflow." );
  1024. return;
  1025. }
  1026. else
  1027. {
  1028. // unreliable snapshots may be dropped
  1029. ConMsg ("WARNING: msg overflowed for %s\n", m_Name);
  1030. msg.Reset();
  1031. }
  1032. }
  1033. // remember this snapshot
  1034. m_pLastSnapshot = pFrame->GetSnapshot();
  1035. // Don't send the datagram to fakeplayers unless sv_stressbots is on (which will make m_NetChannel non-null).
  1036. if ( m_bFakePlayer && !m_NetChannel )
  1037. {
  1038. m_nDeltaTick = pFrame->tick_count;
  1039. m_nStringTableAckTick = m_nDeltaTick;
  1040. return;
  1041. }
  1042. bool bSendOK;
  1043. // is this is a full entity update (no delta) ?
  1044. if ( !deltaFrame )
  1045. {
  1046. VPROF_BUDGET( "SendSnapshot Transmit Full", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  1047. // transmit snapshot as reliable data chunk
  1048. bSendOK = m_NetChannel->SendData( msg );
  1049. bSendOK = bSendOK && m_NetChannel->Transmit();
  1050. // remember this tickcount we send the reliable snapshot
  1051. // so we can continue sending other updates if this has been acknowledged
  1052. m_nForceWaitForTick = pFrame->tick_count;
  1053. }
  1054. else
  1055. {
  1056. VPROF_BUDGET( "SendSnapshot Transmit Delta", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  1057. // just send it as unreliable snapshot
  1058. bSendOK = m_NetChannel->SendDatagram( &msg ) > 0;
  1059. }
  1060. if ( bSendOK )
  1061. {
  1062. if ( IsTracing() )
  1063. {
  1064. TraceNetworkMsg( 0, "Finished [delta %s]", deltaFrame ? "yes" : "no" );
  1065. EndTrace( msg );
  1066. }
  1067. }
  1068. else
  1069. {
  1070. Disconnect( "ERROR! Couldn't send snapshot." );
  1071. }
  1072. }
  1073. bool CBaseClient::ExecuteStringCommand( const char *pCommand )
  1074. {
  1075. if ( !pCommand || !pCommand[0] )
  1076. return false;
  1077. if ( !Q_stricmp( pCommand, "demorestart" ) )
  1078. {
  1079. DemoRestart();
  1080. // trick, dont return true, so serverGameClients gets this command too
  1081. return false;
  1082. }
  1083. return false;
  1084. }
  1085. void CBaseClient::DemoRestart()
  1086. {
  1087. }
  1088. bool CBaseClient::ShouldSendMessages( void )
  1089. {
  1090. if ( !IsConnected() )
  1091. return false;
  1092. // if the reliable message overflowed, drop the client
  1093. if ( m_NetChannel && m_NetChannel->IsOverflowed() )
  1094. {
  1095. m_NetChannel->Reset();
  1096. Disconnect ("%s overflowed reliable buffer\n", m_Name );
  1097. return false;
  1098. }
  1099. // check, if it's time to send the next packet
  1100. bool bSendMessage = m_fNextMessageTime <= net_time ;
  1101. if ( !bSendMessage && !IsActive() )
  1102. {
  1103. // if we are in signon modem instantly reply if
  1104. // we got a answer and have reliable data waiting
  1105. if ( m_bReceivedPacket && m_NetChannel && m_NetChannel->HasPendingReliableData() )
  1106. {
  1107. bSendMessage = true;
  1108. }
  1109. }
  1110. if ( bSendMessage && m_NetChannel && !m_NetChannel->CanPacket() )
  1111. {
  1112. // we would like to send a message, but bandwidth isn't available yet
  1113. // tell netchannel that we are choking a packet
  1114. m_NetChannel->SetChoked();
  1115. // Record an ETW event to indicate that we are throttling.
  1116. ETWThrottled();
  1117. bSendMessage = false;
  1118. }
  1119. return bSendMessage;
  1120. }
  1121. void CBaseClient::UpdateSendState( void )
  1122. {
  1123. // wait for next incoming packet
  1124. m_bReceivedPacket = false;
  1125. // in single player mode always send messages
  1126. if ( !m_Server->IsMultiplayer() && !host_limitlocal.GetFloat() )
  1127. {
  1128. m_fNextMessageTime = net_time; // send ASAP and
  1129. m_bReceivedPacket = true; // don't wait for incoming packets
  1130. }
  1131. else if ( IsActive() ) // multiplayer mode
  1132. {
  1133. // snapshot mode: send snapshots frequently
  1134. float maxDelta = min ( m_Server->GetTickInterval(), m_fSnapshotInterval );
  1135. float delta = clamp( (float)( net_time - m_fNextMessageTime ), 0.0f, maxDelta );
  1136. m_fNextMessageTime = net_time + m_fSnapshotInterval - delta;
  1137. }
  1138. else // multiplayer signon mode
  1139. {
  1140. if ( m_NetChannel && m_NetChannel->HasPendingReliableData() &&
  1141. m_NetChannel->GetTimeSinceLastReceived() < 1.0f )
  1142. {
  1143. // if we have pending reliable data send as fast as possible
  1144. m_fNextMessageTime = net_time;
  1145. }
  1146. else
  1147. {
  1148. // signon mode: only respond on request or after 1 second
  1149. m_fNextMessageTime = net_time + 1.0f;
  1150. }
  1151. }
  1152. }
  1153. void CBaseClient::UpdateUserSettings()
  1154. {
  1155. int rate = m_ConVars->GetInt( "rate", DEFAULT_RATE );
  1156. if ( sv.IsActive() )
  1157. {
  1158. // If we're running a local listen server then set the rate very high
  1159. // in order to avoid delays due to network throttling. This allows for
  1160. // easier profiling of other issues (it removes most of the frame-render
  1161. // time which can otherwise dominate profiles) and saves developer time
  1162. // by making maps and models load much faster.
  1163. if ( rate == DEFAULT_RATE )
  1164. {
  1165. // Only override the rate if the user hasn't customized it.
  1166. // The max rate should be a million or so in order to truly
  1167. // eliminate networking delays.
  1168. rate = MAX_RATE;
  1169. }
  1170. }
  1171. // set server to client network rate
  1172. SetRate( rate, false );
  1173. // set server to client update rate
  1174. SetUpdateRate( m_ConVars->GetInt( "cl_updaterate", 20), false );
  1175. SetMaxRoutablePayloadSize( m_ConVars->GetInt( "net_maxroutable", MAX_ROUTABLE_PAYLOAD ) );
  1176. m_Server->UserInfoChanged( m_nClientSlot );
  1177. m_bConVarsChanged = false;
  1178. }
  1179. void CBaseClient::ClientRequestNameChange( const char *pszNewName )
  1180. {
  1181. // This is called several times. Only show a status message the first time.
  1182. bool bShowStatusMessage = ( m_szPendingNameChange[0] == '\0' );
  1183. V_strcpy_safe( m_szPendingNameChange, pszNewName );
  1184. CheckFlushNameChange( bShowStatusMessage );
  1185. }
  1186. void CBaseClient::CheckFlushNameChange( bool bShowStatusMessage /*= false*/ )
  1187. {
  1188. if ( !IsConnected() )
  1189. return;
  1190. if ( m_szPendingNameChange[0] == '\0' )
  1191. return;
  1192. if ( m_bPlayerNameLocked )
  1193. return;
  1194. // Did they change it back to the original?
  1195. if ( !Q_strcmp( m_szPendingNameChange, m_Name ) )
  1196. {
  1197. // Nothing really pending, they already changed it back
  1198. // we had a chance to apply the other one!
  1199. m_szPendingNameChange[0] = '\0';
  1200. return;
  1201. }
  1202. // Check for throttling name changes
  1203. // Don't do it on bots
  1204. if ( !IsFakeClient() && IsNameChangeOnCooldown( bShowStatusMessage ) )
  1205. {
  1206. return;
  1207. }
  1208. // Set the new name
  1209. m_fTimeLastNameChange = Plat_FloatTime();
  1210. SetName( m_szPendingNameChange );
  1211. }
  1212. bool CBaseClient::IsNameChangeOnCooldown( bool bShowStatusMessage /*= false*/ )
  1213. {
  1214. // Check cooldown. The first name change is free
  1215. if ( m_fTimeLastNameChange > 0.0 )
  1216. {
  1217. // Too recent?
  1218. double timeNow = Plat_FloatTime();
  1219. double dNextChangeTime = m_fTimeLastNameChange + sv_namechange_cooldown_seconds.GetFloat();
  1220. if ( timeNow < dNextChangeTime )
  1221. {
  1222. // Cooldown period still active; throttle the name change
  1223. if ( bShowStatusMessage )
  1224. {
  1225. ClientPrintf( "You have changed your name recently, and must wait %i seconds.\n", (int)abs( timeNow - dNextChangeTime ) );
  1226. }
  1227. return true;
  1228. }
  1229. }
  1230. return false;
  1231. }
  1232. void CBaseClient::OnRequestFullUpdate()
  1233. {
  1234. VPROF_BUDGET( "CBaseClient::OnRequestFullUpdate", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  1235. // client requests a full update
  1236. m_pLastSnapshot = NULL;
  1237. // free old baseline snapshot
  1238. FreeBaselines();
  1239. // and create new baseline snapshot
  1240. m_pBaseline = framesnapshotmanager->CreateEmptySnapshot( 0, MAX_EDICTS );
  1241. DevMsg("Sending full update to Client %s\n", GetClientName() );
  1242. }
  1243. //-----------------------------------------------------------------------------
  1244. // Purpose:
  1245. // Input : *cl -
  1246. //-----------------------------------------------------------------------------
  1247. bool CBaseClient::UpdateAcknowledgedFramecount(int tick)
  1248. {
  1249. if ( IsFakeClient() )
  1250. {
  1251. // fake clients are always fine
  1252. m_nDeltaTick = tick;
  1253. m_nStringTableAckTick = tick;
  1254. return true;
  1255. }
  1256. // are we waiting for full reliable update acknowledge
  1257. if ( m_nForceWaitForTick > 0 )
  1258. {
  1259. if ( tick > m_nForceWaitForTick )
  1260. {
  1261. // we should never get here since full updates are transmitted as reliable data now
  1262. // Disconnect("Acknowledging reliable snapshot failed.\n");
  1263. return true;
  1264. }
  1265. else if ( tick == -1 )
  1266. {
  1267. if( !m_NetChannel->HasPendingReliableData() )
  1268. {
  1269. // that's strange: we sent the client a full update, and it was fully received ( no reliable data in waiting buffers )
  1270. // but the client is requesting another full update.
  1271. //
  1272. // This can happen if they request full updates in succession really quickly (using cl_fullupdate or "record X;stop" quickly).
  1273. // There was a bug here where if we just return out, the client will have nuked its entities and we'd send it
  1274. // a supposedly uncompressed update but m_nDeltaTick was not -1, so it was delta'd and it'd miss lots of stuff.
  1275. // Led to clients getting full spectator mode radar while their player was not a spectator.
  1276. ConDMsg("Client forced immediate full update.\n");
  1277. m_nForceWaitForTick = m_nDeltaTick = -1;
  1278. OnRequestFullUpdate();
  1279. return true;
  1280. }
  1281. }
  1282. else if ( tick < m_nForceWaitForTick )
  1283. {
  1284. // keep on waiting, do nothing
  1285. return true;
  1286. }
  1287. else // ( tick == m_nForceWaitForTick )
  1288. {
  1289. // great, the client acknowledge the tick we send the full update
  1290. m_nForceWaitForTick = -1;
  1291. // continue sending snapshots...
  1292. }
  1293. }
  1294. else
  1295. {
  1296. if ( m_nDeltaTick == -1 )
  1297. {
  1298. // we still want to send a full update, don't change delta_tick from -1
  1299. return true;
  1300. }
  1301. if ( tick == -1 )
  1302. {
  1303. OnRequestFullUpdate();
  1304. }
  1305. else
  1306. {
  1307. if ( m_nDeltaTick > tick )
  1308. {
  1309. // client already acknowledged new tick and now switch back to older
  1310. // thats not allowed since we always delete older frames
  1311. Disconnect("Client delta ticks out of order.\n");
  1312. return false;
  1313. }
  1314. }
  1315. }
  1316. // get acknowledged client frame
  1317. m_nDeltaTick = tick;
  1318. if ( m_nDeltaTick > -1 )
  1319. {
  1320. m_nStringTableAckTick = m_nDeltaTick;
  1321. }
  1322. if ( (m_nBaselineUpdateTick > -1) && (m_nDeltaTick > m_nBaselineUpdateTick) )
  1323. {
  1324. // server sent a baseline update, but it wasn't acknowledged yet so it was probably lost.
  1325. m_nBaselineUpdateTick = -1;
  1326. }
  1327. return true;
  1328. }
  1329. //-----------------------------------------------------------------------------
  1330. // Purpose: return a string version of the userid
  1331. //-----------------------------------------------------------------------------
  1332. const char *GetUserIDString( const USERID_t& id )
  1333. {
  1334. static char idstr[ MAX_NETWORKID_LENGTH ];
  1335. idstr[ 0 ] = 0;
  1336. switch ( id.idtype )
  1337. {
  1338. case IDTYPE_STEAM:
  1339. {
  1340. CSteamID nullID;
  1341. if ( Steam3Server().BLanOnly() && nullID == id.steamid )
  1342. {
  1343. V_strcpy_safe( idstr, "STEAM_ID_LAN" );
  1344. }
  1345. else if ( nullID == id.steamid )
  1346. {
  1347. V_strcpy_safe( idstr, "STEAM_ID_PENDING" );
  1348. }
  1349. else
  1350. {
  1351. V_sprintf_safe( idstr, "%s", id.steamid.Render() );
  1352. }
  1353. }
  1354. break;
  1355. case IDTYPE_HLTV:
  1356. {
  1357. V_strcpy_safe( idstr, "HLTV" );
  1358. }
  1359. break;
  1360. case IDTYPE_REPLAY:
  1361. {
  1362. V_strcpy_safe( idstr, "REPLAY" );
  1363. }
  1364. break;
  1365. default:
  1366. {
  1367. V_strcpy_safe( idstr, "UNKNOWN" );
  1368. }
  1369. break;
  1370. }
  1371. return idstr;
  1372. }
  1373. //-----------------------------------------------------------------------------
  1374. // Purpose: return a string version of the userid
  1375. //-----------------------------------------------------------------------------
  1376. const char *CBaseClient::GetNetworkIDString() const
  1377. {
  1378. if ( IsFakeClient() )
  1379. {
  1380. return "BOT";
  1381. }
  1382. return ( GetUserIDString( GetNetworkID() ) );
  1383. }
  1384. bool CBaseClient::IgnoreTempEntity( CEventInfo *event )
  1385. {
  1386. int iPlayerIndex = GetPlayerSlot()+1;
  1387. return !event->filter.IncludesPlayer( iPlayerIndex );
  1388. }
  1389. const USERID_t CBaseClient::GetNetworkID() const
  1390. {
  1391. USERID_t userID;
  1392. userID.steamid = m_SteamID;
  1393. userID.idtype = IDTYPE_STEAM;
  1394. return userID;
  1395. }
  1396. void CBaseClient::SetSteamID( const CSteamID &steamID )
  1397. {
  1398. m_SteamID = steamID;
  1399. }
  1400. void CBaseClient::SetMaxRoutablePayloadSize( int nMaxRoutablePayloadSize )
  1401. {
  1402. if ( m_NetChannel )
  1403. {
  1404. m_NetChannel->SetMaxRoutablePayloadSize( nMaxRoutablePayloadSize );
  1405. }
  1406. }
  1407. int CBaseClient::GetMaxAckTickCount() const
  1408. {
  1409. int nMaxTick = m_nSignonTick;
  1410. if ( m_nDeltaTick > nMaxTick )
  1411. {
  1412. nMaxTick = m_nDeltaTick;
  1413. }
  1414. if ( m_nStringTableAckTick > nMaxTick )
  1415. {
  1416. nMaxTick = m_nStringTableAckTick;
  1417. }
  1418. return nMaxTick;
  1419. }
  1420. bool CBaseClient::ProcessCmdKeyValues( CLC_CmdKeyValues *msg )
  1421. {
  1422. return true;
  1423. }
  1424. void CBaseClient::OnSignonStateFull()
  1425. {
  1426. #if defined( REPLAY_ENABLED )
  1427. if ( g_pReplay && g_pServerReplayContext )
  1428. {
  1429. g_pServerReplayContext->CreateSessionOnClient( m_nClientSlot );
  1430. }
  1431. #endif
  1432. }