1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2005 - 2015, ioquake3 contributors
7 Copyright (C) 2013 - 2015, OpenJK contributors
8 
9 This file is part of the OpenJK source code.
10 
11 OpenJK is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License version 2 as
13 published by the Free Software Foundation.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 ===========================================================================
23 */
24 
25 #include "server.h"
26 
27 #include "ghoul2/ghoul2_shared.h"
28 #include "sv_gameapi.h"
29 
30 serverStatic_t	svs;				// persistant server info
31 server_t		sv;					// local server
32 
33 cvar_t	*sv_snapsMin;			// minimum snapshots/sec a client can request, also limited by sv_snapsMax
34 cvar_t	*sv_snapsMax;			// maximum snapshots/sec a client can request, also limited by sv_fps
35 cvar_t	*sv_snapsPolicy;		// 0-2
36 cvar_t	*sv_fps = NULL;				// time rate for running non-clients
37 cvar_t	*sv_timeout;			// seconds without any message
38 cvar_t	*sv_zombietime;			// seconds to sink messages after disconnect
39 cvar_t	*sv_rconPassword;		// password for remote server commands
40 cvar_t	*sv_privatePassword;	// password for the privateClient slots
41 cvar_t	*sv_maxclients;
42 cvar_t	*sv_privateClients;		// number of clients reserved for password
43 cvar_t	*sv_hostname;
44 cvar_t	*sv_allowDownload;
45 cvar_t	*sv_master[MAX_MASTER_SERVERS];		// master server ip address
46 cvar_t	*sv_reconnectlimit;		// minimum seconds between connect messages
47 cvar_t	*sv_showghoultraces;	// report ghoul2 traces
48 cvar_t	*sv_showloss;			// report when usercmds are lost
49 cvar_t	*sv_padPackets;			// add nop bytes to messages
50 cvar_t	*sv_killserver;			// menu system can set to 1 to shut server down
51 cvar_t	*sv_mapname;
52 cvar_t	*sv_mapChecksum;
53 cvar_t	*sv_serverid;
54 cvar_t	*sv_ratePolicy;		// 1-2
55 cvar_t	*sv_clientRate;
56 cvar_t	*sv_minRate;
57 cvar_t	*sv_maxRate;
58 cvar_t	*sv_minPing;
59 cvar_t	*sv_maxPing;
60 cvar_t	*sv_gametype;
61 cvar_t	*sv_pure;
62 cvar_t	*sv_floodProtect;
63 cvar_t	*sv_floodProtectSlow;
64 cvar_t	*sv_lanForceRate; // dedicated 1 (LAN) server forces local client rates to 99999 (bug #491)
65 cvar_t	*sv_needpass;
66 cvar_t	*sv_filterCommands; // strict filtering on commands (1: strip ['\r', '\n'], 2: also strip ';')
67 cvar_t	*sv_autoDemo;
68 cvar_t	*sv_autoDemoBots;
69 cvar_t	*sv_autoDemoMaxMaps;
70 cvar_t	*sv_legacyFixes;
71 cvar_t	*sv_banFile;
72 cvar_t	*sv_maxOOBRate;
73 cvar_t	*sv_maxOOBRateIP;
74 cvar_t	*sv_autoWhitelist;
75 
76 serverBan_t serverBans[SERVER_MAXBANS];
77 int serverBansCount = 0;
78 
79 /*
80 =============================================================================
81 
82 EVENT MESSAGES
83 
84 =============================================================================
85 */
86 
87 /*
88 ===============
89 SV_ExpandNewlines
90 
91 Converts newlines to "\n" so a line prints nicer
92 ===============
93 */
SV_ExpandNewlines(char * in)94 char	*SV_ExpandNewlines( char *in ) {
95 	static	char	string[1024];
96 	size_t	l;
97 
98 	l = 0;
99 	while ( *in && l < sizeof(string) - 3 ) {
100 		if ( *in == '\n' ) {
101 			string[l++] = '\\';
102 			string[l++] = 'n';
103 		} else {
104 			string[l++] = *in;
105 		}
106 		in++;
107 	}
108 	string[l] = 0;
109 
110 	return string;
111 }
112 
113 /*
114 ======================
115 SV_AddServerCommand
116 
117 The given command will be transmitted to the client, and is guaranteed to
118 not have future snapshot_t executed before it is executed
119 ======================
120 */
SV_AddServerCommand(client_t * client,const char * cmd)121 void SV_AddServerCommand( client_t *client, const char *cmd ) {
122 	int		index, i;
123 
124 	// do not send commands until the gamestate has been sent
125 	if ( client->state < CS_PRIMED ) {
126 		return;
127 	}
128 
129 	client->reliableSequence++;
130 	// if we would be losing an old command that hasn't been acknowledged,
131 	// we must drop the connection
132 	// we check == instead of >= so a broadcast print added by SV_DropClient()
133 	// doesn't cause a recursive drop client
134 	if ( client->reliableSequence - client->reliableAcknowledge == MAX_RELIABLE_COMMANDS + 1 ) {
135 		Com_Printf( "===== pending server commands =====\n" );
136 		for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
137 			Com_Printf( "cmd %5d: %s\n", i, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
138 		}
139 		Com_Printf( "cmd %5d: %s\n", i, cmd );
140 		SV_DropClient( client, "Server command overflow" );
141 		return;
142 	}
143 	index = client->reliableSequence & ( MAX_RELIABLE_COMMANDS - 1 );
144 	Q_strncpyz( client->reliableCommands[ index ], cmd, sizeof( client->reliableCommands[ index ] ) );
145 }
146 
147 
148 /*
149 =================
150 SV_SendServerCommand
151 
152 Sends a reliable command string to be interpreted by
153 the client game module: "cp", "print", "chat", etc
154 A NULL client will broadcast to all clients
155 =================
156 */
SV_SendServerCommand(client_t * cl,const char * fmt,...)157 void QDECL SV_SendServerCommand(client_t *cl, const char *fmt, ...) {
158 	va_list		argptr;
159 	byte		message[MAX_MSGLEN];
160 	client_t	*client;
161 	int			j;
162 
163 	va_start (argptr,fmt);
164 	Q_vsnprintf((char *)message, sizeof(message), fmt, argptr);
165 	va_end (argptr);
166 
167 	// Fix to http://aluigi.altervista.org/adv/q3msgboom-adv.txt
168 	// The actual cause of the bug is probably further downstream
169 	// and should maybe be addressed later, but this certainly
170 	// fixes the problem for now
171 	if ( strlen ((char *)message) > 1022 ) {
172 		return;
173 	}
174 
175 	if ( cl != NULL ) {
176 		SV_AddServerCommand( cl, (char *)message );
177 		return;
178 	}
179 
180 	// hack to echo broadcast prints to console
181 	if ( com_dedicated->integer && !Q_strncmp( (char *)message, "print", 5) ) {
182 		Com_Printf ("broadcast: %s\n", SV_ExpandNewlines((char *)message) );
183 	}
184 
185 	// send the data to all relevent clients
186 	for (j = 0, client = svs.clients; j < sv_maxclients->integer ; j++, client++) {
187 		SV_AddServerCommand( client, (char *)message );
188 	}
189 }
190 
191 
192 /*
193 ==============================================================================
194 
195 MASTER SERVER FUNCTIONS
196 
197 ==============================================================================
198 */
199 #define NEW_RESOLVE_DURATION		86400000 //24 hours
200 static int g_lastResolveTime[MAX_MASTER_SERVERS];
201 
SV_MasterNeedsResolving(int server,int time)202 static inline bool SV_MasterNeedsResolving(int server, int time)
203 { //refresh every so often regardless of if the actual address was modified -rww
204 	if (g_lastResolveTime[server] > time)
205 	{ //time flowed backwards?
206 		return true;
207 	}
208 
209 	if ((time-g_lastResolveTime[server]) > NEW_RESOLVE_DURATION)
210 	{ //it's time again
211 		return true;
212 	}
213 
214 	return false;
215 }
216 
217 /*
218 ================
219 SV_MasterHeartbeat
220 
221 Send a message to the masters every few minutes to
222 let it know we are alive, and log information.
223 We will also have a heartbeat sent when a server
224 changes from empty to non-empty, and full to non-full,
225 but not on every player enter or exit.
226 ================
227 */
228 #define	HEARTBEAT_MSEC	300*1000
229 #define	HEARTBEAT_GAME	"QuakeArena-1"
SV_MasterHeartbeat(void)230 void SV_MasterHeartbeat( void ) {
231 	static netadr_t	adr[MAX_MASTER_SERVERS];
232 	int			i;
233 	int			time;
234 
235 	// "dedicated 1" is for lan play, "dedicated 2" is for inet public play
236 	if ( !com_dedicated || com_dedicated->integer != 2 ) {
237 		return;		// only dedicated servers send heartbeats
238 	}
239 
240 	// if not time yet, don't send anything
241 	if ( svs.time < svs.nextHeartbeatTime ) {
242 		return;
243 	}
244 	svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
245 
246 	//we need to use this instead of svs.time since svs.time resets over map changes (or rather
247 	//every time the game restarts), and we don't really need to resolve every map change
248 	time = Com_Milliseconds();
249 
250 	// send to group masters
251 	for ( i = 0 ; i < MAX_MASTER_SERVERS ; i++ ) {
252 		if ( !sv_master[i]->string[0] ) {
253 			continue;
254 		}
255 
256 		// see if we haven't already resolved the name
257 		// resolving usually causes hitches on win95, so only
258 		// do it when needed
259 		if ( sv_master[i]->modified || SV_MasterNeedsResolving(i, time) ) {
260 			sv_master[i]->modified = qfalse;
261 
262 			g_lastResolveTime[i] = time;
263 
264 			Com_Printf( "Resolving %s\n", sv_master[i]->string );
265 			if ( !NET_StringToAdr( sv_master[i]->string, &adr[i] ) ) {
266 				// if the address failed to resolve, clear it
267 				// so we don't take repeated dns hits
268 				Com_Printf( "Couldn't resolve address: %s\n", sv_master[i]->string );
269 				Cvar_Set( sv_master[i]->name, "" );
270 				sv_master[i]->modified = qfalse;
271 				continue;
272 			}
273 			if ( !strstr( ":", sv_master[i]->string ) ) {
274 				adr[i].port = BigShort( PORT_MASTER );
275 			}
276 			Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToString(adr[i]) );
277 
278 			SVC_WhitelistAdr( adr[i] );
279 		}
280 
281 		Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string );
282 		// this command should be changed if the server info / status format
283 		// ever incompatably changes
284 		NET_OutOfBandPrint( NS_SERVER, adr[i], "heartbeat %s\n", HEARTBEAT_GAME );
285 	}
286 }
287 
288 /*
289 =================
290 SV_MasterShutdown
291 
292 Informs all masters that this server is going down
293 =================
294 */
SV_MasterShutdown(void)295 void SV_MasterShutdown( void ) {
296 	// send a hearbeat right now
297 	svs.nextHeartbeatTime = -9999;
298 	SV_MasterHeartbeat();
299 
300 	// send it again to minimize chance of drops
301 	svs.nextHeartbeatTime = -9999;
302 	SV_MasterHeartbeat();
303 
304 	// when the master tries to poll the server, it won't respond, so
305 	// it will be removed from the list
306 }
307 
308 
309 /*
310 ==============================================================================
311 
312 CONNECTIONLESS COMMANDS
313 
314 ==============================================================================
315 */
316 
317 /*
318 ================
319 SVC_BucketForAddress
320 
321 Find or allocate a bucket for an address
322 ================
323 */
324 #include <map>
325 
SVC_BucketForAddress(netadr_t address,int burst,int period,int now)326 static leakyBucket_t *SVC_BucketForAddress( netadr_t address, int burst, int period, int now ) {
327 	static std::map<int, leakyBucket_t> bucketMap;
328 	static int lastGC = 0;
329 
330 	if (address.type != NA_IP) {
331 		return NULL;
332 	}
333 
334 	// Consider following spoofed dos scenario:
335 	//
336 	// Packets coming at a steady rate, IPs are never the
337 	// same. The garbage collector will perform
338 	// packet_rate * (1 + gc_rate * period / 1000)
339 	// iterations per second (where rates are in Hz)
340 	//
341 	// Theoretical minimum is packet_rate because buckets need to be
342 	// removed at the same rate they are created. It can be achieved
343 	// with another map, at the cost of higher constants.
344 	//
345 	// gc_rate at 1/s will keep the overhead relatively low.
346 	// Memory consumption is packet_rate * (period / 1000 + 1 / gc_rate)
347 
348 	if (lastGC + 1000 < now) {
349 		lastGC = now;
350 
351 		auto it = bucketMap.begin();
352 
353 		while (it != bucketMap.end()) {
354 			int interval = now - it->second.lastTime;
355 
356 			if (interval > it->second.burst * period || interval < 0) {
357 				it = bucketMap.erase(it);
358 			} else {
359 				++it;
360 			}
361 		}
362 	}
363 
364 	return &bucketMap[address.ipi];
365 }
366 
367 /*
368 ================
369 SVC_RateLimit
370 ================
371 */
SVC_RateLimit(leakyBucket_t * bucket,int burst,int period,int now)372 qboolean SVC_RateLimit( leakyBucket_t *bucket, int burst, int period, int now ) {
373 	qboolean	block = qfalse;
374 
375 	if ( bucket != NULL ) {
376 		int interval = now - bucket->lastTime;
377 		int expired = interval / period;
378 		int expiredRemainder = interval % period;
379 
380 		if ( expired > bucket->burst || interval < 0 ) {
381 			bucket->burst = 0;
382 			bucket->lastTime = now;
383 		} else {
384 			bucket->burst -= expired;
385 			bucket->lastTime = now - expiredRemainder;
386 		}
387 
388 		if ( bucket->burst < burst ) {
389 			bucket->burst++;
390 		} else {
391 			block = qtrue;
392 		}
393 	}
394 
395 	return block;
396 }
397 
398 /*
399 ================
400 SVC_RateLimitAddress
401 
402 Rate limit for a particular address
403 ================
404 */
SVC_RateLimitAddress(netadr_t from,int burst,int period,int now)405 qboolean SVC_RateLimitAddress( netadr_t from, int burst, int period, int now ) {
406 	leakyBucket_t *bucket = SVC_BucketForAddress( from, burst, period, now );
407 
408 	return SVC_RateLimit( bucket, burst, period, now );
409 }
410 
411 /*
412 ================
413 SVC_Status
414 
415 Responds with all the info that qplug or qspy can see about the server
416 and all connected players.  Used for getting detailed information after
417 the simple info query.
418 ================
419 */
SVC_Status(netadr_t from)420 void SVC_Status( netadr_t from ) {
421 	char	player[1024];
422 	char	status[MAX_MSGLEN];
423 	int		i;
424 	client_t	*cl;
425 	playerState_t	*ps;
426 	int		statusLength;
427 	int		playerLength;
428 	char	infostring[MAX_INFO_STRING];
429 
430 	// ignore if we are in single player
431 	/*
432 	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER ) {
433 		return;
434 	}
435 	*/
436 
437 	// A maximum challenge length of 128 should be more than plenty.
438 	if(strlen(Cmd_Argv(1)) > 128)
439 		return;
440 
441 	Q_strncpyz( infostring, Cvar_InfoString( CVAR_SERVERINFO ), sizeof( infostring ) );
442 
443 	// echo back the parameter to status. so master servers can use it as a challenge
444 	// to prevent timed spoofed reply packets that add ghost servers
445 	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
446 
447 	status[0] = 0;
448 	statusLength = 0;
449 
450 	for (i=0 ; i < sv_maxclients->integer ; i++) {
451 		cl = &svs.clients[i];
452 		if ( cl->state >= CS_CONNECTED ) {
453 			ps = SV_GameClientNum( i );
454 			Com_sprintf (player, sizeof(player), "%i %i \"%s\"\n",
455 				ps->persistant[PERS_SCORE], cl->ping, cl->name);
456 			playerLength = strlen(player);
457 			if (statusLength + playerLength >= (int)sizeof(status) ) {
458 				break;		// can't hold any more
459 			}
460 			strcpy (status + statusLength, player);
461 			statusLength += playerLength;
462 		}
463 	}
464 
465 	NET_OutOfBandPrint( NS_SERVER, from, "statusResponse\n%s\n%s", infostring, status );
466 }
467 
468 /*
469 ================
470 SVC_Info
471 
472 Responds with a short info message that should be enough to determine
473 if a user is interested in a server to do a full status
474 ================
475 */
SVC_Info(netadr_t from)476 void SVC_Info( netadr_t from ) {
477 	int		i, count, humans, wDisable;
478 	char	*gamedir;
479 	char	infostring[MAX_INFO_STRING];
480 
481 	// ignore if we are in single player
482 	/*
483 	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
484 		return;
485 	}
486 	*/
487 
488 	if (Cvar_VariableValue("ui_singlePlayerActive"))
489 	{
490 		return;
491 	}
492 
493 	/*
494 	 * Check whether Cmd_Argv(1) has a sane length. This was not done in the original Quake3 version which led
495 	 * to the Infostring bug discovered by Luigi Auriemma. See http://aluigi.altervista.org/ for the advisory.
496 	 */
497 
498 	// A maximum challenge length of 128 should be more than plenty.
499 	if(strlen(Cmd_Argv(1)) > 128)
500 		return;
501 
502 	// don't count privateclients
503 	count = humans = 0;
504 	for ( i = sv_privateClients->integer ; i < sv_maxclients->integer ; i++ ) {
505 		if ( svs.clients[i].state >= CS_CONNECTED ) {
506 			count++;
507 			if ( svs.clients[i].netchan.remoteAddress.type != NA_BOT ) {
508 				humans++;
509 			}
510 		}
511 	}
512 
513 	infostring[0] = 0;
514 
515 	// echo back the parameter to status. so servers can use it as a challenge
516 	// to prevent timed spoofed reply packets that add ghost servers
517 	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
518 
519 	Info_SetValueForKey( infostring, "protocol", va("%i", PROTOCOL_VERSION) );
520 	Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
521 	Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
522 	Info_SetValueForKey( infostring, "clients", va("%i", count) );
523 	Info_SetValueForKey( infostring, "g_humanplayers", va("%i", humans) );
524 	Info_SetValueForKey( infostring, "sv_maxclients",
525 		va("%i", sv_maxclients->integer - sv_privateClients->integer ) );
526 	Info_SetValueForKey( infostring, "gametype", va("%i", sv_gametype->integer ) );
527 	Info_SetValueForKey( infostring, "needpass", va("%i", sv_needpass->integer ) );
528 	Info_SetValueForKey( infostring, "truejedi", va("%i", Cvar_VariableIntegerValue( "g_jediVmerc" ) ) );
529 	if ( sv_gametype->integer == GT_DUEL || sv_gametype->integer == GT_POWERDUEL )
530 	{
531 		wDisable = Cvar_VariableIntegerValue( "g_duelWeaponDisable" );
532 	}
533 	else
534 	{
535 		wDisable = Cvar_VariableIntegerValue( "g_weaponDisable" );
536 	}
537 	Info_SetValueForKey( infostring, "wdisable", va("%i", wDisable ) );
538 	Info_SetValueForKey( infostring, "fdisable", va("%i", Cvar_VariableIntegerValue( "g_forcePowerDisable" ) ) );
539 	//Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );
540 	Info_SetValueForKey( infostring, "autodemo", va("%i", sv_autoDemo->integer ) );
541 
542 	if( sv_minPing->integer ) {
543 		Info_SetValueForKey( infostring, "minPing", va("%i", sv_minPing->integer) );
544 	}
545 	if( sv_maxPing->integer ) {
546 		Info_SetValueForKey( infostring, "maxPing", va("%i", sv_maxPing->integer) );
547 	}
548 	gamedir = Cvar_VariableString( "fs_game" );
549 	if( *gamedir ) {
550 		Info_SetValueForKey( infostring, "game", gamedir );
551 	}
552 
553 	NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring );
554 }
555 
556 /*
557 ================
558 SVC_FlushRedirect
559 
560 ================
561 */
SV_FlushRedirect(char * outputbuf)562 void SV_FlushRedirect( char *outputbuf ) {
563 	NET_OutOfBandPrint( NS_SERVER, svs.redirectAddress, "print\n%s", outputbuf );
564 }
565 
566 /*
567 ===============
568 SVC_RemoteCommand
569 
570 An rcon packet arrived from the network.
571 Shift down the remaining args
572 Redirect all printfs
573 ===============
574 */
SVC_RemoteCommand(netadr_t from,msg_t * msg)575 void SVC_RemoteCommand( netadr_t from, msg_t *msg ) {
576 	qboolean	valid;
577 	char		remaining[1024];
578 	// TTimo - scaled down to accumulate, but not overflow anything network wise, print wise etc.
579 	// (OOB messages are the bottleneck here)
580 #define	SV_OUTPUTBUF_LENGTH	(1024 - 16)
581 	char		sv_outputbuf[SV_OUTPUTBUF_LENGTH];
582 	char		*cmd_aux;
583 
584 	if ( !strlen( sv_rconPassword->string ) ||
585 		strcmp (Cmd_Argv(1), sv_rconPassword->string) ) {
586 		valid = qfalse;
587 		Com_Printf ("Bad rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
588 	} else {
589 		valid = qtrue;
590 		Com_Printf ("Rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
591 	}
592 
593 	// start redirecting all print outputs to the packet
594 	svs.redirectAddress = from;
595 	Com_BeginRedirect (sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
596 
597 	if ( !strlen( sv_rconPassword->string ) ) {
598 		Com_Printf ("No rconpassword set.\n");
599 	} else if ( !valid ) {
600 		Com_Printf ("Bad rconpassword.\n");
601 	} else {
602 		remaining[0] = 0;
603 
604 		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
605 		// get the command directly, "rcon <pass> <command>" to avoid quoting issues
606 		// extract the command by walking
607 		// since the cmd formatting can fuckup (amount of spaces), using a dumb step by step parsing
608 		cmd_aux = Cmd_Cmd();
609 		cmd_aux+=4;
610 		while(cmd_aux[0]==' ')
611 			cmd_aux++;
612 		while(cmd_aux[0] && cmd_aux[0]!=' ') // password
613 			cmd_aux++;
614 		while(cmd_aux[0]==' ')
615 			cmd_aux++;
616 
617 		Q_strcat( remaining, sizeof(remaining), cmd_aux);
618 
619 		Cmd_ExecuteString (remaining);
620 	}
621 
622 	Com_EndRedirect ();
623 }
624 
625 // dos protection whitelist
626 
627 #define WHITELIST_FILE			"ipwhitelist.dat"
628 
629 #include <set>
630 
631 static std::set<int32_t>	svc_whitelist;
632 
SVC_LoadWhitelist(void)633 void SVC_LoadWhitelist( void ) {
634 	fileHandle_t f;
635 	int32_t *data = NULL;
636 	int len = FS_SV_FOpenFileRead(WHITELIST_FILE, &f);
637 
638 	if (len <= 0) {
639 		return;
640 	}
641 
642 	data = (int32_t *)Z_Malloc(len, TAG_TEMP_WORKSPACE);
643 
644 	FS_Read(data, len, f);
645 	FS_FCloseFile(f);
646 
647 	len /= sizeof(int32_t);
648 
649 	for (int i = 0; i < len; i++) {
650 		svc_whitelist.insert(data[i]);
651 	}
652 
653 	Z_Free(data);
654 	data = NULL;
655 }
656 
SVC_WhitelistAdr(netadr_t adr)657 void SVC_WhitelistAdr( netadr_t adr ) {
658 	fileHandle_t f;
659 
660 	if (adr.type != NA_IP) {
661 		return;
662 	}
663 
664 	if (!svc_whitelist.insert(adr.ipi).second) {
665 		return;
666 	}
667 
668 	Com_DPrintf("Whitelisting %s\n", NET_AdrToString(adr));
669 
670 	f = FS_SV_FOpenFileAppend(WHITELIST_FILE);
671 	if (!f) {
672 		Com_Printf("Couldn't open " WHITELIST_FILE ".\n");
673 		return;
674 	}
675 
676 	FS_Write(adr.ip, sizeof(adr.ip), f);
677 	FS_FCloseFile(f);
678 }
679 
SVC_IsWhitelisted(netadr_t adr)680 static qboolean SVC_IsWhitelisted( netadr_t adr ) {
681 	if (adr.type == NA_IP) {
682 		return (qboolean)(svc_whitelist.find(adr.ipi) != svc_whitelist.end());
683 	} else {
684 		return qtrue;
685 	}
686 }
687 
688 /*
689 =================
690 SV_ConnectionlessPacket
691 
692 A connectionless packet has four leading 0xff
693 characters to distinguish it from a game channel.
694 Clients that are in the game can still send
695 connectionless packets.
696 =================
697 */
SV_ConnectionlessPacket(netadr_t from,msg_t * msg)698 void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
699 	static	leakyBucket_t	bucket;
700 	static	int	dropped = 0;
701 	static	int	lastMsg = 0;
702 	int		now = Sys_Milliseconds();
703 	char	*s;
704 	char	*c;
705 
706 	if (sv_maxOOBRateIP->integer) {
707 		int rate = Com_Clampi(1, 1000, sv_maxOOBRateIP->integer);
708 		int period = 1000 / rate;
709 		int burst = 10 * rate;
710 
711 		if (SVC_RateLimitAddress(from, burst, period, now)) {
712 			if (com_developer && com_developer->integer) {
713 				Com_Printf("SV_ConnectionlessPacket: Rate limit from %s exceeded, dropping request\n", NET_AdrToString(from));
714 			}
715 			return;
716 		}
717 	}
718 
719 	if (sv_maxOOBRate->integer) {
720 		int rate = Com_Clampi(1, 1000, sv_maxOOBRate->integer);
721 		int period = 1000 / rate;
722 
723 		if (SVC_IsWhitelisted(from)) {
724 			rate *= 2;
725 		}
726 
727 		if (SVC_RateLimit(&bucket, rate, period, now)) {
728 			dropped++;
729 			return;
730 		}
731 	}
732 
733 	if (dropped > 0 && lastMsg + 5000 < now) {
734 		Com_Printf("SV_ConnectionlessPacket: Rate limit exceeded, dropped %d requests\n", dropped);
735 		dropped = 0;
736 		lastMsg = now;
737 	}
738 
739 	MSG_BeginReadingOOB( msg );
740 	MSG_ReadLong( msg );		// skip the -1 marker
741 
742 	if (!Q_strncmp("connect", (const char *)&msg->data[4], 7)) {
743 		Huff_Decompress(msg, 12);
744 	}
745 
746 	s = MSG_ReadStringLine( msg );
747 	Cmd_TokenizeString( s );
748 
749 	c = Cmd_Argv(0);
750 	if ( com_developer->integer ) {
751 		Com_Printf( "SV packet %s : %s\n", NET_AdrToString( from ), c );
752 	}
753 
754 	if (!Q_stricmp(c, "getstatus")) {
755 		SVC_Status( from  );
756 	} else if (!Q_stricmp(c, "getinfo")) {
757 		SVC_Info( from );
758 	} else if (!Q_stricmp(c, "getchallenge")) {
759 		SV_GetChallenge( from );
760 	} else if (!Q_stricmp(c, "connect")) {
761 		SV_DirectConnect( from );
762 	} else if (!Q_stricmp(c, "ipAuthorize")) {
763 		// ...
764 	} else if (!Q_stricmp(c, "rcon")) {
765 		SVC_RemoteCommand( from, msg );
766 	} else if (!Q_stricmp(c, "disconnect")) {
767 		// if a client starts up a local server, we may see some spurious
768 		// server disconnect messages when their new server sees our final
769 		// sequenced messages to the old client
770 	} else {
771 		if ( com_developer->integer ) {
772 			Com_Printf( "bad connectionless packet from %s:\n%s\n",
773 				NET_AdrToString( from ), s );
774 		}
775 	}
776 }
777 
778 
779 //============================================================================
780 
781 /*
782 =================
783 SV_ReadPackets
784 =================
785 */
SV_PacketEvent(netadr_t from,msg_t * msg)786 void SV_PacketEvent( netadr_t from, msg_t *msg ) {
787 	int			i;
788 	client_t	*cl;
789 	int			qport;
790 
791 	// check for connectionless packet (0xffffffff) first
792 	if ( msg->cursize >= 4 && *(int *)msg->data == -1) {
793 		SV_ConnectionlessPacket( from, msg );
794 		return;
795 	}
796 
797 	// read the qport out of the message so we can fix up
798 	// stupid address translating routers
799 	MSG_BeginReadingOOB( msg );
800 	MSG_ReadLong( msg );				// sequence number
801 	qport = MSG_ReadShort( msg ) & 0xffff;
802 
803 	// find which client the message is from
804 	for (i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
805 		if (cl->state == CS_FREE) {
806 			continue;
807 		}
808 		if ( !NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) ) {
809 			continue;
810 		}
811 		// it is possible to have multiple clients from a single IP
812 		// address, so they are differentiated by the qport variable
813 		if (cl->netchan.qport != qport) {
814 			continue;
815 		}
816 
817 		// the IP port can't be used to differentiate them, because
818 		// some address translating routers periodically change UDP
819 		// port assignments
820 		if (cl->netchan.remoteAddress.port != from.port) {
821 			Com_Printf( "SV_ReadPackets: fixing up a translated port\n" );
822 			cl->netchan.remoteAddress.port = from.port;
823 		}
824 
825 		// make sure it is a valid, in sequence packet
826 		if (SV_Netchan_Process(cl, msg)) {
827 			// zombie clients still need to do the Netchan_Process
828 			// to make sure they don't need to retransmit the final
829 			// reliable message, but they don't do any other processing
830 			if (cl->state != CS_ZOMBIE) {
831 				cl->lastPacketTime = svs.time;	// don't timeout
832 				SV_ExecuteClientMessage( cl, msg );
833 			}
834 		}
835 		return;
836 	}
837 
838 	// if we received a sequenced packet from an address we don't recognize,
839 	// send an out of band disconnect packet to it
840 	NET_OutOfBandPrint( NS_SERVER, from, "disconnect" );
841 }
842 
843 
844 /*
845 ===================
846 SV_CalcPings
847 
848 Updates the cl->ping variables
849 ===================
850 */
SV_CalcPings(void)851 void SV_CalcPings( void ) {
852 	int			i, j;
853 	client_t	*cl;
854 	int			total, count;
855 	int			delta;
856 	playerState_t	*ps;
857 
858 	for (i=0 ; i < sv_maxclients->integer ; i++) {
859 		cl = &svs.clients[i];
860 		if ( cl->state != CS_ACTIVE ) {
861 			cl->ping = 999;
862 			continue;
863 		}
864 		if ( !cl->gentity ) {
865 			cl->ping = 999;
866 			continue;
867 		}
868 		if ( cl->gentity->r.svFlags & SVF_BOT ) {
869 			cl->ping = 0;
870 			continue;
871 		}
872 
873 		total = 0;
874 		count = 0;
875 		for ( j = 0 ; j < PACKET_BACKUP ; j++ ) {
876 			if ( cl->frames[j].messageAcked <= 0 ) {
877 				continue;
878 			}
879 			delta = cl->frames[j].messageAcked - cl->frames[j].messageSent;
880 			count++;
881 			total += delta;
882 		}
883 		if (!count) {
884 			cl->ping = 999;
885 		} else {
886 			cl->ping = total/count;
887 			if ( cl->ping > 999 ) {
888 				cl->ping = 999;
889 			}
890 		}
891 
892 		// let the game dll know about the ping
893 		ps = SV_GameClientNum( i );
894 		ps->ping = cl->ping;
895 	}
896 }
897 
898 /*
899 ==================
900 SV_CheckTimeouts
901 
902 If a packet has not been received from a client for timeout->integer
903 seconds, drop the conneciton.  Server time is used instead of
904 realtime to avoid dropping the local client while debugging.
905 
906 When a client is normally dropped, the client_t goes into a zombie state
907 for a few seconds to make sure any final reliable message gets resent
908 if necessary
909 ==================
910 */
SV_CheckTimeouts(void)911 void SV_CheckTimeouts( void ) {
912 	int		i;
913 	client_t	*cl;
914 	int			droppoint;
915 	int			zombiepoint;
916 
917 	droppoint = svs.time - 1000 * sv_timeout->integer;
918 	zombiepoint = svs.time - 1000 * sv_zombietime->integer;
919 
920 	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
921 		// message times may be wrong across a changelevel
922 		if (cl->lastPacketTime > svs.time) {
923 			cl->lastPacketTime = svs.time;
924 		}
925 
926 		if (cl->state == CS_ZOMBIE
927 		&& cl->lastPacketTime < zombiepoint) {
928 			Com_DPrintf( "Going from CS_ZOMBIE to CS_FREE for %s\n", cl->name );
929 			cl->state = CS_FREE;	// can now be reused
930 			continue;
931 		}
932 		if ( cl->state >= CS_CONNECTED && cl->lastPacketTime < droppoint) {
933 			// wait several frames so a debugger session doesn't
934 			// cause a timeout
935 			if ( ++cl->timeoutCount > 5 ) {
936 				SV_DropClient (cl, "timed out");
937 				cl->state = CS_FREE;	// don't bother with zombie state
938 			}
939 		} else {
940 			cl->timeoutCount = 0;
941 		}
942 	}
943 }
944 
945 
946 /*
947 ==================
948 SV_CheckPaused
949 ==================
950 */
SV_CheckPaused(void)951 qboolean SV_CheckPaused( void ) {
952 	int		count;
953 	client_t	*cl;
954 	int		i;
955 
956 	if ( !cl_paused->integer ) {
957 		return qfalse;
958 	}
959 
960 	// only pause if there is just a single client connected
961 	count = 0;
962 	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
963 		if ( cl->state >= CS_CONNECTED && cl->netchan.remoteAddress.type != NA_BOT ) {
964 			count++;
965 		}
966 	}
967 
968 	if ( count > 1 ) {
969 		// don't pause
970 		if (sv_paused->integer)
971 			Cvar_Set("sv_paused", "0");
972 		return qfalse;
973 	}
974 
975 	if (!sv_paused->integer)
976 		Cvar_Set("sv_paused", "1");
977 	return qtrue;
978 }
979 
980 /*
981 ==================
982 SV_CheckCvars
983 ==================
984 */
SV_CheckCvars(void)985 void SV_CheckCvars( void ) {
986 	static int lastModHostname = -1, lastModFramerate = -1, lastModSnapsMin = -1, lastModSnapsMax = -1;
987 	static int lastModSnapsPolicy = -1, lastModRatePolicy = -1, lastModClientRate = -1;
988 	static int lastModMaxRate = -1, lastModMinRate = -1;
989 	qboolean changed = qfalse;
990 
991 	if ( sv_hostname->modificationCount != lastModHostname ) {
992 		char hostname[MAX_INFO_STRING];
993 		char *c = hostname;
994 		lastModHostname = sv_hostname->modificationCount;
995 
996 		strcpy( hostname, sv_hostname->string );
997 		while( *c )
998 		{
999 			if ( (*c == '\\') || (*c == ';') || (*c == '"'))
1000 			{
1001 				*c = '.';
1002 				changed = qtrue;
1003 			}
1004 			c++;
1005 		}
1006 		if( changed )
1007 		{
1008 			Cvar_Set("sv_hostname", hostname );
1009 		}
1010 	}
1011 
1012 	// check limits on client "rate" values based on server settings
1013 	if ( sv_clientRate->modificationCount != lastModClientRate ||
1014 		 sv_minRate->modificationCount != lastModMinRate ||
1015 		 sv_maxRate->modificationCount != lastModMaxRate ||
1016 		 sv_ratePolicy->modificationCount != lastModRatePolicy )
1017 	{
1018 		sv_clientRate->modificationCount = lastModClientRate;
1019 		sv_maxRate->modificationCount = lastModMaxRate;
1020 		sv_minRate->modificationCount = lastModMinRate;
1021 		sv_ratePolicy->modificationCount = lastModRatePolicy;
1022 
1023 		if (sv_ratePolicy->integer == 1)
1024 		{
1025 			// NOTE: what if server sets some dumb sv_clientRate value?
1026 			client_t *cl = NULL;
1027 			int i = 0;
1028 
1029 			for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) {
1030 				// if the client is on the same subnet as the server and we aren't running an
1031 				// internet public server, assume they don't need a rate choke
1032 				if (Sys_IsLANAddress(cl->netchan.remoteAddress) && com_dedicated->integer != 2 && sv_lanForceRate->integer == 1) {
1033 					cl->rate = 100000;	// lans should not rate limit
1034 				}
1035 				else {
1036 					int val = sv_clientRate->integer;
1037 					if (val != cl->rate) {
1038 						cl->rate = val;
1039 					}
1040 				}
1041 			}
1042 		}
1043 		else if (sv_ratePolicy->integer == 2)
1044 		{
1045 			// NOTE: what if server sets some dumb sv_clientRate value?
1046 			client_t *cl = NULL;
1047 			int i = 0;
1048 
1049 			for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) {
1050 				// if the client is on the same subnet as the server and we aren't running an
1051 				// internet public server, assume they don't need a rate choke
1052 				if (Sys_IsLANAddress(cl->netchan.remoteAddress) && com_dedicated->integer != 2 && sv_lanForceRate->integer == 1) {
1053 					cl->rate = 100000;	// lans should not rate limit
1054 				}
1055 				else {
1056 					int val = cl->rate;
1057 					if (!val) {
1058 						val = sv_maxRate->integer;
1059 					}
1060 					val = Com_Clampi( 1000, 90000, val );
1061 					val = Com_Clampi( sv_minRate->integer, sv_maxRate->integer, val );
1062 					if (val != cl->rate) {
1063 						cl->rate = val;
1064 					}
1065 				}
1066 			}
1067 		}
1068 	}
1069 
1070 	// check limits on client "snaps" value based on server framerate and snapshot rate
1071 	if ( sv_fps->modificationCount != lastModFramerate ||
1072 		 sv_snapsMin->modificationCount != lastModSnapsMin ||
1073 		 sv_snapsMax->modificationCount != lastModSnapsMax ||
1074 		 sv_snapsPolicy->modificationCount != lastModSnapsPolicy )
1075 	{
1076 		lastModFramerate = sv_fps->modificationCount;
1077 		lastModSnapsMin = sv_snapsMin->modificationCount;
1078 		lastModSnapsMax = sv_snapsMax->modificationCount;
1079 		lastModSnapsPolicy = sv_snapsPolicy->modificationCount;
1080 
1081 		if (sv_snapsPolicy->integer == 1)
1082 		{
1083 			client_t *cl = NULL;
1084 			int i = 0;
1085 
1086 			for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) {
1087 				int val = 1000 / sv_fps->integer;
1088 				if (val != cl->snapshotMsec) {
1089 					// Reset last sent snapshot so we avoid desync between server frame time and snapshot send time
1090 					cl->nextSnapshotTime = -1;
1091 					cl->snapshotMsec = val;
1092 				}
1093 			}
1094 		}
1095 		else if (sv_snapsPolicy->integer == 2)
1096 		{
1097 			client_t *cl = NULL;
1098 			int i = 0;
1099 			int minSnaps = Com_Clampi(1, sv_snapsMax->integer, sv_snapsMin->integer); // between 1 and sv_snapsMax ( 1 <-> 40 )
1100 			int maxSnaps = Q_min(sv_fps->integer, sv_snapsMax->integer); // can't produce more than sv_fps snapshots/sec, but can send less than sv_fps snapshots/sec
1101 
1102 			for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) {
1103 				int val = 1000 / Com_Clampi(minSnaps, maxSnaps, cl->wishSnaps);
1104 				if (val != cl->snapshotMsec) {
1105 					// Reset last sent snapshot so we avoid desync between server frame time and snapshot send time
1106 					cl->nextSnapshotTime = -1;
1107 					cl->snapshotMsec = val;
1108 				}
1109 			}
1110 		}
1111 	}
1112 }
1113 
1114 /*
1115 ==================
1116 SV_FrameMsec
1117 Return time in millseconds until processing of the next server frame.
1118 ==================
1119 */
SV_FrameMsec()1120 int SV_FrameMsec()
1121 {
1122 	if(sv_fps)
1123 	{
1124 		int frameMsec;
1125 
1126 		frameMsec = 1000.0f / sv_fps->value;
1127 
1128 		if(frameMsec < sv.timeResidual)
1129 			return 0;
1130 		else
1131 			return frameMsec - sv.timeResidual;
1132 	}
1133 	else
1134 		return 1;
1135 }
1136 
1137 /*
1138 ==================
1139 SV_Frame
1140 
1141 Player movement occurs as a result of packet events, which
1142 happen before SV_Frame is called
1143 ==================
1144 */
SV_Frame(int msec)1145 void SV_Frame( int msec ) {
1146 	int		frameMsec;
1147 	int		startTime;
1148 
1149 	// the menu kills the server with this cvar
1150 	if ( sv_killserver->integer ) {
1151 		SV_Shutdown ("Server was killed.\n");
1152 		Cvar_Set( "sv_killserver", "0" );
1153 		return;
1154 	}
1155 
1156 	if ( !com_sv_running->integer ) {
1157 		return;
1158 	}
1159 
1160 	// allow pause if only the local client is connected
1161 	if ( SV_CheckPaused() ) {
1162 		return;
1163 	}
1164 
1165 	// if it isn't time for the next frame, do nothing
1166 	if ( sv_fps->integer < 1 ) {
1167 		Cvar_Set( "sv_fps", "10" );
1168 	}
1169 	frameMsec = 1000 / sv_fps->integer * com_timescale->value;
1170 	// don't let it scale below 1ms
1171 	if(frameMsec < 1)
1172 	{
1173 		Cvar_Set("timescale", va("%f", sv_fps->integer / 1000.0f));
1174 		frameMsec = 1;
1175 	}
1176 
1177 	sv.timeResidual += msec;
1178 
1179 	if (!com_dedicated->integer) SV_BotFrame( sv.time + sv.timeResidual );
1180 
1181 	// if time is about to hit the 32nd bit, kick all clients
1182 	// and clear sv.time, rather
1183 	// than checking for negative time wraparound everywhere.
1184 	// 2giga-milliseconds = 23 days, so it won't be too often
1185 	if ( svs.time > 0x70000000 ) {
1186 		SV_Shutdown( "Restarting server due to time wrapping" );
1187 		Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
1188 		return;
1189 	}
1190 	// this can happen considerably earlier when lots of clients play and the map doesn't change
1191 	if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
1192 		SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
1193 		Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
1194 		return;
1195 	}
1196 
1197 	if( sv.restartTime && sv.time >= sv.restartTime ) {
1198 		sv.restartTime = 0;
1199 		Cbuf_AddText( "map_restart 0\n" );
1200 		return;
1201 	}
1202 
1203 	// update infostrings if anything has been changed
1204 	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
1205 		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
1206 		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
1207 	}
1208 	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
1209 		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
1210 		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
1211 	}
1212 
1213 	if ( com_speeds->integer ) {
1214 		startTime = Sys_Milliseconds ();
1215 	} else {
1216 		startTime = 0;	// quite a compiler warning
1217 	}
1218 
1219 	// update ping based on the all received frames
1220 	SV_CalcPings();
1221 
1222 	if (com_dedicated->integer) SV_BotFrame( sv.time );
1223 
1224 	// run the game simulation in chunks
1225 	while ( sv.timeResidual >= frameMsec ) {
1226 		sv.timeResidual -= frameMsec;
1227 		svs.time += frameMsec;
1228 		sv.time += frameMsec;
1229 
1230 		// let everything in the world think and move
1231 		GVM_RunFrame( sv.time );
1232 	}
1233 
1234 	//rww - RAGDOLL_BEGIN
1235 	re->G2API_SetTime(sv.time,0);
1236 	//rww - RAGDOLL_END
1237 
1238 	if ( com_speeds->integer ) {
1239 		time_game = Sys_Milliseconds () - startTime;
1240 	}
1241 
1242 	// check timeouts
1243 	SV_CheckTimeouts();
1244 
1245 	// send messages back to the clients
1246 	SV_SendClientMessages();
1247 
1248 	SV_CheckCvars();
1249 
1250 	// send a heartbeat to the master if needed
1251 	SV_MasterHeartbeat();
1252 }
1253 
1254 //============================================================================
1255 
1256