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.
870 lines
27 KiB
870 lines
27 KiB
//====== 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
|
|
|