//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef BASESERVER_H #define BASESERVER_H #ifdef _WIN32 #pragma once #endif #include #include #include #include #include "baseclient.h" #include "netmessages.h" #include "net.h" #include "event_system.h" class CNetworkStringTableContainer; class PackedEntity; class ServerClass; class INetworkStringTable; enum server_state_t { ss_dead = 0, // Dead ss_loading, // Spawning ss_active, // Running ss_paused, // Running, but paused }; // See baseserver.cpp for #define which controls this bool AllowDebugDedicatedServerOutsideSteam(); // time a challenge nonce is valid for, in seconds #define CHALLENGE_NONCE_LIFETIME 6.0f // MAX_DELTA_TICKS defines the maximum delta difference allowed // for delta compression, if clients request on older tick as // delta baseline, send a full update. #define MAX_DELTA_TICKS 192 // this is about 3 seconds typedef struct { netadr_t adr; // Address where challenge value was sent to. int challenge; // To connect, adr IP address must respond with this # float time; // # is valid for only a short duration. } challenge_t; class CBaseServer : public IServer { public: CBaseServer(); virtual ~CBaseServer(); bool RestartOnLevelChange() { return m_bRestartOnLevelChange; } public: // IServer implementation virtual int GetNumClients( void ) const; // returns current number of clients virtual int GetNumProxies( void ) const; // returns number of attached HLTV proxies virtual int GetNumFakeClients() const; // returns number of fake clients/bots virtual int GetMaxClients( void ) const { return m_nMaxclients; } // returns current client limit virtual int GetUDPPort( void ) const { return NET_GetUDPPort( m_Socket ); } virtual IClient *GetClient( int index ) { return m_Clients[index]; } // returns interface to client virtual int GetClientCount() const { return m_Clients.Count(); } // for iteration; virtual float GetTime( void ) const; virtual int GetTick( void ) const { return m_nTickCount; } virtual float GetTickInterval( void ) const { return m_flTickInterval; } virtual const char *GetName( void ) const; virtual const char *GetMapName( void ) const { return m_szMapname; } virtual int GetSpawnCount( void ) const { return m_nSpawnCount; } virtual int GetNumClasses( void ) const { return serverclasses; } virtual int GetClassBits( void ) const { return serverclassbits; } virtual void GetNetStats( float &avgIn, float &avgOut ); virtual int GetNumPlayers(); virtual bool GetPlayerInfo( int nClientIndex, player_info_t *pinfo ); virtual float GetCPUUsage( void ) { return m_fCPUPercent; } virtual bool IsActive( void ) const { return m_State >= ss_active; } virtual bool IsLoading( void ) const { return m_State == ss_loading; } virtual bool IsDedicated( void ) const { return m_bIsDedicated; } virtual bool IsPaused( void ) const { return m_State == ss_paused; } virtual bool IsMultiplayer( void ) const { return m_nMaxclients > 1; } virtual bool IsPausable( void ) const { return false; } virtual bool IsHLTV( void ) const { return false; } virtual bool IsReplay( void ) const { return false; } virtual void BroadcastMessage( INetMessage &msg, bool onlyActive = false, bool reliable = false ); virtual void BroadcastMessage( INetMessage &msg, IRecipientFilter &filter ); virtual void BroadcastPrintf ( PRINTF_FORMAT_STRING const char *fmt, ...) FMTFUNCTION( 2, 3 ); virtual const char * GetPassword() const; virtual void SetMaxClients( int number ); virtual void SetPaused(bool paused); virtual void SetPassword(const char *password); virtual void DisconnectClient(IClient *client, const char *reason ); virtual void WriteDeltaEntities( CBaseClient *client, CClientFrame *to, CClientFrame *from, bf_write &pBuf ); virtual void WriteTempEntities( CBaseClient *client, CFrameSnapshot *to, CFrameSnapshot *from, bf_write &pBuf, int nMaxEnts ); public: // IConnectionlessPacketHandler implementation virtual bool ProcessConnectionlessPacket( netpacket_t * packet ); virtual void Init( bool isDedicated ); virtual void Clear( void ); virtual void Shutdown( void ); virtual CBaseClient *CreateFakeClient( const char *name ); virtual void RemoveClientFromGame( CBaseClient *client ) {}; virtual void SendClientMessages ( bool bSendSnapshots ); virtual void FillServerInfo(SVC_ServerInfo &serverinfo); virtual void UserInfoChanged( int nClientIndex ); bool GetClassBaseline( ServerClass *pClass, void const **pData, int *pDatalen ); void RunFrame( void ); void InactivateClients( void ); void ReconnectClients( void ); void CheckTimeouts (void); void UpdateUserSettings(void); void SendPendingServerInfo(void); const char *CompressPackedEntity(ServerClass *pServerClass, const char *data, int &bits); const char *UncompressPackedEntity(PackedEntity *pPackedEntity, int &size); INetworkStringTable *GetInstanceBaselineTable( void ); INetworkStringTable *GetLightStyleTable( void ); INetworkStringTable *GetUserInfoTable( void ); virtual void RejectConnection(const netadr_t &adr, int clientChallenge, const char *s ); float GetFinalTickTime( void ) const; virtual bool CheckIPRestrictions( const netadr_t &adr, int nAuthProtocol ); void SetMasterServerRulesDirty(); void SendQueryPortToClient( netadr_t &adr ); void RecalculateTags( void ); void AddTag( const char *pszTag ); void RemoveTag( const char *pszTag ); int GetNumConnections( ) { return m_nNumConnections; } void SetReportNewFakeClients( bool bReportNewFakeClients ) { m_bReportNewFakeClients = bReportNewFakeClients; } void SetPausedForced( bool bPaused, float flDuration = -1.f ); protected: virtual IClient *ConnectClient ( netadr_t &adr, int protocol, int challenge, int clientChallenge, int authProtocol, const char *name, const char *password, const char *hashedCDkey, int cdKeyLen ); virtual CBaseClient *GetFreeClient( netadr_t &adr ); virtual CBaseClient *CreateNewClient( int slot ) { AssertMsg( 0, "CBaseServer::CreateNewClient() being called - must be implemented in derived class!" ); return NULL; }; // must be derived virtual bool FinishCertificateCheck( netadr_t &adr, int nAuthProtocol, const char *szRawCertificate, int clientChallenge ) { return true; }; virtual int GetChallengeNr ( netadr_t &adr ); virtual int GetChallengeType ( netadr_t &adr ); virtual bool CheckProtocol( netadr_t &adr, int nProtocol, int clientChallenge ); virtual bool CheckChallengeNr( netadr_t &adr, int nChallengeValue ); virtual bool CheckChallengeType( CBaseClient *client, int nNewUserID, netadr_t & adr, int nAuthProtocol, const char *pchLogonCookie, int cbCookie, int clientChallenge ); virtual bool CheckPassword( netadr_t &adr, const char *password, const char *name ); virtual bool CheckIPConnectionReuse( netadr_t &adr ); virtual void ReplyChallenge(netadr_t &adr, int clientChallenge); virtual void ReplyServerChallenge(netadr_t &adr); virtual void CalculateCPUUsage(); // Keep the master server data updated. virtual bool ShouldUpdateMasterServer(); void CheckMasterServerRequestRestart(); void UpdateMasterServer(); void UpdateMasterServerRules(); virtual void UpdateMasterServerPlayers() {} void ForwardPacketsFromMasterServerUpdater(); void SetRestartOnLevelChange(bool state) { m_bRestartOnLevelChange = state; } bool RequireValidChallenge( netadr_t &adr ); bool ValidChallenge( netadr_t & adr, int challengeNr ); bool ValidInfoChallenge( netadr_t & adr, const char *nugget ); // Data public: server_state_t m_State; // some actions are only valid during load int m_Socket; // network socket int m_nTickCount; // current server tick bool m_bSimulatingTicks; // whether or not the server is currently simulating ticks char m_szMapname[64]; // map name char m_szMapFilename[64]; // map filename, may bear no resemblance to map name char m_szSkyname[64]; // skybox name char m_Password[32]; // server password MD5Value_t worldmapMD5; // For detecting that client has a hacked local copy of map, the client will be dropped if this occurs. CNetworkStringTableContainer *m_StringTables; // newtork string table container INetworkStringTable *m_pInstanceBaselineTable; INetworkStringTable *m_pLightStyleTable; INetworkStringTable *m_pUserInfoTable; INetworkStringTable *m_pServerStartupTable; INetworkStringTable *m_pDownloadableFileTable; // This will get set to NET_MAX_PAYLOAD if the server is MP. bf_write m_Signon; CUtlMemory m_SignonBuffer; int serverclasses; // number of unique server classes int serverclassbits; // log2 of serverclasses private: // Gets the next user ID mod SHRT_MAX and unique (not used by any active clients). int GetNextUserID(); int m_nUserid; // increases by one with every new client protected: int m_nMaxclients; // Current max # int m_nSpawnCount; // Number of servers spawned since start, // used to check late spawns (e.g., when d/l'ing lots of // data) float m_flTickInterval; // time for 1 tick in seconds CUtlVector m_Clients; // array of up to [maxclients] client slots. bool m_bIsDedicated; uint32 m_CurrentRandomNonce; uint32 m_LastRandomNonce; float m_flLastRandomNumberGenerationTime; float m_fCPUPercent; float m_fStartTime; float m_fLastCPUCheckTime; // This is only used for Steam's master server updater to refer to this server uniquely. bool m_bRestartOnLevelChange; bool m_bMasterServerRulesDirty; double m_flLastMasterServerUpdateTime; int m_nNumConnections; //Number of successful client connections. bool m_bReportNewFakeClients; // Whether or not newly created fake clients should be included in server browser totals float m_flPausedTimeEnd; }; extern CThreadFastMutex g_svInstanceBaselineMutex; #endif // BASESERVER_H