dhewm3/neo/framework/async/AsyncServer.h
dhewg 736ec20d4d Untangle the epic precompiled.h mess
Don't include the lazy precompiled.h everywhere, only what's
required for the compilation unit.
platform.h needs to be included instead to provide all essential
defines and types.
All includes use the relative path to the neo or the game
specific root.
Move all idlib related includes from idlib/Lib.h to precompiled.h.
precompiled.h still exists for the MFC stuff in tools/.
Add some missing header guards.
2011-12-19 23:21:47 +01:00

261 lines
10 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __ASYNCSERVER_H__
#define __ASYNCSERVER_H__
#include "framework/UsercmdGen.h"
/*
===============================================================================
Network Server for asynchronous networking.
===============================================================================
*/
// MAX_CHALLENGES is made large to prevent a denial of service attack that could cycle
// all of them out before legitimate users connected
const int MAX_CHALLENGES = 1024;
// if we don't hear from authorize server, assume it is down
const int AUTHORIZE_TIMEOUT = 5000;
// states for the server's authorization process
typedef enum {
CDK_WAIT = 0, // we are waiting for a confirm/deny from auth
// this is subject to timeout if we don't hear from auth
// or a permanent wait if auth said so
CDK_OK,
CDK_ONLYLAN,
CDK_PUREWAIT,
CDK_PUREOK,
CDK_MAXSTATES
} authState_t;
// states from the auth server, while the client is in CDK_WAIT
typedef enum {
AUTH_NONE = 0, // no reply yet
AUTH_OK, // this client is good
AUTH_WAIT, // wait - keep sending me srvAuth though
AUTH_DENY, // denied - don't send me anything about this client anymore
AUTH_MAXSTATES
} authReply_t;
// message from auth to be forwarded back to the client
// some are locally hardcoded to save space, auth has the possibility to send a custom reply
typedef enum {
AUTH_REPLY_WAITING = 0, // waiting on an initial reply from auth
AUTH_REPLY_UNKNOWN, // client unknown to auth
AUTH_REPLY_DENIED, // access denied
AUTH_REPLY_PRINT, // custom message
AUTH_REPLY_SRVWAIT, // auth server replied and tells us he's working on it
AUTH_REPLY_MAXSTATES
} authReplyMsg_t;
typedef struct challenge_s {
netadr_t address; // client address
int clientId; // client identification
int challenge; // challenge code
int time; // time the challenge was created
int pingTime; // time the challenge response was sent to client
bool connected; // true if the client is connected
authState_t authState; // local state regarding the client
authReply_t authReply; // cd key check replies
authReplyMsg_t authReplyMsg; // default auth messages
idStr authReplyPrint; // custom msg
char guid[12]; // guid
int OS;
} challenge_t;
typedef enum {
SCS_FREE, // can be reused for a new connection
SCS_ZOMBIE, // client has been disconnected, but don't reuse connection for a couple seconds
SCS_PUREWAIT, // client needs to update it's pure checksums before we can go further
SCS_CONNECTED, // client is connected
SCS_INGAME // client is in the game
} serverClientState_t;
typedef struct serverClient_s {
int OS;
int clientId;
serverClientState_t clientState;
int clientPrediction;
int clientAheadTime;
int clientRate;
int clientPing;
int gameInitSequence;
int gameFrame;
int gameTime;
idMsgChannel channel;
int lastConnectTime;
int lastEmptyTime;
int lastPingTime;
int lastSnapshotTime;
int lastPacketTime;
int lastInputTime;
int snapshotSequence;
int acknowledgeSnapshotSequence;
int numDuplicatedUsercmds;
char guid[12]; // Even Balance - M. Quinn
} serverClient_t;
class idAsyncServer {
public:
idAsyncServer();
bool InitPort( void );
void ClosePort( void );
void Spawn( void );
void Kill( void );
void ExecuteMapChange( void );
int GetPort( void ) const;
netadr_t GetBoundAdr( void ) const;
bool IsActive( void ) const { return active; }
int GetDelay( void ) const { return gameTimeResidual; }
int GetOutgoingRate( void ) const;
int GetIncomingRate( void ) const;
bool IsClientInGame( int clientNum ) const;
int GetClientPing( int clientNum ) const;
int GetClientPrediction( int clientNum ) const;
int GetClientTimeSinceLastPacket( int clientNum ) const;
int GetClientTimeSinceLastInput( int clientNum ) const;
int GetClientOutgoingRate( int clientNum ) const;
int GetClientIncomingRate( int clientNum ) const;
float GetClientOutgoingCompression( int clientNum ) const;
float GetClientIncomingCompression( int clientNum ) const;
float GetClientIncomingPacketLoss( int clientNum ) const;
int GetNumClients( void ) const;
int GetNumIdleClients( void ) const;
int GetLocalClientNum( void ) const { return localClientNum; }
void RunFrame( void );
void ProcessConnectionLessMessages( void );
void RemoteConsoleOutput( const char *string );
void SendReliableGameMessage( int clientNum, const idBitMsg &msg );
void SendReliableGameMessageExcluding( int clientNum, const idBitMsg &msg );
void LocalClientSendReliableMessage( const idBitMsg &msg );
void MasterHeartbeat( bool force = false );
void DropClient( int clientNum, const char *reason );
void PacifierUpdate( void );
void UpdateUI( int clientNum );
void UpdateAsyncStatsAvg( void );
void GetAsyncStatsAvgMsg( idStr &msg );
void PrintLocalServerInfo( void );
private:
bool active; // true if server is active
int realTime; // absolute time
int serverTime; // local server time
idPort serverPort; // UDP port
int serverId; // server identification
int serverDataChecksum; // checksum of the data used by the server
int localClientNum; // local client on listen server
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
serverClient_t clients[MAX_ASYNC_CLIENTS]; // clients
usercmd_t userCmds[MAX_USERCMD_BACKUP][MAX_ASYNC_CLIENTS];
int gameInitId; // game initialization identification
int gameFrame; // local game frame
int gameTime; // local game time
int gameTimeResidual; // left over time from previous frame
netadr_t rconAddress;
int nextHeartbeatTime;
int nextAsyncStatsTime;
bool serverReloadingEngine; // flip-flop to not loop over when net_serverReloadEngine is on
bool noRconOutput; // for default rcon response when command is silent
int lastAuthTime; // global for auth server timeout
// track the max outgoing rate over the last few secs to watch for spikes
// dependent on net_serverSnapshotDelay. 50ms, for a 3 seconds backlog -> 60 samples
static const int stats_numsamples = 60;
int stats_outrate[ stats_numsamples ];
int stats_current;
int stats_average_sum;
int stats_max;
int stats_max_index;
void PrintOOB( const netadr_t to, int opcode, const char *string );
void DuplicateUsercmds( int frame, int time );
void ClearClient( int clientNum );
void InitClient( int clientNum, int clientId, int clientRate );
void InitLocalClient( int clientNum );
void BeginLocalClient( void );
void LocalClientInput( void );
void CheckClientTimeouts( void );
void SendPrintBroadcast( const char *string );
void SendPrintToClient( int clientNum, const char *string );
void SendUserInfoBroadcast( int userInfoNum, const idDict &info, bool sendToAll = false );
void SendUserInfoToClient( int clientNum, int userInfoNum, const idDict &info );
void SendSyncedCvarsBroadcast( const idDict &cvars );
void SendSyncedCvarsToClient( int clientNum, const idDict &cvars );
void SendApplySnapshotToClient( int clientNum, int sequence );
bool SendEmptyToClient( int clientNum, bool force = false );
bool SendPingToClient( int clientNum );
void SendGameInitToClient( int clientNum );
bool SendSnapshotToClient( int clientNum );
void ProcessUnreliableClientMessage( int clientNum, const idBitMsg &msg );
void ProcessReliableClientMessages( int clientNum );
void ProcessChallengeMessage( const netadr_t from, const idBitMsg &msg );
void ProcessConnectMessage( const netadr_t from, const idBitMsg &msg );
void ProcessRemoteConsoleMessage( const netadr_t from, const idBitMsg &msg );
void ProcessGetInfoMessage( const netadr_t from, const idBitMsg &msg );
bool ConnectionlessMessage( const netadr_t from, const idBitMsg &msg );
bool ProcessMessage( const netadr_t from, idBitMsg &msg );
void ProcessAuthMessage( const idBitMsg &msg );
bool SendPureServerMessage( const netadr_t to, int OS ); // returns false if no pure paks on the list
void ProcessPureMessage( const netadr_t from, const idBitMsg &msg );
int ValidateChallenge( const netadr_t from, int challenge, int clientId ); // returns -1 if validate failed
bool SendReliablePureToClient( int clientNum );
void ProcessReliablePure( int clientNum, const idBitMsg &msg );
bool VerifyChecksumMessage( int clientNum, const netadr_t *from, const idBitMsg &msg, idStr &reply, int OS ); // if from is NULL, clientNum is used for error messages
void SendReliableMessage( int clientNum, const idBitMsg &msg ); // checks for overflow and disconnects the faulty client
int UpdateTime( int clamp );
void SendEnterGameToClient( int clientNum );
void ProcessDownloadRequestMessage( const netadr_t from, const idBitMsg &msg );
};
#endif /* !__ASYNCSERVER_H__ */