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