summaryrefslogtreecommitdiff
path: root/engine/baseserver.h
blob: 86f080b0ebb8bf94f176f80bcfc2c39342816386 (plain) (blame)
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#ifndef BASESERVER_H
#define BASESERVER_H
#ifdef _WIN32
#pragma once
#endif

#include <iserver.h>
#include <netadr.h>
#include <bitbuf.h>
#include <utlvector.h>
#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<byte>	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<CBaseClient*>	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