summaryrefslogtreecommitdiff
path: root/src/server/server.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/server.h')
-rw-r--r--src/server/server.h529
1 files changed, 529 insertions, 0 deletions
diff --git a/src/server/server.h b/src/server/server.h
new file mode 100644
index 0000000..a07b66c
--- /dev/null
+++ b/src/server/server.h
@@ -0,0 +1,529 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2000-2013 Darklegion Development
+Copyright (C) 2012-2018 ET:Legacy team <mail@etlegacy.com>
+Copyright (C) 2015-2019 GrangerHub
+
+This file is part of Tremulous.
+
+Tremulous 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.
+
+Tremulous 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 Tremulous; if not, see <https://www.gnu.org/licenses/>
+
+===========================================================================
+*/
+// server.h
+
+#ifndef SERVER_H
+#define SERVER_H 1
+
+#include "game/g_public.h"
+#include "qcommon/cmd.h"
+#include "qcommon/crypto.h"
+#include "qcommon/cvar.h"
+#include "qcommon/files.h"
+#include "qcommon/huffman.h"
+#include "qcommon/msg.h"
+#include "qcommon/net.h"
+#include "qcommon/q_shared.h"
+#include "qcommon/qcommon.h"
+#include "qcommon/vm.h"
+#include "sys/sys_shared.h"
+
+//=============================================================================
+
+#define PERS_SCORE 0 // !!! MUST NOT CHANGE, SERVER AND GAME BOTH REFERENCE !!!
+#define CS_WARMUP 5 // !!! MUST NOT CHANGE, SERVER AND GAME BOTH REFERENCE !!!
+
+// server attack protection
+#define SVP_IOQ3 0x0001 ///< 1 - ioQuake3 way
+#define SVP_OWOLF 0x0002 ///< 2 - OpenWolf way
+#define SVP_CONSOLE 0x0004 ///< 4 - console print
+
+#define MAX_ENT_CLUSTERS 16
+
+#ifdef USE_VOIP
+#define VOIP_QUEUE_LENGTH 64
+struct voipServerPacket_t {
+ int generation;
+ int sequence;
+ int frames;
+ int len;
+ int sender;
+ int flags;
+ byte data[4000];
+};
+#endif // USE_VOIP
+
+struct svEntity_t {
+ struct worldSector_t *worldSector;
+ svEntity_t *nextEntityInWorldSector;
+
+ entityState_t baseline; // for delta compression of initial sighting
+ int numClusters; // if -1, use headnode instead
+ int clusternums[MAX_ENT_CLUSTERS];
+ int lastCluster; // if all the clusters don't fit in clusternums
+ int areanum, areanum2;
+ int snapshotCounter; // used to prevent double adding from portal views
+};
+
+enum serverState_t {
+ SS_DEAD, // no map loaded
+ SS_LOADING, // spawning level entities
+ SS_GAME // actively running
+};
+
+struct configString_t {
+ char *s;
+ bool restricted; // if true, don't send to clientList
+ clientList_t clientList;
+};
+
+struct server_t {
+ serverState_t state;
+ bool restarting; // if true, send configstring changes during SS_LOADING
+ int serverId; // changes each server start
+ int restartedServerId; // serverId before a map_restart
+ int checksumFeed; // the feed key that we use to compute the pure checksum strings
+ // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475
+ // the serverId associated with the current checksumFeed (always <= serverId)
+ int checksumFeedServerId;
+ int snapshotCounter; // incremented for each snapshot built
+ int timeResidual; // <= 1000 / sv_frame->value
+ int nextFrameTime; // when time > nextFrameTime, process world
+ configString_t configstrings[MAX_CONFIGSTRINGS];
+ svEntity_t svEntities[MAX_GENTITIES];
+
+ char *entityParsePoint; // used during game VM init
+
+ // the game virtual machine will update these on init and changes
+ sharedEntity_t *gentities;
+ int gentitySize;
+ int num_entities; // current number, <= MAX_GENTITIES
+
+ playerState_t *gameClients;
+ int gameClientSize; // will be > sizeof(playerState_t) due to game private data
+
+ int restartTime;
+ int time;
+
+ vm_t *gvm; // game virtual machine
+};
+
+struct clientSnapshot_t {
+ int areabytes;
+ byte areabits[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
+ playerState_t ps;
+ int num_entities;
+ int first_entity; // into the circular sv_packet_entities[]
+ // the entities MUST be in increasing state number
+ // order, otherwise the delta compression will fail
+ int messageSent; // time the message was transmitted
+ int messageAcked; // time the message was acked
+ int messageSize; // used to rate drop packets
+};
+
+enum clientState_t {
+ CS_FREE, // can be reused for a new connection
+ CS_ZOMBIE, // client has been disconnected, but don't reuse
+ // connection for a couple seconds
+ CS_CONNECTED, // has been assigned to a client_t, but no gamestate yet
+ CS_PRIMED, // gamestate has been sent, but client hasn't sent a usercmd
+ CS_ACTIVE // client is fully in game
+};
+
+struct netchan_buffer_t {
+ msg_t msg;
+ byte msgBuffer[MAX_MSGLEN];
+ netchan_buffer_t *next;
+};
+
+struct client_t {
+ clientState_t state;
+ char userinfo[MAX_INFO_STRING]; // name, etc
+ char userinfobuffer[MAX_INFO_STRING]; ///< used for buffering of user info
+
+ char reliableCommands[MAX_RELIABLE_COMMANDS][MAX_STRING_CHARS];
+ int reliableSequence; // last added reliable message, not necesarily sent or acknowledged yet
+ int reliableAcknowledge; // last acknowledged reliable message
+ int reliableSent; // last sent reliable message, not necesarily acknowledged yet
+ int messageAcknowledge;
+
+ int gamestateMessageNum; // netchan->outgoingSequence of gamestate
+ int challenge;
+
+ usercmd_t lastUsercmd;
+ int lastMessageNum; // for delta compression
+ int lastClientCommand; // reliable client message sequence
+ char lastClientCommandString[MAX_STRING_CHARS];
+ sharedEntity_t *gentity; // SV_GentityNum(clientnum)
+ char name[MAX_NAME_LENGTH]; // extracted from userinfo, high bits masked
+
+ // downloading
+ char downloadName[MAX_QPATH]; // if not empty string, we are downloading
+ fileHandle_t download; // file being downloaded
+ int downloadSize; // total bytes (can't use EOF because of paks)
+ int downloadCount; // bytes sent
+ int downloadClientBlock; // last block we sent to the client, awaiting ack
+ int downloadCurrentBlock; // current block number
+ int downloadXmitBlock; // last block we xmited
+ unsigned char *downloadBlocks[MAX_DOWNLOAD_WINDOW]; // the buffers for the download blocks
+ int downloadBlockSize[MAX_DOWNLOAD_WINDOW];
+ bool downloadEOF; // We have sent the EOF block
+ int downloadSendTime; // time we last got an ack from the client
+
+ int deltaMessage; // frame last client usercmd message
+ int nextReliableTime; // svs.time when another reliable command will be allowed
+ int nextReliableUserTime; // svs.time when another userinfo change will be allowed
+ int lastPacketTime; // svs.time when packet was last received
+ int lastConnectTime; // svs.time when connection started
+ int lastSnapshotTime; // svs.time of last sent snapshot
+ bool rateDelayed; // true if nextSnapshotTime was set based on rate instead of snapshotMsec
+ int timeoutCount; // must timeout a few frames in a row so debugging doesn't break
+ clientSnapshot_t frames[PACKET_BACKUP]; // updates can be delta'd from here
+ int ping;
+ int rate; // bytes / second
+ int snapshotMsec; // requests a snapshot every snapshotMsec unless rate choked
+ int pureAuthentic;
+ bool gotCP; // TTimo - additional flag to distinguish between a bad pure checksum, and no cp command at all
+ netchan_t netchan;
+ // TTimo
+ // queuing outgoing fragmented messages to send them properly, without udp packet bursts
+ // in case large fragmented messages are stacking up
+ // buffer them into this queue, and hand them out to netchan as needed
+ netchan_buffer_t *netchan_start_queue;
+ netchan_buffer_t **netchan_end_queue;
+
+ char fingerprint[SHA256_DIGEST_SIZE * 2 + 1];
+
+#ifdef USE_VOIP
+ bool hasVoip;
+ bool muteAllVoip;
+ bool ignoreVoipFromClient[MAX_CLIENTS];
+ voipServerPacket_t *voipPacket[VOIP_QUEUE_LENGTH];
+ size_t queuedVoipPackets;
+ int queuedVoipIndex;
+#endif
+
+ int oldServerTime;
+ bool csUpdated[MAX_CONFIGSTRINGS];
+};
+
+//=============================================================================
+#define STATFRAMES 200 ///< 5 seconds - assumed we run 40 fps
+
+/**
+ * @struct svstats_t
+ * @brief
+ */
+struct svstats_t {
+ double active;
+ double idle;
+ int count;
+
+ double latched_active;
+ double latched_idle;
+
+ float cpu;
+ float avg;
+};
+
+// MAX_CHALLENGES is made large to prevent a denial
+// of service attack that could cycle all of them
+// out before legitimate users connected
+#define MAX_CHALLENGES 2048
+// Allow a certain amount of challenges to have the same IP address
+// to make it a bit harder to DOS one single IP address from connecting
+// while not allowing a single ip to grab all challenge resources
+#define MAX_CHALLENGES_MULTI (MAX_CHALLENGES / 2)
+
+#define AUTHORIZE_TIMEOUT 5000
+
+struct challenge_t {
+ netadr_t adr;
+ int challenge;
+ char challenge2[33];
+ int clientChallenge; // challenge number coming from the client
+ int time; // time the last packet was sent to the autherize server
+ int pingTime; // time the challenge response was sent to client
+ int firstTime; // time the adr was first used, for authorize timeout checks
+ bool wasrefused;
+ bool connected;
+};
+
+/**
+ * @struct receipt_t
+ * @brief
+ */
+struct receipt_t {
+ netadr_t adr;
+ int time;
+};
+
+/**
+ * @def MAX_INFO_RECEIPTS
+ * @brief the maximum number of getstatus+getinfo responses that we send in
+ * a two second time period.
+ */
+#define MAX_INFO_RECEIPTS 48
+
+/**
+ * @struct tempBan_s
+ * @typedef tempBan_t
+ * @brief
+ */
+struct tempBan_t {
+ netadr_t adr;
+ int endtime;
+};
+
+#define MAX_TEMPBAN_ADDRESSES MAX_CLIENTS
+
+#define SERVER_PERFORMANCECOUNTER_FRAMES 600
+#define SERVER_PERFORMANCECOUNTER_SAMPLES 6
+
+// this structure will be cleared only when the game dll changes
+struct serverStatic_t {
+ bool initialized; // sv_init has completed
+
+ int time; // will be strictly increasing across level changes
+
+ int snapFlagServerBit; // ^= SNAPFLAG_SERVERCOUNT every SV_SpawnServer()
+
+ client_t *clients; // [sv_maxclients->integer];
+ int numSnapshotEntities; // sv_maxclients->integer*PACKET_BACKUP*MAX_SNAPSHOT_ENTITIES
+ int nextSnapshotEntities; // next snapshotEntities to use
+ entityState_t *snapshotEntities; // [numSnapshotEntities]
+ int nextHeartbeatTime;
+ challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
+ receipt_t infoReceipts[MAX_INFO_RECEIPTS];
+ netadr_t redirectAddress; // for rcon return messages
+
+ netadr_t authorizeAddress; // for rcon return messages
+
+ int sampleTimes[SERVER_PERFORMANCECOUNTER_SAMPLES];
+ int currentSampleIndex;
+ int totalFrameTime;
+ int currentFrameIndex;
+ int serverLoad;
+ svstats_t stats;
+};
+
+//=============================================================================
+
+extern serverStatic_t svs; // persistant server info across maps
+extern server_t sv; // cleared each map
+
+extern cvar_t *sv_fps;
+extern cvar_t *sv_timeout;
+extern cvar_t *sv_zombietime;
+extern cvar_t *sv_rconPassword;
+extern cvar_t *sv_privatePassword;
+extern cvar_t *sv_allowDownload;
+extern cvar_t *sv_maxclients;
+
+extern cvar_t *sv_privateClients;
+extern cvar_t *sv_hostname;
+extern cvar_t *sv_masters[3][MAX_MASTER_SERVERS];
+extern cvar_t *sv_reconnectlimit;
+extern cvar_t *sv_showloss;
+extern cvar_t *sv_padPackets;
+extern cvar_t *sv_killserver;
+extern cvar_t *sv_mapname;
+extern cvar_t *sv_mapChecksum;
+extern cvar_t *sv_serverid;
+extern cvar_t *sv_minRate;
+extern cvar_t *sv_maxRate;
+extern cvar_t *sv_dlRate;
+extern cvar_t *sv_minPing;
+extern cvar_t *sv_maxPing;
+extern cvar_t *sv_pure;
+extern cvar_t *sv_lanForceRate;
+extern cvar_t *sv_banFile;
+
+extern cvar_t *sv_protect;
+extern cvar_t *sv_protectLog;
+
+#ifdef USE_VOIP
+extern cvar_t *sv_voip;
+extern cvar_t *sv_voipProtocol;
+#endif
+
+extern cvar_t *sv_rsaAuth;
+
+extern cvar_t *sv_schachtmeisterPort;
+
+//===========================================================
+
+//
+// sv_main.c
+//
+struct leakyBucket_t {
+ netadrtype_t type;
+
+ union {
+ byte _4[4];
+ byte _6[16];
+ } ipv;
+
+ int lastTime;
+ signed char burst;
+
+ long hash;
+
+ leakyBucket_t *prev, *next;
+};
+
+extern leakyBucket_t outboundLeakyBucket;
+
+bool SVC_RateLimit(leakyBucket_t *bucket, int burst, int period);
+bool SVC_RateLimitAddress(netadr_t from, int burst, int period);
+
+void SV_FinalMessage(const char *message);
+void QDECL SV_SendServerCommand(client_t *cl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+
+void SV_AddOperatorCommands(void);
+void SV_RemoveOperatorCommands(void);
+
+void SV_MasterShutdown(void);
+int SV_RateMsec(client_t *client);
+
+//
+// sv_init.c
+//
+void SV_SetConfigstring(int index, const char *val);
+void SV_GetConfigstring(int index, char *buffer, int bufferSize);
+void SV_SetConfigstringRestrictions(int index, const clientList_t *clientList);
+void SV_UpdateConfigstrings(client_t *client);
+
+void SV_SetUserinfo(int index, const char *val);
+void SV_GetUserinfo(int index, char *buffer, int bufferSize);
+
+void SV_ChangeMaxClients(void);
+void SV_SpawnServer(char *server);
+void SV_WriteAttackLog(const char *log);
+
+#ifdef NDEBUG
+#define SV_WriteAttackLogD(x)
+#else
+#define SV_WriteAttackLogD(x) SV_WriteAttackLog(x)
+#endif
+
+//
+// sv_client.c
+//
+void SV_GetChallenge(netadr_t from);
+
+void SV_DirectConnect(netadr_t from);
+
+void SV_ExecuteClientMessage(client_t *cl, msg_t *msg);
+void SV_UserinfoChanged(client_t *cl);
+
+void SV_ClientEnterWorld(client_t *client, usercmd_t *cmd);
+void SV_FreeClient(client_t *client);
+void SV_DropClient(client_t *drop, const char *reason);
+
+void SV_ExecuteClientCommand(client_t *cl, const char *s, bool clientOK);
+void SV_ClientThink(client_t *cl, usercmd_t *cmd);
+
+int SV_WriteDownloadToClient(client_t *cl, msg_t *msg);
+int SV_SendDownloadMessages(void);
+int SV_SendQueuedMessages(void);
+
+//
+// sv_ccmds.c
+//
+void SV_Heartbeat_f(void);
+
+//
+// sv_snapshot.c
+//
+void SV_AddServerCommand(client_t *client, const char *cmd);
+void SV_UpdateServerCommandsToClient(client_t *client, msg_t *msg);
+void SV_WriteFrameToClient(client_t *client, msg_t *msg);
+void SV_SendMessageToClient(msg_t *msg, client_t *client);
+void SV_SendClientMessages(void);
+void SV_SendClientSnapshot(client_t *client);
+
+//
+// sv_game.c
+//
+int SV_NumForGentity(sharedEntity_t *ent);
+sharedEntity_t *SV_GentityNum(int num);
+playerState_t *SV_GameClientNum(int num);
+svEntity_t *SV_SvEntityForGentity(sharedEntity_t *gEnt);
+sharedEntity_t *SV_GEntityForSvEntity(svEntity_t *svEnt);
+void SV_InitGameProgs(void);
+void SV_ShutdownGameProgs(void);
+void SV_RestartGameProgs(void);
+bool SV_inPVS(const vec3_t p1, const vec3_t p2);
+
+//============================================================
+//
+// high level object sorting to reduce interaction tests
+//
+
+void SV_ClearWorld(void);
+// called after the world model has been loaded, before linking any entities
+
+void SV_UnlinkEntity(sharedEntity_t *ent);
+// call before removing an entity, and before trying to move one,
+// so it doesn't clip against itself
+
+void SV_LinkEntity(sharedEntity_t *ent);
+// Needs to be called any time an entity changes origin, mins, maxs,
+// or solid. Automatically unlinks if needed.
+// sets ent->r.absmin and ent->r.absmax
+// sets ent->leafnums[] for pvs determination even if the entity
+// is not solid
+
+clipHandle_t SV_ClipHandleForEntity(const sharedEntity_t *ent);
+
+void SV_SectorList_f(void);
+
+int SV_AreaEntities(const vec3_t mins, const vec3_t maxs, int *entityList, int maxcount);
+// fills in a table of entity numbers with entities that have bounding boxes
+// that intersect the given area. It is possible for a non-axial bmodel
+// to be returned that doesn't actually intersect the area on an exact
+// test.
+// returns the number of pointers filled in
+// The world entity is never returned in this list.
+
+int SV_PointContents(const vec3_t p, int passEntityNum);
+// returns the CONTENTS_* value from the world and all entities at the given point.
+
+void SV_Trace(trace_t *results, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int passEntityNum,
+ int contentmask, traceType_t type);
+// mins and maxs are relative
+
+// if the entire move stays in a solid volume, trace.allsolid will be set,
+// trace.startsolid will be set, and trace.fraction will be 0
+
+// if the starting point is in a solid, it will be allowed to move out
+// to an open area
+
+// passEntityNum is explicitly excluded from clipping checks (normally ENTITYNUM_NONE)
+
+void SV_ClipToEntity(trace_t *trace, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end,
+ int entityNum, int contentmask, traceType_t type);
+// clip to a specific entity
+
+//
+// sv_net_chan.c
+//
+void SV_Netchan_Transmit(client_t *client, msg_t *msg);
+int SV_Netchan_TransmitNextFragment(client_t *client);
+bool SV_Netchan_Process(client_t *client, msg_t *msg);
+void SV_Netchan_FreeQueue(client_t *client);
+
+#endif