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 // sv_main.c.
22 // Server main program
23 //
24 
25 #include "sv_local.h"
26 
27 netAdr_t	sv_masterAddresses[MAX_MASTERS];	// address of group servers
28 
29 svClient_t	*sv_currentClient;			// current client
30 
31 cVar_t	*sv_paused;
32 cVar_t	*sv_timedemo;
33 
34 cVar_t	*sv_enforcetime;
35 
36 cVar_t	*timeout;				// seconds without any message
37 cVar_t	*zombietime;			// seconds to sink messages after disconnect
38 
39 cVar_t	*rcon_password;			// password for remote server commands
40 
41 cVar_t	*allow_download;
42 cVar_t	*allow_download_players;
43 cVar_t	*allow_download_models;
44 cVar_t	*allow_download_sounds;
45 cVar_t	*allow_download_maps;
46 
47 cVar_t	*sv_airaccelerate;
48 
49 cVar_t	*sv_noreload;			// don't reload level state when reentering
50 
51 cVar_t	*maxclients;
52 cVar_t	*sv_showclamp;
53 
54 cVar_t	*hostname;
55 cVar_t	*public_server;			// should heartbeats be sent
56 
57 cVar_t	*sv_reconnect_limit;	// minimum seconds between connect messages
58 
59 struct memPool_s	*sv_gameSysPool;
60 struct memPool_s	*sv_genericPool;
61 
62 /*
63 =====================
64 SV_SetState
65 =====================
66 */
SV_SetState(ssState_t state)67 void SV_SetState (ssState_t state)
68 {
69 	Com_SetServerState (state);
70 }
71 
72 
73 /*
74 =====================
75 SV_DropClient
76 
77 Called when the player is totally leaving the server, either willingly
78 or unwillingly.  This is NOT called if the entire server is quiting
79 or crashing.
80 =====================
81 */
SV_DropClient(svClient_t * drop)82 void SV_DropClient (svClient_t *drop)
83 {
84 	// Add the disconnect
85 	MSG_WriteByte (&drop->netChan.message, SVC_DISCONNECT);
86 
87 	if (drop->state == SVCS_SPAWNED) {
88 		// Call the prog function for removing a client
89 		// This will remove the body, among other things
90 		ge->ClientDisconnect (drop->edict);
91 	}
92 
93 	if (drop->download) {
94 		FS_FreeFile (drop->download);
95 		drop->download = NULL;
96 	}
97 
98 	drop->state = SVCS_FREE;		// become free in a few seconds
99 	drop->name[0] = 0;
100 }
101 
102 
103 /*
104 =================
105 SV_UserinfoChanged
106 
107 Pull specific info from a newly changed userinfo string
108 into a more C freindly form.
109 =================
110 */
SV_UserinfoChanged(svClient_t * cl)111 void SV_UserinfoChanged (svClient_t *cl)
112 {
113 	char	*val;
114 	int		i;
115 
116 	// Call prog code to allow overrides
117 	ge->ClientUserinfoChanged (cl->edict, cl->userInfo);
118 
119 	// Name for C code
120 	strncpy (cl->name, Info_ValueForKey (cl->userInfo, "name"), sizeof (cl->name)-1);
121 	// Mask off high bit
122 	for (i=0 ; i<sizeof (cl->name) ; i++)
123 		cl->name[i] &= 127;
124 
125 	// Rate command
126 	val = Info_ValueForKey (cl->userInfo, "rate");
127 	if (strlen (val)) {
128 		i = atoi(val);
129 		cl->rate = clamp (i, 100, 15000);
130 	}
131 	else
132 		cl->rate = 5000;
133 
134 	// MSG command
135 	val = Info_ValueForKey (cl->userInfo, "msg");
136 	if (strlen (val))
137 		cl->messageLevel = atoi (val);
138 }
139 
140 
141 /*
142 ===================
143 SV_UpdateTitle
144 ===================
145 */
SV_UpdateTitle(void)146 void SV_UpdateTitle (void)
147 {
148 #if 0
149 	hostname->modified = qFalse;
150 
151 	if (Com_ServerState() == SS_GAME) {
152 		Sys_SetConsoleTitle (Q_VarArgs ("EGL Server: %s (port %i)", Cvar_GetStringValue ("hostname"), Cvar_GetIntegerValue ("port")));
153 		return;
154 	}
155 
156 	Sys_SetConsoleTitle (NULL);
157 #endif
158 }
159 
160 /*
161 =============================================================================
162 
163 	Com_Printf REDIRECTION
164 
165 =============================================================================
166 */
167 
168 #define SV_OUTPUTBUF_LENGTH	(MAX_SV_MSGLEN - 16)
169 enum {
170 	RD_NONE,
171 	RD_CLIENT,
172 	RD_PACKET
173 };
174 
175 static char	sv_outputBuffer[SV_OUTPUTBUF_LENGTH];
176 
177 /*
178 =================
179 SV_FlushRedirect
180 =================
181 */
SV_FlushRedirect(int target,char * outBuffer)182 static void SV_FlushRedirect (int target, char *outBuffer)
183 {
184 	switch (target) {
185 	case RD_PACKET:
186 		Netchan_OutOfBandPrint (NS_SERVER, &sv_netFrom, "print\n%s", outBuffer);
187 		break;
188 
189 	case RD_CLIENT:
190 		MSG_WriteByte (&sv_currentClient->netChan.message, SVC_PRINT);
191 		MSG_WriteByte (&sv_currentClient->netChan.message, PRINT_HIGH);
192 		MSG_WriteString (&sv_currentClient->netChan.message, outBuffer);
193 		break;
194 	}
195 }
196 
197 /*
198 ==============================================================================
199 
200 	CONNECTIONLESS COMMANDS
201 
202 ==============================================================================
203 */
204 
205 /*
206 ===============
207 SV_StatusString
208 
209 Builds the string that is sent as heartbeats and status replies
210 ===============
211 */
SV_StatusString(void)212 static char *SV_StatusString (void)
213 {
214 	char		player[1024];
215 	static char	status[MAX_SV_MSGLEN - 16];
216 	int			i;
217 	svClient_t	*cl;
218 	int			statusLength;
219 	int			playerLength;
220 
221 	Q_snprintfz (status, sizeof (status), "%s\n", Cvar_BitInfo (CVAR_SERVERINFO));
222 	statusLength = strlen (status);
223 
224 	for (i=0 ; i<maxclients->intVal ; i++) {
225 		if (svs.clients[i].state < SVCS_CONNECTED)
226 			continue;
227 
228 		cl = &svs.clients[i];
229 		Q_snprintfz (player, sizeof (player), "%i %i \"%s\"\n",
230 			cl->edict->client->playerState.stats[STAT_FRAGS], cl->ping, cl->name);
231 
232 		playerLength = strlen (player);
233 		if (statusLength+playerLength >= sizeof(status))
234 			break;		// Can't hold any more
235 
236 		strcpy (status+statusLength, player);
237 		statusLength += playerLength;
238 	}
239 
240 	return status;
241 }
242 
243 
244 /*
245 ================
246 SVC_Status_f
247 
248 Responds with all the info that qplug or qspy can see
249 ================
250 */
SVC_Status_f(void)251 static void SVC_Status_f (void)
252 {
253 	Netchan_OutOfBandPrint (NS_SERVER, &sv_netFrom, "print\n%s", SV_StatusString());
254 }
255 
256 
257 /*
258 ================
259 SVC_Ack_f
260 ================
261 */
SVC_Ack_f(void)262 static void SVC_Ack_f (void)
263 {
264 	int		i;
265 
266 	// R1: could be used to flood server console - only show acks from masters.
267 	for (i=0 ; i<MAX_MASTERS ; i++) {
268 		if (!sv_masterAddresses[i].port)
269 			continue;
270 		if (!NET_CompareBaseAdr (sv_masterAddresses[i], sv_netFrom))
271 			continue;
272 
273 		Com_Printf (0, "Ping acknowledge from %s\n", NET_AdrToString (&sv_netFrom));
274 	}
275 }
276 
277 
278 /*
279 ================
280 SVC_Info_f
281 
282 Responds with short info for broadcast scans
283 The second parameter should be the current protocol version number.
284 ================
285 */
SVC_Info_f(void)286 static void SVC_Info_f (void)
287 {
288 	char	string[64];
289 	int		i, count;
290 	int		version;
291 
292 	if (maxclients->intVal == 1)
293 		return;		// Ignore in single player
294 
295 	version = atoi (Cmd_Argv (1));
296 	if (version != ORIGINAL_PROTOCOL_VERSION)
297 		return;
298 
299 	count = 0;
300 	for (i=0 ; i<maxclients->intVal ; i++) {
301 		if (svs.clients[i].state >= SVCS_CONNECTED)
302 			count++;
303 	}
304 
305 	Q_snprintfz (string, sizeof (string), "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, maxclients->intVal);
306 
307 	Netchan_OutOfBandPrint (NS_SERVER, &sv_netFrom, "info\n%s", string);
308 }
309 
310 
311 /*
312 ================
313 SVC_Ping_f
314 
315 Just responds with an acknowledgement
316 ================
317 */
SVC_Ping_f(void)318 static void SVC_Ping_f (void)
319 {
320 	Netchan_OutOfBandPrint (NS_SERVER, &sv_netFrom, "ack");
321 }
322 
323 
324 /*
325 =================
326 SVC_GetChallenge_f
327 
328 Returns a challenge number that can be used in a subsequent client_connect command.
329 We do this to prevent denial of service attacks that flood the server with invalid connection IPs.
330 With a challenge, they must give a valid IP address.
331 =================
332 */
SVC_GetChallenge_f(void)333 static void SVC_GetChallenge_f (void)
334 {
335 	int		i;
336 	int		oldest;
337 	uint32	oldestTime;
338 
339 	oldest = 0;
340 	oldestTime = 0xffffffff;	// UINT_MAX?
341 
342 	// See if we already have a challenge for this ip
343 	for (i=0 ; i<MAX_CHALLENGES ; i++) {
344 		if (NET_CompareBaseAdr (sv_netFrom, svs.challenges[i].adr))
345 			break;
346 		if (svs.challenges[i].time < oldestTime) {
347 			oldestTime = svs.challenges[i].time;
348 			oldest = i;
349 		}
350 	}
351 
352 	if (i == MAX_CHALLENGES) {
353 		// Overwrite the oldest
354 		svs.challenges[oldest].challenge = rand() & 0x7fff;
355 		svs.challenges[oldest].adr = sv_netFrom;
356 		svs.challenges[oldest].time = Sys_UMilliseconds ();
357 		i = oldest;
358 	}
359 
360 	// Send it back
361 	Netchan_OutOfBandPrint (NS_SERVER, &sv_netFrom, "challenge %i", svs.challenges[i].challenge);
362 }
363 
364 
365 /*
366 ==================
367 SVC_DirectConnect_f
368 
369 A connection request that did not come from the master
370 ==================
371 */
SVC_DirectConnect_f(void)372 static void SVC_DirectConnect_f (void)
373 {
374 	char		userInfo[MAX_INFO_STRING];
375 	netAdr_t	adr;
376 	int			i;
377 	svClient_t	*cl, *newcl;
378 	svClient_t	temp;
379 	edict_t		*ent;
380 	int			edictNum;
381 	int			version;
382 	int			qPort;
383 	int			challenge;
384 
385 	adr = sv_netFrom;
386 
387 	Com_DevPrintf (0, "SVC_DirectConnect_f ()\n");
388 
389 	// Check protocol version
390 	version = atoi (Cmd_Argv (1));
391 	if (version != ORIGINAL_PROTOCOL_VERSION) {
392 		Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nServer is not using same protocol (%i != %i).\n",
393 								version, ORIGINAL_PROTOCOL_VERSION);
394 		Com_DevPrintf (0, "    rejected connect from version %i\n", version);
395 		return;
396 	}
397 
398 	qPort = atoi (Cmd_Argv (2));
399 	challenge = atoi (Cmd_Argv (3));
400 	Q_strncpyz (userInfo, Cmd_Argv (4), sizeof (userInfo));
401 
402 	// Force the IP key/value pair so the game can filter based on ip
403 	Info_SetValueForKey (userInfo, "ip", NET_AdrToString (&sv_netFrom));
404 
405 	// Attractloop servers are ONLY for local clients
406 	if (sv.attractLoop) {
407 		if (!NET_IsLocalAddress (adr)) {
408 			Com_Printf (PRNT_WARNING, "Remote connect in attract loop. Ignored.\n");
409 			Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nConnection refused.\n");
410 			return;
411 		}
412 	}
413 
414 	// See if the challenge is valid
415 	if (!NET_IsLocalAddress (adr)) {
416 		for (i=0 ; i<MAX_CHALLENGES ; i++) {
417 			if (NET_CompareBaseAdr (sv_netFrom, svs.challenges[i].adr)) {
418 				if (challenge == svs.challenges[i].challenge)
419 					break;		// good
420 				Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nBad challenge.\n");
421 				return;
422 			}
423 		}
424 
425 		if (i == MAX_CHALLENGES) {
426 			Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nNo challenge for address.\n");
427 			return;
428 		}
429 	}
430 
431 	newcl = &temp;
432 	memset (newcl, 0, sizeof (svClient_t));
433 
434 	// If there is already a slot for this ip, reuse it
435 	for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
436 		if (cl->state == SVCS_FREE)
437 			continue;
438 
439 		if (NET_CompareBaseAdr (adr, cl->netChan.remoteAddress)
440 		&& (cl->netChan.qPort == qPort || adr.port == cl->netChan.remoteAddress.port)) {
441 			if (!NET_IsLocalAddress (adr) && svs.realTime-cl->lastConnect < sv_reconnect_limit->intVal*1000) {
442 				Com_DevPrintf (0, "%s:reconnect rejected : too soon\n", NET_AdrToString (&adr));
443 				return;
444 			}
445 
446 			Com_Printf (0, "%s:reconnect\n", NET_AdrToString (&adr));
447 
448 			newcl = cl;
449 			goto gotNewClient;
450 		}
451 	}
452 
453 	// Find a client slot
454 	newcl = NULL;
455 	for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
456 		if (cl->state == SVCS_FREE) {
457 			newcl = cl;
458 			break;
459 		}
460 	}
461 
462 	if (!newcl) {
463 		Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nServer is full.\n");
464 		Com_DevPrintf (0, "Rejected a connection.\n");
465 		return;
466 	}
467 
468 gotNewClient:
469 	/*
470 	** Build a new connection and accept the new client
471 	** This is the only place a svClient_t is ever initialized
472 	*/
473 	*newcl = temp;
474 	sv_currentClient = newcl;
475 	edictNum = (newcl-svs.clients)+1;
476 	ent = EDICT_NUM(edictNum);
477 	newcl->edict = ent;
478 	newcl->challenge = challenge; // Save challenge for checksumming
479 
480 	// Get the game a chance to reject this connection or modify the userInfo
481 	if (!ge->ClientConnect (ent, userInfo)) {
482 		Com_DevPrintf (0, "Game rejected a connection.\n");
483 
484 		if (*Info_ValueForKey (userInfo, "rejmsg")) {
485 			Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\n%s\nConnection refused.\n", Info_ValueForKey (userInfo, "rejmsg"));
486 			return;
487 		}
488 
489 		Netchan_OutOfBandPrint (NS_SERVER, &adr, "print\nConnection refused.\n");
490 		return;
491 	}
492 
493 	// Parse some info from the info strings
494 	Q_strncpyz (newcl->userInfo, userInfo, sizeof (newcl->userInfo));
495 	SV_UserinfoChanged (newcl);
496 
497 	// Send the connect packet to the client
498 	Netchan_OutOfBandPrint (NS_SERVER, &adr, "client_connect");
499 
500 	Netchan_Setup (NS_SERVER, &newcl->netChan, &adr, version, qPort, 0);
501 
502 	newcl->protocol = version;
503 	newcl->state = SVCS_CONNECTED;
504 
505 	MSG_Init (&newcl->datagram, newcl->datagramBuff, sizeof (newcl->datagramBuff));
506 	newcl->datagram.allowOverflow = qTrue;
507 
508 	newcl->lastMessage = svs.realTime - ((timeout->floatVal - 5) * 1000);	// don't timeout
509 	newcl->lastConnect = svs.realTime;
510 }
511 
512 
513 /*
514 ===============
515 SVC_RemoteCommand_f
516 
517 A client issued an rcon command.
518 Shift down the remaining args
519 Redirect all printfs
520 ===============
521 */
SVC_RemoteCommand_f(void)522 static void SVC_RemoteCommand_f (void)
523 {
524 	char	remaining[1024];
525 	int		i;
526 
527 	// Check rcon validity
528 	if (!strlen (rcon_password->string) || strcmp (Cmd_Argv(1), rcon_password->string)) {
529 		Com_Printf (PRNT_ERROR, "Bad rcon from %s:\n%s\n", NET_AdrToString (&sv_netFrom), sv_netMessage.data+4);
530 
531 		Com_BeginRedirect (RD_PACKET, sv_outputBuffer, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
532 		Com_Printf (0, "Bad rcon_password.\n");
533 		Com_EndRedirect ();
534 
535 		return;
536 	}
537 
538 	Com_Printf (0, "Rcon from %s:\n%s\n", NET_AdrToString (&sv_netFrom), sv_netMessage.data+4);
539 
540 	Com_BeginRedirect (RD_PACKET, sv_outputBuffer, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
541 
542 	// Echo the command
543 	remaining[0] = 0;
544 	for (i=2 ; i<Cmd_Argc () ; i++) {
545 		Q_strcatz (remaining, Cmd_Argv (i), sizeof (remaining));
546 		Q_strcatz (remaining, " ", sizeof (remaining));
547 	}
548 	Cmd_ExecuteString (remaining);
549 
550 	Com_EndRedirect ();
551 }
552 
553 
554 /*
555 =================
556 SV_ConnectionlessPacket
557 
558 A connectionless packet has four leading 0xff
559 characters to distinguish it from a game channel.
560 Clients that are in the game can still send
561 connectionless packets.
562 =================
563 */
SV_ConnectionlessPacket(void)564 static void SV_ConnectionlessPacket (void)
565 {
566 	char	*s;
567 	char	*c;
568 
569 	// Should NEVER EVER happen
570 	if (sv_netMessage.curSize > 1024) {
571 		Com_Printf (PRNT_WARNING, "Illegitimate packet size (%i) received, ignored.\n", sv_netMessage.curSize);
572 		return;
573 	}
574 
575 	MSG_BeginReading (&sv_netMessage);
576 	assert (MSG_ReadLong (&sv_netMessage) == -1);		// skip the -1 marker
577 
578 	s = MSG_ReadStringLine (&sv_netMessage);
579 
580 	Cmd_TokenizeString (s, qFalse);
581 
582 	c = Cmd_Argv (0);
583 	Com_DevPrintf (0, "Packet %s : %s\n", NET_AdrToString (&sv_netFrom), c);
584 
585 	if (!strcmp (c, "ping"))
586 		SVC_Ping_f ();
587 	else if (!strcmp (c, "ack"))
588 		SVC_Ack_f ();
589 	else if (!strcmp (c, "status"))
590 		SVC_Status_f ();
591 	else if (!strcmp (c, "info"))
592 		SVC_Info_f ();
593 	else if (!strcmp (c, "getchallenge"))
594 		SVC_GetChallenge_f ();
595 	else if (!strcmp (c, "connect"))
596 		SVC_DirectConnect_f ();
597 	else if (!strcmp (c, "rcon"))
598 		SVC_RemoteCommand_f ();
599 	else
600 		Com_Printf (PRNT_WARNING, "SV_ConnectionlessPacket: Bad connectionless packet from %s:\n%s\n", NET_AdrToString (&sv_netFrom), s);
601 }
602 
603 /*
604 ==============================================================================
605 
606 	MASTER SERVERS
607 
608 ==============================================================================
609 */
610 
611 /*
612 ================
613 SV_MasterHeartbeat
614 
615 Send a message to the master every few minutes to
616 let it know we are alive, and log information
617 ================
618 */
619 #define HEARTBEAT_SECONDS	300
SV_MasterHeartbeat(void)620 static void SV_MasterHeartbeat (void)
621 {
622 	char		*string;
623 	int			i;
624 
625 #ifndef DEDICATED_ONLY
626 	if (!dedicated->intVal)
627 		return;		// Only dedicated servers send heartbeats
628 #endif
629 
630 	if (!public_server->intVal)
631 		return;		// A private dedicated game
632 
633 	// Check for time wraparound
634 	if (svs.lastHeartBeat > svs.realTime)
635 		svs.lastHeartBeat = svs.realTime;
636 
637 	if (svs.realTime-svs.lastHeartBeat < HEARTBEAT_SECONDS*1000)
638 		return;		// Not time to send yet
639 
640 	svs.lastHeartBeat = svs.realTime;
641 
642 	// Send the same string that we would give for a status OOB command
643 	string = SV_StatusString ();
644 
645 	// Send to group master
646 	for (i=0 ; i<MAX_MASTERS ; i++) {
647 		if (!sv_masterAddresses[i].port)
648 			continue;
649 
650 		Com_Printf (0, "Sending heartbeat to %s\n", NET_AdrToString (&sv_masterAddresses[i]));
651 		Netchan_OutOfBandPrint (NS_SERVER, &sv_masterAddresses[i], "heartbeat\n%s", string);
652 	}
653 }
654 
655 
656 /*
657 =================
658 SV_MasterShutdown
659 
660 Informs all masters that this server is going down
661 =================
662 */
SV_MasterShutdown(void)663 static void SV_MasterShutdown (void)
664 {
665 	int		i;
666 
667 #ifndef DEDICATED_ONLY
668 	if (!dedicated->intVal)
669 		return;		// Only dedicated servers send heartbeats
670 #endif
671 
672 	if (!public_server->intVal)
673 		return;		// A private dedicated game
674 
675 	// Send to group master
676 	for (i=0 ; i<MAX_MASTERS ; i++) {
677 		if (!sv_masterAddresses[i].port)
678 			continue;
679 
680 		if (i > 0)
681 			Com_Printf (0, "Sending heartbeat to %s\n", NET_AdrToString (&sv_masterAddresses[i]));
682 		Netchan_OutOfBandPrint (NS_SERVER, &sv_masterAddresses[i], "shutdown");
683 	}
684 }
685 
686 /*
687 ==============================================================================
688 
689 	SERVER FRAME LOOP
690 
691 ==============================================================================
692 */
693 
694 /*
695 ===================
696 SV_CalcPings
697 
698 Updates the cl->ping variables
699 ===================
700 */
SV_CalcPings(void)701 static void SV_CalcPings (void)
702 {
703 	int			i, j;
704 	svClient_t	*cl;
705 	int			total, count;
706 
707 	for (i=0 ; i<maxclients->intVal ; i++) {
708 		cl = &svs.clients[i];
709 		if (!cl->edict || !cl->edict->client || cl->state != SVCS_SPAWNED)
710 			continue;
711 
712 		total = 0;
713 		count = 0;
714 		for (j=0 ; j<LATENCY_COUNTS ; j++) {
715 			if (cl->frameLatency[j] > 0) {
716 				count++;
717 				total += cl->frameLatency[j];
718 			}
719 		}
720 
721 		if (!count)
722 			cl->ping = 0;
723 		else
724 			cl->ping = total / count;
725 
726 		// Let the game dll know about the ping
727 		cl->edict->client->ping = cl->ping;
728 	}
729 }
730 
731 
732 /*
733 ===================
734 SV_GiveMsec
735 
736 Every few frames, gives all clients an allotment of milliseconds
737 for their command moves.  If they exceed it, assume cheating.
738 ===================
739 */
SV_GiveMsec(void)740 static void SV_GiveMsec (void)
741 {
742 	int			i;
743 	svClient_t	*cl;
744 
745 	if (sv.frameNum & 15)
746 		return;
747 
748 	for (i=0 ; i<maxclients->intVal ; i++) {
749 		cl = &svs.clients[i];
750 		if (cl->state == SVCS_FREE)
751 			continue;
752 
753 		cl->commandMsec = 1800;		// 1600 + some slop
754 	}
755 }
756 
757 
758 /*
759 =================
760 SV_ReadPackets
761 =================
762 */
SV_ReadPackets(void)763 static void SV_ReadPackets (void)
764 {
765 	int			i;
766 	svClient_t	*cl;
767 	int			qPort;
768 
769 	while (NET_GetPacket (NS_SERVER, &sv_netFrom, &sv_netMessage)) {
770 		// Check for connectionless packet (0xffffffff) first
771 		if (*(int *)sv_netMessage.data == -1) {
772 			SV_ConnectionlessPacket ();
773 			continue;
774 		}
775 
776 		/*
777 		** Read the qPort out of the message so we can fix up
778 		** stupid address translating routers
779 		*/
780 		MSG_BeginReading (&sv_netMessage);
781 		MSG_ReadLong (&sv_netMessage);		// Sequence number
782 		MSG_ReadLong (&sv_netMessage);		// Sequence number
783 		qPort = MSG_ReadShort (&sv_netMessage) & 0xffff;
784 
785 		// Check for packets from connected clients
786 		for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
787 			if (cl->state == SVCS_FREE)
788 				continue;
789 			if (!NET_CompareBaseAdr (sv_netFrom, cl->netChan.remoteAddress))
790 				continue;
791 			if (cl->netChan.qPort != qPort)
792 				continue;
793 			if (cl->netChan.remoteAddress.port != sv_netFrom.port) {
794 				Com_Printf (0, "SV_ReadPackets: fixing up a translated port\n");
795 				cl->netChan.remoteAddress.port = sv_netFrom.port;
796 			}
797 
798 			if (Netchan_Process (&cl->netChan, &sv_netMessage)) {
799 				// This is a valid, sequenced packet, so process it
800 				if (cl->state != SVCS_FREE) {
801 					cl->lastMessage = svs.realTime;	// Don't timeout
802 					SV_ExecuteClientMessage (cl);
803 				}
804 			}
805 			break;
806 		}
807 	}
808 }
809 
810 
811 /*
812 ==================
813 SV_CheckTimeouts
814 
815 If a packet has not been received from a client for timeout->floatVal
816 seconds, drop the conneciton.  Server frames are used instead of
817 realtime to avoid dropping the local client while debugging.
818 
819 When a client is normally dropped, the svClient_t goes into a zombie state
820 for a few seconds to make sure any final reliable message gets resent
821 if necessary
822 ==================
823 */
SV_CheckTimeouts(void)824 static void SV_CheckTimeouts (void)
825 {
826 	int			i;
827 	svClient_t	*cl;
828 	int			droppoint;
829 	int			zombiepoint;
830 
831 	droppoint = svs.realTime - 1000*timeout->floatVal;
832 	zombiepoint = svs.realTime - 1000*zombietime->floatVal;
833 
834 	for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
835 		// Message times may be wrong across a changelevel
836 		if (cl->lastMessage > svs.realTime)
837 			cl->lastMessage = svs.realTime;
838 
839 		if (cl->state == SVCS_FREE && cl->lastMessage < zombiepoint) {
840 			cl->state = SVCS_FREE;	// Can now be reused
841 			continue;
842 		}
843 
844 		if (cl->state >= SVCS_CONNECTED && cl->lastMessage < droppoint) {
845 			SV_BroadcastPrintf (PRINT_HIGH, "%s timed out\n", cl->name);
846 			SV_DropClient (cl);
847 			cl->state = SVCS_FREE;	// Don't bother with zombie state
848 		}
849 	}
850 }
851 
852 
853 /*
854 ================
855 SV_PrepWorldFrame
856 
857 This has to be done before the world logic, because
858 player processing happens outside RunWorldFrame
859 ================
860 */
SV_PrepWorldFrame(void)861 static void SV_PrepWorldFrame (void)
862 {
863 	edict_t	*ent;
864 	int		i;
865 
866 	for (i=0 ; i<ge->numEdicts ; i++, ent++) {
867 		ent = EDICT_NUM(i);
868 		// Events only last for a single message
869 		ent->s.event = 0;
870 	}
871 }
872 
873 
874 /*
875 =================
876 SV_RunGameFrame
877 =================
878 */
SV_RunGameFrame(void)879 static void SV_RunGameFrame (void)
880 {
881 	/*
882 	** We always need to bump framenum, even if we don't run the world, otherwise the delta
883 	** compression can get confused when a client has the "current" frame
884 	*/
885 	sv.frameNum++;
886 	sv.time = sv.frameNum*100;
887 
888 	// Don't run if paused
889 	if (!sv_paused->intVal || maxclients->intVal > 1) {
890 		ge->RunFrame ();
891 
892 		// Never get more than one tic behind
893 		if (sv.time < (uint32)svs.realTime) {
894 			if (sv_showclamp->intVal)
895 				Com_Printf (0, "sv highclamp\n");
896 			svs.realTime = sv.time;
897 		}
898 	}
899 }
900 
901 
902 /*
903 ==================
904 SV_Frame
905 ==================
906 */
SV_Frame(int msec)907 void SV_Frame (int msec)
908 {
909 	// If server is not active, do nothing
910 	if (!svs.initialized)
911 		return;
912 
913 	svs.realTime += msec;
914 
915 	// Keep the random time dependent
916 	rand ();
917 
918 	// Update console title
919 	if (hostname->modified)
920 		SV_UpdateTitle ();
921 
922 	// Check timeouts
923 	SV_CheckTimeouts ();
924 
925 	// Get packets from clients
926 	SV_ReadPackets ();
927 
928 	// Move autonomous things around if enough time has passed
929 	if (!sv_timedemo->floatVal && (uint32)svs.realTime < sv.time) {
930 		// Never let the time get too far off
931 		if (sv.time - svs.realTime > 100) {
932 			if (sv_showclamp->intVal)
933 				Com_Printf (0, "sv lowclamp\n");
934 			svs.realTime = sv.time - 100;
935 		}
936 		NET_Sleep (sv.time - svs.realTime);
937 		return;
938 	}
939 
940 	// Update ping based on the last known frame from all clients
941 	SV_CalcPings ();
942 
943 	// Give the clients some timeslices
944 	SV_GiveMsec ();
945 
946 	// Let everything in the world think and move
947 	SV_RunGameFrame ();
948 
949 	// Send messages back to the clients that had packets read this frame
950 	SV_SendClientMessages ();
951 
952 	// Save the entire world state if recording a serverdemo
953 	SV_RecordDemoMessage ();
954 
955 	// Send a heartbeat to the master if needed
956 	SV_MasterHeartbeat ();
957 
958 	// Clear teleport flags, etc for next frame
959 	SV_PrepWorldFrame ();
960 
961 }
962 
963 //============================================================================
964 
965 /*
966 ===============
967 SV_ServerInit
968 
969 Only called at egl.exe startup, not for each game
970 ===============
971 */
SV_ServerInit(void)972 void SV_ServerInit (void)
973 {
974 	sv_gameSysPool = Mem_CreatePool ("Server: Game system");
975 	sv_genericPool = Mem_CreatePool ("Server: Generic");
976 
977 	SV_OperatorCommandInit	();
978 
979 	Cvar_Register ("skill",			"1",											0);
980 	Cvar_Register ("deathmatch",	"0",											CVAR_SERVERINFO|CVAR_LATCH_SERVER);
981 	Cvar_Register ("coop",			"0",											CVAR_SERVERINFO|CVAR_LATCH_SERVER);
982 	Cvar_Register ("dmflags",		Q_VarArgs ("%i", DF_INSTANT_ITEMS),				CVAR_SERVERINFO);
983 	Cvar_Register ("fraglimit",		"0",											CVAR_SERVERINFO);
984 	Cvar_Register ("timelimit",		"0",											CVAR_SERVERINFO);
985 	Cvar_Register ("cheats",		"0",											CVAR_SERVERINFO|CVAR_LATCH_SERVER);
986 	Cvar_Register ("protocol",		Q_VarArgs ("%i", ORIGINAL_PROTOCOL_VERSION),	CVAR_SERVERINFO|CVAR_READONLY);
987 	Cvar_Register ("mapname",		"",												CVAR_SERVERINFO|CVAR_READONLY);
988 
989 	rcon_password			= Cvar_Register ("rcon_password",			"",			0);
990 
991 	maxclients				= Cvar_Register ("maxclients",				"1",		CVAR_SERVERINFO|CVAR_LATCH_SERVER);
992 	hostname				= Cvar_Register ("hostname",				"noname",	CVAR_SERVERINFO|CVAR_ARCHIVE);
993 	timeout					= Cvar_Register ("timeout",					"125",		0);
994 	zombietime				= Cvar_Register ("zombietime",				"2",		0);
995 
996 	sv_showclamp			= Cvar_Register ("showclamp",				"0",		0);
997 	sv_paused				= Cvar_Register ("paused",					"0",		CVAR_CHEAT);
998 	sv_timedemo				= Cvar_Register ("timedemo",				"0",		CVAR_CHEAT);
999 
1000 	sv_enforcetime			= Cvar_Register ("sv_enforcetime",			"0",		0);
1001 	sv_reconnect_limit		= Cvar_Register ("sv_reconnect_limit",		"3",		CVAR_ARCHIVE);
1002 	sv_noreload				= Cvar_Register ("sv_noreload",				"0",		0);
1003 	sv_airaccelerate		= Cvar_Register ("sv_airaccelerate",		"0",		CVAR_LATCH_SERVER);
1004 
1005 	allow_download			= Cvar_Register ("allow_download",			"1",		CVAR_ARCHIVE);
1006 	allow_download_players	= Cvar_Register ("allow_download_players",	"0",		CVAR_ARCHIVE);
1007 	allow_download_models	= Cvar_Register ("allow_download_models",	"1",		CVAR_ARCHIVE);
1008 	allow_download_sounds	= Cvar_Register ("allow_download_sounds",	"1",		CVAR_ARCHIVE);
1009 	allow_download_maps		= Cvar_Register ("allow_download_maps",		"1",		CVAR_ARCHIVE);
1010 
1011 	public_server			= Cvar_Register ("public",					"0",		0);
1012 
1013 	MSG_Init (&sv_netMessage, sv_netBuffer, sizeof (sv_netBuffer));
1014 }
1015 
1016 
1017 /*
1018 ==================
1019 SV_FinalMessage
1020 
1021 Used by SV_ServerShutdown to send a final message to all connected clients before
1022 the server goes down. The messages are sent immediately, not just stuck on
1023 the outgoing message list, because the server is going to totally exit after
1024 returning from this function.
1025 ==================
1026 */
SV_FinalMessage(char * message,qBool reconnect)1027 static void SV_FinalMessage (char *message, qBool reconnect)
1028 {
1029 	int			i;
1030 	svClient_t	*cl;
1031 
1032 	MSG_Clear (&sv_netMessage);
1033 	MSG_WriteByte (&sv_netMessage, SVC_PRINT);
1034 	MSG_WriteByte (&sv_netMessage, PRINT_HIGH);
1035 	MSG_WriteString (&sv_netMessage, message);
1036 
1037 	if (reconnect)
1038 		MSG_WriteByte (&sv_netMessage, SVC_RECONNECT);
1039 	else
1040 		MSG_WriteByte (&sv_netMessage, SVC_DISCONNECT);
1041 
1042 	// Send it twice
1043 	// stagger the packets to crutch operating system limited buffers
1044 	for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
1045 		if (cl->state >= SVCS_CONNECTED)
1046 			Netchan_Transmit (&cl->netChan, sv_netMessage.curSize, sv_netMessage.data);
1047 	}
1048 
1049 	for (i=0, cl=svs.clients ; i<maxclients->intVal ; i++, cl++) {
1050 		if (cl->state >= SVCS_CONNECTED)
1051 			Netchan_Transmit (&cl->netChan, sv_netMessage.curSize, sv_netMessage.data);
1052 	}
1053 }
1054 
1055 
1056 /*
1057 ================
1058 SV_ServerShutdown
1059 
1060 Called when each game quits, before Sys_Quit or Sys_Error
1061 ================
1062 */
SV_ServerShutdown(char * finalMessage,qBool reconnect,qBool crashing)1063 void SV_ServerShutdown (char *finalMessage, qBool reconnect, qBool crashing)
1064 {
1065 	if (svs.clients)
1066 		SV_FinalMessage (finalMessage, reconnect);
1067 
1068 	SV_MasterShutdown ();
1069 
1070 	if (!crashing) {
1071 		SV_GameAPI_Shutdown ();
1072 
1073 		// Get latched vars
1074 		Cvar_GetLatchedVars (CVAR_LATCH_SERVER);
1075 	}
1076 
1077 	// Free current level
1078 	if (sv.demoFile) {
1079 		FS_CloseFile (sv.demoFile);
1080 		sv.demoFile = 0;
1081 	}
1082 	memset (&sv, 0, sizeof (serverState_t));
1083 	Com_SetServerState (SS_DEAD);
1084 
1085 	// Free server static data
1086 	if (svs.clients)
1087 		Mem_Free (svs.clients);
1088 	if (svs.clientEntities)
1089 		Mem_Free (svs.clientEntities);
1090 	if (svs.demoFile)
1091 		FS_CloseFile (svs.demoFile);
1092 	memset (&svs, 0, sizeof (svs));
1093 
1094 	// If the server is crashing there's no sense in releasing this memory
1095 	// (it may even be the cause! *gasp*)
1096 	if (!crashing)
1097 		CM_UnloadMap ();
1098 
1099 	MSG_Clear (&sv_netMessage);
1100 }
1101