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