|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds the CGCSession class
//
//=============================================================================
#ifndef GCSESSION_H
#define GCSESSION_H
#ifdef _WIN32
#pragma once
#endif
#include "scheduledfunction.h"
#include "framefunction.h"
#include "gcsdk/gc_sharedobjectcache.h"
namespace GCSDK {
class CGCGSSession;
// Spew group for anything related to sessions
extern CGCEmitGroup g_EGSessions;
//-----------------------------------------------------------------------------
// Utility class to handle rate limiting based upon a steam ID and message using two console variables to control rate
//-----------------------------------------------------------------------------
//utility class to handle rate limiting based upon a steam ID
class CSteamIDRateLimit { public: CSteamIDRateLimit( const GCConVar& cvNumPerPeriod, const GCConVar* pcvPeriodS = NULL ); ~CSteamIDRateLimit(); //given a steam ID, this will determine if it should be rate limited
bool BIsRateLimited( CSteamID steamID, uint32 unMsgType ); //frame function to clear the list after a period of time
bool OnFrameFn( const CLimitTimer& timer ); private: //the last time we cleared our list
RTime32 m_LastClear; //the frame function so we can detect when we need to clear
CFrameFunction< CSteamIDRateLimit> m_FrameFunction; //the map of messages we have tracked for each user
CUtlHashMapLarge< CSteamID, uint32 > m_Msgs; //the console variables that track the time window and the messages allowed
const GCConVar& m_cvNumPerPeriod; const GCConVar* m_pcvPeriodS; };
//------------------------------------------------------------------------------------------
// CMsgRateLimitTracker
// A utility class to track when messages go over so that we can see users/msgs that are being spammed
//------------------------------------------------------------------------------------------
class CMsgRateLimitTracker { public:
CMsgRateLimitTracker();
//called to track a message that was rate limited
void TrackRateLimitedMsg( const CSteamID steamID, MsgType_t eMsgType );
//called to report the collected rate limiting stats
void ReportMsgStats() const; void ReportTopUsers( uint32 nMinMsgs, uint32 nListTop ) const; void ReportUserStats() const;
//called to clear all collected stats
void ClearStats();
private:
//the time we started collecting stats at
RTime32 m_StartTime;
//map detailing the number of messages of each type that have been dropped
CUtlHashMapLarge< MsgType_t, uint32 > m_MsgStats; CUtlHashMapLarge< CSteamID, uint32 > m_UserStats; }; extern CMsgRateLimitTracker g_RateLimitTracker;
//-----------------------------------------------------------------------------
// Purpose: Base class for sessions in the GC
//-----------------------------------------------------------------------------
class CGCSession { public: CGCSession( const CSteamID & steamID, CGCSharedObjectCache *pCache ); virtual ~CGCSession();
const CSteamID & GetSteamID() const { return m_steamID; }
const CGCSharedObjectCache *GetSOCache() const { return m_pSOCache; } CGCSharedObjectCache *GetSOCache() { return m_pSOCache; } void RemoveSOCache() { m_pSOCache = NULL; }
EOSType GetOSType() const { return m_osType; }; bool IsTestSession() const { return m_bIsTestSession; } uint32 GetIPPublic() const { return m_unIPPublic; } bool IsSecure() const { return m_bIsSecure; }
bool BIsShuttingDown() const { return m_bIsShuttingDown; } void SetIsShuttingDown( bool bIsShuttingDown ) { m_bIsShuttingDown = bIsShuttingDown; }
virtual void Dump( bool bFull = true ) const = 0;
bool BRateLimitMessage( MsgType_t unMsgType );
CJobTime GetLastPingSendTime() const { return m_jtTimeSentPing; } CJobTime GetLastMessageReceiveTime() const { return m_jtLastMessageReceived; } void SendPing() const;
virtual void MarkAccess() { } virtual void Run(); virtual void YieldingSOCacheReloaded() {} #ifdef DBGFLAG_VALIDATE
virtual void Validate( CValidator &validator, const char *pchName ); #endif // DBGFLAG_VALIDATE
// Geolocation
bool HasGeoLocation() const { return m_haveGeoLocation; } bool GetGeoLocation( float &latitude, float &longittude ) const; virtual void SetGeoLocation( float latitude, float longittude );
//track whether or not this session has been initialized or not
bool BIsInitialized() const { return m_bInitialized; } void SetInitialized( bool b ) { m_bInitialized = b; }
private: CSteamID m_steamID; CGCSharedObjectCache *m_pSOCache;
// Tracks how many messages we've gotten this second so we can block attacks
RTime32 m_rtLastMessageReceived; uint32 m_unMessagesRecievedThisSecond; CJobTime m_jtLastMessageReceived;
// This is mutable because we update it when we send pings, but sending a
// ping to a user/server isn't really a session changing event, so we don't
// want to require locking the session to ping it and update its last
// sent ping time.
mutable CJobTime m_jtTimeSentPing;
EOSType m_osType : 16; bool m_bIsShuttingDown : 1; bool m_bIsTestSession : 1; bool m_bIsSecure : 1; bool m_bInitialized : 1; protected: bool m_haveGeoLocation : 1;
float m_flLatitude; float m_flLongitude;
uint32 m_unIPPublic;
friend class CGCBase; };
//-----------------------------------------------------------------------------
// Purpose: Base class for user sessions in the GC
//-----------------------------------------------------------------------------
class CGCUserSession : public CGCSession { public: CGCUserSession( const CSteamID & steamID, CGCSharedObjectCache *pCache ) : CGCSession( steamID, pCache ) { } virtual ~CGCUserSession();
virtual bool BInit();
const CSteamID &GetSteamIDGS() const { return m_steamIDGS; } const CSteamID &GetSteamIDGSPrev() const { return m_steamIDGSPrev; }
virtual bool BSetServer( const CSteamID &steamIDGS ); virtual bool BLeaveServer(); virtual void Dump( bool bFull = true ) const;
private: CSteamID m_steamIDGS; CSteamID m_steamIDGSPrev; };
//-----------------------------------------------------------------------------
// Purpose: Base class for gameserver sessions in the GC
//-----------------------------------------------------------------------------
class CGCGSSession : public CGCSession { public:
CGCGSSession( const CSteamID & steamID, CGCSharedObjectCache *pCache, uint32 unServerAddr, uint16 usServerPort ) ; virtual ~CGCGSSession();
uint32 GetAddr() const { return m_unServerAddr; } uint16 GetPort() const { return m_usServerPort; } void SetIPAndPort( uint32 unServerAddr, uint16 usServerPort ); int GetUserCount() const { return m_vecUsers.Count(); } CSteamID GetUserID( int nIndex ) const { return m_vecUsers[nIndex]; }
// Manages users on the server. It is very important that these are not
// virtual and not yielding. For custom behavior override the Pre*() hooks below
bool BAddUser( const CSteamID &steamIDUser ); bool BRemoveUser( const CSteamID &steamIDUser ); void RemoveAllUsers();
virtual void Dump( bool bFull = true ) const;
protected: // Hooks to trigger custom behavior when users are added and removed. It is
// very important that these do not yield. If you need to yield, start a job instead
virtual void PreAddUser( const CSteamID &steamIDUser ) {} virtual void PostAddUser( const CSteamID &steamIDUser ) {} virtual void PreRemoveUser( const CSteamID &steamIDUser ) {} virtual void PostRemoveUser( const CSteamID &steamIDUser ) {} virtual void PreRemoveAllUsers() {} virtual void PostRemoveAllUsers() {}
public: float m_lastUpdateTime; // Last time we received a message from the server
#ifdef DBGFLAG_VALIDATE
virtual void Validate( CValidator &validator, const char *pchName ); #endif // DBGFLAG_VALIDATE
protected: CUtlVector<CSteamID> m_vecUsers;
// These are the address of the server as connected to Steam
uint32 m_unServerAddr; uint16 m_usServerPort; };
} // namespace GCSDK
#endif // GCSESSION_H
|