1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
8 
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 
30 #include "server.h"
31 
32 #ifdef USE_VOIP
33 cvar_t *sv_voip;
34 cvar_t *sv_voipProtocol;
35 #endif
36 
37 serverStatic_t svs;                 // persistant server info
38 server_t sv;                        // local server
39 vm_t            *gvm = NULL;                // game virtual machine
40 
41 #ifdef UPDATE_SERVER
42 versionMapping_t versionMap[MAX_UPDATE_VERSIONS];
43 int numVersions = 0;
44 #endif
45 
46 cvar_t  *sv_fps = NULL;                // time rate for running non-clients
47 cvar_t  *sv_timeout;            // seconds without any message
48 cvar_t  *sv_zombietime;         // seconds to sink messages after disconnect
49 cvar_t  *sv_rconPassword;       // password for remote server commands
50 cvar_t  *sv_privatePassword;    // password for the privateClient slots
51 cvar_t  *sv_allowDownload;
52 cvar_t  *sv_maxclients;
53 
54 cvar_t  *sv_privateClients;     // number of clients reserved for password
55 cvar_t  *sv_hostname;
56 cvar_t  *sv_master[MAX_MASTER_SERVERS];     // master server ip address
57 cvar_t  *sv_reconnectlimit;     // minimum seconds between connect messages
58 cvar_t  *sv_showloss;           // report when usercmds are lost
59 cvar_t  *sv_padPackets;         // add nop bytes to messages
60 cvar_t  *sv_killserver;         // menu system can set to 1 to shut server down
61 cvar_t  *sv_mapname;
62 cvar_t  *sv_mapChecksum;
63 cvar_t  *sv_serverid;
64 cvar_t	*sv_minRate;
65 cvar_t  *sv_maxRate;
66 cvar_t	*sv_dlRate;
67 cvar_t  *sv_minPing;
68 cvar_t  *sv_maxPing;
69 cvar_t  *sv_gametype;
70 cvar_t  *sv_pure;
71 cvar_t  *sv_floodProtect;
72 cvar_t  *sv_allowAnonymous;
73 cvar_t  *sv_lanForceRate; // TTimo - dedicated 1 (LAN) server forces local client rates to 99999 (bug #491)
74 cvar_t  *sv_onlyVisibleClients; // DHM - Nerve
75 
76 cvar_t  *sv_forceNameUniq;
77 
78 cvar_t  *sv_friendlyFire;       // NERVE - SMF
79 cvar_t  *sv_maxlives;           // NERVE - SMF
80 cvar_t  *sv_tourney;            // NERVE - SMF
81 
82 cvar_t *sv_dl_maxRate;
83 
84 // Rafael gameskill
85 cvar_t  *sv_gameskill;
86 // done
87 
88 cvar_t  *sv_showAverageBPS;     // NERVE - SMF - net debugging
89 
90 cvar_t	*sv_banFile;
91 
92 serverBan_t serverBans[SERVER_MAXBANS];
93 int serverBansCount = 0;
94 
95 #if defined ANTIWALLHACK
96 cvar_t *awh_active;
97 cvar_t *awh_bbox_horz;
98 cvar_t *awh_bbox_vert;
99 #endif
100 
101 /*
102 =============================================================================
103 
104 EVENT MESSAGES
105 
106 =============================================================================
107 */
108 
109 /*
110 ===============
111 SV_ExpandNewlines
112 
113 Converts newlines to "\n" so a line prints nicer
114 ===============
115 */
SV_ExpandNewlines(char * in)116 static char    *SV_ExpandNewlines( char *in ) {
117 	static char string[1024];
118 	int l;
119 
120 	l = 0;
121 	while ( *in && l < sizeof( string ) - 3 ) {
122 		if ( *in == '\n' ) {
123 			string[l++] = '\\';
124 			string[l++] = 'n';
125 		} else {
126 			// NERVE - SMF - HACK - strip out localization tokens before string command is displayed in syscon window
127 			if ( !Q_strncmp( in, "[lon]", 5 ) || !Q_strncmp( in, "[lof]", 5 ) ) {
128 				in += 5;
129 				continue;
130 			}
131 
132 			string[l++] = *in;
133 		}
134 		in++;
135 	}
136 	string[l] = 0;
137 
138 	return string;
139 }
140 
141 /*
142 ======================
143 SV_AddServerCommand
144 
145 The given command will be transmitted to the client, and is guaranteed to
146 not have future snapshot_t executed before it is executed
147 ======================
148 */
SV_AddServerCommand(client_t * client,const char * cmd)149 void SV_AddServerCommand( client_t *client, const char *cmd ) {
150 	int index, i;
151 
152 	// do not send commands until the gamestate has been sent
153 	if( client->state < CS_PRIMED )
154 		return;
155 
156 	client->reliableSequence++;
157 	// if we would be losing an old command that hasn't been acknowledged,
158 	// we must drop the connection
159 	// we check == instead of >= so a broadcast print added by SV_DropClient()
160 	// doesn't cause a recursive drop client
161 	if ( client->reliableSequence - client->reliableAcknowledge == MAX_RELIABLE_COMMANDS + 1 ) {
162 		Com_Printf( "===== pending server commands =====\n" );
163 		for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
164 			Com_Printf( "cmd %5d: %s\n", i, client->reliableCommands[ i & ( MAX_RELIABLE_COMMANDS - 1 ) ] );
165 		}
166 		Com_Printf( "cmd %5d: %s\n", i, cmd );
167 		SV_DropClient( client, "Server command overflow" );
168 		return;
169 	}
170 	index = client->reliableSequence & ( MAX_RELIABLE_COMMANDS - 1 );
171 	Q_strncpyz( client->reliableCommands[ index ], cmd, sizeof( client->reliableCommands[ index ] ) );
172 }
173 
174 
175 /*
176 =================
177 SV_SendServerCommand
178 
179 Sends a reliable command string to be interpreted by
180 the client game module: "cp", "print", "chat", etc
181 A NULL client will broadcast to all clients
182 =================
183 */
SV_SendServerCommand(client_t * cl,const char * fmt,...)184 void QDECL SV_SendServerCommand( client_t *cl, const char *fmt, ... ) {
185 	va_list argptr;
186 	byte message[MAX_MSGLEN];
187 	client_t    *client;
188 	int j;
189 
190 	va_start( argptr,fmt );
191 	Q_vsnprintf( (char *)message, sizeof( message ), fmt, argptr );
192 	va_end( argptr );
193 
194 	// do not forward server command messages that would be too big to clients
195 	// ( q3infoboom / q3msgboom stuff )
196 	if ( strlen( (char *)message ) > 1022 ) {
197 		return;
198 	}
199 
200 	if ( cl != NULL ) {
201 		SV_AddServerCommand( cl, (char *)message );
202 		return;
203 	}
204 
205 	// hack to echo broadcast prints to console
206 	if ( com_dedicated->integer && !strncmp( (char *)message, "print", 5 ) ) {
207 		Com_Printf( "broadcast: %s\n", SV_ExpandNewlines( (char *)message ) );
208 	}
209 
210 	// send the data to all relevent clients
211 	for ( j = 0, client = svs.clients; j < sv_maxclients->integer ; j++, client++ ) {
212 		// Ridah, don't need to send messages to AI
213 		if ( client->gentity && client->gentity->r.svFlags & SVF_CASTAI ) {
214 			continue;
215 		}
216 		// done.
217 		SV_AddServerCommand( client, (char *)message );
218 	}
219 }
220 
221 
222 /*
223 ==============================================================================
224 
225 MASTER SERVER FUNCTIONS
226 
227 ==============================================================================
228 */
229 
230 /*
231 ================
232 SV_MasterHeartbeat
233 
234 Send a message to the masters every few minutes to
235 let it know we are alive, and log information.
236 We will also have a heartbeat sent when a server
237 changes from empty to non-empty, and full to non-full,
238 but not on every player enter or exit.
239 ================
240 */
241 #define HEARTBEAT_MSEC	300 * 1000
242 #define MASTERDNS_MSEC	24 * 60 * 60 * 1000
SV_MasterHeartbeat(const char * message)243 void SV_MasterHeartbeat(const char *message)
244 {
245 	static netadr_t	adr[MAX_MASTER_SERVERS][2]; // [2] for v4 and v6 address for the same address string.
246 	int			i;
247 	int			res;
248 	int			netenabled;
249 	static qboolean		firstRes = qtrue;
250 
251 	// DHM - Nerve :: Update Server doesn't send heartbeat
252 #ifdef UPDATE_SERVER
253 	return;
254 #endif
255 
256 	netenabled = Cvar_VariableIntegerValue("net_enabled");
257 
258 	// "dedicated 1" is for lan play, "dedicated 2" is for inet public play
259 	if (!com_dedicated || com_dedicated->integer != 2 || !(netenabled & (NET_ENABLEV4 | NET_ENABLEV6)))
260 		return;		// only dedicated servers send heartbeats
261 
262 	// if not time yet, don't send anything
263 	if ( svs.time < svs.nextHeartbeatTime )
264 		return;
265 
266 	if ( !Q_stricmp( com_gamename->string, LEGACY_MASTER_GAMENAME ) )
267 		message = LEGACY_HEARTBEAT_FOR_MASTER;
268 
269 	svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
270 
271 	// send to group masters
272 	for (i = 0; i < MAX_MASTER_SERVERS; i++)
273 	{
274 		if(!sv_master[i]->string[0])
275 			continue;
276 
277 		// if server resolves on first attempt, attempt resolution on subsequent heartbeats
278 		// if server does not resolve on first attempt, do not attempt another dns lookup for 24 hours
279 		if(sv_master[i]->modified || svs.time > svs.masterResolveTime[i])
280 		{
281 			sv_master[i]->modified = qfalse;
282 
283 			if(svs.time > svs.masterResolveTime[i])
284 			{
285 				svs.masterResolveTime[i] = svs.time + MASTERDNS_MSEC;
286 				firstRes = qtrue;
287 			}
288 
289 			if(netenabled & NET_ENABLEV4)
290 			{
291 				if(firstRes || adr[i][0].type != NA_BAD) {
292 					Com_Printf("Resolving %s (IPv4)\n", sv_master[i]->string);
293 					res = NET_StringToAdr(sv_master[i]->string, &adr[i][0], NA_IP);
294 
295 					if(res == 2)
296 					{
297 						// if no port was specified, use the default master port
298 						adr[i][0].port = BigShort(PORT_MASTER);
299 					}
300 
301 					if(res) {
302 						Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][0]));
303 
304 						if(adr[i][0].type != NA_BAD) {
305 							Com_Printf ("Sending heartbeat to %s (IPv4)\n", sv_master[i]->string );
306 							NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message);
307 						}
308 						sv_master[i]->modified = qtrue;
309 					} else {
310 						Com_Printf( "%s has no IPv4 address.\n", sv_master[i]->string);
311 					}
312 				}
313 			}
314 
315 			if(netenabled & NET_ENABLEV6)
316 			{
317 				if(firstRes || adr[i][1].type != NA_BAD) {
318 					Com_Printf("Resolving %s (IPv6)\n", sv_master[i]->string);
319 					res = NET_StringToAdr(sv_master[i]->string, &adr[i][1], NA_IP6);
320 
321 					if(res == 2)
322 					{
323 						// if no port was specified, use the default master port
324 						adr[i][1].port = BigShort(PORT_MASTER);
325 					}
326 
327 					if(res) {
328 						Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][1]));
329 						if(adr[i][1].type != NA_BAD) {
330 							Com_Printf ("Sending heartbeat to %s (IPv6)\n", sv_master[i]->string );
331 							NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message);
332 						}
333 						sv_master[i]->modified = qtrue;
334 					} else {
335 						Com_Printf( "%s has no IPv6 address.\n", sv_master[i]->string);
336 					}
337 				}
338 			}
339 
340 			if(adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD)
341 			{
342 				Com_Printf("Couldn't resolve address: %s\n", sv_master[i]->string);
343 				continue;
344 			}
345 		}
346 	}
347 
348 	firstRes = qfalse;
349 }
350 
351 /*
352 =================
353 SV_MasterShutdown
354 
355 Informs all masters that this server is going down
356 =================
357 */
SV_MasterShutdown(void)358 void SV_MasterShutdown( void ) {
359 	// send a heartbeat right now
360 	svs.nextHeartbeatTime = -9999;
361 	SV_MasterHeartbeat(FLATLINE_FOR_MASTER);
362 
363 	// send it again to minimize chance of drops
364 //	svs.nextHeartbeatTime = -9999;
365 //	SV_MasterHeartbeat(FLATLINE_FOR_MASTER);
366 
367 	// when the master tries to poll the server, it won't respond, so
368 	// it will be removed from the list
369 }
370 
371 
372 /*
373 ==============================================================================
374 
375 CONNECTIONLESS COMMANDS
376 
377 ==============================================================================
378 */
379 
380 // This is deliberately quite large to make it more of an effort to DoS
381 #define MAX_BUCKETS			16384
382 #define MAX_HASHES			1024
383 
384 static leakyBucket_t buckets[ MAX_BUCKETS ];
385 static leakyBucket_t *bucketHashes[ MAX_HASHES ];
386 leakyBucket_t outboundLeakyBucket;
387 
388 /*
389 ================
390 SVC_HashForAddress
391 ================
392 */
SVC_HashForAddress(netadr_t address)393 static long SVC_HashForAddress( netadr_t address ) {
394 	byte 		*ip = NULL;
395 	size_t	size = 0;
396 	int			i;
397 	long		hash = 0;
398 
399 	switch ( address.type ) {
400 		case NA_IP:  ip = address.ip;  size = 4; break;
401 		case NA_IP6: ip = address.ip6; size = 16; break;
402 		default: break;
403 	}
404 
405 	for ( i = 0; i < size; i++ ) {
406 		hash += (long)( ip[ i ] ) * ( i + 119 );
407 	}
408 
409 	hash = ( hash ^ ( hash >> 10 ) ^ ( hash >> 20 ) );
410 	hash &= ( MAX_HASHES - 1 );
411 
412 	return hash;
413 }
414 
415 /*
416 ================
417 SVC_BucketForAddress
418 
419 Find or allocate a bucket for an address
420 ================
421 */
SVC_BucketForAddress(netadr_t address,int burst,int period)422 static leakyBucket_t *SVC_BucketForAddress( netadr_t address, int burst, int period ) {
423 	leakyBucket_t	*bucket = NULL;
424 	int						i;
425 	long					hash = SVC_HashForAddress( address );
426 	int						now = Sys_Milliseconds();
427 
428 	for ( bucket = bucketHashes[ hash ]; bucket; bucket = bucket->next ) {
429 		switch ( bucket->type ) {
430 			case NA_IP:
431 				if ( memcmp( bucket->ipv._4, address.ip, 4 ) == 0 ) {
432 					return bucket;
433 				}
434 				break;
435 
436 			case NA_IP6:
437 				if ( memcmp( bucket->ipv._6, address.ip6, 16 ) == 0 ) {
438 					return bucket;
439 				}
440 				break;
441 
442 			default:
443 				break;
444 		}
445 	}
446 
447 	for ( i = 0; i < MAX_BUCKETS; i++ ) {
448 		int interval;
449 
450 		bucket = &buckets[ i ];
451 		interval = now - bucket->lastTime;
452 
453 		// Reclaim expired buckets
454 		if ( bucket->lastTime > 0 && ( interval > ( burst * period ) ||
455 					interval < 0 ) ) {
456 			if ( bucket->prev != NULL ) {
457 				bucket->prev->next = bucket->next;
458 			} else {
459 				bucketHashes[ bucket->hash ] = bucket->next;
460 			}
461 
462 			if ( bucket->next != NULL ) {
463 				bucket->next->prev = bucket->prev;
464 			}
465 
466 			Com_Memset( bucket, 0, sizeof( leakyBucket_t ) );
467 		}
468 
469 		if ( bucket->type == NA_BAD ) {
470 			bucket->type = address.type;
471 			switch ( address.type ) {
472 				case NA_IP:  Com_Memcpy( bucket->ipv._4, address.ip, 4 );   break;
473 				case NA_IP6: Com_Memcpy( bucket->ipv._6, address.ip6, 16 ); break;
474 				default: break;
475 			}
476 
477 			bucket->lastTime = now;
478 			bucket->burst = 0;
479 			bucket->hash = hash;
480 
481 			// Add to the head of the relevant hash chain
482 			bucket->next = bucketHashes[ hash ];
483 			if ( bucketHashes[ hash ] != NULL ) {
484 				bucketHashes[ hash ]->prev = bucket;
485 			}
486 
487 			bucket->prev = NULL;
488 			bucketHashes[ hash ] = bucket;
489 
490 			return bucket;
491 		}
492 	}
493 
494 	// Couldn't allocate a bucket for this address
495 	return NULL;
496 }
497 
498 /*
499 ================
500 SVC_RateLimit
501 ================
502 */
SVC_RateLimit(leakyBucket_t * bucket,int burst,int period)503 qboolean SVC_RateLimit( leakyBucket_t *bucket, int burst, int period ) {
504 	if ( bucket != NULL ) {
505 		int now = Sys_Milliseconds();
506 		int interval = now - bucket->lastTime;
507 		int expired = interval / period;
508 		int expiredRemainder = interval % period;
509 
510 		if ( expired > bucket->burst || interval < 0 ) {
511 			bucket->burst = 0;
512 			bucket->lastTime = now;
513 		} else {
514 			bucket->burst -= expired;
515 			bucket->lastTime = now - expiredRemainder;
516 		}
517 
518 		if ( bucket->burst < burst ) {
519 			bucket->burst++;
520 
521 			return qfalse;
522 		}
523 	}
524 
525 	return qtrue;
526 }
527 
528 /*
529 ================
530 SVC_RateLimitAddress
531 
532 Rate limit for a particular address
533 ================
534 */
SVC_RateLimitAddress(netadr_t from,int burst,int period)535 qboolean SVC_RateLimitAddress( netadr_t from, int burst, int period ) {
536 	leakyBucket_t *bucket = SVC_BucketForAddress( from, burst, period );
537 
538 	return SVC_RateLimit( bucket, burst, period );
539 }
540 
541 /*
542 ================
543 SVC_Status
544 
545 Responds with all the info that qplug or qspy can see about the server
546 and all connected players.  Used for getting detailed information after
547 the simple info query.
548 ================
549 */
SVC_Status(netadr_t from)550 static void SVC_Status( netadr_t from ) {
551 	char player[1024];
552 	char status[MAX_MSGLEN];
553 	int i;
554 	client_t    *cl;
555 	playerState_t   *ps;
556 	int statusLength;
557 	int playerLength;
558 	char infostring[MAX_INFO_STRING];
559 
560 	// ignore if we are in single player
561 	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
562 		return;
563 	}
564 
565 	// Prevent using getstatus as an amplifier
566 	if ( SVC_RateLimitAddress( from, 10, 1000 ) ) {
567 		Com_DPrintf( "SVC_Status: rate limit from %s exceeded, dropping request\n",
568 			NET_AdrToString( from ) );
569 		return;
570 	}
571 
572 	// Allow getstatus to be DoSed relatively easily, but prevent
573 	// excess outbound bandwidth usage when being flooded inbound
574 	if ( SVC_RateLimit( &outboundLeakyBucket, 10, 100 ) ) {
575 		Com_DPrintf( "SVC_Status: rate limit exceeded, dropping request\n" );
576  		return;
577  	}
578 
579 	// DHM - Nerve
580 #ifdef UPDATE_SERVER
581 	return;
582 #endif
583 
584 	// A maximum challenge length of 128 should be more than plenty.
585 	if(strlen(Cmd_Argv(1)) > 128)
586 		return;
587 
588 	strcpy( infostring, Cvar_InfoString( CVAR_SERVERINFO ) );
589 
590 	// echo back the parameter to status. so master servers can use it as a challenge
591 	// to prevent timed spoofed reply packets that add ghost servers
592 	Info_SetValueForKey( infostring, "challenge", Cmd_Argv( 1 ) );
593 
594 	status[0] = 0;
595 	statusLength = 0;
596 
597 	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
598 		cl = &svs.clients[i];
599 		if ( cl->state >= CS_CONNECTED ) {
600 			ps = SV_GameClientNum( i );
601 			Com_sprintf( player, sizeof( player ), "%i %i \"%s\"\n",
602 						 ps->persistant[PERS_SCORE], cl->ping, cl->name );
603 			playerLength = strlen( player );
604 			if ( statusLength + playerLength >= sizeof( status ) ) {
605 				break;      // can't hold any more
606 			}
607 			strcpy( status + statusLength, player );
608 			statusLength += playerLength;
609 		}
610 	}
611 
612 	NET_OutOfBandPrint( NS_SERVER, from, "statusResponse\n%s\n%s", infostring, status );
613 }
614 
615 /*
616 ================
617 SVC_Info
618 
619 Responds with a short info message that should be enough to determine
620 if a user is interested in a server to do a full status
621 ================
622 */
SVC_Info(netadr_t from)623 void SVC_Info( netadr_t from ) {
624 	int		i, count, humans;
625 	char    *gamedir;
626 	char infostring[MAX_INFO_STRING];
627 	char    *antilag;
628 
629 	// DHM - Nerve
630 #ifdef UPDATE_SERVER
631 	return;
632 #endif
633 
634 	// ignore if we are in single player
635 	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
636 		return;
637 	}
638 
639 	// Prevent using getinfo as an amplifier
640 	if ( SVC_RateLimitAddress( from, 10, 1000 ) ) {
641 		Com_DPrintf( "SVC_Info: rate limit from %s exceeded, dropping request\n",
642 			NET_AdrToString( from ) );
643 		return;
644 	}
645 
646 	// Allow getinfo to be DoSed relatively easily, but prevent
647 	// excess outbound bandwidth usage when being flooded inbound
648 	if ( SVC_RateLimit( &outboundLeakyBucket, 10, 100 ) ) {
649 		Com_DPrintf( "SVC_Info: rate limit exceeded, dropping request\n" );
650 		return;
651 	}
652 
653 	/*
654 	 * Check whether Cmd_Argv(1) has a sane length. This was not done in the original Quake3 version which led
655 	 * to the Infostring bug discovered by Luigi Auriemma. See http://aluigi.altervista.org/ for the advisory.
656 	 */
657 
658 	// A maximum challenge length of 128 should be more than plenty.
659 	if(strlen(Cmd_Argv(1)) > 128)
660 		return;
661 
662 	// don't count privateclients
663 	count = humans = 0;
664 	for ( i = sv_privateClients->integer ; i < sv_maxclients->integer ; i++ ) {
665 		if ( svs.clients[i].state >= CS_CONNECTED ) {
666 			count++;
667 			if (svs.clients[i].netchan.remoteAddress.type != NA_BOT) {
668 				humans++;
669 			}
670 		}
671 	}
672 
673 	infostring[0] = 0;
674 
675 	// echo back the parameter to status. so servers can use it as a challenge
676 	// to prevent timed spoofed reply packets that add ghost servers
677 	Info_SetValueForKey( infostring, "challenge", Cmd_Argv( 1 ) );
678 
679 	Info_SetValueForKey( infostring, "gamename", com_gamename->string );
680 
681 #ifdef LEGACY_PROTOCOL
682 	if(com_legacyprotocol->integer > 0)
683 		Info_SetValueForKey(infostring, "protocol", va("%i", com_legacyprotocol->integer));
684 	else
685 #endif
686 		Info_SetValueForKey(infostring, "protocol", va("%i", com_protocol->integer));
687 
688 	Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
689 	Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
690 	Info_SetValueForKey( infostring, "clients", va( "%i", count ) );
691 	Info_SetValueForKey( infostring, "g_humanplayers", va( "%i", humans ) );
692 	Info_SetValueForKey( infostring, "sv_maxclients",
693 						 va( "%i", sv_maxclients->integer - sv_privateClients->integer ) );
694 	Info_SetValueForKey( infostring, "gametype", va( "%i", sv_gametype->integer ) );
695 	Info_SetValueForKey( infostring, "pure", va( "%i", sv_pure->integer ) );
696 	Info_SetValueForKey( infostring, "g_needpass", va("%d", Cvar_VariableIntegerValue( "g_needpass" ) ) );
697 
698 #ifdef USE_VOIP
699 	if (sv_voipProtocol->string && *sv_voipProtocol->string) {
700 		Info_SetValueForKey( infostring, "voip", sv_voipProtocol->string );
701 	}
702 #endif
703 
704 	if ( sv_minPing->integer ) {
705 		Info_SetValueForKey( infostring, "minPing", va( "%i", sv_minPing->integer ) );
706 	}
707 	if ( sv_maxPing->integer ) {
708 		Info_SetValueForKey( infostring, "maxPing", va( "%i", sv_maxPing->integer ) );
709 	}
710 	gamedir = Cvar_VariableString( "fs_game" );
711 	if ( *gamedir ) {
712 		Info_SetValueForKey( infostring, "game", gamedir );
713 	}
714 	Info_SetValueForKey( infostring, "sv_allowAnonymous", va( "%i", sv_allowAnonymous->integer ) );
715 
716 	// Rafael gameskill
717 	Info_SetValueForKey( infostring, "gameskill", va( "%i", sv_gameskill->integer ) );
718 	// done
719 
720 	Info_SetValueForKey( infostring, "friendlyFire", va( "%i", sv_friendlyFire->integer ) );        // NERVE - SMF
721 	Info_SetValueForKey( infostring, "maxlives", va( "%i", sv_maxlives->integer ? 1 : 0 ) );        // NERVE - SMF
722 	Info_SetValueForKey( infostring, "tourney", va( "%i", sv_tourney->integer ) );              // NERVE - SMF
723 
724 	// TTimo
725 	antilag = Cvar_VariableString( "g_antilag" );
726 	if ( antilag ) {
727 		Info_SetValueForKey( infostring, "g_antilag", antilag );
728 	}
729 
730 	NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring );
731 }
732 
733 // DHM - Nerve
734 #ifdef UPDATE_SERVER
735 /*
736 ================
737 SVC_GetUpdateInfo
738 
739 Responds with a short info message that tells the client if they
740 have an update available for their version
741 ================
742 */
SVC_GetUpdateInfo(netadr_t from)743 void SVC_GetUpdateInfo( netadr_t from ) {
744 	char *version;
745 	char *platform;
746 	int i;
747 	qboolean found = qfalse;
748 
749 	version = Cmd_Argv( 1 );
750 	platform = Cmd_Argv( 2 );
751 
752 	Com_DPrintf( "SVC_GetUpdateInfo: version == %s / %s,\n", version, platform );
753 
754 	for ( i = 0; i < numVersions; i++ ) {
755 		if ( !strcmp( versionMap[i].version, version ) &&
756 			 !strcmp( versionMap[i].platform, platform ) ) {
757 
758 			// If the installer is set to "current", we will skip over it
759 			if ( strcmp( versionMap[i].installer, "current" ) ) {
760 				found = qtrue;
761 			}
762 
763 			break;
764 		}
765 	}
766 
767 	if ( found ) {
768 		NET_OutOfBandPrint( NS_SERVER, from, "updateResponse 1 %s", versionMap[i].installer );
769 		Com_DPrintf( "   SENT:  updateResponse 1 %s\n", versionMap[i].installer );
770 	} else {
771 		NET_OutOfBandPrint( NS_SERVER, from, "updateResponse 0" );
772 		Com_DPrintf( "   SENT:  updateResponse 0\n" );
773 	}
774 }
775 #endif
776 // DHM - Nerve
777 
778 /*
779 ==============
780 SV_FlushRedirect
781 
782 ==============
783 */
SV_FlushRedirect(char * outputbuf)784 static void SV_FlushRedirect( char *outputbuf ) {
785 	NET_OutOfBandPrint( NS_SERVER, svs.redirectAddress, "print\n%s", outputbuf );
786 }
787 
788 /*
789 ===============
790 SVC_RemoteCommand
791 
792 An rcon packet arrived from the network.
793 Shift down the remaining args
794 Redirect all printfs
795 ===============
796 */
SVC_RemoteCommand(netadr_t from,msg_t * msg)797 static void SVC_RemoteCommand( netadr_t from, msg_t *msg ) {
798 	qboolean valid;
799 	char remaining[1024];
800 	// show_bug.cgi?id=376
801 	// if we send an OOB print message this size, 1.31 clients die in a Com_Printf buffer overflow
802 	// the buffer overflow will be fixed in > 1.31 clients
803 	// but we want a server side fix
804 	// we must NEVER send an OOB message that will be > 1.31 MAXPRINTMSG (4096)
805 #define SV_OUTPUTBUF_LENGTH ( 256 - 16 )
806 	char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
807 	char *cmd_aux;
808 
809 	// Prevent using rcon as an amplifier and make dictionary attacks impractical
810 	if ( SVC_RateLimitAddress( from, 10, 1000 ) ) {
811 		Com_DPrintf( "SVC_RemoteCommand: rate limit from %s exceeded, dropping request\n",
812 			NET_AdrToString( from ) );
813 		return;
814 	}
815 
816 	if ( !strlen( sv_rconPassword->string ) ||
817 		strcmp( Cmd_Argv( 1 ), sv_rconPassword->string ) ) {
818 		static leakyBucket_t bucket;
819 
820 		// Make DoS via rcon impractical
821 		if ( SVC_RateLimit( &bucket, 10, 1000 ) ) {
822 			Com_DPrintf( "SVC_RemoteCommand: rate limit exceeded, dropping request\n" );
823 			return;
824 		}
825 
826 		valid = qfalse;
827 		Com_Printf ("Bad rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
828 	} else {
829 		valid = qtrue;
830 		Com_Printf ("Rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
831 	}
832 
833 	// start redirecting all print outputs to the packet
834 	svs.redirectAddress = from;
835 	// FIXME TTimo our rcon redirection could be improved
836 	//   big rcon commands such as status lead to sending
837 	//   out of band packets on every single call to Com_Printf
838 	//   which leads to client overflows
839 	//   see show_bug.cgi?id=51
840 	//     (also a Q3 issue)
841 	Com_BeginRedirect( sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect );
842 
843 	if ( !strlen( sv_rconPassword->string ) ) {
844 		Com_Printf( "No rconpassword set on the server.\n" );
845 	} else if ( !valid ) {
846 		Com_Printf( "Bad rconpassword.\n" );
847 	} else {
848 		remaining[0] = 0;
849 
850 		// ATVI Wolfenstein Misc #284
851 		// get the command directly, "rcon <pass> <command>" to avoid quoting issues
852 		// extract the command by walking
853 		// since the cmd formatting can fuckup (amount of spaces), using a dumb step by step parsing
854 		cmd_aux = Cmd_Cmd();
855 		cmd_aux += 4;
856 		while ( cmd_aux[0] == ' ' )
857 			cmd_aux++;
858 		while ( cmd_aux[0] && cmd_aux[0] != ' ' ) // password
859 			cmd_aux++;
860 		while ( cmd_aux[0] == ' ' )
861 			cmd_aux++;
862 
863 		Q_strcat( remaining, sizeof( remaining ), cmd_aux );
864 
865 		Cmd_ExecuteString( remaining );
866 
867 	}
868 
869 	Com_EndRedirect();
870 }
871 
872 /*
873 =================
874 SV_ConnectionlessPacket
875 
876 A connectionless packet has four leading 0xff
877 characters to distinguish it from a game channel.
878 Clients that are in the game can still send
879 connectionless packets.
880 =================
881 */
SV_ConnectionlessPacket(netadr_t from,msg_t * msg)882 static void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
883 	char    *s;
884 	char    *c;
885 
886 	MSG_BeginReadingOOB( msg );
887 	MSG_ReadLong( msg );        // skip the -1 marker
888 
889 	if (!Q_strncmp("connect", (char *) &msg->data[4], 7)) {
890 		Huff_Decompress( msg, 12 );
891 	}
892 
893 	s = MSG_ReadStringLine( msg );
894 
895 	Cmd_TokenizeString( s );
896 
897 	c = Cmd_Argv( 0 );
898 	Com_DPrintf( "SV packet %s : %s\n", NET_AdrToString( from ), c );
899 
900 	if ( !Q_stricmp( c,"getstatus" ) ) {
901 		SVC_Status( from );
902 	} else if ( !Q_stricmp( c,"getinfo" ) ) {
903 		SVC_Info( from );
904 	} else if ( !Q_stricmp( c,"getchallenge" ) ) {
905 		SV_GetChallenge( from );
906 	} else if ( !Q_stricmp( c,"connect" ) ) {
907 		SV_DirectConnect( from );
908 #ifndef STANDALONE
909 #ifdef USE_AUTHORIZE_SERVER
910 	} else if ( !Q_stricmp( c,"ipAuthorize" ) ) {
911 		SV_AuthorizeIpPacket( from );
912 #endif
913 #endif
914 	} else if ( !Q_stricmp( c, "rcon" ) ) {
915 		SVC_RemoteCommand( from, msg );
916 // DHM - Nerve
917 #ifdef UPDATE_SERVER
918 	} else if ( !Q_stricmp( c, "getUpdateInfo" ) ) {
919 		SVC_GetUpdateInfo( from );
920 #endif
921 // DHM - Nerve
922 	} else if ( !Q_stricmp( c,"disconnect" ) ) {
923 		// if a client starts up a local server, we may see some spurious
924 		// server disconnect messages when their new server sees our final
925 		// sequenced messages to the old client
926 	} else {
927 		Com_DPrintf( "bad connectionless packet from %s:\n%s\n",
928 			 NET_AdrToString( from ), s );
929 	}
930 }
931 
932 //============================================================================
933 
934 /*
935 =================
936 SV_PacketEvent
937 =================
938 */
SV_PacketEvent(netadr_t from,msg_t * msg)939 void SV_PacketEvent( netadr_t from, msg_t *msg ) {
940 	int i;
941 	client_t    *cl;
942 	int qport;
943 
944 	// check for connectionless packet (0xffffffff) first
945 	if ( msg->cursize >= 4 && *(int *)msg->data == -1 ) {
946 		SV_ConnectionlessPacket( from, msg );
947 		return;
948 	}
949 
950 	// read the qport out of the message so we can fix up
951 	// stupid address translating routers
952 	MSG_BeginReadingOOB( msg );
953 	MSG_ReadLong( msg );                // sequence number
954 	qport = MSG_ReadShort( msg ) & 0xffff;
955 
956 	// find which client the message is from
957 	for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
958 		if ( cl->state == CS_FREE ) {
959 			continue;
960 		}
961 		if ( !NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) ) {
962 			continue;
963 		}
964 		// it is possible to have multiple clients from a single IP
965 		// address, so they are differentiated by the qport variable
966 		if ( cl->netchan.qport != qport ) {
967 			continue;
968 		}
969 
970 		// the IP port can't be used to differentiate them, because
971 		// some address translating routers periodically change UDP
972 		// port assignments
973 		if ( cl->netchan.remoteAddress.port != from.port ) {
974 			Com_Printf( "SV_PacketEvent: fixing up a translated port\n" );
975 			cl->netchan.remoteAddress.port = from.port;
976 		}
977 
978 		// make sure it is a valid, in sequence packet
979 		if ( SV_Netchan_Process( cl, msg ) ) {
980 			// zombie clients still need to do the Netchan_Process
981 			// to make sure they don't need to retransmit the final
982 			// reliable message, but they don't do any other processing
983 			if ( cl->state != CS_ZOMBIE ) {
984 				cl->lastPacketTime = svs.time;  // don't timeout
985 				SV_ExecuteClientMessage( cl, msg );
986 			}
987 		}
988 		return;
989 	}
990 
991 }
992 
993 
994 /*
995 ===================
996 SV_CalcPings
997 
998 Updates the cl->ping variables
999 ===================
1000 */
SV_CalcPings(void)1001 static void SV_CalcPings( void ) {
1002 	int i, j;
1003 	client_t    *cl;
1004 	int total, count;
1005 	int delta;
1006 	playerState_t   *ps;
1007 
1008 	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
1009 		cl = &svs.clients[i];
1010 
1011 		// DHM - Nerve
1012 #ifdef UPDATE_SERVER
1013 		if ( !cl ) {
1014 			continue;
1015 		}
1016 #endif
1017 
1018 		if ( cl->state != CS_ACTIVE ) {
1019 			cl->ping = 999;
1020 			continue;
1021 		}
1022 		if ( !cl->gentity ) {
1023 			cl->ping = 999;
1024 			continue;
1025 		}
1026 		if ( cl->gentity->r.svFlags & SVF_BOT ) {
1027 			cl->ping = 0;
1028 			continue;
1029 		}
1030 
1031 		total = 0;
1032 		count = 0;
1033 		for ( j = 0 ; j < PACKET_BACKUP ; j++ ) {
1034 			if ( cl->frames[j].messageAcked <= 0 ) {
1035 				continue;
1036 			}
1037 			delta = cl->frames[j].messageAcked - cl->frames[j].messageSent;
1038 			count++;
1039 			total += delta;
1040 		}
1041 		if ( !count ) {
1042 			cl->ping = 999;
1043 		} else {
1044 			cl->ping = total / count;
1045 			if ( cl->ping > 999 ) {
1046 				cl->ping = 999;
1047 			}
1048 		}
1049 
1050 		// let the game dll know about the ping
1051 		ps = SV_GameClientNum( i );
1052 		ps->ping = cl->ping;
1053 	}
1054 }
1055 
1056 /*
1057 ==================
1058 SV_CheckTimeouts
1059 
1060 If a packet has not been received from a client for timeout->integer
1061 seconds, drop the conneciton.  Server time is used instead of
1062 realtime to avoid dropping the local client while debugging.
1063 
1064 When a client is normally dropped, the client_t goes into a zombie state
1065 for a few seconds to make sure any final reliable message gets resent
1066 if necessary
1067 ==================
1068 */
SV_CheckTimeouts(void)1069 static void SV_CheckTimeouts( void ) {
1070 	int i;
1071 	client_t    *cl;
1072 	int droppoint;
1073 	int zombiepoint;
1074 
1075 	droppoint = svs.time - 1000 * sv_timeout->integer;
1076 	zombiepoint = svs.time - 1000 * sv_zombietime->integer;
1077 
1078 	for ( i = 0,cl = svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
1079 		// message times may be wrong across a changelevel
1080 		if ( cl->lastPacketTime > svs.time ) {
1081 			cl->lastPacketTime = svs.time;
1082 		}
1083 
1084 		if ( cl->state == CS_ZOMBIE
1085 			 && cl->lastPacketTime < zombiepoint ) {
1086 			// using the client id cause the cl->name is empty at this point
1087 			Com_DPrintf( "Going from CS_ZOMBIE to CS_FREE for client %d\n", i );
1088 			cl->state = CS_FREE;    // can now be reused
1089 			continue;
1090 		}
1091 		if ( cl->state >= CS_CONNECTED && cl->lastPacketTime < droppoint ) {
1092 			// wait several frames so a debugger session doesn't
1093 			// cause a timeout
1094 			if ( ++cl->timeoutCount > 5 ) {
1095 				SV_DropClient( cl, "timed out" );
1096 				cl->state = CS_FREE;    // don't bother with zombie state
1097 			}
1098 		} else {
1099 			cl->timeoutCount = 0;
1100 		}
1101 	}
1102 }
1103 
1104 
1105 /*
1106 ==================
1107 SV_CheckPaused
1108 ==================
1109 */
SV_CheckPaused(void)1110 static qboolean SV_CheckPaused( void ) {
1111 	int count;
1112 	client_t    *cl;
1113 	int i;
1114 
1115 	if ( !cl_paused->integer ) {
1116 		return qfalse;
1117 	}
1118 
1119 	// only pause if there is just a single client connected
1120 	count = 0;
1121 	for ( i = 0,cl = svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
1122 		if ( cl->state >= CS_CONNECTED && cl->netchan.remoteAddress.type != NA_BOT ) {
1123 			count++;
1124 		}
1125 	}
1126 
1127 	if ( count > 1 ) {
1128 		// don't pause
1129 		if ( sv_paused->integer ) {
1130 			Cvar_Set( "sv_paused", "0" );
1131 		}
1132 		return qfalse;
1133 	}
1134 
1135 	if ( !sv_paused->integer ) {
1136 		Cvar_Set( "sv_paused", "1" );
1137 	}
1138 	return qtrue;
1139 }
1140 
1141 /*
1142 ==================
1143 SV_FrameMsec
1144 Return time in millseconds until processing of the next server frame.
1145 ==================
1146 */
SV_FrameMsec()1147 int SV_FrameMsec()
1148 {
1149 	if(sv_fps)
1150 	{
1151 		int frameMsec;
1152 
1153 		frameMsec = 1000.0f / sv_fps->value;
1154 
1155 		if(frameMsec < sv.timeResidual)
1156 			return 0;
1157 		else
1158 			return frameMsec - sv.timeResidual;
1159 	}
1160 	else
1161 		return 1;
1162 }
1163 
1164 /*
1165 ==================
1166 SV_Frame
1167 
1168 Player movement occurs as a result of packet events, which
1169 happen before SV_Frame is called
1170 ==================
1171 */
SV_Frame(int msec)1172 void SV_Frame( int msec ) {
1173 	int frameMsec;
1174 	int startTime;
1175 	char mapname[MAX_QPATH];
1176 
1177 	// the menu kills the server with this cvar
1178 	if ( sv_killserver->integer ) {
1179 		SV_Shutdown( "Server was killed." );
1180 		Cvar_Set( "sv_killserver", "0" );
1181 		return;
1182 	}
1183 
1184 	if (!com_sv_running->integer)
1185 	{
1186 		// Running as a server, but no map loaded
1187 #ifdef DEDICATED
1188 		// Block until something interesting happens
1189 		Sys_Sleep(-1);
1190 #endif
1191 
1192 		return;
1193 	}
1194 
1195 	// allow pause if only the local client is connected
1196 	if ( SV_CheckPaused() ) {
1197 		return;
1198 	}
1199 
1200 	// if it isn't time for the next frame, do nothing
1201 	if ( sv_fps->integer < 1 ) {
1202 		Cvar_Set( "sv_fps", "10" );
1203 	}
1204 
1205 	frameMsec = 1000 / sv_fps->integer * com_timescale->value;
1206 	// don't let it scale below 1ms
1207 	if(frameMsec < 1)
1208 	{
1209 		Cvar_Set("timescale", va("%f", sv_fps->integer / 1000.0f));
1210 		frameMsec = 1;
1211 	}
1212 
1213 	sv.timeResidual += msec;
1214 
1215 	if (!com_dedicated->integer) SV_BotFrame (sv.time + sv.timeResidual);
1216 
1217 	// if time is about to hit the 32nd bit, kick all clients
1218 	// and clear sv.time, rather
1219 	// than checking for negative time wraparound everywhere.
1220 	// 2giga-milliseconds = 23 days, so it won't be too often
1221 	if ( svs.time > 0x70000000 ) {
1222 		Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH );
1223 		SV_Shutdown( "Restarting server due to time wrapping" );
1224 		Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
1225 		return;
1226 	}
1227 	// this can happen considerably earlier when lots of clients play and the map doesn't change
1228 	if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
1229 		Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH );
1230 		SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
1231 		Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
1232 		return;
1233 	}
1234 
1235 	if( sv.restartTime && sv.time >= sv.restartTime ) {
1236 		sv.restartTime = 0;
1237 		Cbuf_AddText( "map_restart 0\n" );
1238 		return;
1239 	}
1240 
1241 	// update infostrings if anything has been changed
1242 	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
1243 		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
1244 		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
1245 	}
1246 	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
1247 		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
1248 		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
1249 	}
1250 	// NERVE - SMF
1251 	if ( cvar_modifiedFlags & CVAR_WOLFINFO ) {
1252 		SV_SetConfigstring( CS_WOLFINFO, Cvar_InfoString( CVAR_WOLFINFO ) );
1253 		cvar_modifiedFlags &= ~CVAR_WOLFINFO;
1254 	}
1255 
1256 	if ( com_speeds->integer ) {
1257 		startTime = Sys_Milliseconds();
1258 	} else {
1259 		startTime = 0;  // quite a compiler warning
1260 	}
1261 
1262 	// update ping based on the all received frames
1263 	SV_CalcPings();
1264 
1265 	if (com_dedicated->integer) SV_BotFrame (sv.time);
1266 
1267 	// run the game simulation in chunks
1268 	while ( sv.timeResidual >= frameMsec ) {
1269 		sv.timeResidual -= frameMsec;
1270 		svs.time += frameMsec;
1271 		sv.time += frameMsec;
1272 
1273 		// let everything in the world think and move
1274 #ifndef UPDATE_SERVER
1275 		VM_Call (gvm, GAME_RUN_FRAME, sv.time);
1276 #endif
1277 	}
1278 
1279 	if ( com_speeds->integer ) {
1280 		time_game = Sys_Milliseconds() - startTime;
1281 	}
1282 
1283 	// check timeouts
1284 	SV_CheckTimeouts();
1285 
1286 	// send messages back to the clients
1287 	SV_SendClientMessages();
1288 
1289 	// send a heartbeat to the master if needed
1290 	SV_MasterHeartbeat(HEARTBEAT_FOR_MASTER);
1291 }
1292 
1293 /*
1294 ====================
1295 SV_RateMsec
1296 
1297 Return the number of msec until another message can be sent to
1298 a client based on its rate settings
1299 ====================
1300 */
1301 
1302 #define UDPIP_HEADER_SIZE 28
1303 #define UDPIP6_HEADER_SIZE 48
1304 
SV_RateMsec(client_t * client)1305 int SV_RateMsec(client_t *client)
1306 {
1307 	int rate, rateMsec;
1308 	int messageSize;
1309 
1310 	messageSize = client->netchan.lastSentSize;
1311 	rate = client->rate;
1312 
1313 	if(sv_maxRate->integer)
1314 	{
1315 		if(sv_maxRate->integer < 1000)
1316 			Cvar_Set( "sv_MaxRate", "1000" );
1317 		if(sv_maxRate->integer < rate)
1318 			rate = sv_maxRate->integer;
1319 	}
1320 
1321 	if(sv_minRate->integer)
1322 	{
1323 		if(sv_minRate->integer < 1000)
1324 			Cvar_Set("sv_minRate", "1000");
1325 		if(sv_minRate->integer > rate)
1326 			rate = sv_minRate->integer;
1327 	}
1328 
1329 	if(client->netchan.remoteAddress.type == NA_IP6)
1330 		messageSize += UDPIP6_HEADER_SIZE;
1331 	else
1332 		messageSize += UDPIP_HEADER_SIZE;
1333 
1334 	rateMsec = messageSize * 1000 / ((int) (rate * com_timescale->value));
1335 	rate = Sys_Milliseconds() - client->netchan.lastSentTime;
1336 
1337 	if(rate > rateMsec)
1338 		return 0;
1339 	else
1340 		return rateMsec - rate;
1341 }
1342 
1343 /*
1344 ====================
1345 SV_SendQueuedPackets
1346 
1347 Send download messages and queued packets in the time that we're idle, i.e.
1348 not computing a server frame or sending client snapshots.
1349 Return the time in msec until we expect to be called next
1350 ====================
1351 */
1352 
SV_SendQueuedPackets()1353 int SV_SendQueuedPackets()
1354 {
1355 	int numBlocks;
1356 	int dlStart, deltaT, delayT;
1357 	static int dlNextRound = 0;
1358 	int timeVal = INT_MAX;
1359 
1360 	// Send out fragmented packets now that we're idle
1361 	delayT = SV_SendQueuedMessages();
1362 	if(delayT >= 0)
1363 		timeVal = delayT;
1364 
1365 	if(sv_dlRate->integer)
1366 	{
1367 		// Rate limiting. This is very imprecise for high
1368 		// download rates due to millisecond timedelta resolution
1369 		dlStart = Sys_Milliseconds();
1370 		deltaT = dlNextRound - dlStart;
1371 
1372 		if(deltaT > 0)
1373 		{
1374 			if(deltaT < timeVal)
1375 				timeVal = deltaT + 1;
1376 		}
1377 		else
1378 		{
1379 			numBlocks = SV_SendDownloadMessages();
1380 
1381 			if(numBlocks)
1382 			{
1383 				// There are active downloads
1384 				deltaT = Sys_Milliseconds() - dlStart;
1385 
1386 				delayT = 1000 * numBlocks * MAX_DOWNLOAD_BLKSIZE;
1387 				delayT /= sv_dlRate->integer * 1024;
1388 
1389 				if(delayT <= deltaT + 1)
1390 				{
1391 					// Sending the last round of download messages
1392 					// took too long for given rate, don't wait for
1393 					// next round, but always enforce a 1ms delay
1394 					// between DL message rounds so we don't hog
1395 					// all of the bandwidth. This will result in an
1396 					// effective maximum rate of 1MB/s per user, but the
1397 					// low download window size limits this anyways.
1398 					if(timeVal > 2)
1399 						timeVal = 2;
1400 
1401 					dlNextRound = dlStart + deltaT + 1;
1402 				}
1403 				else
1404 				{
1405 					dlNextRound = dlStart + delayT;
1406 					delayT -= deltaT;
1407 
1408 					if(delayT < timeVal)
1409 						timeVal = delayT;
1410 				}
1411 			}
1412 		}
1413 	}
1414 	else
1415 	{
1416 		if(SV_SendDownloadMessages())
1417 			timeVal = 0;
1418 	}
1419 
1420 	return timeVal;
1421 }
1422