1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
//====== Copyright �, 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
|