Quake II RTX doxygen  1.0 dev
main.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "server.h"
20 #include "client/input.h"
21 
22 pmoveParams_t sv_pmp;
23 
24 LIST_DECL(sv_masterlist); // address of group servers
30 LIST_DECL(sv_clientlist); // linked list of non-free clients
31 
32 client_t *sv_client; // current client
33 edict_t *sv_player; // current client edict
34 
35 qboolean sv_pending_autosave = 0;
36 
39 #if USE_FPS
40 cvar_t *sv_fps;
41 #endif
42 
43 cvar_t *sv_timeout; // seconds without any message
44 cvar_t *sv_zombietime; // seconds to sink messages after disconnect
45 cvar_t *sv_ghostime;
46 cvar_t *sv_idlekick;
47 
48 cvar_t *sv_password;
50 
53 
55 cvar_t *sv_qwmod; // atu QW Physics modificator
56 cvar_t *sv_novis;
57 
58 cvar_t *sv_maxclients;
60 cvar_t *sv_showclamp;
61 cvar_t *sv_locked;
64 
65 cvar_t *sv_hostname;
66 cvar_t *sv_public; // should heartbeats be sent
67 
68 #ifdef _DEBUG
69 cvar_t *sv_debug;
70 cvar_t *sv_pad_packets;
71 #endif
75 
78 #if USE_PACKETDUP
79 cvar_t *sv_packetdup_hack;
80 #endif
81 cvar_t *sv_allow_map;
82 #if !USE_CLIENT
83 cvar_t *sv_recycle;
84 #endif
86 
87 cvar_t *sv_iplimit;
90 cvar_t *sv_uptime;
91 cvar_t *sv_auth_limit;
92 cvar_t *sv_rcon_limit;
94 
96 
98 
99 cvar_t *g_features;
100 
102 
103 qboolean sv_registered;
104 
105 //============================================================================
106 
108 {
109  if (client->msg_pool) {
110  SV_ShutdownClientSend(client);
111  }
112 
113  if (client->netchan) {
114  Netchan_Close(client->netchan);
115  client->netchan = NULL;
116  }
117 
118  // unlink them from active client list, but don't clear the list entry
119  // itself to make code that traverses client list in a loop happy!
120  List_Remove(&client->entry);
121 
122 #if USE_MVD_CLIENT
123  // unlink them from MVD client list
124  if (sv.state == ss_broadcast) {
125  MVD_RemoveClient(client);
126  }
127 #endif
128 
129  Com_DPrintf("Going from cs_zombie to cs_free for %s\n", client->name);
130 
131  client->state = cs_free; // can now be reused
132  client->name[0] = 0;
133 }
134 
136 {
137  int i;
138 #if USE_AC_SERVER
139  string_entry_t *bad, *next;
140 
141  for (bad = client->ac_bad_files; bad; bad = next) {
142  next = bad->next;
143  Z_Free(bad);
144  }
145  client->ac_bad_files = NULL;
146 #endif
147 
148  // close any existing donwload
149  SV_CloseDownload(client);
150 
151  if (client->version_string) {
152  Z_Free(client->version_string);
153  client->version_string = NULL;
154  }
155 
156  // free baselines allocated for this client
157  for (i = 0; i < SV_BASELINES_CHUNKS; i++) {
158  if (client->baselines[i]) {
159  Z_Free(client->baselines[i]);
160  client->baselines[i] = NULL;
161  }
162  }
163 }
164 
165 static void print_drop_reason(client_t *client, const char *reason, clstate_t oldstate)
166 {
167  int announce = oldstate == cs_spawned ? 2 : 1;
168  const char *prefix = " was dropped: ";
169 
170  // parse flags
171  if (*reason == '!') {
172  reason++;
173  announce = 0;
174  }
175  if (*reason == '?') {
176  reason++;
177  prefix = " ";
178  }
179 
180  if (announce == 2) {
181  // announce to others
182 #if USE_MVD_CLIENT
183  if (sv.state == ss_broadcast)
184  MVD_GameClientDrop(client->edict, prefix, reason);
185  else
186 #endif
187  SV_BroadcastPrintf(PRINT_HIGH, "%s%s%s\n",
188  client->name, prefix, reason);
189  }
190 
191  if (announce)
192  // print this to client as they will not receive broadcast
193  SV_ClientPrintf(client, PRINT_HIGH, "%s%s%s\n",
194  client->name, prefix, reason);
195 
196  // print to server console
197  if (COM_DEDICATED && client->netchan)
198  Com_Printf("%s[%s]%s%s\n", client->name,
199  NET_AdrToString(&client->netchan->remote_address),
200  prefix, reason);
201 }
202 
203 /*
204 =====================
205 SV_DropClient
206 
207 Called when the player is totally leaving the server, either willingly
208 or unwillingly. This is NOT called if the entire server is quiting
209 or crashing.
210 =====================
211 */
212 void SV_DropClient(client_t *client, const char *reason)
213 {
214  clstate_t oldstate;
215 
216  if (client->state <= cs_zombie)
217  return; // called recursively?
218 
219  oldstate = client->state;
220  client->state = cs_zombie; // become free in a few seconds
221  client->lastmessage = svs.realtime;
222 
223  // print the reason
224  if (reason)
225  print_drop_reason(client, reason, oldstate);
226 
227  // add the disconnect
228  MSG_WriteByte(svc_disconnect);
230 
231  if (oldstate == cs_spawned || (g_features->integer & GMF_WANT_ALL_DISCONNECTS)) {
232  // call the prog function for removing a client
233  // this will remove the body, among other things
234  ge->ClientDisconnect(client->edict);
235  }
236 
237  AC_ClientDisconnect(client);
238 
239  SV_CleanClient(client);
240 
241  Com_DPrintf("Going to cs_zombie for %s\n", client->name);
242 
243  // give MVD server a chance to detect if its dummy client was dropped
244  SV_MvdClientDropped(client);
245 }
246 
247 
248 //============================================================================
249 
250 // highest power of two that avoids credit overflow for 1 day
251 #define CREDITS_PER_MSEC 32
252 #define CREDITS_PER_SEC (CREDITS_PER_MSEC * 1000)
253 
254 // allows rates up to 10,000 hits per second
255 #define RATE_LIMIT_SCALE 10000
256 
257 /*
258 ===============
259 SV_RateLimited
260 
261 Implements simple token bucket filter. Inspired by xt_limit.c from the Linux
262 kernel. Returns true if limit is exceeded.
263 ===============
264 */
266 {
267  r->credit += (svs.realtime - r->time) * CREDITS_PER_MSEC;
268  r->time = svs.realtime;
269  if (r->credit > r->credit_cap)
270  r->credit = r->credit_cap;
271 
272  if (r->credit >= r->cost) {
273  r->credit -= r->cost;
274  return qfalse;
275  }
276 
277  return qtrue;
278 }
279 
280 /*
281 ===============
282 SV_RateRecharge
283 
284 Reverts the effect of SV_RateLimited.
285 ===============
286 */
288 {
289  r->credit += r->cost;
290  if (r->credit > r->credit_cap)
291  r->credit = r->credit_cap;
292 }
293 
294 static unsigned rate2credits(unsigned rate)
295 {
296  if (rate > UINT_MAX / CREDITS_PER_SEC)
297  return (rate / RATE_LIMIT_SCALE) * CREDITS_PER_SEC;
298 
299  return (rate * CREDITS_PER_SEC) / RATE_LIMIT_SCALE;
300 }
301 
302 /*
303 ===============
304 SV_RateInit
305 
306 Full syntax is: <limit>[/<period>[sec|min|hour]][*<burst>]
307 ===============
308 */
309 void SV_RateInit(ratelimit_t *r, const char *s)
310 {
311  unsigned limit, period, mult, burst, rate;
312  char *p;
313 
314  limit = strtoul(s, &p, 10);
315  if (*p == '/') {
316  period = strtoul(p + 1, &p, 10);
317  if (*p == 's' || *p == 'S') {
318  mult = 1;
319  p++;
320  } else if (*p == 'm' || *p == 'M') {
321  mult = 60;
322  p++;
323  } else if (*p == 'h' || *p == 'H') {
324  mult = 60 * 60;
325  p++;
326  } else {
327  // everything else are seconds
328  mult = 1;
329  }
330  if (!period)
331  period = 1;
332  } else {
333  // default period is one second
334  period = 1;
335  mult = 1;
336  }
337 
338  if (!limit) {
339  // unlimited
340  memset(r, 0, sizeof(*r));
341  return;
342  }
343 
344  if (period > UINT_MAX / (RATE_LIMIT_SCALE * mult)) {
345  Com_Printf("Period too large: %u\n", period);
346  return;
347  }
348 
349  rate = (RATE_LIMIT_SCALE * period * mult) / limit;
350 
351  p = strchr(p, '*');
352  if (p) {
353  burst = strtoul(p + 1, NULL, 10);
354  } else {
355  // default burst is 5 hits
356  burst = 5;
357  }
358 
359  if (burst > UINT_MAX / rate) {
360  Com_Printf("Burst too large: %u\n", burst);
361  return;
362  }
363 
364  r->time = svs.realtime;
365  r->credit = rate2credits(rate * burst);
366  r->credit_cap = rate2credits(rate * burst);
367  r->cost = rate2credits(rate);
368 }
369 
370 addrmatch_t *SV_MatchAddress(list_t *list, netadr_t *addr)
371 {
372  addrmatch_t *match;
373 
374  LIST_FOR_EACH(addrmatch_t, match, list, entry) {
375  if (NET_IsEqualBaseAdrMask(addr, &match->addr, &match->mask)) {
376  match->hits++;
377  match->time = time(NULL);
378  return match;
379  }
380  }
381 
382  return NULL;
383 }
384 
385 /*
386 ==============================================================================
387 
388 CONNECTIONLESS COMMANDS
389 
390 ==============================================================================
391 */
392 
393 /*
394 ===============
395 SV_StatusString
396 
397 Builds the string that is sent as heartbeats and status replies.
398 It is assumed that size of status buffer is at least SV_OUTPUTBUF_LENGTH!
399 ===============
400 */
401 static size_t SV_StatusString(char *status)
402 {
403  char entry[MAX_STRING_CHARS];
404  client_t *cl;
405  size_t total, len;
406  char *tmp = sv_maxclients->string;
407 
408  // XXX: ugly hack to hide reserved slots
409  if (sv_reserved_slots->integer) {
410  Q_snprintf(entry, sizeof(entry), "%d",
411  sv_maxclients->integer - sv_reserved_slots->integer);
412  sv_maxclients->string = entry;
413  }
414 
415  // add server info
416  total = Cvar_BitInfo(status, CVAR_SERVERINFO);
417 
418  sv_maxclients->string = tmp;
419 
420  // add uptime
421  if (sv_uptime->integer > 0) {
422  if (sv_uptime->integer > 1) {
423  len = Com_UptimeLong_m(entry, MAX_INFO_VALUE);
424  } else {
425  len = Com_Uptime_m(entry, MAX_INFO_VALUE);
426  }
427  if (total + 8 + len < MAX_INFO_STRING) {
428  memcpy(status + total, "\\uptime\\", 8);
429  memcpy(status + total + 8, entry, len);
430  total += 8 + len;
431  }
432  }
433 
434  status[total++] = '\n';
435 
436  // add player list
437  if (sv_status_show->integer > 1) {
439  if (cl->state == cs_zombie) {
440  continue;
441  }
442  len = Q_snprintf(entry, sizeof(entry),
443  "%i %i \"%s\"\n",
444  cl->edict->client->ps.stats[STAT_FRAGS],
445  cl->ping, cl->name);
446  if (len >= sizeof(entry)) {
447  continue;
448  }
449  if (total + len >= SV_OUTPUTBUF_LENGTH) {
450  break; // can't hold any more
451  }
452  memcpy(status + total, entry, len);
453  total += len;
454  }
455  }
456 
457  status[total] = 0;
458 
459  return total;
460 }
461 
462 /*
463 ================
464 SVC_Status
465 
466 Responds with all the info that qplug or qspy can see
467 ================
468 */
469 static void SVC_Status(void)
470 {
471  char buffer[MAX_PACKETLEN_DEFAULT];
472  size_t len;
473 
474  if (!sv_status_show->integer) {
475  return;
476  }
477 
479  Com_DPrintf("Dropping status request from %s\n",
481  return;
482  }
483 
484  // write the packet header
485  memcpy(buffer, "\xff\xff\xff\xffprint\n", 10);
486  len = 10;
487 
488  len += SV_StatusString(buffer + len);
489 
490  // send the datagram
491  NET_SendPacket(NS_SERVER, buffer, len, &net_from);
492 }
493 
494 /*
495 ================
496 SVC_Ack
497 
498 ================
499 */
500 static void SVC_Ack(void)
501 {
502  master_t *m;
503 
504  FOR_EACH_MASTER(m) {
505  if (!m->adr.port) {
506  continue;
507  }
508  if (NET_IsEqualBaseAdr(&m->adr, &net_from)) {
509  Com_DPrintf("Ping acknowledge from %s\n",
511  m->last_ack = svs.realtime;
512  break;
513  }
514  }
515 }
516 
517 /*
518 ================
519 SVC_Info
520 
521 Responds with short info for broadcast scans
522 The second parameter should be the current protocol version number.
523 ================
524 */
525 static void SVC_Info(void)
526 {
527  char buffer[MAX_QPATH+10];
528  size_t len;
529  int version;
530 
531  if (sv_maxclients->integer == 1)
532  return; // ignore in single player
533 
534  version = atoi(Cmd_Argv(1));
535  if (version < PROTOCOL_VERSION_DEFAULT || version > PROTOCOL_VERSION_Q2PRO)
536  return; // ignore invalid versions
537 
538  len = Q_scnprintf(buffer, sizeof(buffer),
539  "\xff\xff\xff\xffinfo\n%16s %8s %2i/%2i\n",
540  sv_hostname->string, sv.name, SV_CountClients(),
541  sv_maxclients->integer - sv_reserved_slots->integer);
542 
543  NET_SendPacket(NS_SERVER, buffer, len, &net_from);
544 }
545 
546 /*
547 ================
548 SVC_Ping
549 
550 Just responds with an acknowledgement
551 ================
552 */
553 static void SVC_Ping(void)
554 {
555  OOB_PRINT(NS_SERVER, &net_from, "ack");
556 }
557 
558 /*
559 =================
560 SVC_GetChallenge
561 
562 Returns a challenge number that can be used
563 in a subsequent client_connect command.
564 We do this to prevent denial of service attacks that
565 flood the server with invalid connection IPs. With a
566 challenge, they must give a valid IP address.
567 =================
568 */
569 static void SVC_GetChallenge(void)
570 {
571  int i, oldest;
572  unsigned challenge;
573  unsigned oldestTime;
574 
575  oldest = 0;
576  oldestTime = 0xffffffff;
577 
578  // see if we already have a challenge for this ip
579  for (i = 0; i < MAX_CHALLENGES; i++) {
580  if (NET_IsEqualBaseAdr(&net_from, &svs.challenges[i].adr))
581  break;
582  if (svs.challenges[i].time > com_eventTime) {
584  }
585  if (svs.challenges[i].time < oldestTime) {
586  oldestTime = svs.challenges[i].time;
587  oldest = i;
588  }
589  }
590 
591  challenge = ((rand() << 16) | rand()) & 0x7fffffff;
592  if (i == MAX_CHALLENGES) {
593  // overwrite the oldest
594  svs.challenges[oldest].challenge = challenge;
595  svs.challenges[oldest].adr = net_from;
596  svs.challenges[oldest].time = com_eventTime;
597  } else {
598  svs.challenges[i].challenge = challenge;
600  }
601 
602  // send it back
603  Netchan_OutOfBand(NS_SERVER, &net_from,
604  "challenge %u p=34,35,36", challenge);
605 }
606 
607 /*
608 ==================
609 SVC_DirectConnect
610 
611 A connection request that did not come from the master
612 ==================
613 */
614 
615 typedef struct {
616  int protocol; // major version
617  int version; // minor version
618  int qport;
620 
622  int nctype;
623  qboolean has_zlib;
624 
625  int reserved; // hidden client slots
626  char reconnect_var[16];
627  char reconnect_val[16];
628 } conn_params_t;
629 
630 #define __reject(...) \
631  Netchan_OutOfBand(NS_SERVER, &net_from, "print\n" __VA_ARGS__)
632 
633 // small hack to permit one-line return statement :)
634 #define reject(...) __reject(__VA_ARGS__), qfalse
635 #define reject2(...) __reject(__VA_ARGS__), NULL
636 
638 {
639  p->protocol = atoi(Cmd_Argv(1));
640  p->qport = atoi(Cmd_Argv(2)) ;
641  p->challenge = atoi(Cmd_Argv(3));
642 
643  // check for invalid protocol version
644  if (p->protocol < PROTOCOL_VERSION_OLD ||
645  p->protocol > PROTOCOL_VERSION_Q2PRO)
646  return reject("Unsupported protocol version %d.\n", p->protocol);
647 
648  // check for valid, but outdated protocol version
649  if (p->protocol < PROTOCOL_VERSION_DEFAULT)
650  return reject("You need Quake 2 version 3.19 or higher.\n");
651 
652  return qtrue;
653 }
654 
655 static qboolean permit_connection(conn_params_t *p)
656 {
657  addrmatch_t *match;
658  int i, count;
659  client_t *cl;
660  char *s;
661 
662  // loopback clients are permitted without any checks
663  if (NET_IsLocalAddress(&net_from))
664  return qtrue;
665 
666  // see if the challenge is valid
667  for (i = 0; i < MAX_CHALLENGES; i++) {
668  if (!svs.challenges[i].challenge)
669  continue;
670 
671  if (NET_IsEqualBaseAdr(&net_from, &svs.challenges[i].adr)) {
672  if (svs.challenges[i].challenge == p->challenge)
673  break; // good
674 
675  return reject("Bad challenge.\n");
676  }
677  }
678 
679  if (i == MAX_CHALLENGES)
680  return reject("No challenge for address.\n");
681 
682  svs.challenges[i].challenge = 0;
683 
684  // check for banned address
685  if ((match = SV_MatchAddress(&sv_banlist, &net_from)) != NULL) {
686  s = match->comment;
687  if (!*s) {
688  s = "Your IP address is banned from this server.";
689  }
690  return reject("%s\nConnection refused.\n", s);
691  }
692 
693  // check for locked server
694  if (sv_locked->integer)
695  return reject("Server is locked.\n");
696 
697  // link-local IPv6 addresses are permitted without sv_iplimit check
698  if (net_from.type == NA_IP6 && NET_IsLanAddress(&net_from))
699  return qtrue;
700 
701  // limit number of connections from single IPv4 address or /48 IPv6 network
702  if (sv_iplimit->integer > 0) {
703  count = 0;
705  netadr_t *adr = &cl->netchan->remote_address;
706 
707  if (net_from.type != adr->type)
708  continue;
709  if (net_from.type == NA_IP && net_from.ip.u32[0] != adr->ip.u32[0])
710  continue;
711  if (net_from.type == NA_IP6 && memcmp(net_from.ip.u8, adr->ip.u8, 48 / CHAR_BIT))
712  continue;
713 
714  if (cl->state == cs_zombie)
715  count += 1;
716  else
717  count += 2;
718  }
719  if (count / 2 >= sv_iplimit->integer) {
720  if (net_from.type == NA_IP6)
721  return reject("Too many connections from your IPv6 network.\n");
722  else
723  return reject("Too many connections from your IP address.\n");
724  }
725  }
726 
727  return qtrue;
728 }
729 
731 {
732  char *s;
733 
734  // set maximum packet length
735  p->maxlength = MAX_PACKETLEN_WRITABLE_DEFAULT;
736  if (p->protocol >= PROTOCOL_VERSION_R1Q2) {
737  s = Cmd_Argv(5);
738  if (*s) {
739  p->maxlength = atoi(s);
740  if (p->maxlength < 0 || p->maxlength > MAX_PACKETLEN_WRITABLE)
741  return reject("Invalid maximum message length.\n");
742 
743  // 0 means highest available
744  if (!p->maxlength)
745  p->maxlength = MAX_PACKETLEN_WRITABLE;
746  }
747  }
748 
749  if (!NET_IsLocalAddress(&net_from) && net_maxmsglen->integer > 0) {
750  // cap to server defined maximum value
751  if (p->maxlength > net_maxmsglen->integer)
752  p->maxlength = net_maxmsglen->integer;
753  }
754 
755  // don't allow too small packets
756  if (p->maxlength < MIN_PACKETLEN)
757  p->maxlength = MIN_PACKETLEN;
758 
759  return qtrue;
760 }
761 
763 {
764  char *s;
765 
766  if (p->protocol == PROTOCOL_VERSION_R1Q2) {
767  // set minor protocol version
768  s = Cmd_Argv(6);
769  if (*s) {
770  p->version = atoi(s);
771  clamp(p->version,
772  PROTOCOL_VERSION_R1Q2_MINIMUM,
773  PROTOCOL_VERSION_R1Q2_CURRENT);
774  } else {
775  p->version = PROTOCOL_VERSION_R1Q2_MINIMUM;
776  }
777  p->nctype = NETCHAN_OLD;
778  p->has_zlib = qtrue;
779  } else if (p->protocol == PROTOCOL_VERSION_Q2PRO) {
780  // set netchan type
781  s = Cmd_Argv(6);
782  if (*s) {
783  p->nctype = atoi(s);
784  if (p->nctype < NETCHAN_OLD || p->nctype > NETCHAN_NEW)
785  return reject("Invalid netchan type.\n");
786  } else {
787  p->nctype = NETCHAN_NEW;
788  }
789 
790  // set zlib
791  s = Cmd_Argv(7);
792  if (*s) {
793  p->has_zlib = !!atoi(s);
794  } else {
795  p->has_zlib = qtrue;
796  }
797 
798  // set minor protocol version
799  s = Cmd_Argv(8);
800  if (*s) {
801  p->version = atoi(s);
802  clamp(p->version,
803  PROTOCOL_VERSION_Q2PRO_MINIMUM,
804  PROTOCOL_VERSION_Q2PRO_CURRENT);
805  if (p->version == PROTOCOL_VERSION_Q2PRO_RESERVED) {
806  p->version--; // never use this version
807  }
808  } else {
809  p->version = PROTOCOL_VERSION_Q2PRO_MINIMUM;
810  }
811  }
812 
813  return qtrue;
814 }
815 
816 static char *userinfo_ip_string(void)
817 {
818  static char s[MAX_QPATH];
819 
820  // fake up reserved IPv4 address to prevent IPv6 unaware mods from exploding
821  if (net_from.type == NA_IP6 && !(g_features->integer & GMF_IPV6_ADDRESS_AWARE)) {
822  uint8_t res = 0;
823  int i;
824 
825  // stuff /48 network part into the last byte
826  for (i = 0; i < 48 / CHAR_BIT; i++)
827  res ^= net_from.ip.u8[i];
828 
829  Q_snprintf(s, sizeof(s), "198.51.100.%u:%u", res, BigShort(net_from.port));
830  return s;
831  }
832 
833  return NET_AdrToString(&net_from);
834 }
835 
836 static qboolean parse_userinfo(conn_params_t *params, char *userinfo)
837 {
838  char *info, *s;
839 
840  // validate userinfo
841  info = Cmd_Argv(4);
842  if (!info[0])
843  return reject("Empty userinfo string.\n");
844 
845  if (!Info_Validate(info))
846  return reject("Malformed userinfo string.\n");
847 
848  s = Info_ValueForKey(info, "name");
849  s[MAX_CLIENT_NAME - 1] = 0;
850  if (COM_IsWhite(s))
851  return reject("Please set your name before connecting.\n");
852 
853  // check password
854  s = Info_ValueForKey(info, "password");
855  if (sv_password->string[0]) {
856  if (!s[0])
857  return reject("Please set your password before connecting.\n");
858 
860  return reject("Invalid password.\n");
861 
862  if (strcmp(sv_password->string, s))
863  return reject("Invalid password.\n");
864 
865  // valid connect packets are not rate limited
867 
868  // allow them to use reserved slots
869  } else if (!sv_reserved_password->string[0] ||
870  strcmp(sv_reserved_password->string, s)) {
871  // if no reserved password is set on the server, do not allow
872  // anyone to access reserved slots at all
873  params->reserved = sv_reserved_slots->integer;
874  }
875 
876  if (sv_restrict_rtx->integer)
877  {
878  s = Info_ValueForKey(info, "version");
879  if (strncmp(s, "q2rtx", 5) != 0)
880  {
881  return reject("This server is only available to Q2RTX clients.\n");
882  }
883  }
884 
885  // copy userinfo off
886  Q_strlcpy(userinfo, info, MAX_INFO_STRING);
887 
888  // mvdspec, ip, etc are passed in extra userinfo if supported
889  if (!(g_features->integer & GMF_EXTRA_USERINFO)) {
890  // make sure mvdspec key is not set
891  Info_RemoveKey(userinfo, "mvdspec");
892 
893  if (sv_password->string[0] || sv_reserved_password->string[0]) {
894  // unset password key to make game mod happy
895  Info_RemoveKey(userinfo, "password");
896  }
897 
898  // force the IP key/value pair so the game can filter based on ip
899  if (!Info_SetValueForKey(userinfo, "ip", userinfo_ip_string()))
900  return reject("Oversize userinfo string.\n");
901  }
902 
903  return qtrue;
904 }
905 
906 static client_t *redirect(const char *addr)
907 {
908  Netchan_OutOfBand(NS_SERVER, &net_from, "client_connect");
909 
910  // set up a fake server netchan
911  MSG_WriteLong(1);
912  MSG_WriteLong(0);
913  MSG_WriteByte(svc_print);
914  MSG_WriteByte(PRINT_HIGH);
915  MSG_WriteString(va("Server is full. Redirecting you to %s...\n", addr));
917  MSG_WriteString(va("connect %s\n", addr));
918 
919  NET_SendPacket(NS_SERVER, msg_write.data, msg_write.cursize, &net_from);
921  return NULL;
922 }
923 
925 {
926  client_t *cl;
927  char *s;
928  int i;
929 
930  // if there is already a slot for this ip, reuse it
932  if (NET_IsEqualAdr(&net_from, &cl->netchan->remote_address)) {
933  if (cl->state == cs_zombie) {
934  strcpy(params->reconnect_var, cl->reconnect_var);
935  strcpy(params->reconnect_val, cl->reconnect_val);
936  } else {
937  SV_DropClient(cl, "reconnected");
938  }
939 
940  Com_DPrintf("%s: reconnect\n", NET_AdrToString(&net_from));
942  return cl;
943  }
944  }
945 
946  // check for forced redirect to a different address
947  s = sv_redirect_address->string;
948  if (*s == '!' && sv_reserved_slots->integer == params->reserved)
949  return redirect(s + 1);
950 
951  // find a free client slot
952  for (i = 0; i < sv_maxclients->integer - params->reserved; i++) {
953  cl = &svs.client_pool[i];
954  if (cl->state == cs_free)
955  return cl;
956  }
957 
958  // clients that know the password are never redirected
959  if (sv_reserved_slots->integer != params->reserved)
960  return reject2("Server and reserved slots are full.\n");
961 
962  // optionally redirect them to a different address
963  if (*s)
964  return redirect(s);
965 
966  return reject2("Server is full.\n");
967 }
968 
970 {
971  int force;
972 
973  // copy default pmove parameters
974  newcl->pmp = sv_pmp;
975  newcl->pmp.airaccelerate = sv_airaccelerate->integer ? qtrue : qfalse;
976 
977  // common extensions
978  force = 2;
979  if (newcl->protocol >= PROTOCOL_VERSION_R1Q2) {
980  newcl->pmp.speedmult = 2;
981  force = 1;
982  }
983  newcl->pmp.strafehack = sv_strafejump_hack->integer >= force ? qtrue : qfalse;
984 
985  // r1q2 extensions
986  if (newcl->protocol == PROTOCOL_VERSION_R1Q2) {
987  newcl->esFlags |= MSG_ES_BEAMORIGIN;
988  if (newcl->version >= PROTOCOL_VERSION_R1Q2_LONG_SOLID) {
989  newcl->esFlags |= MSG_ES_LONGSOLID;
990  }
991  }
992 
993  // q2pro extensions
994  force = 2;
995  if (newcl->protocol == PROTOCOL_VERSION_Q2PRO) {
996  if (sv_qwmod->integer) {
997  PmoveEnableQW(&newcl->pmp);
998  }
999  newcl->pmp.flyhack = qtrue;
1000  newcl->pmp.flyfriction = 4;
1001  newcl->esFlags |= MSG_ES_UMASK;
1002  if (newcl->version >= PROTOCOL_VERSION_Q2PRO_LONG_SOLID) {
1003  newcl->esFlags |= MSG_ES_LONGSOLID;
1004  }
1005  if (newcl->version >= PROTOCOL_VERSION_Q2PRO_BEAM_ORIGIN) {
1006  newcl->esFlags |= MSG_ES_BEAMORIGIN;
1007  }
1008  if (newcl->version >= PROTOCOL_VERSION_Q2PRO_WATERJUMP_HACK) {
1009  force = 1;
1010  }
1011  }
1012  newcl->pmp.waterhack = sv_waterjump_hack->integer >= force ? qtrue : qfalse;
1013 }
1014 
1015 static void send_connect_packet(client_t *newcl, int nctype)
1016 {
1017  const char *ncstring = "";
1018  const char *acstring = "";
1019  const char *dlstring1 = "";
1020  const char *dlstring2 = "";
1021 
1022  if (newcl->protocol == PROTOCOL_VERSION_Q2PRO) {
1023  if (nctype == NETCHAN_NEW)
1024  ncstring = " nc=1";
1025  else
1026  ncstring = " nc=0";
1027  }
1028 
1029  if (!sv_force_reconnect->string[0] || newcl->reconnect_var[0])
1030  acstring = AC_ClientConnect(newcl);
1031 
1032  if (sv_downloadserver->string[0]) {
1033  dlstring1 = " dlserver=";
1034  dlstring2 = sv_downloadserver->string;
1035  }
1036 
1037  Netchan_OutOfBand(NS_SERVER, &net_from, "client_connect%s%s%s%s map=%s",
1038  ncstring, acstring, dlstring1, dlstring2, newcl->mapname);
1039 }
1040 
1041 // converts all the extra positional parameters to `connect' command into an
1042 // infostring appended to normal userinfo after terminating NUL. game mod can
1043 // then access these parameters in ClientConnect callback.
1044 static void append_extra_userinfo(conn_params_t *params, char *userinfo)
1045 {
1046  if (!(g_features->integer & GMF_EXTRA_USERINFO)) {
1047  userinfo[strlen(userinfo) + 1] = 0;
1048  return;
1049  }
1050 
1051  Q_snprintf(userinfo + strlen(userinfo) + 1, MAX_INFO_STRING,
1052  "\\challenge\\%d\\ip\\%s"
1053  "\\major\\%d\\minor\\%d\\netchan\\%d"
1054  "\\packetlen\\%d\\qport\\%d\\zlib\\%d",
1055  params->challenge, userinfo_ip_string(),
1056  params->protocol, params->version, params->nctype,
1057  params->maxlength, params->qport, params->has_zlib);
1058 }
1059 
1060 static void SVC_DirectConnect(void)
1061 {
1062  char userinfo[MAX_INFO_STRING * 2];
1063  conn_params_t params;
1064  client_t *newcl;
1065  int number;
1066  qboolean allow;
1067  char *reason;
1068 
1069  memset(&params, 0, sizeof(params));
1070 
1071  // parse and validate parameters
1072  if (!parse_basic_params(&params))
1073  return;
1074  if (!permit_connection(&params))
1075  return;
1076  if (!parse_packet_length(&params))
1077  return;
1078  if (!parse_enhanced_params(&params))
1079  return;
1080  if (!parse_userinfo(&params, userinfo))
1081  return;
1082 
1083  // find a free client slot
1084  newcl = find_client_slot(&params);
1085  if (!newcl)
1086  return;
1087 
1088  number = newcl - svs.client_pool;
1089 
1090  // build a new connection
1091  // accept the new client
1092  // this is the only place a client_t is ever initialized
1093  memset(newcl, 0, sizeof(*newcl));
1094  newcl->number = newcl->slot = number;
1095  newcl->challenge = params.challenge; // save challenge for checksumming
1096  newcl->protocol = params.protocol;
1097  newcl->version = params.version;
1098  newcl->has_zlib = params.has_zlib;
1099  newcl->edict = EDICT_NUM(number + 1);
1100  newcl->gamedir = fs_game->string;
1101  newcl->mapname = sv.name;
1102  newcl->configstrings = (char *)sv.configstrings;
1103  newcl->pool = (edict_pool_t *)&ge->edicts;
1104  newcl->cm = &sv.cm;
1105  newcl->spawncount = sv.spawncount;
1106  newcl->maxclients = sv_maxclients->integer;
1107  newcl->last_valid_cluster = -1;
1108  strcpy(newcl->reconnect_var, params.reconnect_var);
1109  strcpy(newcl->reconnect_val, params.reconnect_val);
1110 #if USE_FPS
1111  newcl->framediv = sv.framediv;
1112  newcl->settings[CLS_FPS] = BASE_FRAMERATE;
1113 #endif
1114 
1115  init_pmove_and_es_flags(newcl);
1116 
1117  append_extra_userinfo(&params, userinfo);
1118 
1119  // get the game a chance to reject this connection or modify the userinfo
1120  sv_client = newcl;
1121  sv_player = newcl->edict;
1122  allow = ge->ClientConnect(newcl->edict, userinfo);
1123  sv_client = NULL;
1124  sv_player = NULL;
1125  if (!allow) {
1126  reason = Info_ValueForKey(userinfo, "rejmsg");
1127  if (*reason) {
1128  __reject("%s\nConnection refused.\n", reason);
1129  } else {
1130  __reject("Connection refused.\n");
1131  }
1132  return;
1133  }
1134 
1135  // setup netchan
1136  newcl->netchan = Netchan_Setup(NS_SERVER, params.nctype,
1137  &net_from, params.qport,
1138  params.maxlength,
1139  params.protocol);
1140  newcl->numpackets = 1;
1141 
1142  // parse some info from the info strings
1143  Q_strlcpy(newcl->userinfo, userinfo, sizeof(newcl->userinfo));
1144  SV_UserinfoChanged(newcl);
1145 
1146  // send the connect packet to the client
1147  send_connect_packet(newcl, params.nctype);
1148 
1150 
1151  SV_InitClientSend(newcl);
1152 
1153  if (newcl->protocol == PROTOCOL_VERSION_DEFAULT) {
1155  } else {
1157  }
1158 
1159  // loopback client doesn't need to reconnect
1160  if (NET_IsLocalAddress(&net_from)) {
1161  newcl->reconnected = qtrue;
1162  }
1163 
1164  // add them to the linked list of connected clients
1165  List_SeqAdd(&sv_clientlist, &newcl->entry);
1166 
1167  Com_DPrintf("Going from cs_free to cs_assigned for %s\n", newcl->name);
1168  newcl->state = cs_assigned;
1169  newcl->framenum = 1; // frame 0 can't be used
1170  newcl->lastframe = -1;
1171  newcl->lastmessage = svs.realtime; // don't timeout
1172  newcl->lastactivity = svs.realtime;
1173  newcl->min_ping = 9999;
1174 }
1175 
1176 static qboolean rcon_valid(void)
1177 {
1178  if (!rcon_password->string[0])
1179  return qfalse;
1180 
1181  if (strcmp(Cmd_Argv(1), rcon_password->string))
1182  return qfalse;
1183 
1184  return qtrue;
1185 }
1186 
1187 /*
1188 ===============
1189 SVC_RemoteCommand
1190 
1191 A client issued an rcon command.
1192 Redirect all printfs.
1193 ===============
1194 */
1195 static void SVC_RemoteCommand(void)
1196 {
1197  char *s;
1198 
1200  Com_DPrintf("Dropping rcon from %s\n",
1202  return;
1203  }
1204 
1205  s = Cmd_RawArgsFrom(2);
1206  if (!rcon_valid()) {
1207  Com_Printf("Invalid rcon from %s:\n%s\n",
1208  NET_AdrToString(&net_from), s);
1209  Netchan_OutOfBand(NS_SERVER, &net_from,
1210  "print\nBad rcon_password.\n");
1211  return;
1212  }
1213 
1214  // valid rcon packets are not rate limited
1216 
1217  if (dedicated->integer)
1218  {
1219  Com_Printf("Rcon from %s: \"%s\"\n", NET_AdrToString(&net_from), s);
1220  }
1221 
1224  Com_EndRedirect();
1225 }
1226 
1227 static const ucmd_t svcmds[] = {
1228  { "ping", SVC_Ping },
1229  { "ack", SVC_Ack },
1230  { "status", SVC_Status },
1231  { "info", SVC_Info },
1232  { "getchallenge", SVC_GetChallenge },
1233  { "connect", SVC_DirectConnect },
1234  { NULL }
1235 };
1236 
1237 /*
1238 =================
1239 SV_ConnectionlessPacket
1240 
1241 A connectionless packet has four leading 0xff
1242 characters to distinguish it from a game channel.
1243 Clients that are in the game can still send
1244 connectionless packets.
1245 =================
1246 */
1247 static void SV_ConnectionlessPacket(void)
1248 {
1249  char string[MAX_STRING_CHARS];
1250  char *c;
1251  int i;
1252  size_t len;
1253 
1255  Com_DPrintf("ignored blackholed connectionless packet\n");
1256  return;
1257  }
1258 
1259  MSG_BeginReading();
1260  MSG_ReadLong(); // skip the -1 marker
1261 
1262  len = MSG_ReadStringLine(string, sizeof(string));
1263  if (len >= sizeof(string)) {
1264  Com_DPrintf("ignored oversize connectionless packet\n");
1265  return;
1266  }
1267 
1268  Cmd_TokenizeString(string, qfalse);
1269 
1270  c = Cmd_Argv(0);
1271  Com_DPrintf("ServerPacket[%s]: %s\n", NET_AdrToString(&net_from), c);
1272 
1273  if (!strcmp(c, "rcon")) {
1275  return; // accept rcon commands even if not active
1276  }
1277 
1278  if (!svs.initialized) {
1279  Com_DPrintf("ignored connectionless packet\n");
1280  return;
1281  }
1282 
1283  for (i = 0; svcmds[i].name; i++) {
1284  if (!strcmp(c, svcmds[i].name)) {
1285  svcmds[i].func();
1286  return;
1287  }
1288  }
1289 
1290  Com_DPrintf("bad connectionless packet\n");
1291 }
1292 
1293 
1294 //============================================================================
1295 
1297 {
1298  client_t *cl;
1299  int count = 0;
1300 
1301  FOR_EACH_CLIENT(cl) {
1302  if (cl->state > cs_zombie) {
1303  count++;
1304  }
1305  }
1306 
1307  return count;
1308 }
1309 
1310 static int ping_nop(client_t *cl)
1311 {
1312  return 0;
1313 }
1314 
1315 static int ping_min(client_t *cl)
1316 {
1317  client_frame_t *frame;
1318  int i, j, count = INT_MAX;
1319 
1320  for (i = 0; i < UPDATE_BACKUP; i++) {
1321  j = cl->framenum - i - 1;
1322  frame = &cl->frames[j & UPDATE_MASK];
1323  if (frame->number != j)
1324  continue;
1325  if (frame->latency == -1)
1326  continue;
1327  if (count > frame->latency)
1328  count = frame->latency;
1329  }
1330 
1331  return count == INT_MAX ? 0 : count;
1332 }
1333 
1334 static int ping_avg(client_t *cl)
1335 {
1336  client_frame_t *frame;
1337  int i, j, total = 0, count = 0;
1338 
1339  for (i = 0; i < UPDATE_BACKUP; i++) {
1340  j = cl->framenum - i - 1;
1341  frame = &cl->frames[j & UPDATE_MASK];
1342  if (frame->number != j)
1343  continue;
1344  if (frame->latency == -1)
1345  continue;
1346  count++;
1347  total += frame->latency;
1348  }
1349 
1350  return count ? total / count : 0;
1351 }
1352 
1353 /*
1354 ===================
1355 SV_CalcPings
1356 
1357 Updates the cl->ping and cl->fps variables
1358 ===================
1359 */
1360 static void SV_CalcPings(void)
1361 {
1362  client_t *cl;
1363  int (*calc)(client_t *);
1364  int res;
1365 
1366  switch (sv_calcpings_method->integer) {
1367  case 0: calc = ping_nop; break;
1368  case 2: calc = ping_min; break;
1369  default: calc = ping_avg; break;
1370  }
1371 
1372  // update avg ping and fps every 10 seconds
1373  res = sv.framenum % (10 * SV_FRAMERATE);
1374 
1375  FOR_EACH_CLIENT(cl) {
1376  if (cl->state == cs_spawned) {
1377  cl->ping = calc(cl);
1378  if (cl->ping) {
1379  if (cl->ping < cl->min_ping) {
1380  cl->min_ping = cl->ping;
1381  } else if (cl->ping > cl->max_ping) {
1382  cl->max_ping = cl->ping;
1383  }
1384  if (!res) {
1385  cl->avg_ping_time += cl->ping;
1386  cl->avg_ping_count++;
1387  }
1388  }
1389  if (!res) {
1390  cl->moves_per_sec = cl->num_moves / 10;
1391  cl->num_moves = 0;
1392  }
1393  } else {
1394  cl->ping = 0;
1395  cl->moves_per_sec = 0;
1396  cl->num_moves = 0;
1397  }
1398 
1399  // let the game dll know about the ping
1400  cl->edict->client->ping = cl->ping;
1401  }
1402 }
1403 
1404 
1405 /*
1406 ===================
1407 SV_GiveMsec
1408 
1409 Every few frames, gives all clients an allotment of milliseconds
1410 for their command moves. If they exceed it, assume cheating.
1411 ===================
1412 */
1413 static void SV_GiveMsec(void)
1414 {
1415  client_t *cl;
1416 
1417  if (sv.framenum % (16 * SV_FRAMEDIV))
1418  return;
1419 
1420  FOR_EACH_CLIENT(cl) {
1421  cl->command_msec = 1800; // 1600 + some slop
1422  }
1423 }
1424 
1425 
1426 /*
1427 =================
1428 SV_PacketEvent
1429 =================
1430 */
1431 static void SV_PacketEvent(void)
1432 {
1433  client_t *client;
1434  netchan_t *netchan;
1435  int qport;
1436 
1437  // check for connectionless packet (0xffffffff) first
1438  // connectionless packets are processed even if the server is down
1439  if (*(int *)msg_read.data == -1) {
1441  return;
1442  }
1443 
1444  if (!svs.initialized) {
1445  return;
1446  }
1447 
1448  // check for packets from connected clients
1449  FOR_EACH_CLIENT(client) {
1450  netchan = client->netchan;
1451  if (!NET_IsEqualBaseAdr(&net_from, &netchan->remote_address)) {
1452  continue;
1453  }
1454 
1455  // read the qport out of the message so we can fix up
1456  // stupid address translating routers
1457  if (client->protocol == PROTOCOL_VERSION_DEFAULT) {
1458  qport = msg_read.data[8] | (msg_read.data[9] << 8);
1459  if (netchan->qport != qport) {
1460  continue;
1461  }
1462  } else if (netchan->qport) {
1463  qport = msg_read.data[8];
1464  if (netchan->qport != qport) {
1465  continue;
1466  }
1467  } else {
1468  if (netchan->remote_address.port != net_from.port) {
1469  continue;
1470  }
1471  }
1472 
1473  if (netchan->remote_address.port != net_from.port) {
1474  Com_DPrintf("Fixing up a translated port for %s: %d --> %d\n",
1475  client->name, netchan->remote_address.port, net_from.port);
1476  netchan->remote_address.port = net_from.port;
1477  }
1478 
1479  if (!netchan->Process(netchan))
1480  break;
1481 
1482  if (client->state == cs_zombie)
1483  break;
1484 
1485  // this is a valid, sequenced packet, so process it
1486  client->lastmessage = svs.realtime; // don't timeout
1487 #if USE_ICMP
1488  client->unreachable = qfalse; // don't drop
1489 #endif
1490  if (netchan->dropped > 0)
1491  client->frameflags |= FF_CLIENTDROP;
1492 
1493  SV_ExecuteClientMessage(client);
1494  break;
1495  }
1496 }
1497 
1498 #if USE_PMTUDISC
1499 // We are doing path MTU discovery and got ICMP fragmentation-needed.
1500 // Update MTU for connecting clients only to minimize spoofed ICMP interference.
1501 // Total 64 bytes of headers is assumed.
1502 static void update_client_mtu(client_t *client, int ee_info)
1503 {
1504  netchan_t *netchan = client->netchan;
1505  size_t newpacketlen;
1506 
1507  // sanity check discovered MTU
1508  if (ee_info < 576 || ee_info > 4096)
1509  return;
1510 
1511  if (client->state != cs_primed)
1512  return;
1513 
1514  // TODO: old clients require entire queue flush :(
1515  if (netchan->type == NETCHAN_OLD)
1516  return;
1517 
1518  if (!netchan->reliable_length)
1519  return;
1520 
1521  newpacketlen = ee_info - 64;
1522  if (newpacketlen >= netchan->maxpacketlen)
1523  return;
1524 
1525  Com_Printf("Fixing up maxmsglen for %s: %"PRIz" --> %"PRIz"\n",
1526  client->name, netchan->maxpacketlen, newpacketlen);
1527  netchan->maxpacketlen = newpacketlen;
1528 }
1529 #endif
1530 
1531 #if USE_ICMP
1532 /*
1533 =================
1534 SV_ErrorEvent
1535 =================
1536 */
1537 void SV_ErrorEvent(netadr_t *from, int ee_errno, int ee_info)
1538 {
1539  client_t *client;
1540  netchan_t *netchan;
1541 
1542  if (!svs.initialized) {
1543  return;
1544  }
1545 
1546  // check for errors from connected clients
1547  FOR_EACH_CLIENT(client) {
1548  if (client->state == cs_zombie) {
1549  continue; // already a zombie
1550  }
1551  netchan = client->netchan;
1552  if (!NET_IsEqualBaseAdr(from, &netchan->remote_address)) {
1553  continue;
1554  }
1555  if (from->port && netchan->remote_address.port != from->port) {
1556  continue;
1557  }
1558 #if USE_PMTUDISC
1559  // for EMSGSIZE ee_info should hold discovered MTU
1560  if (ee_errno == EMSGSIZE) {
1561  update_client_mtu(client, ee_info);
1562  continue;
1563  }
1564 #endif
1565  client->unreachable = qtrue; // drop them soon
1566  break;
1567  }
1568 }
1569 #endif
1570 
1571 /*
1572 ==================
1573 SV_CheckTimeouts
1574 
1575 If a packet has not been received from a client for timeout->value
1576 seconds, drop the conneciton.
1577 
1578 When a client is normally dropped, the client_t goes into a zombie state
1579 for a few seconds to make sure any final reliable message gets resent
1580 if necessary
1581 ==================
1582 */
1583 static void SV_CheckTimeouts(void)
1584 {
1585  client_t *client;
1586  unsigned zombie_time = 1000 * sv_zombietime->value;
1587  unsigned drop_time = 1000 * sv_timeout->value;
1588  unsigned ghost_time = 1000 * sv_ghostime->value;
1589  unsigned idle_time = 1000 * sv_idlekick->value;
1590  unsigned delta;
1591 
1592  FOR_EACH_CLIENT(client) {
1593  // never timeout local clients
1594  if (NET_IsLocalAddress(&client->netchan->remote_address)) {
1595  continue;
1596  }
1597  // NOTE: delta calculated this way is not sensitive to overflow
1598  delta = svs.realtime - client->lastmessage;
1599  if (client->state == cs_zombie) {
1600  if (delta > zombie_time) {
1601  SV_RemoveClient(client);
1602  }
1603  continue;
1604  }
1605  if (client->drop_hack) {
1606  SV_DropClient(client, NULL);
1607  continue;
1608  }
1609 #if USE_ICMP
1610  if (client->unreachable) {
1611  if (delta > ghost_time) {
1612  SV_DropClient(client, "connection reset by peer");
1613  SV_RemoveClient(client); // don't bother with zombie state
1614  continue;
1615  }
1616  }
1617 #endif
1618  if (delta > drop_time || (client->state == cs_assigned && delta > ghost_time)) {
1619  SV_DropClient(client, "?timed out");
1620  SV_RemoveClient(client); // don't bother with zombie state
1621  continue;
1622  }
1623 
1624  if (client->frames_nodelta > 64 && !sv_allow_nodelta->integer) {
1625  SV_DropClient(client, "too many nodelta frames");
1626  continue;
1627  }
1628 
1629  delta = svs.realtime - client->lastactivity;
1630  if (idle_time && delta > idle_time) {
1631  SV_DropClient(client, "idling");
1632  continue;
1633  }
1634  }
1635 }
1636 
1637 /*
1638 ================
1639 SV_PrepWorldFrame
1640 
1641 This has to be done before the world logic, because
1642 player processing happens outside RunWorldFrame
1643 ================
1644 */
1645 static void SV_PrepWorldFrame(void)
1646 {
1647  edict_t *ent;
1648  int i;
1649 
1650 #if USE_MVD_CLIENT
1651  if (sv.state == ss_broadcast) {
1653  return;
1654  }
1655 #endif
1656 
1657  sv.tracecount = 0;
1658 
1659  if (!SV_FRAMESYNC)
1660  return;
1661 
1662  for (i = 1; i < ge->num_edicts; i++) {
1663  ent = EDICT_NUM(i);
1664 
1665  // events only last for a single keyframe
1666  ent->s.event = 0;
1667  }
1668 }
1669 
1670 // pause if there is only local client on the server
1671 static inline qboolean check_paused(void)
1672 {
1673 #if USE_CLIENT
1674  if (dedicated->integer)
1675  goto resume;
1676 
1677  if (!cl_paused->integer)
1678  goto resume;
1679 
1680  if (com_timedemo->integer)
1681  goto resume;
1682 
1683  if (!LIST_SINGLE(&sv_clientlist))
1684  goto resume;
1685 
1686 #if USE_MVD_CLIENT
1687  if (!LIST_EMPTY(&mvd_gtv_list))
1688  goto resume;
1689 #endif
1690 
1691  if (!sv_paused->integer) {
1692  Cvar_Set("sv_paused", "1");
1693  IN_Activate();
1694  }
1695 
1696  return qtrue; // don't run if paused
1697 
1698 resume:
1699  if (sv_paused->integer) {
1700  Cvar_Set("sv_paused", "0");
1701  IN_Activate();
1702  }
1703 #endif
1704 
1705  return qfalse;
1706 }
1707 
1708 /*
1709 =================
1710 SV_RunGameFrame
1711 =================
1712 */
1713 static void SV_RunGameFrame(void)
1714 {
1715  // save the entire world state if recording a serverdemo
1716  SV_MvdBeginFrame();
1717 
1718 #if USE_CLIENT
1719  if (host_speeds->integer)
1720  time_before_game = Sys_Milliseconds();
1721 #endif
1722 
1723  X86_PUSH_FPCW;
1724  X86_SINGLE_FPCW;
1725 
1726  ge->RunFrame();
1727 
1728  X86_POP_FPCW;
1729 
1730 #if USE_CLIENT
1731  if (host_speeds->integer)
1732  time_after_game = Sys_Milliseconds();
1733 #endif
1734 
1735  if (msg_write.cursize) {
1736  Com_WPrintf("Game left %"PRIz" bytes "
1737  "in multicast buffer, cleared.\n",
1738  msg_write.cursize);
1739  SZ_Clear(&msg_write);
1740  }
1741 
1742  // save the entire world state if recording a serverdemo
1743  SV_MvdEndFrame();
1744 }
1745 
1746 /*
1747 ================
1748 SV_MasterHeartbeat
1749 
1750 Send a message to the master every few minutes to
1751 let it know we are alive, and log information
1752 ================
1753 */
1754 static void SV_MasterHeartbeat(void)
1755 {
1756  char buffer[MAX_PACKETLEN_DEFAULT];
1757  size_t len;
1758  master_t *m;
1759 
1760  if (!COM_DEDICATED)
1761  return; // only dedicated servers send heartbeats
1762 
1763  if (!sv_public->integer)
1764  return; // a private dedicated game
1765 
1767  return; // not time to send yet
1768 
1770 
1771  // write the packet header
1772  memcpy(buffer, "\xff\xff\xff\xffheartbeat\n", 14);
1773  len = 14;
1774 
1775  // send the same string that we would give for a status OOB command
1776  len += SV_StatusString(buffer + len);
1777 
1778  // send to group master
1779  FOR_EACH_MASTER(m) {
1780  if (m->adr.port) {
1781  Com_DPrintf("Sending heartbeat to %s\n",
1782  NET_AdrToString(&m->adr));
1783  NET_SendPacket(NS_SERVER, buffer, len, &m->adr);
1784  }
1785  }
1786 }
1787 
1788 /*
1789 =================
1790 SV_MasterShutdown
1791 
1792 Informs all masters that this server is going down
1793 =================
1794 */
1795 static void SV_MasterShutdown(void)
1796 {
1797  master_t *m;
1798 
1799  // reset ack times
1800  FOR_EACH_MASTER(m) {
1801  m->last_ack = 0;
1802  }
1803 
1804  if (!COM_DEDICATED)
1805  return; // only dedicated servers send heartbeats
1806 
1807  if (!sv_public || !sv_public->integer)
1808  return; // a private dedicated game
1809 
1810  // send to group master
1811  FOR_EACH_MASTER(m) {
1812  if (m->adr.port) {
1813  Com_DPrintf("Sending shutdown to %s\n",
1814  NET_AdrToString(&m->adr));
1815  OOB_PRINT(NS_SERVER, &m->adr, "shutdown");
1816  }
1817  }
1818 }
1819 
1820 /*
1821 ==================
1822 SV_Frame
1823 
1824 Some things like MVD client connections and command buffer
1825 processing are run even when server is not yet initalized.
1826 
1827 Returns amount of extra frametime available for sleeping on IO.
1828 ==================
1829 */
1830 unsigned SV_Frame(unsigned msec)
1831 {
1832 #if USE_CLIENT
1833  time_before_game = time_after_game = 0;
1834 #endif
1835 
1836  // advance local server time
1837  svs.realtime += msec;
1838 
1839  if (COM_DEDICATED) {
1840  // process console commands if not running a client
1842  }
1843 
1844 #if USE_MVD_CLIENT
1845  // run connections to MVD/GTV servers
1846  MVD_Frame();
1847 #endif
1848 
1849  // read packets from UDP clients
1850  NET_GetPackets(NS_SERVER, SV_PacketEvent);
1851 
1852  if (svs.initialized) {
1853  // run connection to the anticheat server
1854  AC_Run();
1855 
1856  // run connections from MVD/GTV clients
1857  SV_MvdRunClients();
1858 
1859  // deliver fragments and reliable messages for connecting clients
1861  }
1862 
1863  // move autonomous things around if enough time has passed
1864  sv.frameresidual += msec;
1865  if (sv.frameresidual < SV_FRAMETIME) {
1866  return SV_FRAMETIME - sv.frameresidual;
1867  }
1868 
1869  if (svs.initialized && !check_paused()) {
1870  // check timeouts
1871  SV_CheckTimeouts();
1872 
1873  // update ping based on the last known frame from all clients
1874  SV_CalcPings();
1875 
1876  // give the clients some timeslices
1877  SV_GiveMsec();
1878 
1879  // let everything in the world think and move
1880  SV_RunGameFrame();
1881 
1882  // send messages back to the UDP clients
1884 
1885  // send a heartbeat to the master if needed
1887 
1888  // clear teleport flags, etc for next frame
1890 
1891  // advance for next frame
1892  sv.framenum++;
1893  }
1894 
1895  if (COM_DEDICATED) {
1896  // run cmd buffer in dedicated mode
1897  if (cmd_buffer.waitCount > 0) {
1898  cmd_buffer.waitCount--;
1899  }
1900  }
1901 
1902  // decide how long to sleep next frame
1904  if (sv.frameresidual < SV_FRAMETIME) {
1905  return SV_FRAMETIME - sv.frameresidual;
1906  }
1907 
1908  // don't accumulate bogus residual
1909  if (sv.frameresidual > 250) {
1910  Com_DDDPrintf("Reset residual %u\n", sv.frameresidual);
1911  sv.frameresidual = 100;
1912  }
1913 
1914  return 0;
1915 }
1916 
1917 //============================================================================
1918 
1919 /*
1920 =================
1921 SV_UserinfoChanged
1922 
1923 Pull specific info from a newly changed userinfo string
1924 into a more C freindly form.
1925 =================
1926 */
1928 {
1929  char name[MAX_CLIENT_NAME];
1930  char *val;
1931  size_t len;
1932  int i;
1933 
1934  // call prog code to allow overrides
1935  ge->ClientUserinfoChanged(cl->edict, cl->userinfo);
1936 
1937  // name for C code
1938  val = Info_ValueForKey(cl->userinfo, "name");
1939  len = Q_strlcpy(name, val, sizeof(name));
1940  if (len >= sizeof(name)) {
1941  len = sizeof(name) - 1;
1942  }
1943  // mask off high bit
1944  for (i = 0; i < len; i++)
1945  name[i] &= 127;
1946  if (cl->name[0] && strcmp(cl->name, name)) {
1947  if (COM_DEDICATED) {
1948  Com_Printf("%s[%s] changed name to %s\n", cl->name,
1949  NET_AdrToString(&cl->netchan->remote_address), name);
1950  }
1951 #if USE_MVD_CLIENT
1952  if (sv.state == ss_broadcast) {
1953  MVD_GameClientNameChanged(cl->edict, name);
1954  } else
1955 #endif
1956  if (sv_show_name_changes->integer) {
1957  SV_BroadcastPrintf(PRINT_HIGH, "%s changed name to %s\n",
1958  cl->name, name);
1959  }
1960  }
1961  memcpy(cl->name, name, len + 1);
1962 
1963  // rate command
1964  val = Info_ValueForKey(cl->userinfo, "rate");
1965  if (*val) {
1966  cl->rate = atoi(val);
1967  clamp(cl->rate, 100, 15000);
1968  } else {
1969  cl->rate = 5000;
1970  }
1971 
1972  // never drop over the loopback
1973  if (NET_IsLocalAddress(&cl->netchan->remote_address)) {
1974  cl->rate = 0;
1975  }
1976 
1977  // don't drop over LAN connections
1978  if (sv_lan_force_rate->integer &&
1979  NET_IsLanAddress(&cl->netchan->remote_address)) {
1980  cl->rate = 0;
1981  }
1982 
1983  // msg command
1984  val = Info_ValueForKey(cl->userinfo, "msg");
1985  if (*val) {
1986  cl->messagelevel = atoi(val);
1987  clamp(cl->messagelevel, PRINT_LOW, PRINT_CHAT + 1);
1988  }
1989 }
1990 
1991 
1992 //============================================================================
1993 
1994 #if USE_SYSCON
1995 void SV_SetConsoleTitle(void)
1996 {
1997  char buffer[MAX_STRING_CHARS];
1998 
1999  Q_snprintf(buffer, sizeof(buffer), "%s (port %d%s)",
2000  sv_hostname->string, net_port->integer,
2001  sv_running->integer ? "" : ", down");
2002 
2003  Sys_SetConsoleTitle(buffer);
2004 }
2005 #endif
2006 
2007 static void sv_status_limit_changed(cvar_t *self)
2008 {
2009  SV_RateInit(&svs.ratelimit_status, self->string);
2010 }
2011 
2012 static void sv_auth_limit_changed(cvar_t *self)
2013 {
2014  SV_RateInit(&svs.ratelimit_auth, self->string);
2015 }
2016 
2017 static void sv_rcon_limit_changed(cvar_t *self)
2018 {
2019  SV_RateInit(&svs.ratelimit_rcon, self->string);
2020 }
2021 
2022 static void init_rate_limits(void)
2023 {
2027 }
2028 
2029 static void sv_namechange_limit_changed(cvar_t *self)
2030 {
2031  client_t *client;
2032 
2033  FOR_EACH_CLIENT(client) {
2034  SV_RateInit(&client->ratelimit_namechange, self->string);
2035  }
2036 }
2037 
2038 #if USE_SYSCON
2039 static void sv_hostname_changed(cvar_t *self)
2040 {
2041  SV_SetConsoleTitle();
2042 }
2043 #endif
2044 
2045 #if USE_ZLIB
2046 voidpf SV_zalloc(voidpf opaque, uInt items, uInt size)
2047 {
2048  return SV_Malloc(items * size);
2049 }
2050 
2051 void SV_zfree(voidpf opaque, voidpf address)
2052 {
2053  Z_Free(address);
2054 }
2055 #endif
2056 
2057 /*
2058 ===============
2059 SV_Init
2060 
2061 Only called at quake2.exe startup, not for each game
2062 ===============
2063 */
2064 void SV_Init(void)
2065 {
2067 
2068  SV_MvdRegister();
2069 
2070 #if USE_MVD_CLIENT
2071  MVD_Register();
2072 #endif
2073 
2074  AC_Register();
2075 
2077 
2078  Cvar_Get("protocol", STRINGIFY(PROTOCOL_VERSION_DEFAULT), CVAR_SERVERINFO | CVAR_ROM);
2079 
2080  Cvar_Get("skill", "1", CVAR_LATCH);
2081  Cvar_Get("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH);
2082  Cvar_Get("coop", "0", /*CVAR_SERVERINFO|*/CVAR_LATCH);
2083  Cvar_Get("cheats", "0", CVAR_SERVERINFO | CVAR_LATCH);
2084  Cvar_Get("dmflags", va("%i", DF_INSTANT_ITEMS), CVAR_SERVERINFO);
2085  Cvar_Get("fraglimit", "0", CVAR_SERVERINFO);
2086  Cvar_Get("timelimit", "0", CVAR_SERVERINFO);
2087 
2088  sv_maxclients = Cvar_Get("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH);
2089  sv_reserved_slots = Cvar_Get("sv_reserved_slots", "0", CVAR_LATCH);
2090  sv_hostname = Cvar_Get("hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE);
2091 #if USE_SYSCON
2092  sv_hostname->changed = sv_hostname_changed;
2093 #endif
2094  sv_timeout = Cvar_Get("timeout", "90", 0);
2095  sv_zombietime = Cvar_Get("zombietime", "2", 0);
2096  sv_ghostime = Cvar_Get("sv_ghostime", "6", 0);
2097  sv_idlekick = Cvar_Get("sv_idlekick", "0", 0);
2098  sv_showclamp = Cvar_Get("showclamp", "0", 0);
2099  sv_enforcetime = Cvar_Get("sv_enforcetime", "1", 0);
2100  sv_allow_nodelta = Cvar_Get("sv_allow_nodelta", "1", 0);
2101 #if USE_FPS
2102  sv_fps = Cvar_Get("sv_fps", "10", CVAR_LATCH);
2103 #endif
2104  sv_force_reconnect = Cvar_Get("sv_force_reconnect", "", CVAR_LATCH);
2105  sv_show_name_changes = Cvar_Get("sv_show_name_changes", "0", 0);
2106 
2107  sv_airaccelerate = Cvar_Get("sv_airaccelerate", "0", CVAR_LATCH);
2108  sv_qwmod = Cvar_Get("sv_qwmod", "0", CVAR_LATCH); //atu QWMod
2109  sv_public = Cvar_Get("public", "0", CVAR_LATCH);
2110  sv_password = Cvar_Get("sv_password", "", CVAR_PRIVATE);
2111  sv_reserved_password = Cvar_Get("sv_reserved_password", "", CVAR_PRIVATE);
2112  sv_locked = Cvar_Get("sv_locked", "0", 0);
2113  sv_novis = Cvar_Get("sv_novis", "0", 0);
2114  sv_downloadserver = Cvar_Get("sv_downloadserver", "", 0);
2115  sv_redirect_address = Cvar_Get("sv_redirect_address", "", 0);
2116 
2117 #ifdef _DEBUG
2118  sv_debug = Cvar_Get("sv_debug", "0", 0);
2119  sv_pad_packets = Cvar_Get("sv_pad_packets", "0", 0);
2120 #endif
2121  sv_lan_force_rate = Cvar_Get("sv_lan_force_rate", "0", CVAR_LATCH);
2122  sv_calcpings_method = Cvar_Get("sv_calcpings_method", "2", 0);
2123  sv_changemapcmd = Cvar_Get("sv_changemapcmd", "", 0);
2124 
2125  sv_strafejump_hack = Cvar_Get("sv_strafejump_hack", "1", CVAR_LATCH);
2126  sv_waterjump_hack = Cvar_Get("sv_waterjump_hack", "0", CVAR_LATCH);
2127 
2128 #if USE_PACKETDUP
2129  sv_packetdup_hack = Cvar_Get("sv_packetdup_hack", "0", 0);
2130 #endif
2131 
2132  sv_allow_map = Cvar_Get("sv_allow_map", "0", 0);
2133 
2134 #if !USE_CLIENT
2135  sv_recycle = Cvar_Get("sv_recycle", "0", 0);
2136 #endif
2137 
2138  sv_enhanced_setplayer = Cvar_Get("sv_enhanced_setplayer", "0", 0);
2139 
2140  sv_iplimit = Cvar_Get("sv_iplimit", "3", 0);
2141 
2142  sv_status_show = Cvar_Get("sv_status_show", "2", 0);
2143 
2144  sv_status_limit = Cvar_Get("sv_status_limit", "15", 0);
2146 
2147  sv_uptime = Cvar_Get("sv_uptime", "0", 0);
2148 
2149  sv_auth_limit = Cvar_Get("sv_auth_limit", "1", 0);
2151 
2152  sv_rcon_limit = Cvar_Get("sv_rcon_limit", "1", 0);
2154 
2155  sv_namechange_limit = Cvar_Get("sv_namechange_limit", "5/min", 0);
2157 
2158  sv_restrict_rtx = Cvar_Get("sv_restrict_rtx", "1", 0);
2159 
2160  sv_allow_unconnected_cmds = Cvar_Get("sv_allow_unconnected_cmds", "0", 0);
2161 
2162  Cvar_Get("sv_features", va("%d", SV_FEATURES), CVAR_ROM);
2163  g_features = Cvar_Get("g_features", "0", CVAR_ROM);
2164 
2165  map_override_path = Cvar_Get("map_override_path", "", 0);
2166 
2167  init_rate_limits();
2168 
2169 #if USE_FPS
2170  // set up default frametime for main loop
2171  sv.frametime = BASE_FRAMETIME;
2172 #endif
2173 
2174  // set up default pmove parameters
2175  PmoveInit(&sv_pmp);
2176 
2177 #if USE_SYSCON
2178  SV_SetConsoleTitle();
2179 #endif
2180 
2181  sv_registered = qtrue;
2182 }
2183 
2184 /*
2185 ==================
2186 SV_FinalMessage
2187 
2188 Used by SV_Shutdown to send a final message to all
2189 connected clients before the server goes down. The messages are sent
2190 immediately, not just stuck on the outgoing message list, because the
2191 server is going to totally exit after returning from this function.
2192 
2193 Also resposible for freeing all clients.
2194 ==================
2195 */
2196 static void SV_FinalMessage(const char *message, error_type_t type)
2197 {
2198  client_t *client;
2199  netchan_t *netchan;
2200  int i;
2201 
2202  if (LIST_EMPTY(&sv_clientlist))
2203  return;
2204 
2205  if (message) {
2206  MSG_WriteByte(svc_print);
2207  MSG_WriteByte(PRINT_HIGH);
2208  MSG_WriteString(message);
2209  }
2210 
2211  if (type == ERR_RECONNECT)
2212  MSG_WriteByte(svc_reconnect);
2213  else
2214  MSG_WriteByte(svc_disconnect);
2215 
2216  // send it twice
2217  // stagger the packets to crutch operating system limited buffers
2218  for (i = 0; i < 2; i++) {
2219  FOR_EACH_CLIENT(client) {
2220  if (client->state == cs_zombie) {
2221  continue;
2222  }
2223  netchan = client->netchan;
2224  while (netchan->fragment_pending) {
2225  netchan->TransmitNextFragment(netchan);
2226  }
2227  netchan->Transmit(netchan, msg_write.cursize, msg_write.data, 1);
2228  }
2229  }
2230 
2231  SZ_Clear(&msg_write);
2232 
2233  // free any data dynamically allocated
2234  FOR_EACH_CLIENT(client) {
2235  if (client->state != cs_zombie) {
2236  SV_CleanClient(client);
2237  }
2238  SV_RemoveClient(client);
2239  }
2240 
2241  List_Init(&sv_clientlist);
2242 }
2243 
2244 /*
2245 ================
2246 SV_Shutdown
2247 
2248 Called when each game quits, from Com_Quit or Com_Error.
2249 Should be safe to call even if server is not fully initalized yet.
2250 ================
2251 */
2252 void SV_Shutdown(const char *finalmsg, error_type_t type)
2253 {
2254  if (!sv_registered)
2255  return;
2256 
2257 #if USE_MVD_CLIENT
2258  if (ge != &mvd_ge && !(type & MVD_SPAWN_INTERNAL)) {
2259  // shutdown MVD client now if not already running the built-in MVD game module
2260  // don't shutdown if called from internal MVD spawn function (ugly hack)!
2261  MVD_Shutdown();
2262  }
2263  type &= ~MVD_SPAWN_MASK;
2264 #endif
2265 
2266  AC_Disconnect();
2267 
2268  SV_MvdShutdown(type);
2269 
2270  SV_FinalMessage(finalmsg, type);
2273 
2274  // free current level
2275  CM_FreeMap(&sv.cm);
2277  memset(&sv, 0, sizeof(sv));
2278 
2279  // free server static data
2281  Z_Free(svs.entities);
2282 #if USE_ZLIB
2283  deflateEnd(&svs.z);
2284 #endif
2285  memset(&svs, 0, sizeof(svs));
2286 
2287  // reset rate limits
2288  init_rate_limits();
2289 
2290 #if USE_FPS
2291  // set up default frametime for main loop
2292  sv.frametime = BASE_FRAMETIME;
2293 #endif
2294 
2295  sv_client = NULL;
2296  sv_player = NULL;
2297 
2298  Cvar_Set("sv_running", "0");
2299  Cvar_Set("sv_paused", "0");
2300 
2301 #if USE_SYSCON
2302  SV_SetConsoleTitle();
2303 #endif
2304 
2305  Z_LeakTest(TAG_SERVER);
2306 }
2307 
sv_blacklist
list_t sv_blacklist
client_s::lastframe
int lastframe
Definition: server.h:290
sv_enforcetime
cvar_t * sv_enforcetime
Definition: main.c:37
server_t::framenum
int framenum
Definition: server.h:155
sv_pending_autosave
qboolean sv_pending_autosave
Definition: main.c:35
client_s::version_string
char * version_string
Definition: server.h:282
server_t::entitystring
char * entitystring
Definition: server.h:162
SV_Shutdown
void SV_Shutdown(const char *finalmsg, error_type_t type)
Definition: main.c:2252
SV_RegisterSavegames
void SV_RegisterSavegames(void)
Definition: save.c:706
conn_params_t::reconnect_val
char reconnect_val[16]
Definition: main.c:627
reject
#define reject(...)
Definition: main.c:634
sv_auth_limit
cvar_t * sv_auth_limit
Definition: main.c:91
sv_downloadserver
cvar_t * sv_downloadserver
Definition: main.c:62
redirect
static client_t * redirect(const char *addr)
Definition: main.c:906
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
__reject
#define __reject(...)
Definition: main.c:630
SV_MvdRunClients
void SV_MvdRunClients(void)
Definition: mvd.c:1783
CM_FreeMap
void CM_FreeMap(cm_t *cm)
Definition: cmodel.c:47
MVD_SPAWN_INTERNAL
#define MVD_SPAWN_INTERNAL
Definition: server.h:96
SVC_GetChallenge
static void SVC_GetChallenge(void)
Definition: main.c:569
PmoveEnableQW
void PmoveEnableQW(pmoveParams_t *pmp)
Definition: pmove.c:1250
cs_spawned
@ cs_spawned
Definition: server.h:192
msg_read
sizebuf_t msg_read
Definition: msg.c:37
parse_basic_params
static qboolean parse_basic_params(conn_params_t *p)
Definition: main.c:637
sv_novis
cvar_t * sv_novis
Definition: main.c:56
svs
server_static_t svs
Definition: init.c:21
NET_AdrToString
char * NET_AdrToString(const netadr_t *a)
Definition: net.c:257
sv_masterlist
list_t sv_masterlist
sv_banlist
list_t sv_banlist
sv_qwmod
cvar_t * sv_qwmod
Definition: main.c:55
Cvar_BitInfo
size_t Cvar_BitInfo(char *info, int bit)
Definition: cvar.c:1109
SV_BASELINES_CHUNKS
#define SV_BASELINES_CHUNKS
Definition: server.h:71
Info_Validate
qboolean Info_Validate(const char *s)
Definition: shared.c:1040
MVD_GameClientNameChanged
void MVD_GameClientNameChanged(edict_t *ent, const char *name)
Definition: game.c:1922
sv_redirect_address
cvar_t * sv_redirect_address
Definition: main.c:63
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
sv_iplimit
cvar_t * sv_iplimit
Definition: main.c:87
challenge_t::adr
netadr_t adr
Definition: server.h:390
SV_ShutdownClientSend
void SV_ShutdownClientSend(client_t *client)
Definition: send.c:1063
client_s::protocol
int protocol
Definition: server.h:324
server_t::tracecount
unsigned tracecount
Definition: server.h:168
ratelimit_t
Definition: server.h:249
ratelimit_t::time
unsigned time
Definition: server.h:250
conn_params_t::reconnect_var
char reconnect_var[16]
Definition: main.c:626
MVD_Shutdown
void MVD_Shutdown(void)
Definition: client.c:2528
MSG_BeginReading
void MSG_BeginReading(void)
Definition: msg.c:1437
SV_FinalMessage
static void SV_FinalMessage(const char *message, error_type_t type)
Definition: main.c:2196
master_t
Definition: server.h:429
client_s::has_zlib
qboolean has_zlib
Definition: server.h:267
server_static_s::entities
entity_packed_t * entities
Definition: server.h:460
sv_showclamp
cvar_t * sv_showclamp
Definition: main.c:60
sv_enhanced_setplayer
cvar_t * sv_enhanced_setplayer
Definition: main.c:85
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
CREDITS_PER_MSEC
#define CREDITS_PER_MSEC
Definition: main.c:251
c
statCounters_t c
Definition: main.c:30
ping_nop
static int ping_nop(client_t *cl)
Definition: main.c:1310
Z_LeakTest
void Z_LeakTest(memtag_t tag)
Definition: zone.c:120
IN_Activate
void IN_Activate(void)
Definition: input.c:117
SV_MvdShutdown
void SV_MvdShutdown(error_type_t type)
Definition: mvd.c:2118
client_s::state
clstate_t state
Definition: server.h:260
SV_SendClientMessages
void SV_SendClientMessages(void)
Definition: send.c:880
SV_MvdRegister
void SV_MvdRegister(void)
Definition: mvd.c:2364
Netchan_Setup
netchan_t * Netchan_Setup(netsrc_t sock, netchan_type_t type, const netadr_t *adr, int qport, size_t maxpacketlen, int protocol)
Definition: chan.c:835
MSG_CLEAR
#define MSG_CLEAR
Definition: server.h:215
sv_namechange_limit_changed
static void sv_namechange_limit_changed(cvar_t *self)
Definition: main.c:2029
sv_waterjump_hack
cvar_t * sv_waterjump_hack
Definition: main.c:77
client_s::number
int number
Definition: server.h:262
sv_auth_limit_changed
static void sv_auth_limit_changed(cvar_t *self)
Definition: main.c:2012
conn_params_t::challenge
int challenge
Definition: main.c:619
MSG_RELIABLE
#define MSG_RELIABLE
Definition: server.h:214
client_s::gamedir
char * gamedir
Definition: server.h:344
sv_force_reconnect
cvar_t * sv_force_reconnect
Definition: main.c:51
sv_ghostime
cvar_t * sv_ghostime
Definition: main.c:45
net_maxmsglen
cvar_t * net_maxmsglen
Definition: chan.c:99
Netchan_OutOfBand
void Netchan_OutOfBand(netsrc_t sock, const netadr_t *address, const char *format,...)
Definition: chan.c:140
server_static_s::ratelimit_rcon
ratelimit_t ratelimit_rcon
Definition: server.h:470
client_s::spawncount
int spawncount
Definition: server.h:348
SV_WriteFrameToClient_Default
void SV_WriteFrameToClient_Default(client_t *client)
Definition: entities.c:174
client_s::slot
int slot
Definition: server.h:347
addrmatch_t::time
time_t time
Definition: server.h:400
addrmatch_t::hits
unsigned hits
Definition: server.h:399
Cmd_ExecuteString
void Cmd_ExecuteString(cmdbuf_t *buf, const char *text)
Definition: cmd.c:1698
SV_FRAMESYNC
#define SV_FRAMESYNC
Definition: server.h:141
addrmatch_t::comment
char comment[1]
Definition: server.h:401
sv_namechange_limit
cvar_t * sv_namechange_limit
Definition: main.c:93
SVC_Ack
static void SVC_Ack(void)
Definition: main.c:500
addrmatch_t::mask
netadr_t mask
Definition: server.h:398
SV_FRAMETIME
#define SV_FRAMETIME
Definition: server.h:139
SV_MvdEndFrame
void SV_MvdEndFrame(void)
Definition: mvd.c:1023
sv_reserved_password
cvar_t * sv_reserved_password
Definition: main.c:49
sv_paused
cvar_t * sv_paused
Definition: common.c:96
client_s::maxclients
int maxclients
Definition: server.h:349
clstate_t
clstate_t
Definition: server.h:185
SV_GiveMsec
static void SV_GiveMsec(void)
Definition: main.c:1413
client_s::mapname
char * mapname
Definition: server.h:344
Cmd_TokenizeString
void Cmd_TokenizeString(const char *text, qboolean macroExpand)
Definition: cmd.c:1399
conn_params_t::nctype
int nctype
Definition: main.c:622
LIST_DECL
LIST_DECL(sv_masterlist)
sv_timeout
cvar_t * sv_timeout
Definition: main.c:43
SV_PacketEvent
static void SV_PacketEvent(void)
Definition: main.c:1431
server_static_s::ratelimit_auth
ratelimit_t ratelimit_auth
Definition: server.h:469
sv_client
client_t * sv_client
Definition: main.c:32
sv_changemapcmd
cvar_t * sv_changemapcmd
Definition: main.c:74
Cmd_RawArgsFrom
char * Cmd_RawArgsFrom(int from)
Definition: cmd.c:1021
CREDITS_PER_SEC
#define CREDITS_PER_SEC
Definition: main.c:252
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
com_timedemo
cvar_t * com_timedemo
Definition: common.c:97
server_static_s::ratelimit_status
ratelimit_t ratelimit_status
Definition: server.h:468
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
rate2credits
static unsigned rate2credits(unsigned rate)
Definition: main.c:294
svc_stufftext
#define svc_stufftext
Definition: g_local.h:41
sv_airaccelerate
cvar_t * sv_airaccelerate
Definition: main.c:54
Sys_Milliseconds
unsigned Sys_Milliseconds(void)
Definition: system.c:644
SV_MasterHeartbeat
static void SV_MasterHeartbeat(void)
Definition: main.c:1754
client_s::last_valid_cluster
int last_valid_cluster
Definition: server.h:362
print_drop_reason
static void print_drop_reason(client_t *client, const char *reason, clstate_t oldstate)
Definition: main.c:165
SV_ClientAddMessage
void SV_ClientAddMessage(client_t *client, int flags)
Definition: send.c:399
SVC_Ping
static void SVC_Ping(void)
Definition: main.c:553
net_from
netadr_t net_from
Definition: net.c:90
SV_CleanClient
void SV_CleanClient(client_t *client)
Definition: main.c:135
FOR_EACH_MASTER
#define FOR_EACH_MASTER(m)
Definition: server.h:447
SV_UserinfoChanged
void SV_UserinfoChanged(client_t *cl)
Definition: main.c:1927
client_s::drop_hack
qboolean drop_hack
Definition: server.h:268
FOR_EACH_CLIENT
#define FOR_EACH_CLIENT(client)
Definition: server.h:239
find_client_slot
static client_t * find_client_slot(conn_params_t *params)
Definition: main.c:924
sv_allow_map
cvar_t * sv_allow_map
Definition: main.c:81
SV_Malloc
#define SV_Malloc(size)
Definition: server.h:54
sv_reserved_slots
cvar_t * sv_reserved_slots
Definition: main.c:59
cmd_buffer
cmdbuf_t cmd_buffer
Definition: cmd.c:49
rcon_password
cvar_t * rcon_password
Definition: common.c:114
addrmatch_t::addr
netadr_t addr
Definition: server.h:397
AC_ClientConnect
char * AC_ClientConnect(client_t *cl)
Definition: ac.c:1094
MVD_PrepWorldFrame
void void MVD_PrepWorldFrame(void)
Definition: game.c:2263
NET_GetPackets
void NET_GetPackets(netsrc_t sock, void(*packet_cb)(void))
Definition: net.c:895
sv_pmp
pmoveParams_t sv_pmp
Definition: main.c:22
server_static_s::last_heartbeat
unsigned last_heartbeat
Definition: server.h:466
HEARTBEAT_SECONDS
#define HEARTBEAT_SECONDS
Definition: server.h:427
dedicated
cvar_t * dedicated
Definition: g_main.c:46
SV_CountClients
int SV_CountClients(void)
Definition: main.c:1296
sv_lan_force_rate
cvar_t * sv_lan_force_rate
Definition: main.c:72
SV_FRAMERATE
#define SV_FRAMERATE
Definition: server.h:138
SV_SendAsyncPackets
void SV_SendAsyncPackets(void)
Definition: send.c:987
ratelimit_t::cost
unsigned cost
Definition: server.h:253
sv
server_t sv
Definition: init.c:22
client_s::baselines
entity_packed_t * baselines[SV_BASELINES_CHUNKS]
Definition: server.h:340
msg_write
sizebuf_t msg_write
Definition: msg.c:34
init_rate_limits
static void init_rate_limits(void)
Definition: main.c:2022
conn_params_t::qport
int qport
Definition: main.c:618
sv_uptime
cvar_t * sv_uptime
Definition: main.c:90
ratelimit_t::credit_cap
unsigned credit_cap
Definition: server.h:252
net_port
cvar_t * net_port
Definition: net.c:88
conn_params_t::maxlength
int maxlength
Definition: main.c:621
ratelimit_t::credit
unsigned credit
Definition: server.h:251
client_s::lastactivity
unsigned lastactivity
Definition: server.h:289
Com_EndRedirect
void Com_EndRedirect(void)
Definition: common.c:172
client_s::entry
list_t entry
Definition: server.h:257
Info_ValueForKey
char * Info_ValueForKey(const char *s, const char *key)
Definition: shared.c:945
va
char * va(const char *format,...)
Definition: shared.c:429
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
sv_zombietime
cvar_t * sv_zombietime
Definition: main.c:44
server_static_s::client_pool
client_t * client_pool
Definition: server.h:456
SVC_Info
static void SVC_Info(void)
Definition: main.c:525
server_static_s::initialized
qboolean initialized
Definition: server.h:453
server_static_s::challenges
challenge_t challenges[MAX_CHALLENGES]
Definition: server.h:472
MSG_ReadLong
int MSG_ReadLong(void)
Definition: msg.c:1517
m
static struct mdfour * m
Definition: mdfour.c:32
client_s::challenge
int challenge
Definition: server.h:323
cs_free
@ cs_free
Definition: server.h:186
SV_ExecuteClientMessage
void SV_ExecuteClientMessage(client_t *cl)
Definition: user.c:1482
sv_restrict_rtx
cvar_t * sv_restrict_rtx
Definition: main.c:95
cs_zombie
@ cs_zombie
Definition: server.h:187
SV_FreeFile
#define SV_FreeFile(buf)
Definition: server.h:58
SV_MvdClientDropped
void SV_MvdClientDropped(client_t *client)
Definition: mvd.c:2054
MVD_GameClientDrop
void MVD_GameClientDrop(edict_t *ent, const char *prefix, const char *reason)
Definition: game.c:1934
SV_CloseDownload
void SV_CloseDownload(client_t *client)
Definition: user.c:545
sv_allow_unconnected_cmds
cvar_t * sv_allow_unconnected_cmds
Definition: main.c:97
fs_game
cvar_t * fs_game
Definition: files.c:202
SV_MvdBeginFrame
void SV_MvdBeginFrame(void)
Definition: mvd.c:1009
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
client_s::reconnect_val
char reconnect_val[16]
Definition: server.h:284
client_s::lastmessage
unsigned lastmessage
Definition: server.h:288
COM_IsWhite
qboolean COM_IsWhite(const char *s)
Definition: shared.c:366
sv_clientlist
list_t sv_clientlist
SV_ConnectionlessPacket
static void SV_ConnectionlessPacket(void)
Definition: main.c:1247
client_frame_t::latency
int latency
Definition: server.h:108
client_s::version
int version
Definition: server.h:325
AC_Register
void AC_Register(void)
Definition: ac.c:1721
check_paused
static qboolean check_paused(void)
Definition: main.c:1671
SV_MasterShutdown
static void SV_MasterShutdown(void)
Definition: main.c:1795
client_frame_t
Definition: server.h:99
ge
game_export_t * ge
Definition: game.c:22
conn_params_t::protocol
int protocol
Definition: main.c:616
sv_registered
qboolean sv_registered
Definition: main.c:103
SV_DropClient
void SV_DropClient(client_t *client, const char *reason)
Definition: main.c:212
SVC_DirectConnect
static void SVC_DirectConnect(void)
Definition: main.c:1060
sv_idlekick
cvar_t * sv_idlekick
Definition: main.c:46
conn_params_t
Definition: main.c:615
sv_rcon_limit
cvar_t * sv_rcon_limit
Definition: main.c:92
send_connect_packet
static void send_connect_packet(client_t *newcl, int nctype)
Definition: main.c:1015
MAX_CHALLENGES
#define MAX_CHALLENGES
Definition: server.h:387
SV_OUTPUTBUF_LENGTH
#define SV_OUTPUTBUF_LENGTH
Definition: server.h:582
ping_min
static int ping_min(client_t *cl)
Definition: main.c:1315
Com_UptimeLong_m
size_t Com_UptimeLong_m(char *buffer, size_t size)
Definition: common.c:667
SV_InitOperatorCommands
void SV_InitOperatorCommands(void)
Definition: commands.c:1593
client_frame_t::number
int number
Definition: server.h:100
SV_CheckTimeouts
static void SV_CheckTimeouts(void)
Definition: main.c:1583
sv_hostname
cvar_t * sv_hostname
Definition: main.c:65
challenge_t::time
unsigned time
Definition: server.h:392
client_state_s::frames
server_frame_t frames[UPDATE_BACKUP]
Definition: client.h:209
SV_RateRecharge
void SV_RateRecharge(ratelimit_t *r)
Definition: main.c:287
server_t::cm
cm_t cm
Definition: server.h:161
client_s::reconnect_var
char reconnect_var[16]
Definition: server.h:283
MSG_WriteString
void MSG_WriteString(const char *string)
Definition: msg.c:160
SV_BroadcastPrintf
void SV_BroadcastPrintf(int level, const char *fmt,...)
Definition: send.c:154
SV_PrepWorldFrame
static void SV_PrepWorldFrame(void)
Definition: main.c:1645
SV_WriteFrameToClient_Enhanced
void SV_WriteFrameToClient_Enhanced(client_t *client)
Definition: entities.c:218
MVD_Frame
int MVD_Frame(void)
Definition: client.c:406
rcon_valid
static qboolean rcon_valid(void)
Definition: main.c:1176
MSG_WriteLong
void MSG_WriteLong(int c)
Definition: msg.c:144
cs_assigned
@ cs_assigned
Definition: server.h:189
reject2
#define reject2(...)
Definition: main.c:635
conn_params_t::has_zlib
qboolean has_zlib
Definition: main.c:623
challenge_t::challenge
unsigned challenge
Definition: server.h:391
NET_SendPacket
qboolean NET_SendPacket(netsrc_t sock, const void *data, size_t len, const netadr_t *to)
Definition: net.c:918
conn_params_t::version
int version
Definition: main.c:617
sv_filterlist
list_t sv_filterlist
client_s::settings
int settings[CLS_MAX]
Definition: server.h:326
g_features
cvar_t * g_features
Definition: main.c:99
userinfo_ip_string
static char * userinfo_ip_string(void)
Definition: main.c:816
SV_CalcPings
static void SV_CalcPings(void)
Definition: main.c:1360
AC_Run
void AC_Run(void)
Definition: ac.c:1388
sv_recycle
cvar_t * sv_recycle
Definition: main.c:83
SV_Init
void SV_Init(void)
Definition: main.c:2064
SV_FRAMEDIV
#define SV_FRAMEDIV
Definition: server.h:140
PmoveInit
void PmoveInit(pmoveParams_t *pmp)
Definition: pmove.c:1237
Com_Uptime_m
size_t Com_Uptime_m(char *buffer, size_t size)
Definition: common.c:662
server_static_s::realtime
unsigned realtime
Definition: server.h:454
RATE_LIMIT_SCALE
#define RATE_LIMIT_SCALE
Definition: main.c:255
sv_status_limit_changed
static void sv_status_limit_changed(cvar_t *self)
Definition: main.c:2007
sv_allow_nodelta
cvar_t * sv_allow_nodelta
Definition: main.c:38
client_s::pool
edict_pool_t * pool
Definition: server.h:345
Cbuf_Execute
void Cbuf_Execute(cmdbuf_t *buf)
Definition: cmd.c:152
conn_params_t::reserved
int reserved
Definition: main.c:625
ping_avg
static int ping_avg(client_t *cl)
Definition: main.c:1334
SV_ShutdownGameProgs
void SV_ShutdownGameProgs(void)
Definition: game.c:786
client_s::WriteFrame
void(* WriteFrame)(struct client_s *)
Definition: server.h:353
cs_primed
@ cs_primed
Definition: server.h:191
SV_ClientPrintf
void SV_ClientPrintf(client_t *client, int level, const char *fmt,...)
Definition: send.c:121
server_t::state
server_state_t state
Definition: server.h:146
sv_player
edict_t * sv_player
Definition: main.c:33
sv_status_show
cvar_t * sv_status_show
Definition: main.c:89
client_s::frameflags
unsigned frameflags
Definition: server.h:307
client_s::netchan
netchan_t * netchan
Definition: server.h:357
client_s
Definition: server.h:256
sv_status_limit
cvar_t * sv_status_limit
Definition: main.c:88
mvd_ge
game_export_t mvd_ge
Definition: game.c:2285
AC_Disconnect
void AC_Disconnect(void)
Definition: ac.c:1479
sv_running
cvar_t * sv_running
Definition: common.c:95
SV_MatchAddress
addrmatch_t * SV_MatchAddress(list_t *list, netadr_t *addr)
Definition: main.c:370
client_s::numpackets
int numpackets
Definition: server.h:358
client_s::msg_pool
message_packet_t * msg_pool
Definition: server.h:335
cl
client_state_t cl
Definition: main.c:99
parse_userinfo
static qboolean parse_userinfo(conn_params_t *params, char *userinfo)
Definition: main.c:836
Netchan_Close
void Netchan_Close(netchan_t *netchan)
Definition: chan.c:866
MSG_ReadStringLine
size_t MSG_ReadStringLine(char *dest, size_t size)
Definition: msg.c:1553
sv_show_name_changes
cvar_t * sv_show_name_changes
Definition: main.c:52
client_s::reconnected
qboolean reconnected
Definition: server.h:265
SV_FEATURES
#define SV_FEATURES
Definition: server.h:89
EDICT_NUM
#define EDICT_NUM(n)
Definition: server.h:173
append_extra_userinfo
static void append_extra_userinfo(conn_params_t *params, char *userinfo)
Definition: main.c:1044
MVD_RemoveClient
void MVD_RemoveClient(client_t *client)
Definition: game.c:1685
svcmds
static const ucmd_t svcmds[]
Definition: main.c:1227
sv_public
cvar_t * sv_public
Definition: main.c:66
server_t::frameresidual
unsigned frameresidual
Definition: server.h:156
server_t::spawncount
int spawncount
Definition: server.h:147
Info_SetValueForKey
qboolean Info_SetValueForKey(char *s, const char *key, const char *value)
Definition: shared.c:1137
client_s::min_ping
int min_ping
Definition: server.h:297
sv_rcon_limit_changed
static void sv_rcon_limit_changed(cvar_t *self)
Definition: main.c:2017
sv_cmdlist_begin
list_t sv_cmdlist_begin
SV_StatusString
static size_t SV_StatusString(char *status)
Definition: main.c:401
sv_locked
cvar_t * sv_locked
Definition: main.c:61
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
SV_PacketRedirect
#define SV_PacketRedirect()
Definition: server.h:587
AC_ClientDisconnect
void AC_ClientDisconnect(client_t *cl)
Definition: ac.c:1128
server.h
server_t::configstrings
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: server.h:164
sv_strafejump_hack
cvar_t * sv_strafejump_hack
Definition: main.c:76
SV_InitClientSend
void SV_InitClientSend(client_t *newcl)
Definition: send.c:1040
map_override_path
cvar_t * map_override_path
Definition: main.c:101
SV_RemoveClient
void SV_RemoveClient(client_t *client)
Definition: main.c:107
addrmatch_t
Definition: server.h:395
SV_RateInit
void SV_RateInit(ratelimit_t *r, const char *s)
Definition: main.c:309
Q_scnprintf
size_t Q_scnprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:867
init_pmove_and_es_flags
static void init_pmove_and_es_flags(client_t *newcl)
Definition: main.c:969
client_s::ratelimit_namechange
ratelimit_t ratelimit_namechange
Definition: server.h:279
client_s::userinfo
char userinfo[MAX_INFO_STRING]
Definition: server.h:275
client_s::configstrings
char * configstrings
Definition: server.h:343
sv_password
cvar_t * sv_password
Definition: main.c:48
sv_cmdlist_connect
list_t sv_cmdlist_connect
client_s::framenum
int framenum
Definition: server.h:303
sv_calcpings_method
cvar_t * sv_calcpings_method
Definition: main.c:73
SV_Frame
unsigned SV_Frame(unsigned msec)
Definition: main.c:1830
SV_RateLimited
qboolean SV_RateLimited(ratelimit_t *r)
Definition: main.c:265
server_t::name
char name[MAX_QPATH]
Definition: server.h:160
SVC_RemoteCommand
static void SVC_RemoteCommand(void)
Definition: main.c:1195
MVD_Register
void MVD_Register(void)
Definition: client.c:2582
permit_connection
static qboolean permit_connection(conn_params_t *p)
Definition: main.c:655
SV_RunGameFrame
static void SV_RunGameFrame(void)
Definition: main.c:1713
client_s::pmp
pmoveParams_t pmp
Definition: server.h:328
client_s::cm
cm_t * cm
Definition: server.h:346
client_s::esFlags
msgEsFlags_t esFlags
Definition: server.h:329
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
Info_RemoveKey
void Info_RemoveKey(char *s, const char *key)
Definition: shared.c:991
com_eventTime
unsigned com_eventTime
Definition: common.c:122
SVC_Status
static void SVC_Status(void)
Definition: main.c:469
parse_packet_length
static qboolean parse_packet_length(conn_params_t *p)
Definition: main.c:730
parse_enhanced_params
static qboolean parse_enhanced_params(conn_params_t *p)
Definition: main.c:762
client_s::frames_nodelta
unsigned frames_nodelta
Definition: server.h:302
MVD_SPAWN_MASK
#define MVD_SPAWN_MASK
Definition: server.h:97
client_s::name
char name[MAX_CLIENT_NAME]
Definition: server.h:276
client_s::edict
edict_t * edict
Definition: server.h:261
sv_maxclients
cvar_t * sv_maxclients
Definition: main.c:58