1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_SERVER_SERVER_H
4#define ENGINE_SERVER_SERVER_H
5
6#include <base/hash.h>
7
8#include <engine/console.h>
9#include <engine/server.h>
10
11#include <engine/shared/demo.h>
12#include <engine/shared/econ.h>
13#include <engine/shared/fifo.h>
14#include <engine/shared/http.h>
15#include <engine/shared/netban.h>
16#include <engine/shared/network.h>
17#include <engine/shared/protocol.h>
18#include <engine/shared/snapshot.h>
19#include <engine/shared/uuid_manager.h>
20
21#include <list>
22#include <memory>
23#include <optional>
24#include <vector>
25
26#include "antibot.h"
27#include "authmanager.h"
28#include "name_ban.h"
29#include "snap_id_pool.h"
30
31#if defined(CONF_UPNP)
32#include "upnp.h"
33#endif
34
35class CConfig;
36class CHostLookup;
37class CLogMessage;
38class CMsgPacker;
39class CPacker;
40class IEngine;
41class IEngineMap;
42class ILogger;
43
44class CServerBan : public CNetBan
45{
46 class CServer *m_pServer;
47
48 template<class T>
49 int BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason);
50
51public:
52 class CServer *Server() const { return m_pServer; }
53
54 void InitServerBan(class IConsole *pConsole, class IStorage *pStorage, class CServer *pServer);
55
56 int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason) override;
57 int BanRange(const CNetRange *pRange, int Seconds, const char *pReason) override;
58
59 static void ConBanExt(class IConsole::IResult *pResult, void *pUser);
60 static void ConBanRegion(class IConsole::IResult *pResult, void *pUser);
61 static void ConBanRegionRange(class IConsole::IResult *pResult, void *pUser);
62};
63
64class CServer : public IServer
65{
66 friend class CServerLogger;
67
68 class IGameServer *m_pGameServer;
69 class CConfig *m_pConfig;
70 class IConsole *m_pConsole;
71 class IStorage *m_pStorage;
72 class IEngineAntibot *m_pAntibot;
73 class IRegister *m_pRegister;
74 IEngine *m_pEngine;
75
76#if defined(CONF_UPNP)
77 CUPnP m_UPnP;
78#endif
79
80#if defined(CONF_FAMILY_UNIX)
81 UNIXSOCKETADDR m_ConnLoggingDestAddr;
82 bool m_ConnLoggingSocketCreated;
83 UNIXSOCKET m_ConnLoggingSocket;
84#endif
85
86 class CDbConnectionPool *m_pConnectionPool;
87
88#ifdef CONF_DEBUG
89 int m_PreviousDebugDummies = 0;
90 void UpdateDebugDummies(bool ForceDisconnect);
91#endif
92
93public:
94 class IGameServer *GameServer() { return m_pGameServer; }
95 class CConfig *Config() { return m_pConfig; }
96 const CConfig *Config() const { return m_pConfig; }
97 class IConsole *Console() { return m_pConsole; }
98 class IStorage *Storage() { return m_pStorage; }
99 class IEngineAntibot *Antibot() { return m_pAntibot; }
100 class CDbConnectionPool *DbPool() { return m_pConnectionPool; }
101 IEngine *Engine() { return m_pEngine; }
102
103 enum
104 {
105 MAX_RCONCMD_SEND = 16,
106 };
107
108 class CClient
109 {
110 public:
111 enum
112 {
113 STATE_EMPTY = 0,
114 STATE_PREAUTH,
115 STATE_AUTH,
116 STATE_CONNECTING,
117 STATE_READY,
118 STATE_INGAME,
119 STATE_REDIRECTED,
120
121 SNAPRATE_INIT = 0,
122 SNAPRATE_FULL,
123 SNAPRATE_RECOVER,
124
125 DNSBL_STATE_NONE = 0,
126 DNSBL_STATE_PENDING,
127 DNSBL_STATE_BLACKLISTED,
128 DNSBL_STATE_WHITELISTED,
129 };
130
131 class CInput
132 {
133 public:
134 int m_aData[MAX_INPUT_SIZE];
135 int m_GameTick; // the tick that was chosen for the input
136 };
137
138 // connection state info
139 int m_State;
140 int m_Latency;
141 int m_SnapRate;
142
143 double m_Traffic;
144 int64_t m_TrafficSince;
145
146 int m_LastAckedSnapshot;
147 int m_LastInputTick;
148 CSnapshotStorage m_Snapshots;
149
150 CInput m_LatestInput;
151 CInput m_aInputs[200]; // TODO: handle input better
152 int m_CurrentInput;
153
154 char m_aName[MAX_NAME_LENGTH];
155 char m_aClan[MAX_CLAN_LENGTH];
156 int m_Country;
157 std::optional<int> m_Score;
158 int m_Authed;
159 int m_AuthKey;
160 int m_AuthTries;
161 int m_NextMapChunk;
162 int m_Flags;
163 bool m_ShowIps;
164 bool m_DebugDummy;
165
166 const IConsole::CCommandInfo *m_pRconCmdToSend;
167
168 bool m_HasPersistentData;
169 void *m_pPersistentData;
170
171 void Reset();
172
173 // DDRace
174
175 NETADDR m_Addr;
176 bool m_GotDDNetVersionPacket;
177 bool m_DDNetVersionSettled;
178 int m_DDNetVersion;
179 char m_aDDNetVersionStr[64];
180 CUuid m_ConnectionId;
181 int64_t m_RedirectDropTime;
182
183 // DNSBL
184 int m_DnsblState;
185 std::shared_ptr<CHostLookup> m_pDnsblLookup;
186
187 bool m_Sixup;
188
189 bool IncludedInServerInfo() const
190 {
191 return m_State != STATE_EMPTY && !m_DebugDummy;
192 }
193 };
194
195 CClient m_aClients[MAX_CLIENTS];
196 int m_aIdMap[MAX_CLIENTS * VANILLA_MAX_CLIENTS];
197
198 CSnapshotDelta m_SnapshotDelta;
199 CSnapshotBuilder m_SnapshotBuilder;
200 CSnapIdPool m_IdPool;
201 CNetServer m_NetServer;
202 CEcon m_Econ;
203 CFifo m_Fifo;
204 CServerBan m_ServerBan;
205 CHttp m_Http;
206
207 IEngineMap *m_pMap;
208
209 int64_t m_GameStartTime;
210 //int m_CurrentGameTick;
211
212 enum
213 {
214 UNINITIALIZED = 0,
215 RUNNING = 1,
216 STOPPING = 2
217 };
218
219 int m_RunServer;
220
221 bool m_MapReload;
222 bool m_ReloadedWhenEmpty;
223 int m_RconClientId;
224 int m_RconAuthLevel;
225 int m_PrintCBIndex;
226 char m_aShutdownReason[128];
227 void *m_pPersistentData;
228
229 enum
230 {
231 MAP_TYPE_SIX = 0,
232 MAP_TYPE_SIXUP,
233 NUM_MAP_TYPES
234 };
235
236 enum
237 {
238 RECORDER_MANUAL = MAX_CLIENTS,
239 RECORDER_AUTO = MAX_CLIENTS + 1,
240 NUM_RECORDERS = MAX_CLIENTS + 2,
241 };
242
243 char m_aCurrentMap[IO_MAX_PATH_LENGTH];
244 SHA256_DIGEST m_aCurrentMapSha256[NUM_MAP_TYPES];
245 unsigned m_aCurrentMapCrc[NUM_MAP_TYPES];
246 unsigned char *m_apCurrentMapData[NUM_MAP_TYPES];
247 unsigned int m_aCurrentMapSize[NUM_MAP_TYPES];
248
249 CDemoRecorder m_aDemoRecorder[NUM_RECORDERS];
250 CAuthManager m_AuthManager;
251
252 int64_t m_ServerInfoFirstRequest;
253 int m_ServerInfoNumRequests;
254
255 char m_aErrorShutdownReason[128];
256
257 CNameBans m_NameBans;
258
259 size_t m_AnnouncementLastLine;
260 std::vector<std::string> m_vAnnouncements;
261 char m_aAnnouncementFile[IO_MAX_PATH_LENGTH];
262
263 std::shared_ptr<ILogger> m_pFileLogger = nullptr;
264 std::shared_ptr<ILogger> m_pStdoutLogger = nullptr;
265
266 CServer();
267 ~CServer();
268
269 bool IsClientNameAvailable(int ClientId, const char *pNameRequest);
270 bool SetClientNameImpl(int ClientId, const char *pNameRequest, bool Set);
271 bool SetClientClanImpl(int ClientId, const char *pClanRequest, bool Set);
272
273 bool WouldClientNameChange(int ClientId, const char *pNameRequest) override;
274 bool WouldClientClanChange(int ClientId, const char *pClanRequest) override;
275 void SetClientName(int ClientId, const char *pName) override;
276 void SetClientClan(int ClientId, const char *pClan) override;
277 void SetClientCountry(int ClientId, int Country) override;
278 void SetClientScore(int ClientId, std::optional<int> Score) override;
279 void SetClientFlags(int ClientId, int Flags) override;
280
281 void Kick(int ClientId, const char *pReason) override;
282 void Ban(int ClientId, int Seconds, const char *pReason) override;
283 void RedirectClient(int ClientId, int Port, bool Verbose = false) override;
284
285 void DemoRecorder_HandleAutoStart() override;
286
287 //int Tick()
288 int64_t TickStartTime(int Tick);
289 //int TickSpeed()
290
291 int Init();
292
293 void SendLogLine(const CLogMessage *pMessage);
294 void SetRconCid(int ClientId) override;
295 int GetAuthedState(int ClientId) const override;
296 const char *GetAuthName(int ClientId) const override;
297 void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, SHA256_DIGEST *pMapSha256, int *pMapCrc) override;
298 bool GetClientInfo(int ClientId, CClientInfo *pInfo) const override;
299 void SetClientDDNetVersion(int ClientId, int DDNetVersion) override;
300 void GetClientAddr(int ClientId, char *pAddrStr, int Size) const override;
301 const char *ClientName(int ClientId) const override;
302 const char *ClientClan(int ClientId) const override;
303 int ClientCountry(int ClientId) const override;
304 bool ClientSlotEmpty(int ClientId) const override;
305 bool ClientIngame(int ClientId) const override;
306 bool ClientAuthed(int ClientId) const override;
307 int Port() const override;
308 int MaxClients() const override;
309 int ClientCount() const override;
310 int DistinctClientCount() const override;
311
312 int GetClientVersion(int ClientId) const override;
313 int SendMsg(CMsgPacker *pMsg, int Flags, int ClientId) override;
314
315 void DoSnapshot();
316
317 static int NewClientCallback(int ClientId, void *pUser, bool Sixup);
318 static int NewClientNoAuthCallback(int ClientId, void *pUser);
319 static int DelClientCallback(int ClientId, const char *pReason, void *pUser);
320
321 static int ClientRejoinCallback(int ClientId, void *pUser);
322
323 void SendRconType(int ClientId, bool UsernameReq);
324 void SendCapabilities(int ClientId);
325 void SendMap(int ClientId);
326 void SendMapData(int ClientId, int Chunk);
327 void SendConnectionReady(int ClientId);
328 void SendRconLine(int ClientId, const char *pLine);
329 // Accepts -1 as ClientId to mean "all clients with at least auth level admin"
330 void SendRconLogLine(int ClientId, const CLogMessage *pMessage);
331
332 void SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientId);
333 void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientId);
334 int GetConsoleAccessLevel(int ClientId);
335 int NumRconCommands(int ClientId);
336 void UpdateClientRconCommands();
337
338 bool CheckReservedSlotAuth(int ClientId, const char *pPassword);
339 void ProcessClientPacket(CNetChunk *pPacket);
340
341 class CCache
342 {
343 public:
344 class CCacheChunk
345 {
346 public:
347 CCacheChunk(const void *pData, int Size);
348 CCacheChunk(const CCacheChunk &) = delete;
349 CCacheChunk(CCacheChunk &&) = default;
350
351 std::vector<uint8_t> m_vData;
352 };
353
354 std::vector<CCacheChunk> m_vCache;
355
356 CCache();
357 ~CCache();
358
359 void AddChunk(const void *pData, int Size);
360 void Clear();
361 };
362 CCache m_aServerInfoCache[3 * 2];
363 CCache m_aSixupServerInfoCache[2];
364 bool m_ServerInfoNeedsUpdate;
365
366 void FillAntibot(CAntibotRoundData *pData) override;
367
368 void ExpireServerInfo() override;
369 void CacheServerInfo(CCache *pCache, int Type, bool SendClients);
370 void CacheServerInfoSixup(CCache *pCache, bool SendClients);
371 void SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients);
372 void GetServerInfoSixup(CPacker *pPacker, int Token, bool SendClients);
373 bool RateLimitServerInfoConnless();
374 void SendServerInfoConnless(const NETADDR *pAddr, int Token, int Type);
375 void UpdateRegisterServerInfo();
376 void UpdateServerInfo(bool Resend = false);
377
378 void PumpNetwork(bool PacketWaiting);
379
380 void ChangeMap(const char *pMap) override;
381 const char *GetMapName() const override;
382 int LoadMap(const char *pMapName);
383
384 void SaveDemo(int ClientId, float Time) override;
385 void StartRecord(int ClientId) override;
386 void StopRecord(int ClientId) override;
387 bool IsRecording(int ClientId) override;
388 void StopDemos() override;
389
390 int Run();
391
392 static void ConKick(IConsole::IResult *pResult, void *pUser);
393 static void ConStatus(IConsole::IResult *pResult, void *pUser);
394 static void ConShutdown(IConsole::IResult *pResult, void *pUser);
395 static void ConRecord(IConsole::IResult *pResult, void *pUser);
396 static void ConStopRecord(IConsole::IResult *pResult, void *pUser);
397 static void ConMapReload(IConsole::IResult *pResult, void *pUser);
398 static void ConLogout(IConsole::IResult *pResult, void *pUser);
399 static void ConShowIps(IConsole::IResult *pResult, void *pUser);
400
401 static void ConAuthAdd(IConsole::IResult *pResult, void *pUser);
402 static void ConAuthAddHashed(IConsole::IResult *pResult, void *pUser);
403 static void ConAuthUpdate(IConsole::IResult *pResult, void *pUser);
404 static void ConAuthUpdateHashed(IConsole::IResult *pResult, void *pUser);
405 static void ConAuthRemove(IConsole::IResult *pResult, void *pUser);
406 static void ConAuthList(IConsole::IResult *pResult, void *pUser);
407
408 // console commands for sqlmasters
409 static void ConAddSqlServer(IConsole::IResult *pResult, void *pUserData);
410 static void ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData);
411
412 static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
413 static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
414 static void ConchainCommandAccessUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
415
416 void LogoutClient(int ClientId, const char *pReason);
417 void LogoutKey(int Key, const char *pReason);
418
419 void ConchainRconPasswordChangeGeneric(int Level, const char *pCurrent, IConsole::IResult *pResult);
420 static void ConchainRconPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
421 static void ConchainRconModPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
422 static void ConchainRconHelperPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
423 static void ConchainMapUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
424 static void ConchainSixupUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
425 static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
426 static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
427
428#if defined(CONF_FAMILY_UNIX)
429 static void ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
430#endif
431
432 void RegisterCommands();
433
434 int SnapNewId() override;
435 void SnapFreeId(int Id) override;
436 void *SnapNewItem(int Type, int Id, int Size) override;
437 void SnapSetStaticsize(int ItemType, int Size) override;
438
439 // DDRace
440
441 void GetClientAddr(int ClientId, NETADDR *pAddr) const override;
442 int m_aPrevStates[MAX_CLIENTS];
443 const char *GetAnnouncementLine(const char *pFileName) override;
444
445 int *GetIdMap(int ClientId) override;
446
447 void InitDnsbl(int ClientId);
448 bool DnsblWhite(int ClientId) override
449 {
450 return m_aClients[ClientId].m_DnsblState == CClient::DNSBL_STATE_NONE ||
451 m_aClients[ClientId].m_DnsblState == CClient::DNSBL_STATE_WHITELISTED;
452 }
453 bool DnsblPending(int ClientId) override
454 {
455 return m_aClients[ClientId].m_DnsblState == CClient::DNSBL_STATE_PENDING;
456 }
457 bool DnsblBlack(int ClientId) override
458 {
459 return m_aClients[ClientId].m_DnsblState == CClient::DNSBL_STATE_BLACKLISTED;
460 }
461
462 void AuthRemoveKey(int KeySlot);
463 bool ClientPrevIngame(int ClientId) override { return m_aPrevStates[ClientId] == CClient::STATE_INGAME; }
464 const char *GetNetErrorString(int ClientId) override { return m_NetServer.ErrorString(ClientId); }
465 void ResetNetErrorString(int ClientId) override { m_NetServer.ResetErrorString(ClientId); }
466 bool SetTimedOut(int ClientId, int OrigId) override;
467 void SetTimeoutProtected(int ClientId) override { m_NetServer.SetTimeoutProtected(ClientId); }
468
469 void SendMsgRaw(int ClientId, const void *pData, int Size, int Flags) override;
470
471 bool ErrorShutdown() const { return m_aErrorShutdownReason[0] != 0; }
472 void SetErrorShutdown(const char *pReason) override;
473
474 bool IsSixup(int ClientId) const override { return ClientId != SERVER_DEMO_CLIENT && m_aClients[ClientId].m_Sixup; }
475
476 void SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger);
477
478#ifdef CONF_FAMILY_UNIX
479 enum CONN_LOGGING_CMD
480 {
481 OPEN_SESSION = 1,
482 CLOSE_SESSION = 2,
483 };
484
485 void SendConnLoggingCommand(CONN_LOGGING_CMD Cmd, const NETADDR *pAddr);
486#endif
487};
488
489extern CServer *CreateServer();
490#endif
491