1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include "server.h"
22 #include "mvd.h"
23 
24 netadr_t	master_adr[MAX_MASTERS];	// address of group servers
25 
26 client_t	*sv_client;			// current client
27 
28 cvar_t	*sv_enforcetime;
29 
30 cvar_t	*timeout;				// seconds without any message
31 cvar_t	*zombietime;			// seconds to sink messages after disconnect
32 
33 cvar_t	*rcon_password;			// password for remote server commands
34 cvar_t  *sv_password;
35 cvar_t  *sv_mvd_password;
36 
37 cvar_t *allow_download;
38 cvar_t *allow_download_players;
39 cvar_t *allow_download_models;
40 cvar_t *allow_download_sounds;
41 cvar_t *allow_download_maps;
42 cvar_t *allow_download_demos;
43 cvar_t *allow_download_other;
44 
45 cvar_t	*sv_airaccelerate;
46 cvar_t	*sv_qwmod;				// atu QW Physics modificator
47 cvar_t	*sv_noreload;			// don't reload level state when reentering
48 
49 cvar_t	*sv_maxclients;
50 cvar_t	*sv_mvd_enable;
51 cvar_t	*sv_reserved_slots;
52 cvar_t	*sv_showclamp;
53 
54 cvar_t	*sv_hostname;
55 cvar_t	*public_server;			// should heartbeats be sent
56 
57 cvar_t	*sv_debug_send;
58 cvar_t	*sv_pad_packets;
59 cvar_t	*sv_lan_force_rate;
60 
61 cvar_t	*sv_strafejump_hack;
62 cvar_t	*sv_bodyque_hack;
63 #ifndef _WIN32
64 cvar_t	*sv_oldgame_hack;
65 #endif
66 
67 cvar_t	*sv_iplimit;
68 cvar_t	*sv_status_limit;
69 cvar_t	*sv_status_show;
70 cvar_t	*sv_badauth_time;
71 
72 cvar_t	*sv_nextserver;
73 
74 void Master_Shutdown (void);
75 
76 
77 //============================================================================
78 
SV_RemoveClient(client_t * client)79 void SV_RemoveClient( client_t *client ) {
80     if( client->netchan->type == NETCHAN_OLD ) {
81         SV_OldClientClearMessages( client );
82 
83         Z_Free( client->msgPool );
84         client->msgPool = NULL;
85     } else {
86     	Z_Free( client->datagram_buffer );
87 	    client->datagram_buffer = NULL;
88     }
89 
90 	Netchan_Close( client->netchan );
91 	client->netchan = NULL;
92 
93     List_DeleteElem( client );
94     List_Append( &svs.freeclients, client );
95 
96 	Com_DPrintf( "Going from cs_zombie to cs_free for %s\n", client->name );
97 
98 	client->state = cs_free;	// can now be reused
99 	client->name[0] = 0;
100 }
101 
SV_CleanClient(client_t * client)102 void SV_CleanClient( client_t *client ) {
103 	int i;
104 
105 	if( client->download ) {
106 		FS_FreeFile( client->download );
107 		client->download = NULL;
108 	}
109 
110 	if( client->versionString ) {
111 		Z_Free( client->versionString );
112 		client->versionString = NULL;
113 	}
114 
115 	for( i = 0; i < SV_BASELINES_CHUNKS; i++ ) {
116 		if( client->baselines[i] ) {
117 			Z_Free( client->baselines[i] );
118 			client->baselines[i] = NULL;
119 		}
120 	}
121 
122 }
123 
124 /*
125 =====================
126 SV_DropClient
127 
128 Called when the player is totally leaving the server, either willingly
129 or unwillingly.  This is NOT called if the entire server is quiting
130 or crashing.
131 =====================
132 */
SV_DropClient(client_t * client,const char * reason)133 void SV_DropClient( client_t *client, const char *reason ) {
134 	if( reason ) {
135         SV_BroadcastPrintf( PRINT_HIGH, "%s was dropped, reason: %s\n",
136             client->name, reason );
137         if( client->state != cs_spawned ) {
138             SV_ClientPrintf( client, PRINT_HIGH,
139                     "You were dropped, reason: %s\n", reason );
140         }
141 	}
142 
143 	// add the disconnect
144 	MSG_WriteByte( svc_disconnect );
145 	SV_ClientAddMessage( client, MSG_RELIABLE|MSG_CLEAR );
146 
147 	if( client->state == cs_spawned ) {
148 		// call the prog function for removing a client
149 		// this will remove the body, among other things
150 		ge->ClientDisconnect( client->edict );
151 	}
152 
153 	SV_CleanClient( client );
154 
155 	Com_DPrintf( "Going from %s to cs_zombie for %s\n",
156             ( client->state == cs_spawned ) ? "cs_spawned" : "cs_connected",
157                 client->name );
158 
159 	client->state = cs_zombie;		// become free in a few seconds
160 
161 }
162 
163 
164 
165 /*
166 ==============================================================================
167 
168 CONNECTIONLESS COMMANDS
169 
170 ==============================================================================
171 */
172 
SV_RateLimited(ratelimit_t * r)173 qboolean SV_RateLimited( ratelimit_t *r ) {
174 	if( !r->limit ) {
175 		return qfalse;
176 	}
177 	if( r->time < svs.realtime ) {
178 		r->count = 0;
179 		r->time = svs.realtime + r->period;
180 		return qfalse;
181 	}
182 
183 	if( r->count < r->limit ) {
184 		return qfalse;
185 	}
186 
187 	return qtrue;
188 }
189 
SV_RateInit(ratelimit_t * r,int limit,int period)190 void SV_RateInit( ratelimit_t *r, int limit, int period ) {
191 	if( limit < 0 ) {
192 		limit = 0;
193 	}
194 	if( period < 100 ) {
195 		period = 100;
196 	}
197 	r->count = 0;
198 	r->time = svs.realtime + period;
199 	r->limit = limit;
200 	r->period = period;
201 }
202 
203 /*
204 ===============
205 SV_StatusString
206 
207 Builds the string that is sent as heartbeats and status replies
208 ===============
209 */
SV_StatusString(qboolean big)210 static char	*SV_StatusString( qboolean big ) {
211 	char	player[MAX_STRING_CHARS];
212 	static char	status[MAX_PACKETLEN - 16];
213 	int		j;
214 	client_t	*cl;
215 	int		statusLength;
216 	int		playerLength;
217 	char	*s;
218 
219 	if( big ) {
220 		s = Cvar_BitInfo_Big( CVAR_SERVERINFO );
221 	} else {
222 		s = Cvar_BitInfo( CVAR_SERVERINFO );
223 	}
224 
225 	statusLength = Com_sprintf( status, sizeof( status ), "%s\n", s );
226 
227 	if( sv_status_show->integer < 2 ) {
228 		return status;
229 	}
230 
231     FOR_EACH_CLIENT( cl ) {
232 		if( cl->state >= cs_connected ) {
233 			if( sv.state == ss_broadcast ) {
234 				j = 0;
235 			} else {
236 				j = cl->edict->client->ps.stats[STAT_FRAGS];
237 			}
238 			playerLength = Com_sprintf( player, sizeof( player ),
239 				"%i %i \"%s\"\n", j, cl->ping, cl->name );
240 			if( statusLength + playerLength > sizeof( status ) - 1 )
241 				break;		// can't hold any more
242 			strcpy( status + statusLength, player );
243 			statusLength += playerLength;
244 		}
245 	}
246 
247 	return status;
248 }
249 
250 /*
251 ================
252 SVC_Status
253 
254 Responds with all the info that qplug or qspy can see
255 ================
256 */
SVC_Status(void)257 static void SVC_Status( void ) {
258 	char *s;
259 	int i, j, k;
260 	qboolean big = qfalse;
261 
262 	if( !sv_status_show->integer ) {
263 		return;
264 	}
265 
266 	if( SV_RateLimited( &svs.ratelimit_status ) ) {
267 		Com_DPrintf( "Dropping status request from %s\n",
268                 NET_AdrToString( &net_from ) );
269 		return;
270 	}
271 
272 	svs.ratelimit_status.count++;
273 
274 	/* parse additional parameters */
275     j = Cmd_Argc();
276 	for( i = 1; i < j; i++ ) {
277 		s = Cmd_Argv( i );
278 		if( !strncmp( s, "p=", 2 ) ) {
279 			s += 2;
280 			while( *s ) {
281 				k = atoi( s );
282 				if( k == PROTOCOL_VERSION_Q2PRO ) {
283 					big = qtrue;
284 				}
285 				s = strchr( s, ',' );
286 				if( s == NULL ) {
287 					break;
288 				}
289 				s++;
290 			}
291 		}
292     }
293 
294 	Netchan_OutOfBandPrint( NS_SERVER, &net_from, "print\n%s",
295             SV_StatusString( big ) );
296 }
297 
298 /*
299 ================
300 SVC_Ack
301 
302 ================
303 */
SVC_Ack(void)304 static void SVC_Ack( void ) {
305 	int i;
306 
307 	for( i = 0; i < MAX_MASTERS; i++ ) {
308 		if( !master_adr[i].port ) {
309 			continue;
310 		}
311 		if( NET_IsEqualBaseAdr( &master_adr[i], &net_from ) ) {
312 			Com_Printf( "Ping acknowledge from %s\n",
313                     NET_AdrToString( &net_from ) );
314 			break;
315 		}
316 	}
317 }
318 
319 /*
320 ================
321 SVC_Info
322 
323 Responds with short info for broadcast scans
324 The second parameter should be the current protocol version number.
325 ================
326 */
SVC_Info(void)327 static void SVC_Info (void)
328 {
329 	char	string[MAX_QPATH];
330 	int		count;
331 	int		version;
332     client_t *client;
333 
334 	if (sv_maxclients->integer == 1)
335 		return;		// ignore in single player
336 
337 	version = atoi (Cmd_Argv(1));
338 
339 	if (version != PROTOCOL_VERSION_DEFAULT) {
340 		return;
341 	}
342 
343 	count = 0;
344     FOR_EACH_CLIENT( client ) {
345 		if (client->state >= cs_connected)
346 			count++;
347     }
348 
349 	Com_sprintf (string, sizeof(string), "%16s %8s %2i/%2i\n",
350 		sv_hostname->string, sv.name, count, sv_maxclients->integer);
351 
352 	Netchan_OutOfBandPrint (NS_SERVER, &net_from, "info\n%s", string);
353 }
354 
355 /*
356 ================
357 SVC_Ping
358 
359 Just responds with an acknowledgement
360 ================
361 */
SVC_Ping(void)362 static void SVC_Ping (void)
363 {
364 	Netchan_OutOfBandPrint (NS_SERVER, &net_from, "ack");
365 }
366 
SV_OutOfBandPrintf(const char * format,...)367 static int SV_OutOfBandPrintf( const char *format, ... ) {
368 	va_list		argptr;
369 	byte        send_data[MAX_PACKETLEN];
370 	int			length;
371 	int			ret;
372 
373 /* write the packet header */
374 	*( uint32 * )send_data = -1;	/* -1 sequence means out of band */
375 	strcpy( ( char * )send_data + 4, "print\n" );
376 
377 	va_start( argptr, format );
378 	length = Q_vsnprintf( ( char * )send_data + 10, sizeof( send_data ) - 10, format, argptr );
379 	va_end( argptr );
380 
381 /* send the datagram */
382 	ret = NET_SendPacket( NS_SERVER, &net_from, length + 10, send_data );
383 
384 	return ret;
385 }
386 
SV_AllowMVD(void)387 static qboolean SV_AllowMVD( void ) {
388 	if( sv_mvd_enable->integer < 2 ) {
389 		return qfalse;
390 	}
391 	if( sv.state >= ss_cinematic ) {
392 		return qfalse;
393 	}
394 	if( sv.state == ss_broadcast && mvd.serverProtocol != PROTOCOL_VERSION_MVD ) {
395 		return qfalse;
396 	}
397 	return qtrue;
398 }
399 
400 
401 /*
402 =================
403 SVC_GetChallenge
404 
405 Returns a challenge number that can be used
406 in a subsequent client_connect command.
407 We do this to prevent denial of service attacks that
408 flood the server with invalid connection IPs.  With a
409 challenge, they must give a valid IP address.
410 =================
411 */
SVC_GetChallenge(void)412 static void SVC_GetChallenge( void ) {
413 	int		i, challenge;
414 	int		oldest;
415 	int		oldestTime;
416     char    protocols[16];
417 
418 	oldest = 0;
419 	oldestTime = 0x7fffffff;
420 
421 	// see if we already have a challenge for this ip
422 	for( i = 0; i < MAX_CHALLENGES; i++ ) {
423 		if( NET_IsEqualBaseAdr ( &net_from, &svs.challenges[i].adr ) )
424 			break;
425 		if( svs.challenges[i].time < oldestTime ) {
426 			oldestTime = svs.challenges[i].time;
427 			oldest = i;
428 		}
429 	}
430 
431     challenge = ( ( rand() << 16 ) | rand() ) & 0x7fffffff;
432 	if( i == MAX_CHALLENGES ) {
433 		// overwrite the oldest
434 		svs.challenges[oldest].challenge = challenge;
435 		svs.challenges[oldest].adr = net_from;
436 		svs.challenges[oldest].time = Sys_Milliseconds();
437 	} else {
438 		svs.challenges[i].challenge = challenge;
439 		svs.challenges[i].time = Sys_Milliseconds();
440 	}
441 
442     strcpy( protocols, "34,35,36" );
443 	if( SV_AllowMVD() ) {
444         strcat( protocols, ",37" );
445     }
446 
447 	// send it back
448 	Netchan_OutOfBandPrint( NS_SERVER, &net_from, "challenge %d p=%s",
449             challenge, protocols );
450 }
451 
SV_PasswordValid(const char * password,const char * check,int protocol,int challenge)452 static qboolean SV_PasswordValid( const char *password, const char *check,
453         int protocol, int challenge )
454 {
455 	if( SV_RateLimited( &svs.ratelimit_badpass ) ) {
456 		Com_DPrintf( "    rejected a connection - auth attempt limit exceeded.\n" );
457 		return qfalse;
458 	}
459 
460     if( !check[0] ) {
461 		SV_OutOfBandPrintf(
462 			"Please specify the password before connecting.\n" );
463         Com_DPrintf( "    rejected a connection - empty password.\n" );
464         return qfalse;
465     }
466 #if 0
467     if( protocol < PROTOCOL_VERSION_Q2PRO ) {
468         if( !strcmp( password, check ) ) {
469             return qtrue;
470         }
471     } else {
472         mdfour_t md;
473         uint8 passHash[16];
474         uint8 checkHash[16];
475         int i, ch, lo, hi;
476 
477         for( i = 0; i < 16; i++ ) {
478             ch = check[0];
479             if( ch >= '0' && ch <= '9' ) {
480                 hi = ch - '0';
481             } else if( ch >= 'a' && ch <= 'f' ) {
482                 hi = ch - 'a' + 10;
483             } else if( ch >= 'A' && ch <= 'F' ) {
484                 hi = ch - 'A' + 10;
485             } else {
486                 goto invalid;
487             }
488 
489             ch = check[1];
490             if( ch >= '0' && ch <= '9' ) {
491                 lo = ch - '0';
492             } else if( ch >= 'a' && ch <= 'f' ) {
493                 lo = ch - 'a' + 10;
494             } else if( ch >= 'A' && ch <= 'F' ) {
495                 lo = ch - 'A' + 10;
496             } else {
497                 goto invalid;
498             }
499 
500             checkHash[i] = ( hi << 4 ) | lo;
501             check += 2;
502         }
503 
504         mdfour_begin( &md );
505         mdfour_update( &md, ( uint8 * )password, strlen( password ) );
506         mdfour_update( &md, ( uint8 * )&challenge, sizeof( challenge ) );
507         mdfour_result( &md, passHash );
508 
509         if( !memcmp( passHash, checkHash, 16 ) ) {
510             return qtrue;
511         }
512     }
513 
514 invalid:
515 #else
516         if( !strcmp( password, check ) ) {
517             return qtrue;
518         }
519 #endif
520 	svs.ratelimit_badpass.count++;
521     SV_OutOfBandPrintf( "Invalid password.\n" );
522     Com_DPrintf( "    rejected a connection - invalid password.\n" );
523     return qfalse;
524 }
525 
526 /*
527 ==================
528 SVC_DirectConnect
529 
530 A connection request that did not come from the master
531 ==================
532 */
SVC_DirectConnect(void)533 static void SVC_DirectConnect( void ) {
534 	char		userinfo[MAX_INFO_STRING];
535 	int			i, entnum, count;
536 	client_t	*cl, *newcl;
537 	int			protocol;
538 	int			qport;
539 	int			challenge;
540 	qboolean	allow;
541 	char		*info, *s;
542 	int			length;
543     int         maxlength;
544     netchan_type_t nctype;
545 	clientMessage_t	*msg;
546 
547 	protocol = atoi( Cmd_Argv( 1 ) );
548 	qport = atoi( Cmd_Argv( 2 ) ) ;
549 	challenge = atoi( Cmd_Argv( 3 ) );
550 
551 	Com_DPrintf( "SVC_DirectConnect: protocol=%i, qport=%i, challenge=%i\n",
552             protocol, qport, challenge );
553 
554 	if( protocol == PROTOCOL_VERSION_MVD ) {
555 		if( !SV_AllowMVD() ) {
556 			SV_OutOfBandPrintf( "This server does not allow MVD connections.\n" );
557 			Com_DPrintf( "    rejected connect with MVD protocol version %i\n",
558                 protocol );
559 			return;
560 		}
561 	} else {
562 		if( protocol != PROTOCOL_VERSION_DEFAULT &&
563 			protocol != PROTOCOL_VERSION_R1Q2 &&
564 			protocol != PROTOCOL_VERSION_Q2PRO )
565 		{
566 			SV_OutOfBandPrintf( "Unsupported protocol %d.\n"
567 				"This server supports protocols %d, %d and %d.\n",
568 					protocol,
569 					PROTOCOL_VERSION_DEFAULT,
570 					PROTOCOL_VERSION_R1Q2,
571 					PROTOCOL_VERSION_Q2PRO );
572 			Com_DPrintf( "    rejected connect with protocol version %i\n",
573 					protocol );
574 			return;
575 		}
576 	}
577 
578 	// attractloop servers are ONLY for local clients
579 	if( sv.attractloop ) {
580 		if( !NET_IsLocalAddress( &net_from ) ) {
581 			SV_OutOfBandPrintf( "Connection refused.\n" );
582 			Com_DPrintf( "    rejected a remote connection in attract loop.\n" );
583 			return;
584 		}
585 	}
586 
587 	// see if the challenge is valid
588 	if( !NET_IsLocalAddress( &net_from ) ) {
589 		for( i = 0; i < MAX_CHALLENGES; i++ ) {
590 			if( !svs.challenges[i].challenge ) {
591 				continue;
592 			}
593 			if( NET_IsEqualBaseAdr( &net_from, &svs.challenges[i].adr ) ) {
594 				if( svs.challenges[i].challenge == challenge )
595 					break;		// good
596 				SV_OutOfBandPrintf( "Bad challenge.\n" );
597 				Com_DPrintf( "    rejected a connection - bad challenge.\n" );
598 				return;
599 			}
600 		}
601 		if( i == MAX_CHALLENGES ) {
602 			SV_OutOfBandPrintf( "No challenge for address.\n" );
603 			Com_DPrintf( "    rejected a connection - no challenge.\n" );
604 			return;
605 		}
606 		svs.challenges[i].challenge = 0;
607 	}
608 
609 	// limit number of connections from single IP
610 	if( sv_iplimit->integer > 0 ) {
611 		count = 0;
612         FOR_EACH_CLIENT( cl ) {
613 			if( NET_IsEqualBaseAdr( &net_from, &cl->netchan->remote_address ) )
614             {
615 				if( cl->state == cs_zombie ) {
616 					count++;
617 				} else {
618 					count += 2;
619 				}
620 			}
621 		}
622 		count >>= 1;
623 		if( count >= sv_iplimit->integer ) {
624 			SV_OutOfBandPrintf( "Too many connections from your IP address.\n" );
625 			Com_DPrintf( "    rejected a connection - too many connections.\n" );
626 			return;
627 		}
628 	}
629 
630     maxlength = 1390;
631     if( protocol >= PROTOCOL_VERSION_R1Q2 ) {
632         s = Cmd_Argv( 5 );
633         if( *s ) {
634             maxlength = atoi( s );
635             if( maxlength < 0 || maxlength > MAX_PACKETLEN_WRITABLE ) {
636                 SV_OutOfBandPrintf( "Invalid maximum packet length.\n" );
637                 Com_DPrintf( "    rejected a connection - bad maxpacketlen.\n" );
638                 return;
639             }
640             if( !maxlength ) {
641                 maxlength = MAX_PACKETLEN_WRITABLE;
642             }
643         }
644     }
645 
646     if( net_maxmsglen->integer && maxlength > net_maxmsglen->integer ) {
647         maxlength = net_maxmsglen->integer;
648     }
649 
650     if( protocol >= PROTOCOL_VERSION_Q2PRO ) {
651         s = Cmd_Argv( 6 );
652         if( *s ) {
653             nctype = atoi( s );
654             if( nctype != NETCHAN_OLD && nctype != NETCHAN_NEW ) {
655                 SV_OutOfBandPrintf( "Invalid netchan type.\n" );
656                 Com_DPrintf( "    rejected a connection - bad nctype.\n" );
657                 return;
658             }
659         } else {
660             nctype = NETCHAN_NEW;
661         }
662     } else {
663         nctype = NETCHAN_OLD;
664     }
665 
666 	info = Cmd_Argv( 4 );
667 	if( !info[0] ) {
668 		SV_OutOfBandPrintf( "Empty userinfo string.\n" );
669 		Com_DPrintf( "    rejected a connection - empty userinfo.\n" );
670 		return;
671 	}
672 
673 	if( !Info_Validate( info ) ) {
674 		SV_OutOfBandPrintf( "Malformed userinfo string.\n" );
675 		Com_DPrintf( "    rejected a connection - malformed userinfo.\n" );
676 		return;
677 	}
678 
679 	s = Info_ValueForKey( info, "name" );
680 	if( !s[0] || Q_IsWhiteSpace( s ) ) {
681 		SV_OutOfBandPrintf( "Please set your name before connecting.\n" );
682 		Com_DPrintf( "    rejected a connection - empty name.\n" );
683 		return;
684 	}
685 
686 	length = strlen( s );
687 	if( length > MAX_CLIENT_NAME - 1 ) {
688 		SV_OutOfBandPrintf( "Names longer than %d characters are not allowed.\n", MAX_CLIENT_NAME - 1 );
689 		Com_DPrintf( "    rejected a connection - oversize name.\n" );
690 		return;
691 	}
692 
693 	s = Info_ValueForKey( info, "skin" );
694 	if( !s[0] ) {
695 		SV_OutOfBandPrintf( "Please set your skin before connecting.\n" );
696 		Com_DPrintf( "    rejected a connection - empty skin.\n" );
697 		return;
698 	}
699 
700 	length = strlen( s );
701 	if( !Q_ispath( s[0] ) || !Q_ispath( s[ length - 1 ] ) || strchr( s, '.' ) ) {
702 		SV_OutOfBandPrintf( "Malformed skin.\n" );
703 		Com_DPrintf( "    rejected a connection - malformed skin.\n" );
704 		return;
705 	}
706 
707 	if( protocol != PROTOCOL_VERSION_MVD ) {
708         if( sv_password->string[0] ) {
709             s = Info_ValueForKey( info, "password" );
710             if( !SV_PasswordValid( sv_password->string, s,
711                         protocol, challenge ) )
712             {
713                 return;
714             }
715         }
716 	} else {
717         s = Info_ValueForKey( info, "password" );
718         if( sv_mvd_password->string[0] ) {
719             if( !SV_PasswordValid( sv_mvd_password->string, s,
720                         protocol, challenge ) )
721             {
722                 return;
723             }
724         } else if( sv_password->string[0] ) {
725             if( !SV_PasswordValid( sv_password->string, s,
726                         protocol, challenge ) )
727             {
728                 return;
729             }
730         }
731 
732     }
733 
734 	Q_strncpyz( userinfo, info, sizeof( userinfo ) );
735 
736 	// force the IP key/value pair so the game can filter based on ip
737 	s = NET_AdrToString( &net_from );
738 	if( !Info_AttemptSetValueForKey( userinfo, "ip", s ) ) {
739 		SV_OutOfBandPrintf( "Oversize userinfo string.\n" );
740 		Com_DPrintf( "    rejected a connection - oversize userinfo.\n" );
741 		return;
742 	}
743 
744 	newcl = NULL;
745 
746 	// if there is already a slot for this ip, reuse it
747     FOR_EACH_CLIENT( cl ) {
748 		if( NET_IsEqualAdr( &net_from, &cl->netchan->remote_address ) ) {
749 			if( cl->state != cs_zombie ) {
750 				SV_DropClient( cl, "reconnected" );
751 			}
752 
753 			if( cl->protocol != protocol ) {
754 				Com_DPrintf( "%s: reconnect using different protocol\n",
755 					NET_AdrToString( &net_from ) );
756 			} else {
757 				Com_DPrintf( "%s: reconnect\n",
758 					NET_AdrToString( &net_from ) );
759 				newcl = cl;
760 			}
761 
762 			// NOTE: it's safe to call SV_Remove since we exit the loop
763 			SV_RemoveClient( cl );
764 			break;
765 		}
766 	}
767 
768 	// find a client slot
769 	if( !newcl ) {
770         newcl = ( client_t * )svs.freeclients.first;
771 		if( !newcl ) {
772 			SV_OutOfBandPrintf( "Server is full.\n" );
773 			Com_DPrintf( "    rejected a connection - server is full.\n" );
774 			return;
775 		}
776 	}
777 
778 	// build a new connection
779 	// accept the new client
780 	// this is the only place a client_t is ever initialized
781 	memset( newcl, 0, sizeof( *newcl ) );
782 	newcl->clientNum = newcl - svs.clientpool;
783 	newcl->challenge = challenge; // save challenge for checksumming
784 	newcl->protocol = protocol;
785 
786 	entnum = newcl->clientNum + 1;
787 	newcl->edict = EDICT_NUM( entnum );
788 
789 	if( protocol == PROTOCOL_VERSION_R1Q2 ||
790 		protocol == PROTOCOL_VERSION_Q2PRO )
791 	{
792 		newcl->pmp.speedMultiplier = 2;
793 		newcl->pmp.strafeHack = sv_strafejump_hack->integer ? qtrue : qfalse;
794 	} else {
795 		newcl->pmp.speedMultiplier = 1;
796 		newcl->pmp.strafeHack = qfalse;
797 	}
798 	if( protocol == PROTOCOL_VERSION_Q2PRO && sv_qwmod->integer ) {
799 		newcl->pmp.qwmod = sv_qwmod->integer;
800 		newcl->pmp.maxspeed = 320;
801 		newcl->pmp.upspeed = ( sv_qwmod->integer > 1 ) ? 310 : 350;
802 		newcl->pmp.friction = 4;
803 		newcl->pmp.waterfriction = 4;
804 		newcl->pmp.airaccelerate = qtrue;
805 	} else {
806 		newcl->pmp.qwmod = 0;
807 		newcl->pmp.maxspeed = 300;
808 		newcl->pmp.upspeed = 350;
809 		newcl->pmp.friction = 6;
810 		newcl->pmp.waterfriction = 1;
811 		newcl->pmp.airaccelerate = sv_airaccelerate->integer ? qtrue : qfalse;
812 	}
813 	//newcl->pmp.highprec=qtrue;
814 
815 	// get the game a chance to reject this connection or modify the userinfo
816 	sv_client = newcl;
817 	sv_player = newcl->edict;
818 	allow = ge->ClientConnect( newcl->edict, userinfo );
819 	sv_client = NULL;
820 	sv_player = NULL;
821 	if ( !allow ) {
822 		char *reason;
823 
824 		reason = Info_ValueForKey( userinfo, "rejmsg" );
825 		if( *reason ) {
826 			SV_OutOfBandPrintf( "%s\nConnection refused.\n", reason );
827 		} else {
828 			SV_OutOfBandPrintf( "Connection refused.\n" );
829 		}
830 		Com_DPrintf( "    game rejected a connection.\n" );
831 		return;
832 	}
833 
834 	// parse some info from the info strings
835 	Q_strncpyz( newcl->userinfo, userinfo, sizeof( newcl->userinfo ) );
836 	SV_UserinfoChanged( newcl );
837 
838 	// send the connect packet to the client
839 	Netchan_OutOfBandPrint( NS_SERVER, &net_from, "client_connect nc=%u",
840             nctype );
841 
842     // setup netchan
843     newcl->netchan = Netchan_Setup( NS_SERVER, nctype, &net_from,
844             qport, maxlength, protocol );
845     if( nctype == NETCHAN_NEW ) {
846 		newcl->datagram_buffer = SV_Malloc( MAX_MSGLEN );
847 		SZ_Init( &newcl->datagram, newcl->datagram_buffer, MAX_MSGLEN );
848         newcl->datagram.allowoverflow = qtrue;
849 		newcl->AddMessage = SV_NewClientAddMessage;
850 	    newcl->WriteDatagram = SV_NewClientWriteDatagram;
851     } else {
852 		newcl->msgPool = SV_Mallocz( sizeof( *msg ) * MSGQUEUE_POOLSIZE );
853         for( i = 0, msg = newcl->msgPool; i < MSGQUEUE_POOLSIZE; i++, msg++ ) {
854             List_Append( &newcl->freeMsgList, msg );
855         }
856 		newcl->AddMessage = SV_OldClientAddMessage;
857 	    newcl->WriteDatagram = SV_OldClientWriteDatagram;
858     }
859 
860     // setup protocol
861     if( protocol == PROTOCOL_VERSION_MVD ) {
862 		newcl->WriteFrame = SV_WriteFrameToClient_Mvd;
863         newcl->BuildFrame = sv.state == ss_broadcast ?
864             SV_BuildProxyMvdFrame : SV_BuildMvdFrame;
865         if( nctype == NETCHAN_NEW ) {
866             newcl->AddUnicast = SV_NewClientAddUnicast;
867             newcl->AddMulticast = SV_NewClientAddMulticast;
868         } else {
869             newcl->AddUnicast = SV_OldClientAddUnicast;
870             newcl->AddMulticast = SV_OldClientAddMulticast;
871         }
872     } else {
873         if( protocol == PROTOCOL_VERSION_DEFAULT ) {
874 		    newcl->WriteFrame = SV_WriteFrameToClient_Default;
875         } else {
876 	        newcl->WriteFrame = SV_WriteFrameToClient_Enhanced;
877         }
878         newcl->BuildFrame = sv.state == ss_broadcast ?
879             SV_BuildProxyClientFrame : SV_BuildClientFrame;
880     }
881 
882     List_Append( &svs.clients, newcl );
883 
884 	Com_DPrintf( "Going from cs_free to cs_connected for %s\n", newcl->name );
885 	newcl->state = cs_connected;
886 
887 	newcl->sendTime = 0;
888 	newcl->surpressCount = 0;
889 	newcl->lastframe = -1;
890 	newcl->lastmessage = svs.realtime;	// don't timeout
891 	newcl->lastconnect = svs.realtime;
892 }
893 
Rcon_Validate(void)894 static int Rcon_Validate (void)
895 {
896 	if (!rcon_password->string[0])
897 		return 0;
898 
899 	if (strcmp (Cmd_Argv(1), rcon_password->string) )
900 		return 0;
901 
902 	return 1;
903 }
904 
905 /*
906 ===============
907 SVC_RemoteCommand
908 
909 A client issued an rcon command.
910 Redirect all printfs.
911 ===============
912 */
SVC_RemoteCommand(void)913 static void SVC_RemoteCommand( void ) {
914 	int		i;
915 	char *string;
916 
917 	if( SV_RateLimited( &svs.ratelimit_badrcon ) ) {
918 		Com_DPrintf( "Dropping rcon from %s\n",
919 			NET_AdrToString( &net_from ) );
920 		return;
921 	}
922 
923 	i = Rcon_Validate();
924 	string = Cmd_RawArgsFrom( 2 );
925 	if( i == 0 ) {
926 		Com_Printf( "Invalid rcon from %s:\n%s\n",
927 			NET_AdrToString( &net_from ), string );
928 		SV_OutOfBandPrintf( "Bad rcon_password.\n" );
929 		svs.ratelimit_badrcon.count++;
930 		return;
931     }
932 
933 	Com_Printf( "Rcon from %s:\n%s\n",
934 		NET_AdrToString( &net_from ), string );
935 
936 	Com_BeginRedirect( RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH,
937             SV_FlushRedirect );
938 
939 	Cmd_ExecuteString( string );
940 
941 	Com_EndRedirect();
942 }
943 
944 /*
945 =================
946 SV_ConnectionlessPacket
947 
948 A connectionless packet has four leading 0xff
949 characters to distinguish it from a game channel.
950 Clients that are in the game can still send
951 connectionless packets.
952 =================
953 */
SV_ConnectionlessPacket(void)954 static void SV_ConnectionlessPacket( void ) {
955 	char	*s;
956 	char	*c;
957 
958 	MSG_BeginReading();
959 	MSG_ReadLong();		// skip the -1 marker
960 
961 	s = MSG_ReadStringLine();
962 
963 	Cmd_TokenizeString( s, qfalse );
964 
965 	c = Cmd_Argv( 0 );
966 	Com_DPrintf( "ServerPacket %s : %s\n", NET_AdrToString( &net_from ), c );
967 
968 	if( !NET_IsLocalAddress( &net_from ) && net_from.ip[0] == 127 &&
969 		net_from.port == Cvar_VariableInteger( "net_port" ) )
970 	{
971 		Com_DPrintf( "dropped connectionless packet from self\n" );
972 		return;
973 	}
974 
975 	if( svs.initialized ) {
976 		if( !strcmp( c, "ping" ) ) {
977 			SVC_Ping();
978 			return;
979 		}
980 		if( !strcmp( c, "ack" ) ) {
981 			SVC_Ack();
982 			return;
983 		}
984 		if( !strcmp( c, "status" ) ) {
985 			SVC_Status();
986 			return;
987 		}
988 		if( !strcmp( c, "info" ) ) {
989 			SVC_Info();
990 			return;
991 		}
992 		if( !strcmp( c, "getchallenge" ) ) {
993 			SVC_GetChallenge();
994 			return;
995 		}
996 		if( !strcmp( c, "connect" ) ) {
997 			SVC_DirectConnect();
998 			return;
999 		}
1000 	}
1001 
1002 	if( !strcmp( c, "rcon" ) ) {
1003 		SVC_RemoteCommand();
1004 		return;
1005 	}
1006 
1007 	Com_DPrintf( "bad connectionless packet from %s:\n%s\n",
1008 		NET_AdrToString( &net_from ), s );
1009 }
1010 
1011 
1012 //============================================================================
1013 
1014 /*
1015 ===================
1016 SV_CalcPings
1017 
1018 Updates the cl->ping variables
1019 ===================
1020 */
SV_CalcPings(void)1021 void SV_CalcPings( void ) {
1022 	int			j;
1023 	client_t	*cl;
1024 	int			total, count;
1025 
1026     FOR_EACH_CLIENT( cl ) {
1027 		if( cl->state != cs_spawned )
1028 			continue;
1029 
1030 		total = 0;
1031 		count = 0;
1032 		for( j = 0; j < LATENCY_COUNTS; j++ ) {
1033 			if( cl->frame_latency[j] > 0 ) {
1034 				count++;
1035 				total += cl->frame_latency[j];
1036 			}
1037 		}
1038 		if( !count )
1039 			cl->ping = 0;
1040 		else
1041 			cl->ping = total / count;
1042 
1043 		// let the game dll know about the ping
1044 		cl->edict->client->ping = cl->ping;
1045 	}
1046 }
1047 
1048 
1049 /*
1050 ===================
1051 SV_GiveMsec
1052 
1053 Every few frames, gives all clients an allotment of milliseconds
1054 for their command moves.  If they exceed it, assume cheating.
1055 ===================
1056 */
SV_GiveMsec(void)1057 void SV_GiveMsec( void ) {
1058 	client_t	*cl;
1059 
1060 	if( sv.framenum & 15 )
1061 		return;
1062 
1063     FOR_EACH_CLIENT( cl ) {
1064 		cl->commandMsec = 1800;		// 1600 + some slop
1065 	}
1066 }
1067 
1068 
1069 /*
1070 =================
1071 SV_PacketEvent
1072 =================
1073 */
SV_PacketEvent(int ret)1074 void SV_PacketEvent( int ret ) {
1075 	client_t	*client;
1076 	int			qport;
1077 
1078 	if( ret == -1 ) {
1079 		if( !svs.initialized ) {
1080 			return;
1081 		}
1082 		// check for packets from connected clients
1083         FOR_EACH_CLIENT( client ) {
1084 			if( client->state < cs_connected ) {
1085 				continue;
1086 			}
1087 			if( !NET_IsEqualAdr( &net_from, &client->netchan->remote_address ) ) {
1088 				continue;
1089 			}
1090 			SV_DropClient( client, "connection reset by peer" );
1091 			break;
1092 		}
1093 		return;
1094 	}
1095 
1096 	// check for connectionless packet (0xffffffff) first
1097 	if( *( int * )msg_read.data == -1 ) {
1098 		SV_ConnectionlessPacket();
1099 		return;
1100 	}
1101 
1102 	if( !svs.initialized ) {
1103 		return;
1104 	}
1105 
1106 	// check for packets from connected clients
1107     FOR_EACH_CLIENT( client ) {
1108 		if( !NET_IsEqualBaseAdr( &net_from,
1109                     &client->netchan->remote_address ) )
1110         {
1111 			continue;
1112 		}
1113 
1114 		// read the qport out of the message so we can fix up
1115 		// stupid address translating routers
1116 		if( client->protocol == PROTOCOL_VERSION_DEFAULT ) {
1117 			qport = msg_read.data[8] | ( msg_read.data[9] << 8 );
1118 			if( client->netchan->qport != qport ) {
1119 				continue;
1120 			}
1121 		} else if( client->netchan->qport ) {
1122 			qport = msg_read.data[8];
1123 			if( client->netchan->qport != qport ) {
1124 				continue;
1125 			}
1126 		}
1127 
1128 		if( client->netchan->remote_address.port != net_from.port ) {
1129 			client->netchan->remote_address.port = net_from.port;
1130 			Com_DPrintf( "SV_PacketEvent: fixing up a translated port\n" );
1131 		}
1132 
1133 		if( client->netchan->Process( client->netchan ) ) {
1134 			// this is a valid, sequenced packet, so process it
1135 			if( client->state != cs_zombie ) {
1136 				client->lastmessage = svs.realtime;	// don't timeout
1137 				SV_ExecuteClientMessage( client );
1138 			}
1139 		}
1140 
1141 		break;
1142 
1143 	}
1144 }
1145 
1146 /*
1147 ==================
1148 SV_SendAsyncPackets
1149 
1150 If the client is just connecting, it is pointless waiting 100ms
1151 before sending next command and/or acknowledge, send it as soon
1152 as client rate limit allows.
1153 
1154 For spawned clients, we are forced to send svc_frame packets
1155 synchronously with game DLL ticks.
1156 ==================
1157 */
SV_SendAsyncPackets(void)1158 void SV_SendAsyncPackets( void ) {
1159 	qboolean retransmit;
1160 	client_t	*client;
1161 	int cursize;
1162 
1163     FOR_EACH_CLIENT( client ) {
1164 		// don't overrun bandwidth
1165 		if( client->sendTime > svs.realtime ) {
1166 			continue;
1167 		}
1168 
1169         // make sure all fragments are transmitted first
1170         if( client->netchan->fragment_pending ) {
1171             cursize = client->netchan->TransmitNextFragment( client->netchan );
1172             SV_CalcSendTime( client, cursize );
1173             continue;
1174         }
1175 
1176 		// spawned clients are handled elsewhere
1177 		if( client->state == cs_spawned && !client->download &&
1178                 !client->nodata )
1179         {
1180 			continue;
1181 		}
1182 
1183         // see if it's time to resend a (possibly dropped) packet
1184         retransmit = qfalse;
1185         if( Sys_Milliseconds() - client->netchan->last_sent > 1000 ) {
1186             retransmit = qtrue;
1187         }
1188 
1189         // don't write new reliables if not yet acknowledged
1190         if( client->netchan->reliable_length ) {
1191             if( !retransmit ) {
1192                 continue;
1193             }
1194         }
1195 
1196 		// just update reliable	if needed
1197 		if( client->netchan->type == NETCHAN_OLD ) {
1198 			SV_OldClientWriteReliableMessages( client,
1199                     client->netchan->maxpacketlen );
1200 		}
1201 		if( client->netchan->message.cursize ||
1202             client->netchan->reliable_ack_pending ||
1203             client->netchan->reliable_length ||
1204             retransmit )
1205         {
1206 			cursize = client->netchan->Transmit( client->netchan, 0, NULL );
1207 			SV_CalcSendTime( client, cursize );
1208 			if( sv_debug_send->integer ) {
1209 				Com_Printf( "SV_SendAsyncPackets( %s ): %d bytes\n",
1210                         client->name, cursize );
1211             }
1212 		}
1213 
1214 	}
1215 
1216 }
1217 
1218 /*
1219 ==================
1220 SV_CheckTimeouts
1221 
1222 If a packet has not been received from a client for timeout->value
1223 seconds, drop the conneciton.  Server frames are used instead of
1224 realtime to avoid dropping the local client while debugging.
1225 
1226 When a client is normally dropped, the client_t goes into a zombie state
1227 for a few seconds to make sure any final reliable message gets resent
1228 if necessary
1229 ==================
1230 */
SV_CheckTimeouts(void)1231 void SV_CheckTimeouts( void ) {
1232 	client_t	*client, *next;
1233 	uint32		droppoint, timeoutMsec;
1234 	uint32		zombiepoint, zombieMsec;
1235 
1236 	timeoutMsec = 1000 * timeout->value;
1237 	if( svs.realtime > timeoutMsec ) {
1238 		droppoint = svs.realtime - timeoutMsec;
1239 	} else {
1240 		droppoint = 0;
1241 	}
1242 
1243 	zombieMsec = 1000 * zombietime->value;
1244 	if( svs.realtime > zombieMsec ) {
1245 		zombiepoint = svs.realtime - zombieMsec;
1246 	} else {
1247 		zombiepoint = 0;
1248 	}
1249 
1250 	for( client = ( client_t * )svs.clients.first; client; client = next ) {
1251         next = ( client_t * )client->elem.next;
1252 		// message times may be wrong across a changelevel
1253 		if( client->lastmessage > svs.realtime ) {
1254 			client->lastmessage = svs.realtime;
1255 		}
1256 #ifndef DEDICATED_ONLY
1257 		// never timeout local clients
1258 		if( NET_IsLocalAddress( &client->netchan->remote_address ) ) {
1259 			continue;
1260 		}
1261 #endif
1262 		if( client->state == cs_zombie && client->lastmessage < zombiepoint ) {
1263 			SV_RemoveClient( client );
1264 			continue;
1265 		}
1266 		if( client->state >= cs_connected && client->lastmessage < droppoint ) {
1267 			SV_DropClient( client, "timed out" );
1268 			SV_RemoveClient( client );	// don't bother with zombie state
1269 		}
1270 	}
1271 }
1272 
1273 /*
1274 ================
1275 SV_PrepWorldFrame
1276 
1277 This has to be done before the world logic, because
1278 player processing happens outside RunWorldFrame
1279 ================
1280 */
SV_PrepWorldFrame(void)1281 void SV_PrepWorldFrame( void ) {
1282 	edict_t	*ent;
1283 	int		i;
1284 
1285 	for( i = 1; i < ge->num_edicts; i++, ent++ ) {
1286 		ent = EDICT_NUM( i );
1287 		// events only last for a single message
1288 		ent->s.event = 0;
1289 	}
1290 
1291 	sv.tracecount = 0;
1292 
1293 }
1294 
1295 
1296 /*
1297 =================
1298 SV_RunGameFrame
1299 =================
1300 */
SV_RunGameFrame(void)1301 static void SV_RunGameFrame( void ) {
1302 	if( host_speeds->integer )
1303 		time_before_game = Sys_Milliseconds();
1304 
1305 	// we always need to bump framenum, even if we
1306 	// don't run the world, otherwise the delta
1307 	// compression can get confused when a client
1308 	// has the "current" frame
1309 	sv.framenum++;
1310 	sv.time += 100;
1311 
1312 	MVD_RecBeginFrame();
1313 
1314 	ge->RunFrame();
1315 
1316 	if( msg_write.cursize ) {
1317 		Com_EPrintf( "Game DLL left garbage in multicast buffer, cleared." );
1318 		SZ_Clear( &msg_write );
1319 	}
1320 
1321 	// save the entire world state if recording a serverdemo
1322 	MVD_RecEndFrame();
1323 
1324 	// never get more than one tic behind
1325 	if( sv.time < svs.realtime ) {
1326 		if( sv_showclamp->integer )
1327 			Com_Printf( "sv highclamp\n" );
1328 		svs.realtime = sv.time;
1329 	}
1330 
1331 	if( host_speeds->integer )
1332 		time_after_game = Sys_Milliseconds();
1333 
1334 }
1335 
1336 #ifndef DEDICATED_ONLY
SV_CheckPaused(void)1337 static void SV_CheckPaused( void ) {
1338 	client_t *client;
1339 
1340 	sv_paused->integer = 0;
1341 	if( cl_paused->integer ) {
1342         FOR_EACH_CLIENT( client ) {
1343             if( client->state != cs_spawned ) {
1344                 break; // never pause if loading
1345             }
1346             if( !NET_IsLocalAddress( &client->netchan->remote_address ) ) {
1347                 break; // never pause in multiplayer
1348             }
1349 		}
1350 		if( !client ) {
1351 			sv_paused->integer = 1;
1352 			return; // don't run if paused
1353 		}
1354 
1355 		cl_paused->integer = 0;
1356 	}
1357 }
1358 #endif
1359 
1360 /*
1361 ==================
1362 SV_Frame
1363 
1364 ==================
1365 */
SV_Frame(int msec)1366 void SV_Frame( int msec ) {
1367 	time_before_game = time_after_game = 0;
1368 
1369 	svs.realtime += msec;
1370 
1371 	MVD_ClientFrame( msec );
1372 
1373 	// if server is not active, do nothing
1374 	if( !svs.initialized ) {
1375 		if( dedicated->integer ) {
1376 			Sys_Sleep( 1 );
1377 		}
1378 		return;
1379 	}
1380 
1381 #ifndef DEDICATED_ONLY
1382 	SV_CheckPaused();
1383 	if( sv_paused->integer ) {
1384 		return;
1385 	}
1386 #endif
1387 
1388 	// check timeouts
1389 	SV_CheckTimeouts ();
1390 
1391     // deliver fragments and reliable messages for connecting clients
1392 	SV_SendAsyncPackets();
1393 
1394 	// move autonomous things around if enough time has passed
1395 	if( !com_timedemo->integer && svs.realtime < sv.time ) {
1396 		// never let the time get too far off
1397 		if( sv.time - svs.realtime > 100 ) {
1398 			if( sv_showclamp->integer )
1399 				Com_Printf( "sv lowclamp\n" );
1400 			svs.realtime = sv.time - 100;
1401 		}
1402 		if( dedicated->integer && com_sleep->integer ) {
1403             if( com_sleep->integer > 1 ) {
1404     			Sys_Sleep( sv.time - svs.realtime );
1405             } else {
1406                 Sys_Sleep( 1 );
1407             }
1408 		}
1409 		return;
1410 	}
1411 
1412 	// update ping based on the last known frame from all clients
1413 	SV_CalcPings ();
1414 
1415 	// give the clients some timeslices
1416 	SV_GiveMsec ();
1417 
1418 	// let everything in the world think and move
1419 	SV_RunGameFrame ();
1420 
1421 	// send messages back to the clients that had packets read this frame
1422 	SV_SendClientMessages ();
1423 
1424 	// send a heartbeat to the master if needed
1425 	Master_Heartbeat ();
1426 
1427 	// clear teleport flags, etc for next frame
1428 	if( sv.state != ss_broadcast ) {
1429 		SV_PrepWorldFrame ();
1430 	}
1431 }
1432 
1433 //============================================================================
1434 
1435 /*
1436 ================
1437 Master_Heartbeat
1438 
1439 Send a message to the master every few minutes to
1440 let it know we are alive, and log information
1441 ================
1442 */
1443 #define	HEARTBEAT_SECONDS	300
Master_Heartbeat(void)1444 void Master_Heartbeat (void)
1445 {
1446 	char		*string;
1447 	int			i;
1448 
1449 	// pgm post3.19 change, cvar pointer not validated before dereferencing
1450 	if (!dedicated || !dedicated->integer)
1451 		return;		// only dedicated servers send heartbeats
1452 
1453 	// pgm post3.19 change, cvar pointer not validated before dereferencing
1454 	if (!public_server || !public_server->integer)
1455 		return;		// a private dedicated game
1456 
1457 	// check for time wraparound
1458 	if (svs.last_heartbeat > svs.realtime)
1459 		svs.last_heartbeat = svs.realtime;
1460 
1461 	if (svs.realtime - svs.last_heartbeat < HEARTBEAT_SECONDS*1000)
1462 		return;		// not time to send yet
1463 
1464 	svs.last_heartbeat = svs.realtime;
1465 
1466 	// send the same string that we would give for a status OOB command
1467 	string = SV_StatusString( qfalse );
1468 
1469 	// send to group master
1470 	for (i=0 ; i<MAX_MASTERS ; i++)
1471 		if (master_adr[i].port)
1472 		{
1473 			Com_Printf ("Sending heartbeat to %s\n",
1474                     NET_AdrToString (&master_adr[i]));
1475 			Netchan_OutOfBandPrint (NS_SERVER, &master_adr[i],
1476                     "heartbeat\n%s", string);
1477 		}
1478 }
1479 
1480 /*
1481 =================
1482 Master_Shutdown
1483 
1484 Informs all masters that this server is going down
1485 =================
1486 */
Master_Shutdown(void)1487 void Master_Shutdown (void)
1488 {
1489 	int			i;
1490 
1491 	// pgm post3.19 change, cvar pointer not validated before dereferencing
1492 	if (!dedicated || !dedicated->integer)
1493 		return;		// only dedicated servers send heartbeats
1494 
1495 	// pgm post3.19 change, cvar pointer not validated before dereferencing
1496 	if (!public_server || !public_server->integer)
1497 		return;		// a private dedicated game
1498 
1499 	// send to group master
1500 	for (i=0 ; i<MAX_MASTERS ; i++)
1501 		if (master_adr[i].port)
1502 		{
1503 			if (i > 0)
1504 				Com_Printf ("Sending heartbeat to %s\n",
1505                         NET_AdrToString (&master_adr[i]));
1506 			Netchan_OutOfBandPrint (NS_SERVER, &master_adr[i], "shutdown");
1507 		}
1508 }
1509 
1510 //============================================================================
1511 
1512 /*
1513 =================
1514 SV_UpdateUserinfo
1515 
1516 Ensures that name, skin and ip are properly set.
1517 WARNING: may modify userinfo in place!
1518 =================
1519 */
SV_UpdateUserinfo(char * userinfo)1520 void SV_UpdateUserinfo( char *userinfo ) {
1521 	char *s;
1522 	int length;
1523 
1524 	if( !userinfo[0] ) {
1525 		SV_ClientPrintf( sv_client, PRINT_HIGH,
1526 			"Empty userinfo string supplied. Ignored.\n" );
1527 		return;
1528 	}
1529 
1530 	if( !Info_Validate( userinfo ) ) {
1531 		SV_ClientPrintf( sv_client, PRINT_HIGH,
1532 			"Malformed userinfo string supplied. Ignored.\n" );
1533 		return;
1534 	}
1535 
1536 	s = Info_ValueForKey( userinfo, "name" );
1537 	if( !s[0] || Q_IsWhiteSpace( s ) ) {
1538 		SV_ClientPrintf( sv_client, PRINT_HIGH,
1539 			"Empty name supplied in userinfo. Ignored.\n" );
1540 		return;
1541 	}
1542 
1543 	length = strlen( s );
1544 	if(	length > MAX_CLIENT_NAME - 1 ) {
1545 		SV_ClientPrintf( sv_client, PRINT_HIGH,
1546 			"Oversize name supplied in userinfo. Ignored.\n" );
1547 		return;
1548 	}
1549 
1550 	if( sv_client->protocol != PROTOCOL_VERSION_MVD ) {
1551 		s = Info_ValueForKey( userinfo, "skin" );
1552 		if( !s[0] ) {
1553 			SV_ClientPrintf( sv_client, PRINT_HIGH,
1554 				"Empty skin supplied in userinfo. Ignored.\n" );
1555 			return;
1556 		}
1557 
1558 		length = strlen( s );
1559 		if( !Q_ispath( s[0] ) || !Q_ispath( s[ length - 1 ] ) || strchr( s, '.' ) ) {
1560 			SV_ClientPrintf( sv_client, PRINT_HIGH,
1561 				"Malformed skin supplied in userinfo. Ignored.\n" );
1562 			return;
1563 		}
1564 	}
1565 
1566 	// force the IP key/value pair so the game can filter based on ip
1567 	s = NET_AdrToString( &sv_client->netchan->remote_address );
1568 	if( !Info_AttemptSetValueForKey( userinfo, "ip", s ) ) {
1569 		return;
1570 	}
1571 
1572 	strcpy( sv_client->userinfo, userinfo );
1573 
1574 	SV_UserinfoChanged( sv_client );
1575 }
1576 
1577 
1578 /*
1579 =================
1580 SV_UserinfoChanged
1581 
1582 Pull specific info from a newly changed userinfo string
1583 into a more C freindly form.
1584 =================
1585 */
SV_UserinfoChanged(client_t * cl)1586 void SV_UserinfoChanged( client_t *cl ) {
1587 	char	*val;
1588 	int		i;
1589 
1590 	// call prog code to allow overrides
1591 	ge->ClientUserinfoChanged( cl->edict, cl->userinfo );
1592 
1593 	// name for C code
1594 	val = Info_ValueForKey( cl->userinfo, "name" );
1595 	Q_strncpyz( cl->name, val, sizeof( cl->name ) );
1596 	// mask off high bit
1597 	for( i = 0; cl->name[i]; i++ )
1598 		cl->name[i] &= 127;
1599 
1600 	// rate command
1601 	val = Info_ValueForKey( cl->userinfo, "rate" );
1602 	if( *val ) {
1603 		cl->rate = atoi( val );
1604 		clamp( cl->rate, 100, 15000 );
1605 	} else {
1606 		if( cl->protocol == PROTOCOL_VERSION_MVD ) {
1607 			cl->rate = 15000;
1608 		} else {
1609 			cl->rate = 5000;
1610 		}
1611 	}
1612 
1613 	// msg command
1614 	val = Info_ValueForKey( cl->userinfo, "msg" );
1615 	if( *val ) {
1616 		cl->messagelevel = atoi( val );
1617 	}
1618 
1619 }
1620 
1621 
1622 //============================================================================
1623 
StatusLimit_OnChange(cvar_t * self,void * arg)1624 static void StatusLimit_OnChange( cvar_t *self, void *arg ) {
1625 	SV_RateInit( &svs.ratelimit_status, self->integer, 1000 );
1626 }
1627 
BadAuthTime_OnChange(cvar_t * self,void * arg)1628 static void BadAuthTime_OnChange( cvar_t *self, void *arg ) {
1629 	SV_RateInit( &svs.ratelimit_badpass, 1, self->value * 1000 );
1630 	SV_RateInit( &svs.ratelimit_badrcon, 1, self->value * 1000 );
1631 }
1632 
1633 /*
1634 ===============
1635 SV_Init
1636 
1637 Only called at quake2.exe startup, not for each game
1638 ===============
1639 */
SV_Init(void)1640 void SV_Init (void)
1641 {
1642 	SV_InitOperatorCommands	();
1643 	MVD_Register();
1644 
1645 	Cvar_Get( "protocol", va( "%i", PROTOCOL_VERSION_DEFAULT ), CVAR_SERVERINFO|CVAR_ROM );
1646 
1647 	Cvar_Get( "skill", "1", CVAR_LATCH );
1648 	Cvar_Get( "deathmatch", "0", CVAR_SERVERINFO|CVAR_LATCH );
1649 	Cvar_Get( "coop", "0", CVAR_SERVERINFO|CVAR_LATCH );
1650 	Cvar_Get( "cheats", "0", CVAR_SERVERINFO|CVAR_LATCH );
1651 	Cvar_Get( "dmflags", va( "%i", DF_INSTANT_ITEMS ), CVAR_SERVERINFO );
1652 	Cvar_Get( "fraglimit", "0", CVAR_SERVERINFO );
1653 	Cvar_Get( "timelimit", "0", CVAR_SERVERINFO );
1654 
1655 	sv_maxclients = Cvar_Get( "maxclients", "1", CVAR_SERVERINFO|CVAR_LATCH );
1656 	sv_mvd_enable = Cvar_Get( "mvd_enable", "0", CVAR_SERVERINFO|CVAR_LATCH );
1657 	sv_reserved_slots = Cvar_Get( "sv_reserved_slots", "0", CVAR_LATCH );
1658 	sv_hostname = Cvar_Get( "hostname", "noname", CVAR_SERVERINFO|CVAR_ARCHIVE );
1659 	timeout = Cvar_Get( "timeout", "125", 0 );
1660 	zombietime = Cvar_Get( "zombietime", "2", 0 );
1661 	sv_showclamp = Cvar_Get( "showclamp", "0", 0 );
1662 
1663 	sv_enforcetime = Cvar_Get ( "sv_enforcetime", "1", 0 );
1664 
1665 	allow_download = Cvar_Get( "allow_download", "1", CVAR_ARCHIVE );
1666 	allow_download_players = Cvar_Get( "allow_download_players", "0", CVAR_ARCHIVE );
1667 	allow_download_models = Cvar_Get( "allow_download_models", "1", CVAR_ARCHIVE );
1668 	allow_download_sounds = Cvar_Get( "allow_download_sounds", "1", CVAR_ARCHIVE );
1669 	allow_download_maps	= Cvar_Get( "allow_download_maps", "1", CVAR_ARCHIVE );
1670 	allow_download_demos = Cvar_Get( "allow_download_demos", "0", 0 );
1671 	allow_download_other = Cvar_Get( "allow_download_other", "0", 0 );
1672 
1673 	sv_noreload = Cvar_Get ("sv_noreload", "0", 0);
1674 	sv_airaccelerate = Cvar_Get("sv_airaccelerate", "0", CVAR_LATCH);
1675 	sv_qwmod = Cvar_Get( "sv_qwmod", "0", CVAR_LATCH ); //atu QWMod
1676 	public_server = Cvar_Get ("public", "0", 0);
1677 	rcon_password = Cvar_Get( "rcon_password", "", CVAR_PRIVATE );
1678 	sv_password = Cvar_Get( "sv_password", "", CVAR_PRIVATE );
1679 	sv_mvd_password = Cvar_Get( "sv_mvd_password", "", CVAR_PRIVATE );
1680 
1681 	sv_debug_send = Cvar_Get( "sv_debug_send", "0", 0 );
1682 	sv_pad_packets = Cvar_Get( "sv_pad_packets", "0", 0 );
1683 	sv_lan_force_rate = Cvar_Get( "sv_lan_force_rate", "0", 0 );
1684 
1685 	sv_strafejump_hack = Cvar_Get( "sv_strafejump_hack", "0", CVAR_LATCH );
1686 
1687 	sv_bodyque_hack = Cvar_Get( "sv_bodyque_hack", "0", 0 );
1688 #ifndef _WIN32
1689 	sv_oldgame_hack = Cvar_Get( "sv_oldgame_hack", "0", CVAR_LATCH );
1690 #endif
1691 
1692 	sv_iplimit = Cvar_Get( "sv_iplimit", "3", 0 );
1693 	sv_nextserver = Cvar_Get( "nextserver", "", 0 );
1694 
1695 	sv_status_show = Cvar_Get( "sv_status_show", "2", 0 );
1696 
1697 	sv_status_limit = Cvar_Get( "sv_status_limit", "15", 0 );
1698 	sv_status_limit->changedFunc = StatusLimit_OnChange;
1699 
1700 	sv_badauth_time = Cvar_Get( "sv_badauth_time", "1", 0 );
1701 	sv_badauth_time->changedFunc = BadAuthTime_OnChange;
1702 
1703 	SV_RateInit( &svs.ratelimit_status, sv_status_limit->integer, 1000 );
1704 	SV_RateInit( &svs.ratelimit_badpass, 1, sv_badauth_time->value * 1000 );
1705 	SV_RateInit( &svs.ratelimit_badrcon, 1, sv_badauth_time->value * 1000 );
1706 }
1707 
1708 /*
1709 ==================
1710 SV_FinalMessage
1711 
1712 Used by SV_Shutdown to send a final message to all
1713 connected clients before the server goes down.  The messages are sent immediately,
1714 not just stuck on the outgoing message list, because the server is going
1715 to totally exit after returning from this function.
1716 ==================
1717 */
SV_FinalMessage(const char * message,int cmd)1718 static void SV_FinalMessage( const char *message, int cmd ) {
1719 	client_t	*client, *next;
1720 
1721 	MSG_WriteByte( svc_print );
1722 	MSG_WriteByte( PRINT_HIGH );
1723 	MSG_WriteString( message );
1724 	MSG_WriteByte( cmd );
1725 
1726 	// send it twice
1727 	// stagger the packets to crutch operating system limited buffers
1728 
1729     FOR_EACH_CLIENT( client ) {
1730 		if( client->state < cs_connected ) {
1731 			continue;
1732 		}
1733 		while( client->netchan->fragment_pending ) {
1734 			client->netchan->TransmitNextFragment( client->netchan );
1735 		}
1736 		client->netchan->Transmit( client->netchan,
1737                 msg_write.cursize, msg_write.data );
1738 	}
1739 
1740     FOR_EACH_CLIENT( client ) {
1741 		if( client->state < cs_connected ) {
1742 			continue;
1743 		}
1744 		while( client->netchan->fragment_pending ) {
1745 			client->netchan->TransmitNextFragment( client->netchan );
1746 		}
1747 		client->netchan->Transmit( client->netchan,
1748                 msg_write.cursize, msg_write.data );
1749 	}
1750 
1751 	SZ_Clear( &msg_write );
1752 
1753 	// free any data dynamically allocated
1754 	for( client = ( client_t * )svs.clients.first; client; client = next ) {
1755         next = ( client_t * )client->elem.next;
1756 		if( client->state != cs_zombie ) {
1757 			SV_CleanClient( client );
1758 		}
1759 		SV_RemoveClient( client );
1760 	}
1761 }
1762 
1763 
1764 
1765 /*
1766 ================
1767 SV_Shutdown
1768 
1769 Called when each game quits,
1770 before Sys_Quit or Sys_Error
1771 ================
1772 */
SV_Shutdown(const char * finalmsg,killtype_t type)1773 void SV_Shutdown( const char *finalmsg, killtype_t type ) {
1774 	int cmd;
1775 
1776 	Cvar_Set( "sv_running", "0" );
1777 	Cvar_Set( "sv_paused", "0" );
1778 
1779 	MVD_Disconnect();
1780 
1781 	if( !svs.initialized ) {
1782 		return;
1783 	}
1784 	if( svs.clientpool ) {
1785 		switch( type ) {
1786 		case KILL_RESTART:
1787 			cmd = svc_reconnect;
1788 			break;
1789 		case KILL_DISCONNECT:
1790 			if( !dedicated->integer ) {
1791 				cmd = svc_disconnect;
1792 				break;
1793 			}
1794 
1795 			if( mvd_safecmd->string[0] ) {
1796 				Cbuf_AddText( mvd_safecmd->string );
1797 				cmd = svc_reconnect;
1798 			} else {
1799 				cmd = svc_disconnect;
1800 			}
1801 			break;
1802 		default:
1803 			cmd = svc_disconnect;
1804 			break;
1805 		}
1806 		SV_FinalMessage( finalmsg, cmd );
1807 	}
1808 
1809 	Master_Shutdown();
1810 	SV_ShutdownGameProgs();
1811 
1812 	MVD_RecStop();
1813 
1814 	// free current level
1815 	CM_FreeMap( &sv.cm );
1816 	if( sv.demofile ) {
1817 		FS_FCloseFile( sv.demofile );
1818 	}
1819 	memset( &sv, 0, sizeof( sv ) );
1820 
1821 	// free server static data
1822 	if( svs.clientpool )
1823 		Z_Free( svs.clientpool );
1824 	if( svs.entityStates )
1825 		Z_Free( svs.entityStates );
1826 	if( svs.playerStates )
1827 		Z_Free( svs.playerStates );
1828 	memset( &svs, 0, sizeof( svs ) );
1829 
1830 	sv_client = NULL;
1831 	sv_player = NULL;
1832 
1833 	Z_LeakTest( TAG_SERVER );
1834 
1835 }
1836 
1837