//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #if defined(_WIN32) && !defined(_X360) #include #elif POSIX #include #include #elif !defined(_X360) #error "define socket.h" #endif #include "host.h" #include "blockingudpsocket.h" #include "cserserverprotocol_engine.h" #include "KeyValues.h" #include "bitbuf.h" #include "mathlib/IceKey.H" #include "net.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" static int CountFields( KeyValues *fields ) { int c = 0; KeyValues *kv = fields->GetFirstSubKey(); while ( kv ) { c++; kv = kv->GetNextKey(); } return c; } //----------------------------------------------------------------------------- // Purpose: encrypts an 8-byte sequence //----------------------------------------------------------------------------- static inline void Encrypt8ByteSequence( IceKey& cipher, const unsigned char *plainText, unsigned char *cipherText) { cipher.encrypt(plainText, cipherText); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- static void EncryptBuffer( IceKey& cipher, unsigned char *bufData, uint bufferSize) { unsigned char *cipherText = bufData; unsigned char *plainText = bufData; uint bytesEncrypted = 0; while (bytesEncrypted < bufferSize) { // encrypt 8 byte section Encrypt8ByteSequence( cipher, plainText, cipherText); bytesEncrypted += 8; cipherText += 8; plainText += 8; } } static void BuildUploadDataMessage( bf_write& buf, char const *tablename, KeyValues *fields ) { bf_write encrypted; ALIGN4 byte encrypted_data[ 2048 ] ALIGN4_POST; buf.WriteByte( C2M_UPLOADDATA ); buf.WriteByte( '\n' ); buf.WriteByte( C2M_UPLOADDATA_PROTOCOL_VERSION ); // encryption object IceKey cipher(1); /* medium encryption level */ unsigned char ucEncryptionKey[8] = { 54, 175, 165, 5, 76, 251, 29, 113 }; cipher.set( ucEncryptionKey ); encrypted.StartWriting( encrypted_data, sizeof( encrypted_data ) ); byte corruption_identifier = 0x01; encrypted.WriteByte( corruption_identifier ); // Data version protocol encrypted.WriteByte( C2M_UPLOADDATA_DATA_VERSION ); encrypted.WriteString( tablename ); int fieldCount = CountFields( fields ); if ( fieldCount > 255 ) { Host_Error( "Too many fields in uploaddata (%i max = 255)\n", fieldCount ); } encrypted.WriteByte( (byte)fieldCount ); KeyValues *kv = fields->GetFirstSubKey(); while ( kv ) { encrypted.WriteString( kv->GetName() ); encrypted.WriteString( kv->GetString() ); kv = kv->GetNextKey(); } // Round to multiple of 8 for encrypted while ( encrypted.GetNumBytesWritten() % 8 ) { encrypted.WriteByte( 0 ); } EncryptBuffer( cipher, (unsigned char *)encrypted.GetData(), encrypted.GetNumBytesWritten() ); buf.WriteShort( (int)encrypted.GetNumBytesWritten() ); buf.WriteBytes( (unsigned char *)encrypted.GetData(), encrypted.GetNumBytesWritten() ); } //----------------------------------------------------------------------------- // Purpose: // Input : *cserIP - // *tablename - // *fields - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool UploadData( char const *cserIP, char const *tablename, KeyValues *fields ) { #ifndef _XBOX bf_write buf; ALIGN4 byte data[ 2048 ] ALIGN4_POST; buf.StartWriting( data, sizeof( data ) ); BuildUploadDataMessage( buf, tablename, fields ); netadr_t cseradr; if ( NET_StringToAdr( cserIP, &cseradr ) ) { CBlockingUDPSocket *socket = new CBlockingUDPSocket(); if ( socket ) { struct sockaddr_in sa; cseradr.ToSockadr( (struct sockaddr *)&sa ); // Don't bother waiting for response here socket->SendSocketMessage( sa, (const byte *)buf.GetData(), buf.GetNumBytesWritten() ); delete socket; return true; } } return false; #else return true; #endif } /* CON_COMMAND( datatest, "" ) { KeyValues *kv = new KeyValues( "data" ); kv->SetString( "IDHash", "abcdefg" ); kv->SetString( "Time", "DATETIME" ); kv->SetString( "DXDeviceID", "1001" ); kv->SetString( "DXVendorID", "1001" ); kv->SetString( "Framerate", "999" ); kv->SetString( "BuildNumber", va( "%i", build_number() ) ); bool bret = UploadData( "127.0.0.1:27013", "benchmark", kv ); kv->deleteThis(); } */