Quake II RTX doxygen  1.0 dev
send.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 // sv_send.c
19 
20 #include "server.h"
21 
22 /*
23 =============================================================================
24 
25 MISC
26 
27 =============================================================================
28 */
29 
31 
32 void SV_FlushRedirect(int redirected, char *outputbuf, size_t len)
33 {
34  byte buffer[MAX_PACKETLEN_DEFAULT];
35 
36  if (redirected == RD_PACKET) {
37  memcpy(buffer, "\xff\xff\xff\xffprint\n", 10);
38  memcpy(buffer + 10, outputbuf, len);
39  NET_SendPacket(NS_SERVER, buffer, len + 10, &net_from);
40  } else if (redirected == RD_CLIENT) {
41  MSG_WriteByte(svc_print);
42  MSG_WriteByte(PRINT_HIGH);
43  MSG_WriteData(outputbuf, len);
44  MSG_WriteByte(0);
46  }
47 }
48 
49 /*
50 =======================
51 SV_RateDrop
52 
53 Returns qtrue if the client is over its current
54 bandwidth estimation and should not be sent another packet
55 =======================
56 */
57 static qboolean SV_RateDrop(client_t *client)
58 {
59  size_t total;
60  int i;
61 
62  // never drop over the loopback
63  if (!client->rate) {
64  return qfalse;
65  }
66 
67  total = 0;
68  for (i = 0; i < RATE_MESSAGES; i++) {
69  total += client->message_size[i];
70  }
71 
72 #if USE_FPS
73  total = total * sv.framediv / client->framediv;
74 #endif
75 
76  if (total > client->rate) {
77  SV_DPrintf(0, "Frame %d suppressed for %s (total = %"PRIz")\n",
78  client->framenum, client->name, total);
79  client->frameflags |= FF_SUPPRESSED;
80  client->suppress_count++;
81  client->message_size[client->framenum % RATE_MESSAGES] = 0;
82  return qtrue;
83  }
84 
85  return qfalse;
86 }
87 
88 static void SV_CalcSendTime(client_t *client, size_t size)
89 {
90  // never drop over the loopback
91  if (!client->rate) {
92  client->send_time = svs.realtime;
93  client->send_delta = 0;
94  return;
95  }
96 
97  if (client->state == cs_spawned)
98  client->message_size[client->framenum % RATE_MESSAGES] = size;
99 
100  client->send_time = svs.realtime;
101  client->send_delta = size * 1000 / client->rate;
102 }
103 
104 /*
105 =============================================================================
106 
107 EVENT MESSAGES
108 
109 =============================================================================
110 */
111 
112 
113 /*
114 =================
115 SV_ClientPrintf
116 
117 Sends text across to be displayed if the level passes.
118 NOT archived in MVD stream.
119 =================
120 */
121 void SV_ClientPrintf(client_t *client, int level, const char *fmt, ...)
122 {
123  va_list argptr;
124  char string[MAX_STRING_CHARS];
125  size_t len;
126 
127  if (level < client->messagelevel)
128  return;
129 
130  va_start(argptr, fmt);
131  len = Q_vsnprintf(string, sizeof(string), fmt, argptr);
132  va_end(argptr);
133 
134  if (len >= sizeof(string)) {
135  Com_WPrintf("%s: overflow\n", __func__);
136  return;
137  }
138 
139  MSG_WriteByte(svc_print);
141  MSG_WriteData(string, len + 1);
142 
144 }
145 
146 /*
147 =================
148 SV_BroadcastPrintf
149 
150 Sends text to all active clients.
151 NOT archived in MVD stream.
152 =================
153 */
154 void SV_BroadcastPrintf(int level, const char *fmt, ...)
155 {
156  va_list argptr;
157  char string[MAX_STRING_CHARS];
158  client_t *client;
159  size_t len;
160 
161  va_start(argptr, fmt);
162  len = Q_vsnprintf(string, sizeof(string), fmt, argptr);
163  va_end(argptr);
164 
165  if (len >= sizeof(string)) {
166  Com_WPrintf("%s: overflow\n", __func__);
167  return;
168  }
169 
170  MSG_WriteByte(svc_print);
172  MSG_WriteData(string, len + 1);
173 
174  FOR_EACH_CLIENT(client) {
175  if (client->state != cs_spawned)
176  continue;
177  if (level < client->messagelevel)
178  continue;
180  }
181 
183 }
184 
185 void SV_ClientCommand(client_t *client, const char *fmt, ...)
186 {
187  va_list argptr;
188  char string[MAX_STRING_CHARS];
189  size_t len;
190 
191  va_start(argptr, fmt);
192  len = Q_vsnprintf(string, sizeof(string), fmt, argptr);
193  va_end(argptr);
194 
195  if (len >= sizeof(string)) {
196  Com_WPrintf("%s: overflow\n", __func__);
197  return;
198  }
199 
201  MSG_WriteData(string, len + 1);
202 
204 }
205 
206 /*
207 =================
208 SV_BroadcastCommand
209 
210 Sends command to all active clients.
211 NOT archived in MVD stream.
212 =================
213 */
214 void SV_BroadcastCommand(const char *fmt, ...)
215 {
216  va_list argptr;
217  char string[MAX_STRING_CHARS];
218  client_t *client;
219  size_t len;
220 
221  va_start(argptr, fmt);
222  len = Q_vsnprintf(string, sizeof(string), fmt, argptr);
223  va_end(argptr);
224 
225  if (len >= sizeof(string)) {
226  Com_WPrintf("%s: overflow\n", __func__);
227  return;
228  }
229 
231  MSG_WriteData(string, len + 1);
232 
233  FOR_EACH_CLIENT(client) {
235  }
236 
238 }
239 
240 
241 /*
242 =================
243 SV_Multicast
244 
245 Sends the contents of the write buffer to a subset of the clients,
246 then clears the write buffer.
247 
248 Archived in MVD stream.
249 
250 MULTICAST_ALL same as broadcast (origin can be NULL)
251 MULTICAST_PVS send to clients potentially visible from org
252 MULTICAST_PHS send to clients potentially hearable from org
253 =================
254 */
255 void SV_Multicast(vec3_t origin, multicast_t to)
256 {
257  client_t *client;
258  byte mask[VIS_MAX_BYTES];
259  mleaf_t *leaf1, *leaf2;
260  int leafnum q_unused;
261  int flags;
262  vec3_t org;
263 
264  if (!sv.cm.cache) {
265  Com_Error(ERR_DROP, "%s: no map loaded", __func__);
266  }
267 
268  flags = 0;
269 
270  switch (to) {
271  case MULTICAST_ALL_R:
272  flags |= MSG_RELIABLE;
273  // intentional fallthrough
274  case MULTICAST_ALL:
275  leaf1 = NULL;
276  leafnum = 0;
277  break;
278  case MULTICAST_PHS_R:
279  flags |= MSG_RELIABLE;
280  // intentional fallthrough
281  case MULTICAST_PHS:
282  leaf1 = CM_PointLeaf(&sv.cm, origin);
283  leafnum = leaf1 - sv.cm.cache->leafs;
284  BSP_ClusterVis(sv.cm.cache, mask, leaf1->cluster, DVIS_PHS);
285  break;
286  case MULTICAST_PVS_R:
287  flags |= MSG_RELIABLE;
288  // intentional fallthrough
289  case MULTICAST_PVS:
290  leaf1 = CM_PointLeaf(&sv.cm, origin);
291  leafnum = leaf1 - sv.cm.cache->leafs;
292  BSP_ClusterVis(sv.cm.cache, mask, leaf1->cluster, DVIS_PVS2);
293  break;
294  default:
295  Com_Error(ERR_DROP, "SV_Multicast: bad to: %i", to);
296  }
297 
298  // send the data to all relevent clients
299  FOR_EACH_CLIENT(client) {
300  if (client->state < cs_primed) {
301  continue;
302  }
303  // do not send unreliables to connecting clients
304  if (!(flags & MSG_RELIABLE) && (client->state != cs_spawned ||
305  client->download || client->nodata)) {
306  continue;
307  }
308 
309  if (leaf1) {
310  // find the client's PVS
311 #if 0
312  player_state_t *ps = &client->edict->client->ps;
313  VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin, org);
314 #else
315  // FIXME: for some strange reason, game code assumes the server
316  // uses entity origin for PVS/PHS culling, not the view origin
317  VectorCopy(client->edict->s.origin, org);
318 #endif
319  leaf2 = CM_PointLeaf(&sv.cm, org);
320  if (!CM_AreasConnected(&sv.cm, leaf1->area, leaf2->area))
321  continue;
322  if (leaf2->cluster == -1)
323  continue;
324  if (!Q_IsBitSet(mask, leaf2->cluster))
325  continue;
326  }
327 
328  SV_ClientAddMessage(client, flags);
329  }
330 
331  // add to MVD datagram
332  SV_MvdMulticast(leafnum, to);
333 
334  // clear the buffer
336 }
337 
338 static qboolean compress_message(client_t *client, int flags)
339 {
340 #if USE_ZLIB
341  byte buffer[MAX_MSGLEN];
342 
343  if (!(flags & MSG_COMPRESS))
344  return qfalse;
345 
346  if (!client->has_zlib)
347  return qfalse;
348 
349  // older clients have problems seamlessly writing svc_zpackets
350  if (client->settings[CLS_RECORDING]) {
351  if (client->protocol != PROTOCOL_VERSION_Q2PRO)
352  return qfalse;
353  if (client->version < PROTOCOL_VERSION_Q2PRO_EXTENDED_LAYOUT)
354  return qfalse;
355  }
356 
357  // compress only sufficiently large layouts
358  if (msg_write.cursize < client->netchan->maxpacketlen / 2)
359  return qfalse;
360 
361  deflateReset(&svs.z);
362  svs.z.next_in = msg_write.data;
363  svs.z.avail_in = (uInt)msg_write.cursize;
364  svs.z.next_out = buffer + 5;
365  svs.z.avail_out = (uInt)(MAX_MSGLEN - 5);
366 
367  if (deflate(&svs.z, Z_FINISH) != Z_STREAM_END)
368  return qfalse;
369 
370  buffer[0] = svc_zpacket;
371  buffer[1] = svs.z.total_out & 255;
372  buffer[2] = (svs.z.total_out >> 8) & 255;
373  buffer[3] = msg_write.cursize & 255;
374  buffer[4] = (msg_write.cursize >> 8) & 255;
375 
376  SV_DPrintf(0, "%s: comp: %lu into %lu\n",
377  client->name, svs.z.total_in, svs.z.total_out + 5);
378 
379  if (svs.z.total_out + 5 > msg_write.cursize)
380  return qfalse;
381 
382  client->AddMessage(client, buffer, svs.z.total_out + 5,
383  (flags & MSG_RELIABLE) ? qtrue : qfalse);
384  return qtrue;
385 #else
386  return qfalse;
387 #endif
388 }
389 
390 /*
391 =======================
392 SV_ClientAddMessage
393 
394 Adds contents of the current write buffer to client's message list.
395 Does NOT clean the buffer for multicast delivery purpose,
396 unless told otherwise.
397 =======================
398 */
399 void SV_ClientAddMessage(client_t *client, int flags)
400 {
401  SV_DPrintf(1, "Added %sreliable message to %s: %"PRIz" bytes\n",
402  (flags & MSG_RELIABLE) ? "" : "un", client->name, msg_write.cursize);
403 
404  if (!msg_write.cursize) {
405  return;
406  }
407 
408  if (compress_message(client, flags)) {
409  goto clear;
410  }
411 
412  client->AddMessage(client, msg_write.data, msg_write.cursize,
413  (flags & MSG_RELIABLE) ? qtrue : qfalse);
414 
415 clear:
416  if (flags & MSG_CLEAR) {
418  }
419 }
420 
421 /*
422 ===============================================================================
423 
424 FRAME UPDATES - COMMON
425 
426 ===============================================================================
427 */
428 
429 static inline void free_msg_packet(client_t *client, message_packet_t *msg)
430 {
431  List_Remove(&msg->entry);
432 
433  if (msg->cursize > MSG_TRESHOLD) {
434  if (msg->cursize > client->msg_dynamic_bytes) {
435  Com_Error(ERR_FATAL, "%s: bad packet size", __func__);
436  }
437  client->msg_dynamic_bytes -= msg->cursize;
438  Z_Free(msg);
439  } else {
440  List_Insert(&client->msg_free_list, &msg->entry);
441  }
442 }
443 
444 #define FOR_EACH_MSG_SAFE(list) \
445  LIST_FOR_EACH_SAFE(message_packet_t, msg, next, list, entry)
446 #define MSG_FIRST(list) \
447  LIST_FIRST(message_packet_t, list, entry)
448 
449 static void free_all_messages(client_t *client)
450 {
451  message_packet_t *msg, *next;
452 
454  free_msg_packet(client, msg);
455  }
457  free_msg_packet(client, msg);
458  }
459  client->msg_unreliable_bytes = 0;
460  client->msg_dynamic_bytes = 0;
461 }
462 
463 static void add_msg_packet(client_t *client,
464  byte *data,
465  size_t len,
466  qboolean reliable)
467 {
469 
470  if (!client->msg_pool) {
471  return; // already dropped
472  }
473 
474  if (len > MSG_TRESHOLD) {
475  if (len > MAX_MSGLEN) {
476  Com_Error(ERR_FATAL, "%s: oversize packet", __func__);
477  }
478  if (client->msg_dynamic_bytes + len > MAX_MSGLEN) {
479  Com_WPrintf("%s: %s: out of dynamic memory\n",
480  __func__, client->name);
481  goto overflowed;
482  }
483  msg = SV_Malloc(sizeof(*msg) + len - MSG_TRESHOLD);
484  client->msg_dynamic_bytes += len;
485  } else {
486  if (LIST_EMPTY(&client->msg_free_list)) {
487  Com_WPrintf("%s: %s: out of message slots\n",
488  __func__, client->name);
489  goto overflowed;
490  }
491  msg = MSG_FIRST(&client->msg_free_list);
492  List_Remove(&msg->entry);
493  }
494 
495  memcpy(msg->data, data, len);
496  msg->cursize = (uint16_t)len;
497 
498  if (reliable) {
499  List_Append(&client->msg_reliable_list, &msg->entry);
500  } else {
501  List_Append(&client->msg_unreliable_list, &msg->entry);
502  client->msg_unreliable_bytes += len;
503  }
504 
505  return;
506 
507 overflowed:
508  if (reliable) {
509  free_all_messages(client);
510  SV_DropClient(client, "reliable queue overflowed");
511  }
512 }
513 
514 // check if this entity is present in current client frame
515 static qboolean check_entity(client_t *client, int entnum)
516 {
517  client_frame_t *frame;
518  unsigned i, j;
519 
520  frame = &client->frames[client->framenum & UPDATE_MASK];
521 
522  for (i = 0; i < frame->num_entities; i++) {
523  j = (frame->first_entity + i) % svs.num_entities;
524  if (svs.entities[j].number == entnum) {
525  return qtrue;
526  }
527  }
528 
529  return qfalse;
530 }
531 
532 // sounds reliative to entities are handled specially
533 static void emit_snd(client_t *client, message_packet_t *msg)
534 {
535  int flags, entnum;
536  int i;
537 
538  entnum = msg->sendchan >> 3;
539  flags = msg->flags;
540 
541  // check if position needs to be explicitly sent
542  if (!(flags & SND_POS) && !check_entity(client, entnum)) {
543  SV_DPrintf(0, "Forcing position on entity %d for %s\n",
544  entnum, client->name);
545  flags |= SND_POS; // entity is not present in frame
546  }
547 
548  MSG_WriteByte(svc_sound);
549  MSG_WriteByte(flags);
550  MSG_WriteByte(msg->index);
551 
552  if (flags & SND_VOLUME)
553  MSG_WriteByte(msg->volume);
554  if (flags & SND_ATTENUATION)
555  MSG_WriteByte(msg->attenuation);
556  if (flags & SND_OFFSET)
557  MSG_WriteByte(msg->timeofs);
558 
559  MSG_WriteShort(msg->sendchan);
560 
561  if (flags & SND_POS) {
562  for (i = 0; i < 3; i++) {
563  MSG_WriteShort(msg->pos[i]);
564  }
565  }
566 }
567 
568 static inline void write_snd(client_t *client, message_packet_t *msg, size_t maxsize)
569 {
570  // if this msg fits, write it
571  if (msg_write.cursize + MAX_SOUND_PACKET <= maxsize) {
572  emit_snd(client, msg);
573  }
574  List_Remove(&msg->entry);
575  List_Insert(&client->msg_free_list, &msg->entry);
576 }
577 
578 static inline void write_msg(client_t *client, message_packet_t *msg, size_t maxsize)
579 {
580  // if this msg fits, write it
581  if (msg_write.cursize + msg->cursize <= maxsize) {
582  MSG_WriteData(msg->data, msg->cursize);
583  }
584  free_msg_packet(client, msg);
585 }
586 
587 static inline void write_unreliables(client_t *client, size_t maxsize)
588 {
589  message_packet_t *msg, *next;
590 
592  if (msg->cursize) {
593  write_msg(client, msg, maxsize);
594  } else {
595  write_snd(client, msg, maxsize);
596  }
597  }
598 }
599 
600 /*
601 ===============================================================================
602 
603 FRAME UPDATES - OLD NETCHAN
604 
605 ===============================================================================
606 */
607 
608 static void add_message_old(client_t *client, byte *data,
609  size_t len, qboolean reliable)
610 {
611  if (len > client->netchan->maxpacketlen) {
612  if (reliable) {
613  SV_DropClient(client, "oversize reliable message");
614  } else {
615  Com_DPrintf("Dumped oversize unreliable for %s\n", client->name);
616  }
617  return;
618  }
619 
620  add_msg_packet(client, data, len, reliable);
621 }
622 
623 // this should be the only place data is ever written to netchan message for old clients
624 static void write_reliables_old(client_t *client, size_t maxsize)
625 {
626  message_packet_t *msg, *next;
627  int count;
628 
629  if (client->netchan->reliable_length) {
630  SV_DPrintf(1, "%s to %s: unacked\n", __func__, client->name);
631  return; // there is still outgoing reliable message pending
632  }
633 
634  // find at least one reliable message to send
635  count = 0;
637  // stop if this msg doesn't fit (reliables must be delivered in order)
638  if (client->netchan->message.cursize + msg->cursize > maxsize) {
639  if (!count) {
640  // this should never happen
641  Com_WPrintf("%s to %s: overflow on the first message\n",
642  __func__, client->name);
643  }
644  break;
645  }
646 
647  SV_DPrintf(1, "%s to %s: writing msg %d: %d bytes\n",
648  __func__, client->name, count, msg->cursize);
649 
650  SZ_Write(&client->netchan->message, msg->data, msg->cursize);
651  free_msg_packet(client, msg);
652  count++;
653  }
654 }
655 
656 // unreliable portion doesn't fit, then throw out low priority effects
657 static void repack_unreliables(client_t *client, size_t maxsize)
658 {
659  message_packet_t *msg, *next;
660 
661  if (msg_write.cursize + 4 > maxsize) {
662  return;
663  }
664 
665  // temp entities first
667  if (!msg->cursize || msg->data[0] != svc_temp_entity) {
668  continue;
669  }
670  // ignore some low-priority effects, these checks come from r1q2
671  if (msg->data[1] == TE_BLOOD || msg->data[1] == TE_SPLASH ||
672  msg->data[1] == TE_GUNSHOT || msg->data[1] == TE_BULLET_SPARKS ||
673  msg->data[1] == TE_SHOTGUN) {
674  continue;
675  }
676  write_msg(client, msg, maxsize);
677  }
678 
679  if (msg_write.cursize + 4 > maxsize) {
680  return;
681  }
682 
683  // then entity sounds
685  if (!msg->cursize) {
686  write_snd(client, msg, maxsize);
687  }
688  }
689 
690  if (msg_write.cursize + 4 > maxsize) {
691  return;
692  }
693 
694  // then positioned sounds
696  if (msg->cursize && msg->data[0] == svc_sound) {
697  write_msg(client, msg, maxsize);
698  }
699  }
700 
701  if (msg_write.cursize + 4 > maxsize) {
702  return;
703  }
704 
705  // then everything else left
707  if (msg->cursize) {
708  write_msg(client, msg, maxsize);
709  }
710  }
711 }
712 
713 static void write_datagram_old(client_t *client)
714 {
716  size_t maxsize, cursize;
717 
718  // determine how much space is left for unreliable data
719  maxsize = client->netchan->maxpacketlen;
720  if (client->netchan->reliable_length) {
721  // there is still unacked reliable message pending
722  maxsize -= client->netchan->reliable_length;
723  } else {
724  // find at least one reliable message to send
725  // and make sure to reserve space for it
726  if (!LIST_EMPTY(&client->msg_reliable_list)) {
727  msg = MSG_FIRST(&client->msg_reliable_list);
728  maxsize -= msg->cursize;
729  }
730  }
731 
732  // send over all the relevant entity_state_t
733  // and the player_state_t
734  client->WriteFrame(client);
735  if (msg_write.cursize > maxsize) {
736  SV_DPrintf(0, "Frame %d overflowed for %s: %"PRIz" > %"PRIz"\n",
737  client->framenum, client->name, msg_write.cursize, maxsize);
739  }
740 
741  // now write unreliable messages
742  // it is necessary for this to be after the WriteFrame
743  // so that entity references will be current
744  if (msg_write.cursize + client->msg_unreliable_bytes > maxsize) {
745  // throw out some low priority effects
746  repack_unreliables(client, maxsize);
747  } else {
748  // all messages fit, write them in order
749  write_unreliables(client, maxsize);
750  }
751 
752  // write at least one reliable message
753  write_reliables_old(client, client->netchan->maxpacketlen - msg_write.cursize);
754 
755  // send the datagram
756  cursize = client->netchan->Transmit(client->netchan,
757  msg_write.cursize,
758  msg_write.data,
759  client->numpackets);
760 
761  // record the size for rate estimation
762  SV_CalcSendTime(client, cursize);
763 
764  // clear the write buffer
766 }
767 
768 /*
769 ===============================================================================
770 
771 FRAME UPDATES - NEW NETCHAN
772 
773 ===============================================================================
774 */
775 
776 static void add_message_new(client_t *client, byte *data,
777  size_t len, qboolean reliable)
778 {
779  if (reliable) {
780  // don't packetize, netchan level will do fragmentation as needed
781  SZ_Write(&client->netchan->message, data, len);
782  } else {
783  // still have to packetize, relative sounds need special processing
784  add_msg_packet(client, data, len, qfalse);
785  }
786 }
787 
788 static void write_datagram_new(client_t *client)
789 {
790  size_t cursize;
791 
792  // send over all the relevant entity_state_t
793  // and the player_state_t
794  client->WriteFrame(client);
795 
796  if (msg_write.overflowed) {
797  // should never really happen
798  Com_WPrintf("Frame overflowed for %s\n", client->name);
800  }
801 
802  // now write unreliable messages
803  // for this client out to the message
804  // it is necessary for this to be after the WriteFrame
805  // so that entity references will be current
806  if (msg_write.cursize + client->msg_unreliable_bytes > msg_write.maxsize) {
807  Com_WPrintf("Dumping datagram for %s\n", client->name);
808  } else {
809  write_unreliables(client, msg_write.maxsize);
810  }
811 
812 #ifdef _DEBUG
813  if (sv_pad_packets->integer) {
814  size_t pad = msg_write.cursize + sv_pad_packets->integer;
815 
816  if (pad > msg_write.maxsize) {
817  pad = msg_write.maxsize;
818  }
819  for (; pad > 0; pad--) {
820  MSG_WriteByte(svc_nop);
821  }
822  }
823 #endif
824 
825  // send the datagram
826  cursize = client->netchan->Transmit(client->netchan,
827  msg_write.cursize,
828  msg_write.data,
829  client->numpackets);
830 
831  // record the size for rate estimation
832  SV_CalcSendTime(client, cursize);
833 
834  // clear the write buffer
836 }
837 
838 
839 /*
840 ===============================================================================
841 
842 COMMON STUFF
843 
844 ===============================================================================
845 */
846 
847 static void finish_frame(client_t *client)
848 {
849  message_packet_t *msg, *next;
850 
852  free_msg_packet(client, msg);
853  }
854  client->msg_unreliable_bytes = 0;
855 }
856 
857 #if (defined _DEBUG) && USE_FPS
858 static void check_key_sync(client_t *client)
859 {
860  int div = sv.framediv / client->framediv;
861  int key1 = !(sv.framenum % sv.framediv);
862  int key2 = !(client->framenum % div);
863 
864  if (key1 != key2) {
865  Com_LPrintf(PRINT_DEVELOPER,
866  "[%d] frame %d for %s not synced (%d != %d)\n",
867  sv.framenum, client->framenum, client->name, key1, key2);
868  }
869 }
870 #endif
871 
872 /*
873 =======================
874 SV_SendClientMessages
875 
876 Called each game frame, sends svc_frame messages to spawned clients only.
877 Clients in earlier connection state are handled in SV_SendAsyncPackets.
878 =======================
879 */
881 {
882  client_t *client;
883  size_t cursize;
884 
885  // send a message to each connected client
886  FOR_EACH_CLIENT(client) {
887  if (client->state != cs_spawned || client->download || client->nodata)
888  goto finish;
889 
890  if (!SV_CLIENTSYNC(client))
891  continue;
892 
893 #if (defined _DEBUG) && USE_FPS
894  if (developer->integer)
895  check_key_sync(client);
896 #endif
897 
898  // if the reliable message overflowed,
899  // drop the client (should never happen)
900  if (client->netchan->message.overflowed) {
901  SZ_Clear(&client->netchan->message);
902  SV_DropClient(client, "reliable message overflowed");
903  goto finish;
904  }
905 
906  // don't overrun bandwidth
907  if (SV_RateDrop(client))
908  goto advance;
909 
910  // don't write any frame data until all fragments are sent
911  if (client->netchan->fragment_pending) {
912  client->frameflags |= FF_SUPPRESSED;
913  cursize = client->netchan->TransmitNextFragment(client->netchan);
914  SV_CalcSendTime(client, cursize);
915  goto advance;
916  }
917 
918  // build the new frame and write it
919  SV_BuildClientFrame(client);
920  client->WriteDatagram(client);
921 
922 advance:
923  // advance for next frame
924  client->framenum++;
925 
926 finish:
927  // clear all unreliable messages still left
928  finish_frame(client);
929  }
930 }
931 
932 static void write_pending_download(client_t *client)
933 {
934  sizebuf_t *buf;
935  size_t remaining;
936  int chunk, percent;
937 
938  if (!client->download)
939  return;
940 
941  if (!client->downloadpending)
942  return;
943 
944  if (client->netchan->reliable_length)
945  return;
946 
947  buf = &client->netchan->message;
948  if (buf->cursize > client->netchan->maxpacketlen)
949  return;
950 
951  remaining = client->netchan->maxpacketlen - buf->cursize;
952  if (remaining <= 4)
953  return;
954 
955  chunk = client->downloadsize - client->downloadcount;
956  if (chunk > remaining - 4)
957  chunk = remaining - 4;
958 
959  client->downloadpending = qfalse;
960  client->downloadcount += chunk;
961 
962  percent = client->downloadcount * 100 / client->downloadsize;
963 
964  SZ_WriteByte(buf, client->downloadcmd);
965  SZ_WriteShort(buf, chunk);
966  SZ_WriteByte(buf, percent);
967  SZ_Write(buf, client->download + client->downloadcount - chunk, chunk);
968 
969  if (client->downloadcount == client->downloadsize) {
970  SV_CloseDownload(client);
971  SV_AlignKeyFrames(client);
972  }
973 }
974 
975 /*
976 ==================
977 SV_SendAsyncPackets
978 
979 If the client is just connecting, it is pointless to wait another 100ms
980 before sending next command and/or reliable acknowledge, send it as soon
981 as client rate limit allows.
982 
983 For spawned clients, this is not used, as we are forced to send svc_frame
984 packets synchronously with game DLL ticks.
985 ==================
986 */
988 {
989  qboolean retransmit;
990  client_t *client;
991  netchan_t *netchan;
992  size_t cursize;
993 
994  FOR_EACH_CLIENT(client) {
995  // don't overrun bandwidth
996  if (svs.realtime - client->send_time < client->send_delta) {
997  continue;
998  }
999 
1000  netchan = client->netchan;
1001 
1002  // make sure all fragments are transmitted first
1003  if (netchan->fragment_pending) {
1004  cursize = netchan->TransmitNextFragment(netchan);
1005  SV_DPrintf(0, "%s: frag: %"PRIz"\n", client->name, cursize);
1006  goto calctime;
1007  }
1008 
1009  // spawned clients are handled elsewhere
1010  if (client->state == cs_spawned && !client->download && !client->nodata && !SV_PAUSED) {
1011  continue;
1012  }
1013 
1014  // see if it's time to resend a (possibly dropped) packet
1015  retransmit = (com_localTime - netchan->last_sent > 1000);
1016 
1017  // don't write new reliables if not yet acknowledged
1018  if (netchan->reliable_length && !retransmit && client->state != cs_zombie) {
1019  continue;
1020  }
1021 
1022  // just update reliable if needed
1023  if (netchan->type == NETCHAN_OLD) {
1024  write_reliables_old(client, netchan->maxpacketlen);
1025  }
1026 
1027  // now fill up remaining buffer space with download
1028  write_pending_download(client);
1029 
1030  if (netchan->message.cursize || netchan->reliable_ack_pending ||
1031  netchan->reliable_length || retransmit) {
1032  cursize = netchan->Transmit(netchan, 0, NULL, 1);
1033  SV_DPrintf(0, "%s: send: %"PRIz"\n", client->name, cursize);
1034 calctime:
1035  SV_CalcSendTime(client, cursize);
1036  }
1037  }
1038 }
1039 
1041 {
1042  int i;
1043 
1044  List_Init(&newcl->msg_free_list);
1045  List_Init(&newcl->msg_unreliable_list);
1046  List_Init(&newcl->msg_reliable_list);
1047 
1048  newcl->msg_pool = SV_Malloc(sizeof(message_packet_t) * MSG_POOLSIZE);
1049  for (i = 0; i < MSG_POOLSIZE; i++) {
1050  List_Append(&newcl->msg_free_list, &newcl->msg_pool[i].entry);
1051  }
1052 
1053  // setup protocol
1054  if (newcl->netchan->type == NETCHAN_NEW) {
1055  newcl->AddMessage = add_message_new;
1057  } else {
1058  newcl->AddMessage = add_message_old;
1060  }
1061 }
1062 
1064 {
1065  free_all_messages(client);
1066 
1067  Z_Free(client->msg_pool);
1068  client->msg_pool = NULL;
1069 
1070  List_Init(&client->msg_free_list);
1071 }
1072 
server_t::framenum
int framenum
Definition: server.h:155
client_s::msg_dynamic_bytes
size_t msg_dynamic_bytes
Definition: server.h:337
SV_BuildClientFrame
void SV_BuildClientFrame(client_t *client)
Definition: entities.c:382
client_frame_t::first_entity
unsigned first_entity
Definition: server.h:102
free_msg_packet
static void free_msg_packet(client_t *client, message_packet_t *msg)
Definition: send.c:429
write_snd
static void write_snd(client_t *client, message_packet_t *msg, size_t maxsize)
Definition: send.c:568
cs_spawned
@ cs_spawned
Definition: server.h:192
SV_BroadcastCommand
void SV_BroadcastCommand(const char *fmt,...)
Definition: send.c:214
svs
server_static_t svs
Definition: init.c:21
RD_CLIENT
@ RD_CLIENT
Definition: server.h:581
compress_message
static qboolean compress_message(client_t *client, int flags)
Definition: send.c:338
client_s::send_delta
unsigned send_delta
Definition: server.h:312
SV_ShutdownClientSend
void SV_ShutdownClientSend(client_t *client)
Definition: send.c:1063
client_s::protocol
int protocol
Definition: server.h:324
message_packet_t
Definition: server.h:220
write_reliables_old
static void write_reliables_old(client_t *client, size_t maxsize)
Definition: send.c:624
client_s::has_zlib
qboolean has_zlib
Definition: server.h:267
server_static_s::entities
entity_packed_t * entities
Definition: server.h:460
client_s::msg_free_list
list_t msg_free_list
Definition: server.h:332
BSP_ClusterVis
byte * BSP_ClusterVis(bsp_t *bsp, byte *mask, int cluster, int vis)
Definition: bsp.c:1339
client_s::state
clstate_t state
Definition: server.h:260
SV_SendClientMessages
void SV_SendClientMessages(void)
Definition: send.c:880
MSG_CLEAR
#define MSG_CLEAR
Definition: server.h:215
add_message_new
static void add_message_new(client_t *client, byte *data, size_t len, qboolean reliable)
Definition: send.c:776
MSG_RELIABLE
#define MSG_RELIABLE
Definition: server.h:214
SV_CalcSendTime
static void SV_CalcSendTime(client_t *client, size_t size)
Definition: send.c:88
client_s::WriteDatagram
void(* WriteDatagram)(struct client_s *)
Definition: server.h:354
RATE_MESSAGES
#define RATE_MESSAGES
Definition: server.h:237
client_s::downloadcount
int downloadcount
Definition: server.h:317
SZ_WriteByte
void SZ_WriteByte(sizebuf_t *sb, int c)
Definition: sizebuf.c:82
SZ_WriteShort
void SZ_WriteShort(sizebuf_t *sb, int c)
Definition: sizebuf.c:90
Q_vsnprintf
size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:791
sv_client
client_t * sv_client
Definition: main.c:32
finish_frame
static void finish_frame(client_t *client)
Definition: send.c:847
client_s::suppress_count
int suppress_count
Definition: server.h:311
client_s::msg_reliable_list
list_t msg_reliable_list
Definition: server.h:334
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
svc_stufftext
#define svc_stufftext
Definition: g_local.h:41
SV_Multicast
void SV_Multicast(vec3_t origin, multicast_t to)
Definition: send.c:255
SV_ClientAddMessage
void SV_ClientAddMessage(client_t *client, int flags)
Definition: send.c:399
net_from
netadr_t net_from
Definition: net.c:90
SV_AlignKeyFrames
#define SV_AlignKeyFrames(client)
Definition: server.h:698
FOR_EACH_CLIENT
#define FOR_EACH_CLIENT(client)
Definition: server.h:239
SV_Malloc
#define SV_Malloc(size)
Definition: server.h:54
CM_AreasConnected
qboolean CM_AreasConnected(cm_t *cm, int area1, int area2)
Definition: cmodel.c:890
client_s::nodata
qboolean nodata
Definition: server.h:266
client_frame_t::num_entities
unsigned num_entities
Definition: server.h:101
MSG_COMPRESS
#define MSG_COMPRESS
Definition: server.h:216
write_unreliables
static void write_unreliables(client_t *client, size_t maxsize)
Definition: send.c:587
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
MSG_TRESHOLD
#define MSG_TRESHOLD
Definition: server.h:212
client_s::download
byte * download
Definition: server.h:315
SV_SendAsyncPackets
void SV_SendAsyncPackets(void)
Definition: send.c:987
client_s::downloadpending
qboolean downloadpending
Definition: server.h:320
sv
server_t sv
Definition: init.c:22
svc_temp_entity
#define svc_temp_entity
Definition: g_local.h:38
client_s::downloadcmd
int downloadcmd
Definition: server.h:319
SV_FlushRedirect
void SV_FlushRedirect(int redirected, char *outputbuf, size_t len)
Definition: send.c:32
msg_write
sizebuf_t msg_write
Definition: msg.c:34
client_s::frames
client_frame_t frames[UPDATE_BACKUP]
Definition: server.h:301
emit_snd
static void emit_snd(client_t *client, message_packet_t *msg)
Definition: send.c:533
SV_MvdMulticast
void SV_MvdMulticast(int leafnum, multicast_t to)
Definition: mvd.c:1122
add_msg_packet
static void add_msg_packet(client_t *client, byte *data, size_t len, qboolean reliable)
Definition: send.c:463
sv_outputbuf
char sv_outputbuf[SV_OUTPUTBUF_LENGTH]
Definition: send.c:30
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
repack_unreliables
static void repack_unreliables(client_t *client, size_t maxsize)
Definition: send.c:657
cs_zombie
@ cs_zombie
Definition: server.h:187
origin
static vec3_t origin
Definition: mesh.c:27
SV_ClientCommand
void SV_ClientCommand(client_t *client, const char *fmt,...)
Definition: send.c:185
SV_CloseDownload
void SV_CloseDownload(client_t *client)
Definition: user.c:545
SV_PAUSED
#define SV_PAUSED
Definition: server.h:79
Com_LPrintf
void Com_LPrintf(print_type_t type, const char *fmt,...)
Definition: g_main.c:242
MSG_POOLSIZE
#define MSG_POOLSIZE
Definition: server.h:211
write_pending_download
static void write_pending_download(client_t *client)
Definition: send.c:932
client_s::version
int version
Definition: server.h:325
client_frame_t
Definition: server.h:99
MSG_WriteShort
void MSG_WriteShort(int c)
Definition: msg.c:125
write_msg
static void write_msg(client_t *client, message_packet_t *msg, size_t maxsize)
Definition: send.c:578
client_s::message_size
size_t message_size[RATE_MESSAGES]
Definition: server.h:310
SV_DropClient
void SV_DropClient(client_t *client, const char *reason)
Definition: main.c:212
SV_OUTPUTBUF_LENGTH
#define SV_OUTPUTBUF_LENGTH
Definition: server.h:582
com_localTime
unsigned com_localTime
Definition: common.c:123
server_static_s::num_entities
unsigned num_entities
Definition: server.h:458
server_t::cm
cm_t cm
Definition: server.h:161
SV_BroadcastPrintf
void SV_BroadcastPrintf(int level, const char *fmt,...)
Definition: send.c:154
SV_CLIENTSYNC
#define SV_CLIENTSYNC(cl)
Definition: server.h:142
NET_SendPacket
qboolean NET_SendPacket(netsrc_t sock, const void *data, size_t len, const netadr_t *to)
Definition: net.c:918
CM_PointLeaf
mleaf_t * CM_PointLeaf(cm_t *cm, vec3_t p)
Definition: cmodel.c:209
MAX_SOUND_PACKET
#define MAX_SOUND_PACKET
Definition: server.h:218
client_s::settings
int settings[CLS_MAX]
Definition: server.h:326
write_datagram_new
static void write_datagram_new(client_t *client)
Definition: send.c:788
server_static_s::realtime
unsigned realtime
Definition: server.h:454
client_s::AddMessage
void(* AddMessage)(struct client_s *, byte *, size_t, qboolean)
Definition: server.h:352
level
level_locals_t level
Definition: g_main.c:22
client_s::WriteFrame
void(* WriteFrame)(struct client_s *)
Definition: server.h:353
cs_primed
@ cs_primed
Definition: server.h:191
add_message_old
static void add_message_old(client_t *client, byte *data, size_t len, qboolean reliable)
Definition: send.c:608
SV_ClientPrintf
void SV_ClientPrintf(client_t *client, int level, const char *fmt,...)
Definition: send.c:121
client_s::msg_unreliable_bytes
size_t msg_unreliable_bytes
Definition: server.h:336
msg
const char * msg
Definition: win.h:25
client_s::msg_unreliable_list
list_t msg_unreliable_list
Definition: server.h:333
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
client_s::send_time
unsigned send_time
Definition: server.h:312
client_s::downloadsize
int downloadsize
Definition: server.h:316
client_s::numpackets
int numpackets
Definition: server.h:358
client_s::msg_pool
message_packet_t * msg_pool
Definition: server.h:335
SV_DPrintf
#define SV_DPrintf(...)
Definition: server.h:65
free_all_messages
static void free_all_messages(client_t *client)
Definition: send.c:449
client_s::rate
size_t rate
Definition: server.h:278
server.h
message_packet_t::entry
list_t entry
Definition: server.h:221
SV_InitClientSend
void SV_InitClientSend(client_t *newcl)
Definition: send.c:1040
SV_RateDrop
static qboolean SV_RateDrop(client_t *client)
Definition: send.c:57
RD_PACKET
@ RD_PACKET
Definition: server.h:581
client_s::framenum
int framenum
Definition: server.h:303
write_datagram_old
static void write_datagram_old(client_t *client)
Definition: send.c:713
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
check_entity
static qboolean check_entity(client_t *client, int entnum)
Definition: send.c:515
FOR_EACH_MSG_SAFE
#define FOR_EACH_MSG_SAFE(list)
Definition: send.c:444
MSG_FIRST
#define MSG_FIRST(list)
Definition: send.c:446
client_s::name
char name[MAX_CLIENT_NAME]
Definition: server.h:276
client_s::edict
edict_t * edict
Definition: server.h:261