diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /public/gcsdk/msgbase.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/gcsdk/msgbase.h')
| -rw-r--r-- | public/gcsdk/msgbase.h | 870 |
1 files changed, 870 insertions, 0 deletions
diff --git a/public/gcsdk/msgbase.h b/public/gcsdk/msgbase.h new file mode 100644 index 0000000..3850914 --- /dev/null +++ b/public/gcsdk/msgbase.h @@ -0,0 +1,870 @@ +//====== Copyright �, Valve Corporation, All rights reserved. ======= +// +// Purpose: Holds the CMsgBase_t class +// +//============================================================================= + +#ifndef GCMSGBASE_H +#define GCMSGBASE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/tsmultimempool.h" +#include "gclogger.h" +#include "gcconstants.h" +#include "refcount.h" + +namespace GCSDK +{ + +class CNetPacket; + +// used for message types in GCSDK where we don't have the actual enum +typedef uint32 MsgType_t; +const uint32 k_EMsgProtoBufFlag = 0x80000000; + +//extern ConVar g_ConVarMsgErrorDump; +extern CThreadSafeMultiMemoryPool g_MemPoolMsg; + +enum EMsgFormatType +{ + k_EMsgFormatTypeStruct = 0, + k_EMsgFormatTypeClientStruct = 1, + k_EMsgFormatTypeClientStructDeprecated = 2, + k_EMsgFormatTypeProtocolBuffer = 3 +}; + + +// +// Interface that the CNetPacket wrappers for both old/new inter-server +// message formats must implement. +// +class IMsgNetPacket : public CRefCount +{ +public: + + virtual EMsgFormatType GetEMsgFormatType() const = 0; + + virtual CNetPacket *GetCNetPacket() const = 0; + virtual uint8 *PubData() const = 0; + virtual uint CubData() const = 0; + + // + // Inter-server or client messages in both old/new formats + // + virtual MsgType_t GetEMsg() const = 0; + virtual JobID_t GetSourceJobID() const = 0; + virtual JobID_t GetTargetJobID() const = 0; + virtual void SetTargetJobID( JobID_t ulJobID ) = 0; + + // + // Client messages only in the old format, optional in any msg in the new format + // + virtual CSteamID GetSteamID() const = 0; + virtual void SetSteamID( CSteamID steamID ) = 0; + + // Inter-gc messages only + virtual AppId_t GetSourceAppID() const = 0; + virtual void SetSourceAppID( AppId_t appId ) = 0; + + // + // The name of the job type to route this message to. ProtoBuf messages only + // + virtual bool BHasTargetJobName() const = 0; + virtual const char *GetTargetJobName() const = 0; + +protected: + + // Needed due to CRefCount inheritance which makes this not a pure interface class + virtual ~IMsgNetPacket() {} + +}; + +IMsgNetPacket *IMsgNetPacketFromCNetPacket( CNetPacket *pNetPacket ); + + +// Wrapper around IMsgNetPacket which auto-releases +class CIMsgNetPacketAutoRelease +{ +public: + CIMsgNetPacketAutoRelease( CNetPacket *pNetPacket ) { m_pMsgNetPacket = IMsgNetPacketFromCNetPacket( pNetPacket ); } + ~CIMsgNetPacketAutoRelease() { SAFE_RELEASE( m_pMsgNetPacket ); } + + void Replace( CNetPacket *pNetPacket, bool bIsClientMsg ) { SAFE_RELEASE( m_pMsgNetPacket ); m_pMsgNetPacket = IMsgNetPacketFromCNetPacket( pNetPacket ); } + + IMsgNetPacket *Get() { return m_pMsgNetPacket; } + IMsgNetPacket *operator->() { return m_pMsgNetPacket; } + +protected: + void operator=( const CIMsgNetPacketAutoRelease &that ) { AssertMsg( false, "Not safe to copy since releases references on destruction" ); } + CIMsgNetPacketAutoRelease( const CIMsgNetPacketAutoRelease &that ) { AssertMsg( false, "Not safe to copy since releases references on destruction" ); } + + IMsgNetPacket *m_pMsgNetPacket; +}; + + +//----------------------------------------------------------------------------- +// Purpose: Helper class for incoming and outgoing network packets. +// IMPORTANT: Note the distinction between pubData and cubData +// (which refer to the message payload), and pubMsg and cubMsg +// (which refer to the entire message, with the header). +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +class CMsgBase_t +{ +public: + // Send constructor + CMsgBase_t( uint32 cubStruct, uint32 cubReserve = 0 ); + + // copies data from pubPkt + CMsgBase_t( const uint8 *pubPkt, uint32 cubPkt ); + + // Receive constructor - aliases pubPkt + CMsgBase_t( uint32 cubHdr, uint32 cubStruct, uint8 *pubPkt, uint32 cubPkt/*, HCONNECTION hConnection = NULL*/ ); + + // set packet after using empty constructor + void SetPacket( IMsgNetPacket *pNetPacket ); + + // Destructor + virtual ~CMsgBase_t(); + + // Accessors + uint8 *PubVarData() { return ( m_pubPkt + m_cubMsgHdr + m_cubStruct ); } + const uint8 *PubVarData() const { return ( m_pubPkt + m_cubMsgHdr + m_cubStruct ); } + uint32 CubVarData() const + { + if ( m_cubPkt >= ( m_cubMsgHdr + m_cubStruct ) ) + return m_cubPkt - m_cubMsgHdr - m_cubStruct; + else + return 0; + } + uint8 *PubPkt() { return m_pubPkt; } + const uint8 *PubPkt() const { return m_pubPkt; } + uint32 CubPkt() const { return m_cubPkt; } + MSG_HEADER_TYPE &Hdr() { return * ( MSG_HEADER_TYPE * ) ( m_pubPkt ); } + const MSG_HEADER_TYPE &Hdr() const { return * ( MSG_HEADER_TYPE * ) ( m_pubPkt ); } + uint32 CubHdr() const { return m_cubMsgHdr; } + + uint8* PubBody() { return m_pubBody; } + const uint8* PubBody() const { return m_pubBody; } + uint32 CubBody() const { return CubPkt() - CubHdr(); } + + // Add additional data + int DubWriteCur() { return m_cubPkt - m_cubMsgHdr - m_cubStruct; } // Our current offset within the var data block + void AddBoolData( bool bData ); + void AddUint8Data( uint8 ubData ); + void AddUintData( uint32 unData ); + void AddIntData( int32 nData ); + void AddInt16Data( int16 sData ); + void AddUint16Data( uint16 usData ); + void AddUint64Data( uint64 ulData ); + void AddInt64Data( int64 lData ); + void AddFloatData( float lData ); + void AddVariableLenData( const void *pvData, uint cubLen ); + void AddStrData( const char *pchIn ); + template<typename T> void AddStructure(T& structure ) ; + + // Read variable-length data (can also read manually using PubVarData(), CubVarData() + void ResetReadPtr() { m_pubVarRead = PubVarData(); } + uint8 *PubReadCur() { return m_pubVarRead; } + const uint8 *PubReadCur() const { return m_pubVarRead; } + uint32 CubReadRemaining() const { return (uint32)(m_pubPkt + m_cubPkt - m_pubVarRead); } + void AdvanceReadPtr( int cubSkip ) { m_pubVarRead += cubSkip; } + bool BReadBoolData( bool *pbData ); + bool BReadUint8Data( uint8 *pbData ); + bool BReadUintData( uint32 *punData ); + bool BReadIntData( int32 *pnData ); + bool BReadInt16Data( int16 *psData ); + bool BReadUint16Data( uint16 *pusData ); + bool BReadUint64Data( uint64 *pulData ); + bool BReadInt64Data( int64 *plData ); + bool BReadFloatData( float *pflData ); + bool BReadVariableLenData( void *pvBuff, uint32 cubRead ); + bool BReadStr( char *pchBuff, int cchBuff ); + bool BReadStr( CUtlString *pstr ); + template<typename T> bool BReadStructure(T& structure) ; + + // returns pointer to data (and size of data in out ptr), and NULLs out own pointer; + // caller now owns this memory and must free + uint8 * DetachPkt( int * pcubPkt ) + { + Assert( pcubPkt ); + *pcubPkt = m_cubPkt; + uint8 * pRetVal = m_pubPkt; + m_pubPkt = NULL; + m_pubBody = NULL; + m_cubPkt = 0; + return pRetVal; + } + + void ResetWritePtr() + { + m_cubPkt = m_cubMsgHdr + m_cubStruct; + } + + uint32 GetWriteOffset() const { return m_cubPkt; } + void SetWriteOffset( uint32 nWriteOffset ) { m_cubPkt = nWriteOffset; } + + // Called to set the JobID that will be expecting + // a reply to this message. + void ExpectingReply( JobID_t jobIDSource ) + { + Hdr().m_JobIDSource = jobIDSource; + } + + bool BIsExpectingReply() const { return Hdr().m_JobIDSource != k_GIDNil; } + + // make sure the buffer can hold this extra amount of data + void EnsurePacketSize( uint32 cubNewsize ); + //HCONNECTION GetHConnection() const { return m_hConnection; } + + void ReportBufferOverflow(); + void PacketDump(); // spews complete packet content to console + +protected: + // Shared by send & receive + uint8 *m_pubPkt; // Raw packet data + uint8 *m_pubBody; // pointer to body; always equal to m_pubPkt + m_cubMsgHdr + uint32 m_cubPkt; // Raw packet size + const uint32 m_cubMsgHdr; // Size of our message header + uint32 m_cubStruct; // Size of our message-specific struct + //HCONNECTION m_hConnection; // Connection on which we received the message +private: + // stop people from hurting themselves + CMsgBase_t( const CMsgBase_t &rhs ) {}; + CMsgBase_t &operator=( const CMsgBase_t &rhs ) {}; + + bool m_bAlloced; // Did we allocate this buffer or does someone else own it + + // Receive only + uint8 *m_pubVarRead; // Our current read pointer in the variable-length data +}; + +template <typename MSG_HEADER_TYPE> +CMsgBase_t<MSG_HEADER_TYPE>::CMsgBase_t( uint32 cubStruct, uint32 cubReserve ) +: m_cubMsgHdr( sizeof( MSG_HEADER_TYPE ) ) +{ + m_cubStruct = cubStruct; + + // Alloc a buffer + m_cubPkt = m_cubMsgHdr + m_cubStruct; + m_pubPkt = (uint8 *) g_MemPoolMsg.Alloc( m_cubPkt + cubReserve ); + m_pubBody = m_pubPkt + m_cubMsgHdr; + memset(m_pubPkt, 0, m_cubPkt ); + m_bAlloced = true; + m_pubVarRead = NULL; +} + + +template <typename MSG_HEADER_TYPE> +CMsgBase_t<MSG_HEADER_TYPE>::CMsgBase_t( const uint8 *pubPkt, uint32 cubPkt ) +: m_cubMsgHdr( 0 ) +{ + m_cubStruct = 0; + + // Alloc a buffer + m_cubPkt = cubPkt; + m_pubPkt = (uint8 *) g_MemPoolMsg.Alloc( m_cubPkt ); + m_pubBody = m_pubPkt + m_cubMsgHdr; + Q_memcpy(m_pubPkt, pubPkt, cubPkt ); + m_bAlloced = true; + m_pubVarRead = NULL; +} + + +template <typename MSG_HEADER_TYPE> +CMsgBase_t<MSG_HEADER_TYPE>::CMsgBase_t( uint32 cubHdr, uint32 cubStruct, uint8 *pubPkt, uint32 cubPkt ) +: m_cubMsgHdr( cubHdr ) +{ + Assert( cubHdr != 0 ); + Assert( !cubPkt || ( cubPkt >= ( cubHdr + cubStruct ) ) ); + m_cubStruct = cubStruct; + m_pubPkt = pubPkt; + m_pubBody = m_pubPkt + m_cubMsgHdr; + m_cubPkt = cubPkt; + m_bAlloced = false; + m_pubVarRead = PubVarData(); +} + + +template <typename MSG_HEADER_TYPE> +CMsgBase_t<MSG_HEADER_TYPE>::~CMsgBase_t() +{ + // if we allocated memory, free it + if ( m_bAlloced && m_pubPkt ) + g_MemPoolMsg.Free( m_pubPkt ); +} + + +//----------------------------------------------------------------------------- +// Purpose: ensure the packet can contain at least this much extra data +// Input: cubExtraSize - the amount of bytes to have room for +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::SetPacket( IMsgNetPacket *pNetPacket ) +{ + m_pubPkt = pNetPacket->PubData(); + m_pubBody = m_pubPkt + m_cubMsgHdr; + m_cubPkt = pNetPacket->CubData(); + Assert( !m_cubPkt || ( m_cubPkt >= ( m_cubMsgHdr + m_cubStruct ) ) ); + m_bAlloced = false; + m_pubVarRead = PubVarData(); +} + + +//----------------------------------------------------------------------------- +// Purpose: ensure the packet can contain at least this much extra data +// Input: cubExtraSize - the amount of bytes to have room for +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::EnsurePacketSize( uint32 cubExtraSize ) +{ + m_pubPkt = (uint8 *) g_MemPoolMsg.ReAlloc( m_pubPkt, m_cubPkt + cubExtraSize ); + m_pubBody = m_pubPkt + m_cubMsgHdr; +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a bool to the variable length data associated with this message +// Input: bData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddBoolData( bool ubData ) +{ + return AddUint8Data( static_cast< uint8 >( ubData ) ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a uint8 to the variable length data associated with this message +// Input: ubData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddUint8Data( uint8 ubData ) +{ + EnsurePacketSize( sizeof( uint8 ) ); + *( ( uint8 * ) ( m_pubPkt + m_cubPkt ) ) = ubData; + m_cubPkt += sizeof( uint8 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a uint to the variable length data associated with this message +// Input: unData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddUintData( uint32 unData ) +{ + EnsurePacketSize( sizeof( uint32 ) ); + *( ( uint32 * ) ( m_pubPkt + m_cubPkt ) ) = unData; + m_cubPkt += sizeof( uint32 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends an int to the variable length data associated with this message +// Input: nData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddIntData( int32 nData ) +{ + EnsurePacketSize( sizeof( int32 ) ); + *( ( int32 * ) ( m_pubPkt + m_cubPkt ) ) = nData; + m_cubPkt += sizeof( int32 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends an int16 to the variable length data associated with this message +// Input: nData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddInt16Data( int16 sData ) +{ + EnsurePacketSize( sizeof( int16 ) ); + *( ( int16 * ) ( m_pubPkt + m_cubPkt ) ) = sData; + m_cubPkt += sizeof( int16 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends an int16 to the variable length data associated with this message +// Input: nData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddUint16Data( uint16 usData ) +{ + EnsurePacketSize( sizeof( uint16 ) ); + *( ( uint16 * ) ( m_pubPkt + m_cubPkt ) ) = usData; + m_cubPkt += sizeof( uint16 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a uint64 to the variable length data associated with this message +// Input: ulData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddUint64Data( uint64 ulData ) +{ + EnsurePacketSize( sizeof( uint64 ) ); + *( ( uint64 * ) ( m_pubPkt + m_cubPkt ) ) = ulData; + m_cubPkt += sizeof( uint64 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends an int64 to the variable length data associated with this message +// Input: lData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddInt64Data( int64 lData ) +{ + EnsurePacketSize( sizeof( int64 ) ); + *( ( int64 * ) ( m_pubPkt + m_cubPkt ) ) = lData; + m_cubPkt += sizeof( int64 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends variable length data to this message. (Can be called +// repeatedly to append multiple data blocks.) +// Input: pvData - pointer to data to append +// cubData - size of data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddVariableLenData( const void *pvData, uint cubLen ) +{ + if ( cubLen > 0 ) + { + EnsurePacketSize( cubLen ); + memcpy( ( m_pubPkt + m_cubPkt ), pvData, cubLen ); + m_cubPkt += cubLen; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a float to the variable length data associated with this message +// Input: nData - data to append +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddFloatData( float flData ) +{ + EnsurePacketSize( sizeof( float ) ); + *( ( float * ) ( m_pubPkt + m_cubPkt ) ) = flData; + m_cubPkt += sizeof( float ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Appends a string to the variable-length portion of this message. +// Input: pchIn - String to append to the message +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::AddStrData( const char *pchIn ) +{ + if ( !pchIn ) + { + Assert( pchIn ); // passing a null string here is a code bug + return; + } + + int cchIn = Q_strlen( pchIn ); + + EnsurePacketSize( cchIn + 1 ); + + Q_strncpy( ( char * ) ( m_pubPkt + m_cubPkt ), pchIn, cchIn + 1 ); + m_cubPkt += ( cchIn + 1 ); +} + +template <typename MSG_HEADER_TYPE> +template <typename T> +void CMsgBase_t<MSG_HEADER_TYPE>::AddStructure( T& structure ) +{ + + EnsurePacketSize(sizeof(structure)) ; + *( reinterpret_cast<T*>(m_pubPkt+m_cubPkt)) = structure ; + m_cubPkt += sizeof(structure) ; +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a bool from the variable-length part of the message +// Input: pbData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadBoolData( bool *pbData ) +{ + return BReadUint8Data( ( uint8* ) pbData ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a uint8 from the variable-length part of the message +// Input: pbData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadUint8Data( uint8 *pbData ) +{ + if ( m_pubVarRead + sizeof( uint8 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *pbData = * ( ( uint8 * ) m_pubVarRead ); + m_pubVarRead += sizeof( uint8 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a uint32 from the variable-length part of the message +// Input: punData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadUintData( uint32 *punData ) +{ + if ( m_pubVarRead + sizeof( uint32 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *punData = * ( ( uint32 * ) m_pubVarRead ); + m_pubVarRead += sizeof( uint32 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an int32 from the variable-length part of the message +// Input: pnData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadIntData( int32 *pnData ) +{ + if ( m_pubVarRead + sizeof( int32 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *pnData = * ( ( int32 * ) m_pubVarRead ); + m_pubVarRead += sizeof( int32 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an int16 from the variable-length part of the message +// Input: pnData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadInt16Data( int16 *psData ) +{ + if ( m_pubVarRead + sizeof( int16 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *psData = * ( ( int16 * ) m_pubVarRead ); + m_pubVarRead += sizeof( int16 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an uint16 from the variable-length part of the message +// Input: pnData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadUint16Data( uint16 *pusData ) +{ + if ( m_pubVarRead + sizeof( uint16 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *pusData = * ( ( uint16 * ) m_pubVarRead ); + m_pubVarRead += sizeof( uint16 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a uint64 from the variable-length part of the message +// Input: pulData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadUint64Data( uint64 *pulData ) +{ + if ( m_pubVarRead + sizeof( uint64 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *pulData = * ( ( uint64 * ) m_pubVarRead ); + m_pubVarRead += sizeof( uint64 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an int64 from the variable-length part of the message +// Input: plData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadInt64Data( int64 *plData ) +{ + if ( m_pubVarRead + sizeof( int64 ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *plData = * ( ( int64 * ) m_pubVarRead ); + m_pubVarRead += sizeof( int64 ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads a float from the variable-length part of the message +// Input: pflData - [return] The value we read goes here +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadFloatData( float *pflData ) +{ + if ( m_pubVarRead + sizeof( float ) > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + *pflData = * ( ( float * ) m_pubVarRead ); + m_pubVarRead += sizeof( float ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads a block of data from the variable-length part of the message +// Input: pvBuff - [return] Buffer to copy the data into +// cubRead - Amount of data to read +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadVariableLenData( void *pvBuff, uint32 cubRead ) +{ + if ( m_pubVarRead + cubRead > m_pubPkt + m_cubPkt ) + { + ReportBufferOverflow(); + return false; + } + + Q_memcpy( pvBuff, m_pubVarRead, cubRead ); + m_pubVarRead += cubRead; + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads a string from the variable-length part of the message +// Input: pchBuff - [return] Buffer to copy the string into +// cchBuff - Size of the buffer +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadStr( char *pchBuff, int cchBuff ) +{ + int cchRead = 0; + int cchLeft = CubReadRemaining(); // get bytes left in message + + // search for string end in rest of message + while ( cchRead < cchLeft ) + { + // if we hit the 0, stop + if ( *(m_pubVarRead+cchRead) == 0 ) + break; + + cchRead++; + } + + cchRead++; // add the 0 + + // check if string fits into buffer and was found within packet bounds + if ( ( cchRead > cchBuff ) || (cchRead > cchLeft) ) + { + // at least return an empty string since most code doesn't check the return value + if ( cchBuff > 0 ) + pchBuff[0] = 0; + + ReportBufferOverflow(); + + return false; + } + + // copy the string to output buffer + Q_memcpy( pchBuff, m_pubVarRead, cchRead ); + m_pubVarRead += ( cchRead * sizeof( char ) ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads a string from the variable-length part of the message +// Input: pchString - [return] copied string +// Output: true if we were able to read, false if we overran the buffer +//----------------------------------------------------------------------------- +template <typename MSG_HEADER_TYPE> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadStr( CUtlString *pstr ) +{ + if ( pstr == NULL ) + return false; + + int cchRead = 0; + int cchLeft = CubReadRemaining(); // get bytes left in message + + // search for string end in rest of message + while ( cchRead < cchLeft ) + { + // if we hit the 0, stop + if ( *(m_pubVarRead+cchRead) == 0 ) + break; + + cchRead++; + } + + cchRead++; // add the 0 + + // check if string was found within packet bounds + if ( cchRead > cchLeft ) + { + ReportBufferOverflow(); + return false; + } + + // copy the string + *pstr = (const char*)m_pubVarRead; + m_pubVarRead += ( cchRead * sizeof( char ) ); + + return true; +} + +template <typename MSG_HEADER_TYPE> +template <typename T> +bool CMsgBase_t<MSG_HEADER_TYPE>::BReadStructure( T& structure ) +{ + int cbLeft = CubReadRemaining() ; + + if( cbLeft >= sizeof(structure)) + { + structure = *( reinterpret_cast<T*>(m_pubVarRead)) ; + m_pubVarRead += sizeof(structure) ; + return true ; + } + return false ; +} + + + +template <typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::PacketDump() +{ + //if ( !g_ConVarMsgErrorDump.GetBool() ) + // return; + + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "Packet dump: raw size %u, header size %u, body size %u, var size %u\n", m_cubPkt, m_cubMsgHdr, m_cubStruct, CubVarData() ); + + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "Header dump: %s\n", Hdr().GetHeaderDescription().String() ); + + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "Struct dump: %u bytes\n", m_cubStruct ); + char szLine[100] = ""; + char szText[32] = ""; + + for ( uint i=0; i<m_cubStruct; i++ ) + { + byte nValue = PubBody()[i]; + uint nIndex = i%16; + + Q_snprintf( szLine+3*nIndex, 8, "%02X ", nValue ); + + if ( nValue > 31 && nValue != '%' ) + szText[nIndex] = nValue; + else + szText[nIndex] = '.'; + + if ( nIndex == 15 || i==(m_cubStruct-1)) + { + szText[nIndex+1] = '\n'; + szText[nIndex+2] = 0; + Q_strcat( szLine, "; ", sizeof(szLine) ); + Q_strcat( szLine, szText, sizeof(szLine) ); + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "%s", szLine ); + szLine[0]=0; + } + } + + uint cubVarData = MIN( CubVarData(), 1024u ); + + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "VarData dump: %u bytes\n", cubVarData ); + + for ( uint i=0; i<cubVarData; i++ ) + { + byte nValue = PubVarData()[i]; + uint nIndex = i%16; + + Q_snprintf( szLine+3*nIndex, 8, "%02X ", nValue ); + + if ( nValue > 31 && nValue != '%' ) + szText[nIndex] = nValue; + else + szText[nIndex] = '.'; + + if ( nIndex == 15 || i==(cubVarData-1)) + { + szText[nIndex+1] = '\n'; + szText[nIndex+2] = 0; + Q_strcat( szLine, " ; ", sizeof(szLine) ); + Q_strcat( szLine, szText, sizeof(szLine) ); + EmitInfo( SPEW_NETWORK, SPEW_NEVER, LOG_ALWAYS, "%s", szLine ); + szLine[0]=0; + } + } +} + +template<typename MSG_HEADER_TYPE> +void CMsgBase_t<MSG_HEADER_TYPE>::ReportBufferOverflow() +{ + EmitWarning( SPEW_NETWORK, SPEW_ALWAYS, "Read buffer overflowed on incoming %s packet\n", Hdr().PchMsgName( ) ); + PacketDump(); +} + +} // namespace GCSDK + +#endif // GCMSGBASE_H |