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 | |
35 | class CConfig; |
36 | class CHostLookup; |
37 | class CLogMessage; |
38 | class CMsgPacker; |
39 | class CPacker; |
40 | class IEngine; |
41 | class IEngineMap; |
42 | class ILogger; |
43 | |
44 | class 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 | |
51 | public: |
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 | |
64 | class 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 | |
93 | public: |
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 | |
489 | extern CServer *CreateServer(); |
490 | #endif |
491 | |