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.

336 lines
11 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "netmessages.h"
  7. #include "bitbuf.h"
  8. #include "const.h"
  9. #include "../engine/net_chan.h"
  10. #include "mathlib/mathlib.h"
  11. #include "networkstringtabledefs.h"
  12. #include "../engine/audio/public/sound.h"
  13. #include "../engine/event_system.h"
  14. #include "../engine/dt.h"
  15. #include "mathlib/IceKey.H"
  16. #include "tier0/vprof.h"
  17. static char s_text[1024];
  18. const char *g_MostCommonPathIDs[] =
  19. {
  20. "GAME",
  21. "MOD"
  22. };
  23. const char *g_MostCommonPrefixes[] =
  24. {
  25. "materials",
  26. "models",
  27. "sounds",
  28. "scripts"
  29. };
  30. static int FindCommonPathID( const char *pPathID )
  31. {
  32. for ( int i = 0; i < ARRAYSIZE( g_MostCommonPathIDs ); i++ )
  33. {
  34. if ( V_stricmp( pPathID, g_MostCommonPathIDs[i] ) == 0 )
  35. return i;
  36. }
  37. return -1;
  38. }
  39. static int FindCommonPrefix( const char *pStr )
  40. {
  41. for ( int i = 0; i < ARRAYSIZE( g_MostCommonPrefixes ); i++ )
  42. {
  43. if ( V_stristr( pStr, g_MostCommonPrefixes[i] ) == pStr )
  44. {
  45. int iNextChar = V_strlen( g_MostCommonPrefixes[i] );
  46. if ( pStr[iNextChar] == '/' || pStr[iNextChar] == '\\' )
  47. return i;
  48. }
  49. }
  50. return -1;
  51. }
  52. void CCLCMsg_FileCRCCheck_t::SetPath( CCLCMsg_FileCRCCheck& msg, const char *path )
  53. {
  54. int iCode = FindCommonPathID( path );
  55. if ( iCode == -1 )
  56. {
  57. msg.set_code_path( -1 );
  58. msg.set_path( path );
  59. }
  60. else
  61. {
  62. msg.set_code_path( iCode );
  63. }
  64. }
  65. const char *CCLCMsg_FileCRCCheck_t::GetPath( const CCLCMsg_FileCRCCheck& msg )
  66. {
  67. int iCode = msg.code_path();
  68. if( ( iCode >= 0 ) && ( iCode < ARRAYSIZE( g_MostCommonPathIDs ) ) )
  69. {
  70. return g_MostCommonPathIDs[ iCode ];
  71. }
  72. Assert( msg.code_path() == -1 );
  73. return msg.path().c_str();
  74. }
  75. void CCLCMsg_FileCRCCheck_t::SetFileName( CCLCMsg_FileCRCCheck& msg, const char *fileName )
  76. {
  77. int iCode = FindCommonPrefix( fileName );
  78. if ( iCode == -1 )
  79. {
  80. msg.set_code_filename( -1 );
  81. msg.set_filename( fileName );
  82. }
  83. else
  84. {
  85. msg.set_code_filename( iCode );
  86. msg.set_filename( &fileName[ V_strlen( g_MostCommonPrefixes[ iCode ] ) + 1 ] );
  87. }
  88. }
  89. const char *CCLCMsg_FileCRCCheck_t::GetFileName( const CCLCMsg_FileCRCCheck& msg )
  90. {
  91. int iCode = msg.code_filename();
  92. if( ( iCode >= 0 ) && ( iCode < ARRAYSIZE( g_MostCommonPrefixes ) ) )
  93. {
  94. return va( "%s%c%s", g_MostCommonPrefixes[ iCode ], CORRECT_PATH_SEPARATOR, msg.filename().c_str() );
  95. }
  96. Assert( msg.code_filename() == -1 );
  97. return msg.filename().c_str();
  98. }
  99. void CmdKeyValuesHelper::CLCMsg_SetKeyValues( CCLCMsg_CmdKeyValues& msg, const KeyValues *keyValues )
  100. {
  101. CUtlBuffer bufData;
  102. keyValues->WriteAsBinary( bufData );
  103. int numBytes = bufData.TellPut();
  104. msg.set_keyvalues( bufData.Base(), numBytes );
  105. }
  106. KeyValues *CmdKeyValuesHelper::CLCMsg_GetKeyValues ( const CCLCMsg_CmdKeyValues& msg )
  107. {
  108. KeyValues *pKeyValues = new KeyValues( "" );
  109. const std::string& msgStr = msg.keyvalues();
  110. int numBytes = msgStr.size();
  111. CUtlBuffer bufRead( msgStr.data(), numBytes, CUtlBuffer::READ_ONLY );
  112. if ( !pKeyValues->ReadAsBinary( bufRead, 90 ) ) // we are expecting very few nest levels of keyvalues here!
  113. {
  114. Assert( false );
  115. }
  116. return pKeyValues;
  117. }
  118. void CmdKeyValuesHelper::SVCMsg_SetKeyValues( CSVCMsg_CmdKeyValues& msg, const KeyValues *keyValues )
  119. {
  120. CUtlBuffer bufData;
  121. keyValues->WriteAsBinary( bufData );
  122. int numBytes = bufData.TellPut();
  123. msg.set_keyvalues( bufData.Base(), numBytes );
  124. }
  125. KeyValues *CmdKeyValuesHelper::SVCMsg_GetKeyValues ( const CSVCMsg_CmdKeyValues& msg )
  126. {
  127. KeyValues *pKeyValues = new KeyValues( "" );
  128. const std::string& msgStr = msg.keyvalues();
  129. int numBytes = msgStr.size();
  130. CUtlBuffer bufRead( msgStr.data(), numBytes, CUtlBuffer::READ_ONLY );
  131. if ( !pKeyValues->ReadAsBinary( bufRead ) )
  132. {
  133. Assert( false );
  134. }
  135. return pKeyValues;
  136. }
  137. /*
  138. bool CmdEncryptedDataMessageCodec::SVCMsg_EncryptedData_EncryptMessage( CSVCMsg_EncryptedData_t &msgEncryptedResult, const ::google::protobuf::Message &msgPlaintextInput )
  139. {
  140. static char const *szEncryptedTag = "[[ENCRYPTED_DATA]]";
  141. static size_t nEncryptedLen = Q_strlen( szEncryptedTag );
  142. int32 const numBytesWritten = msgPlaintextInput.ByteSize();
  143. msgEncryptedResult.mutable_encrypted()->resize( nEncryptedLen + sizeof( int32 ) + numBytesWritten );
  144. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at(0), szEncryptedTag, nEncryptedLen );
  145. int32 const numBytesWrittenWire = BigLong( numBytesWritten ); // byteswap for the wire
  146. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at( nEncryptedLen ), &numBytesWrittenWire, sizeof( numBytesWrittenWire ) );
  147. return msgPlaintextInput.SerializeWithCachedSizesToArray( ( uint8 * ) &msgEncryptedResult.mutable_encrypted()->at( nEncryptedLen + sizeof( int32 ) ) );
  148. }
  149. */
  150. bool CmdEncryptedDataMessageCodec::SVCMsg_EncryptedData_EncryptMessage( CSVCMsg_EncryptedData_t &msgEncryptedResult, INetMessage *pMsgPlaintextInput, char const *key )
  151. {
  152. // Prepare encryption key
  153. IceKey iceKey( 2 );
  154. if ( iceKey.keySize() != Q_strlen( key ) )
  155. {
  156. Warning( "CmdEncryptedDataMessageCodec key size is %d, but %d is expected!\n", Q_strlen( key ), iceKey.keySize() );
  157. return false; // we cannot encrypt with the supplied key
  158. }
  159. iceKey.set( ( const unsigned char * ) key );
  160. // supporting smaller stack
  161. net_scratchbuffer_t scratch;
  162. bf_write msg( "SVCMsg_EncryptedData_EncryptMessage", scratch.GetBuffer(), scratch.Size() );
  163. if ( !pMsgPlaintextInput->WriteToBuffer( msg ) )
  164. return false;
  165. int32 const numBytesWritten = msg.GetNumBytesWritten();
  166. // Generate some random fudge, ICE operates on 64-bit blocks, so make sure our total size is a multiple of 8 bytes
  167. int numRandomFudgeBytes = RandomInt( 16, 72 );
  168. int numTotalEncryptedBytes = 1 + numRandomFudgeBytes + sizeof( int32 ) + numBytesWritten;
  169. numRandomFudgeBytes += iceKey.blockSize() - ( numTotalEncryptedBytes % iceKey.blockSize() );
  170. numTotalEncryptedBytes = 1 + numRandomFudgeBytes + sizeof( int32 ) + numBytesWritten;
  171. char *pchRandomFudgeBytes = ( char * ) stackalloc( numRandomFudgeBytes );
  172. for ( int k = 0; k < numRandomFudgeBytes; ++ k )
  173. pchRandomFudgeBytes[k] = RandomInt( 16, 250 );
  174. msgEncryptedResult.mutable_encrypted()->resize( numTotalEncryptedBytes );
  175. msgEncryptedResult.mutable_encrypted()->at(0) = numRandomFudgeBytes;
  176. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at(1), pchRandomFudgeBytes, numRandomFudgeBytes );
  177. int32 const numBytesWrittenWire = BigLong( numBytesWritten ); // byteswap for the wire
  178. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at( 1 + numRandomFudgeBytes ), &numBytesWrittenWire, sizeof( numBytesWrittenWire ) );
  179. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at( 1 + numRandomFudgeBytes + sizeof( int32 ) ), msg.GetBasePointer(), numBytesWritten );
  180. // Encrypt the message
  181. unsigned char *pchCryptoBuffer = ( unsigned char * ) stackalloc( iceKey.blockSize() );
  182. for ( int k = 0; k < numTotalEncryptedBytes; k += iceKey.blockSize() )
  183. {
  184. iceKey.encrypt( ( const unsigned char * ) &msgEncryptedResult.mutable_encrypted()->at(k), pchCryptoBuffer );
  185. Q_memcpy( &msgEncryptedResult.mutable_encrypted()->at(k), pchCryptoBuffer, iceKey.blockSize() );
  186. }
  187. return true;
  188. }
  189. bool CmdEncryptedDataMessageCodec::SVCMsg_EncryptedData_Process( CSVCMsg_EncryptedData const &msgEncryptedInput, INetChannel *pProcessingChannelInterface, char const *key )
  190. {
  191. CNetChan *pProcessingChannel = ( CNetChan * ) pProcessingChannelInterface;
  192. if ( !pProcessingChannel )
  193. return false;
  194. if ( !msgEncryptedInput.has_encrypted() )
  195. return true;
  196. if ( !key || !*key )
  197. return true; // key is not supplied, so ignore the message
  198. // Decrypt the message
  199. IceKey iceKey( 2 );
  200. if ( iceKey.keySize() != Q_strlen( key ) )
  201. return true; // we cannot decrypt with the supplied key
  202. iceKey.set( ( const unsigned char * ) key );
  203. if ( msgEncryptedInput.encrypted().size() % iceKey.blockSize() )
  204. return true; // message malformed, cannot decrypt
  205. if ( msgEncryptedInput.encrypted().size() > NET_MAX_PAYLOAD )
  206. return true; // size too large, cannot decrypt
  207. net_scratchbuffer_t scratch;
  208. byte *buffer = scratch.GetBuffer();
  209. unsigned char *pchCryptoBuffer = ( unsigned char * ) stackalloc( iceKey.blockSize() );
  210. for ( int k = 0; k < ( int ) msgEncryptedInput.encrypted().size(); k += iceKey.blockSize() )
  211. {
  212. iceKey.decrypt( ( const unsigned char * ) &msgEncryptedInput.encrypted().at(k), pchCryptoBuffer );
  213. Q_memcpy( &buffer[k], pchCryptoBuffer, iceKey.blockSize() );
  214. }
  215. // Check how much random fudge we have
  216. int numRandomFudgeBytes = *buffer;
  217. if ( ( numRandomFudgeBytes > 0 ) && ( numRandomFudgeBytes + 1 + sizeof( int32 ) < msgEncryptedInput.encrypted().size() ) )
  218. {
  219. // Fetch the size of the encrypted message
  220. int32 numBytesWrittenWire = 0;
  221. Q_memcpy( &numBytesWrittenWire, &buffer[ 1 + numRandomFudgeBytes ], sizeof( int32 ) );
  222. int32 const numBytesWritten = BigLong( numBytesWrittenWire ); // byteswap from the wire
  223. // Make sure the total size of the message matches the expectations
  224. if ( numRandomFudgeBytes + 1 + sizeof( int32 ) + numBytesWritten == msgEncryptedInput.encrypted().size() )
  225. {
  226. bf_read bufRead( &buffer[ 1 + numRandomFudgeBytes + sizeof( int32 ) ], numBytesWritten );
  227. unsigned char cmd = bufRead.ReadVarInt32();
  228. // See if the netchan has the required binder registered
  229. int iMsgHandler = 0;
  230. INetMessageBinder *pMsgBind = pProcessingChannel->FindMessageBinder( cmd, iMsgHandler++ );
  231. if ( pMsgBind )
  232. {
  233. int startbit = bufRead.GetNumBitsRead();
  234. INetMessage *pEmbeddedMessage = pMsgBind->CreateFromBuffer( bufRead );
  235. if ( !pEmbeddedMessage )
  236. {
  237. Msg( "CmdEncryptedDataMessageCodec failed to parse embedded message" );
  238. Assert( 0 );
  239. return false;
  240. }
  241. pEmbeddedMessage->SetReliable( pProcessingChannel->WasLastMessageReliable() );
  242. pProcessingChannel->UpdateMessageStats( pEmbeddedMessage->GetGroup(), bufRead.GetNumBitsRead() - startbit );
  243. do
  244. {
  245. bool bRet = pMsgBind->Process( *pEmbeddedMessage );
  246. if ( !bRet )
  247. {
  248. ConDMsg( "CmdEncryptedDataMessageCodec: netchannel failed processing embedded message %s.\n", pEmbeddedMessage->GetName() );
  249. Assert ( 0 );
  250. delete pEmbeddedMessage;
  251. return false;
  252. }
  253. // Move to another binder
  254. pMsgBind = pProcessingChannel->FindMessageBinder( cmd, iMsgHandler++ );
  255. } while ( pMsgBind );
  256. delete pEmbeddedMessage;
  257. }
  258. }
  259. }
  260. return true;
  261. }
  262. CTSPool< net_scratchbuffer_t::buffer_t > net_scratchbuffer_t::sm_NetScratchBuffers;
  263. #if defined( REPLAY_ENABLED )
  264. bool CLC_SaveReplay::WriteToBuffer( bf_write &buffer ) const
  265. {
  266. buffer.WriteUBitLong( GetType(), NETMSG_TYPE_BITS );
  267. buffer.WriteString( m_szFilename );
  268. buffer.WriteUBitLong( m_nStartSendByte, sizeof( m_nStartSendByte ) );
  269. buffer.WriteFloat( m_flPostDeathRecordTime );
  270. return !buffer.IsOverflowed();
  271. }
  272. bool CLC_SaveReplay::ReadFromBuffer( bf_read &buffer )
  273. {
  274. buffer.ReadString( m_szFilename, sizeof( m_szFilename ) );
  275. m_nStartSendByte = buffer.ReadUBitLong( sizeof( m_nStartSendByte ) );
  276. m_flPostDeathRecordTime = buffer.ReadFloat();
  277. return !buffer.IsOverflowed();
  278. }
  279. const char *CLC_SaveReplay::ToString() const
  280. {
  281. V_snprintf( s_text, sizeof( s_text ), "%s: filename: %s, start byte: %i, post death record time: %f", GetName(), m_szFilename, m_nStartSendByte, m_flPostDeathRecordTime );
  282. return s_text;
  283. }
  284. #endif