source-engine/public/gcsdk/messagelist.h

174 lines
6.0 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
//====== Copyright <20>, Valve Corporation, All rights reserved. =======
//
// Purpose: Maps message types to strings and vice versa
//
//=============================================================================
#ifndef MESSAGELIST_H
#define MESSAGELIST_H
#ifdef _WIN32
#pragma once
#endif
// Protobuf headers interfere with the valve min/max/malloc overrides. so we need to do all
// this funky wrapping to make the include happy.
#include <tier0/valve_minmax_off.h>
#include "google/protobuf/descriptor.h"
#include <tier0/valve_minmax_on.h>
#include "gcsdk/jobtime.h"
namespace GCSDK
{
extern CGCEmitGroup g_EGMessages;
extern const char *PchMsgNameFromEMsg( MsgType_t eMsg );
//-----------------------------------------------------------------------------
// message type flags
//-----------------------------------------------------------------------------
static const int MT_GC = 0x01; // this message is sent to or from a Game Coordinator (will be proxied by servers along the way)
static const int MT_GC_SYSTEM = 0x02; // this message was sent to or from the steam servers as a system message. Clients can't send these
//-----------------------------------------------------------------------------
// Various info about each message type
//-----------------------------------------------------------------------------
struct MsgInfo_t
{
MsgType_t eMsg;
int nFlags;
const char *pchMsgName;
struct Stats_t
{
Stats_t() : nSourceMask(0), nCount( 0 ), uBytes( 0 ) {}
uint32 nSourceMask;
uint32 nCount;
uint64 uBytes;
};
enum EStatsType
{
k_EStatsTypeSent,
k_EStatsTypeReceived,
k_EStatsTypeMultiplexedSends,
k_EStatsTypeMultiplexedSendsRaw,
k_EStatsType_Count
};
enum EStatsGroup
{
k_EStatsGroupGlobal,
k_EStatsGroupProfile,
k_EStatsGroupWindow,
k_EStatsGroup_Count
};
Stats_t stats[ k_EStatsGroup_Count ][ k_EStatsType_Count ];
};
//-----------------------------------------------------------------------------
// Purpose: Using protobuf reflection, bind them into a message list
//-----------------------------------------------------------------------------
void MsgRegistrationFromEnumDescriptor( const ::google::protobuf::EnumDescriptor *pEnumDescriptor, int nTypeMask );
//-----------------------------------------------------------------------------
// manages a hashed list of messages, allowing fast tests for validity and
// info lookup.
//-----------------------------------------------------------------------------
class CMessageList
{
public:
CMessageList();
~CMessageList();
bool BInit( );
// returns false if a message isn't valid or isn't one of the types specified
// or true if the message is valid. ppMsgName can be NULL.
bool GetMessage( MsgType_t eMsg, const char **ppMsgName, int nTypeMask );
// make stats about sending messages
void TallySendMessage( MsgType_t eMsg, uint32 uMsgSize, uint32 nSourceMask = 0 );
void TallyReceiveMessage( MsgType_t eMsg, uint32 uMsgSize, uint32 nSourceMask = 0);
void TallyMultiplexedMessage( MsgType_t eMsg, uint32 uSent, uint32 cRecipients, uint32 uMsgSize, uint32 nSourceMask = 0 );
// profiling
void EnableProfiling( bool bEnableProfiling );
// print out our stats
void PrintStats( bool bShowAll, bool bSortByFrequency, MsgInfo_t::EStatsGroup eGroup, MsgInfo_t::EStatsType eType, uint32 nSourceMask = 0 ) const;
void PrintMultiplexStats( MsgInfo_t::EStatsGroup eGroup, bool bSortByFrequency, uint32 nSourceMask = 0 ) const;
// Window management - This is similar to profiling in many ways, but is separate so that the base system can monitor traffic rates without
// interfering with profiles.
//called to obtain the totals for the timing window
const MsgInfo_t::Stats_t& GetWindowTotal( MsgInfo_t::EStatsType eType ) const;
//called to reset the window timings
void ResetWindow();
//returns how long this window has been running in microseconds
uint64 GetWindowDuration() const { return GetGroupDuration( MsgInfo_t::k_EStatsGroupWindow ); }
private:
void TallyMessageInternal( MsgInfo_t &msgInfo, MsgInfo_t::EStatsType eBucket, uint32 unMsgSize, uint32 nSourceMask, uint32 cMessages = 1 );
void AssureBucket( int nBucket );
//-----------------------------------------------------------------------------
// given a particular message ID, find out what bucket it would be in,
// as well as which slot in that bucket.
//-----------------------------------------------------------------------------
static int HashMessage( MsgType_t eMsg, int &nSlot )
{
// hash is everything except the lowest nibble,
// because buckets are 16 entries
int nBucket = eMsg / m_kcBucketSize;
nSlot = eMsg % m_kcBucketSize;
return nBucket;
}
short GetMessageIndex( MsgType_t eMsg );
//given a group, this will return the time that the stats have been collected over
uint64 GetGroupDuration( MsgInfo_t::EStatsGroup eGroup ) const;
private:
//totalled stats for the current window. It would be too costly to total these all the time
MsgInfo_t::Stats_t m_WindowTotals[ MsgInfo_t::k_EStatsType_Count ];
//the time that we have been collecting each of these buckets
CJobTime m_sCollectTime[ MsgInfo_t::k_EStatsGroup_Count ];
//are we currently actively tracking a profile?
bool m_bProfiling;
//the duration of the last finished profile (if it is no longer running, otherwise use the timer)
uint64 m_ulProfileMicrosecs;
CUtlVector< short* > m_vecMessageInfoBuckets;
CUtlVector<MsgInfo_t> m_vecMsgInfo;
static const int m_kcBucketSize = 16;
};
extern CMessageList g_theMessageList;
//-----------------------------------------------------------------------------
// Purpose: Returns the true if the specified message is a valid GC system message.
// Input : eMsg - message type to test
// ppMsgName - Optional pointer to receive message name
//-----------------------------------------------------------------------------
inline bool BIsValidSystemMsg( MsgType_t eMsg, const char **ppMsgName )
{
return g_theMessageList.GetMessage( eMsg, ppMsgName, MT_GC_SYSTEM );
}
} // namespace GCSDK
#endif // MESSAGELIST_H