diff options
Diffstat (limited to 'engine/sv_uploaddata.cpp')
| -rw-r--r-- | engine/sv_uploaddata.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/engine/sv_uploaddata.cpp b/engine/sv_uploaddata.cpp new file mode 100644 index 0000000..979b4ce --- /dev/null +++ b/engine/sv_uploaddata.cpp @@ -0,0 +1,179 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + + +#if defined(_WIN32) && !defined(_X360) +#include <winsock.h> +#elif POSIX +#include <sys/socket.h> +#include <netinet/in.h> +#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(); +} +*/ |