19 #include "shared/shared.h"
20 #include "common/common.h"
21 #include "common/cvar.h"
22 #include "common/msg.h"
23 #include "common/net/chan.h"
24 #include "common/net/net.h"
25 #include "common/protocol.h"
26 #include "common/sizebuf.h"
27 #include "common/zone.h"
28 #include "system/system.h"
85 static cvar_t *showpackets;
86 static cvar_t *showdrop;
87 #define SHOWPACKET(...) \
88 if (showpackets->integer) \
89 Com_LPrintf(PRINT_DEVELOPER, __VA_ARGS__)
90 #define SHOWDROP(...) \
91 if (showdrop->integer) \
92 Com_LPrintf(PRINT_DEVELOPER, __VA_ARGS__)
94 #define SHOWPACKET(...)
121 showpackets =
Cvar_Get(
"showpackets",
"0", 0);
122 showdrop =
Cvar_Get(
"showdrop",
"0", 0);
141 const char *format, ...)
146 char data[MAX_PACKETLEN_DEFAULT - 4];
151 packet.header = 0xffffffff;
153 va_start(argptr, format);
154 len =
Q_vsnprintf(packet.data,
sizeof(packet.data), format, argptr);
157 if (len >=
sizeof(packet.data)) {
158 Com_WPrintf(
"%s: overflow\n", __func__);
170 Com_Error(ERR_FATAL,
"%s: not implemented", __func__);
186 netchan_old_t *chan = (netchan_old_t *)netchan;
188 byte send_buf[MAX_PACKETLEN];
189 qboolean send_reliable;
194 if (netchan->message.overflowed) {
195 netchan->fatal_error = qtrue;
196 Com_WPrintf(
"%s: outgoing message overflow\n",
201 send_reliable = qfalse;
204 if (netchan->incoming_acknowledged > chan->last_reliable_sequence &&
205 chan->incoming_reliable_acknowledged != chan->reliable_sequence) {
206 send_reliable = qtrue;
210 if (!netchan->reliable_length && netchan->message.cursize) {
211 send_reliable = qtrue;
212 memcpy(chan->reliable_buf, chan->message_buf,
213 netchan->message.cursize);
214 netchan->reliable_length = netchan->message.cursize;
215 netchan->message.cursize = 0;
216 chan->reliable_sequence ^= 1;
220 w1 = (netchan->outgoing_sequence & ~(1 << 31)) |
221 (send_reliable << 31);
222 w2 = (netchan->incoming_sequence & ~(1 << 31)) |
223 (chan->incoming_reliable_sequence << 31);
225 SZ_TagInit(&send, send_buf,
sizeof(send_buf), SZ_NC_SEND_OLD);
232 if (netchan->sock == NS_CLIENT) {
233 if (netchan->protocol < PROTOCOL_VERSION_R1Q2) {
235 }
else if (netchan->qport) {
243 SZ_Write(&send, chan->reliable_buf, netchan->reliable_length);
244 chan->last_reliable_sequence = netchan->outgoing_sequence;
248 if (send.maxsize - send.cursize >= length)
249 SZ_Write(&send, data, length);
251 Com_WPrintf(
"%s: dumped unreliable\n",
254 SHOWPACKET(
"send %4"PRIz
" : s=%d ack=%d rack=%d",
256 netchan->outgoing_sequence,
257 netchan->incoming_sequence,
258 chan->incoming_reliable_sequence);
260 SHOWPACKET(
" reliable=%i", chan->reliable_sequence);
265 for (i = 0; i < numpackets; i++) {
267 &netchan->remote_address);
270 netchan->outgoing_sequence++;
271 netchan->reliable_ack_pending = qfalse;
274 return send.cursize * numpackets;
287 netchan_old_t *chan = (netchan_old_t *)netchan;
288 uint32_t sequence, sequence_ack;
289 uint32_t reliable_ack, reliable_message;
298 if (netchan->sock == NS_SERVER)
301 if (netchan->protocol < PROTOCOL_VERSION_R1Q2) {
303 }
else if (netchan->qport) {
308 reliable_message = sequence >> 31;
309 reliable_ack = sequence_ack >> 31;
311 sequence &= ~(1 << 31);
312 sequence_ack &= ~(1 << 31);
314 SHOWPACKET(
"recv %4"PRIz
" : s=%d ack=%d rack=%d",
319 if (reliable_message) {
320 SHOWPACKET(
" reliable=%d", chan->incoming_reliable_sequence ^ 1);
327 if (sequence <= netchan->incoming_sequence) {
328 SHOWDROP(
"%s: out of order packet %i at %i\n",
330 sequence, netchan->incoming_sequence);
337 netchan->dropped = sequence - (netchan->incoming_sequence + 1);
338 if (netchan->dropped > 0) {
339 SHOWDROP(
"%s: dropped %i packets at %i\n",
341 netchan->dropped, sequence);
348 chan->incoming_reliable_acknowledged = reliable_ack;
349 if (reliable_ack == chan->reliable_sequence)
350 netchan->reliable_length = 0;
355 netchan->incoming_sequence = sequence;
356 netchan->incoming_acknowledged = sequence_ack;
357 if (reliable_message) {
358 netchan->reliable_ack_pending = qtrue;
359 chan->incoming_reliable_sequence ^= 1;
367 netchan->total_dropped += netchan->dropped;
368 netchan->total_received += netchan->dropped + 1;
380 if (netchan->message.cursize || netchan->reliable_ack_pending ||
396 int qport,
size_t maxpacketlen)
402 sock == NS_SERVER ? TAG_SERVER : TAG_GENERAL);
405 memset(chan, 0,
sizeof(*chan));
406 netchan = (netchan_t *)chan;
407 netchan->sock = sock;
408 netchan->remote_address = *adr;
409 netchan->qport = qport;
410 netchan->maxpacketlen = maxpacketlen;
413 netchan->incoming_sequence = 0;
414 netchan->outgoing_sequence = 1;
422 SZ_Init(&netchan->message, chan->message_buf, maxpacketlen);
439 netchan_new_t *chan = (netchan_new_t *)netchan;
441 byte send_buf[MAX_PACKETLEN];
442 qboolean send_reliable;
445 size_t fragment_length;
446 qboolean more_fragments;
448 send_reliable = netchan->reliable_length ? qtrue : qfalse;
451 w1 = (netchan->outgoing_sequence & 0x3FFFFFFF) | (1 << 30) |
452 (send_reliable << 31);
453 w2 = (netchan->incoming_sequence & 0x3FFFFFFF) | (0 << 30) |
454 (chan->incoming_reliable_sequence << 31);
456 SZ_TagInit(&send, send_buf,
sizeof(send_buf), SZ_NC_SEND_FRG);
463 if (netchan->sock == NS_CLIENT && netchan->qport) {
468 fragment_length = chan->fragment_out.cursize - chan->fragment_out.readcount;
469 if (fragment_length > netchan->maxpacketlen) {
470 fragment_length = netchan->maxpacketlen;
473 more_fragments = qtrue;
474 if (chan->fragment_out.readcount + fragment_length ==
475 chan->fragment_out.cursize) {
476 more_fragments = qfalse;
480 offset = (chan->fragment_out.readcount & 0x7FFF) |
481 (more_fragments << 15);
485 SZ_Write(&send, chan->fragment_out.data + chan->fragment_out.readcount,
488 SHOWPACKET(
"send %4"PRIz
" : s=%d ack=%d rack=%d "
489 "fragment_offset=%"PRIz
" more_fragments=%d",
491 netchan->outgoing_sequence,
492 netchan->incoming_sequence,
493 chan->incoming_reliable_sequence,
494 chan->fragment_out.readcount,
497 SHOWPACKET(
" reliable=%i ", chan->reliable_sequence);
501 chan->fragment_out.readcount += fragment_length;
502 netchan->fragment_pending = more_fragments;
505 if (!netchan->fragment_pending) {
506 netchan->outgoing_sequence++;
513 &netchan->remote_address);
525 netchan_new_t *chan = (netchan_new_t *)netchan;
527 byte send_buf[MAX_PACKETLEN];
528 qboolean send_reliable;
533 if (netchan->message.overflowed) {
534 netchan->fatal_error = qtrue;
535 Com_WPrintf(
"%s: outgoing message overflow\n",
540 if (netchan->fragment_pending) {
544 send_reliable = qfalse;
547 if (netchan->incoming_acknowledged > chan->last_reliable_sequence &&
548 chan->incoming_reliable_acknowledged != chan->reliable_sequence) {
549 send_reliable = qtrue;
553 if (!netchan->reliable_length && netchan->message.cursize) {
554 send_reliable = qtrue;
555 memcpy(chan->reliable_buf, chan->message_buf,
556 netchan->message.cursize);
557 netchan->reliable_length = netchan->message.cursize;
558 netchan->message.cursize = 0;
559 chan->reliable_sequence ^= 1;
562 if (length > netchan->maxpacketlen || (send_reliable &&
563 (netchan->reliable_length + length > netchan->maxpacketlen))) {
565 chan->last_reliable_sequence = netchan->outgoing_sequence;
566 SZ_Write(&chan->fragment_out, chan->reliable_buf,
567 netchan->reliable_length);
570 if (chan->fragment_out.maxsize - chan->fragment_out.cursize >= length)
571 SZ_Write(&chan->fragment_out, data, length);
573 Com_WPrintf(
"%s: dumped unreliable\n",
579 w1 = (netchan->outgoing_sequence & 0x3FFFFFFF) | (send_reliable << 31);
580 w2 = (netchan->incoming_sequence & 0x3FFFFFFF) |
581 (chan->incoming_reliable_sequence << 31);
583 SZ_TagInit(&send, send_buf,
sizeof(send_buf), SZ_NC_SEND_NEW);
590 if (netchan->sock == NS_CLIENT && netchan->qport) {
597 chan->last_reliable_sequence = netchan->outgoing_sequence;
598 SZ_Write(&send, chan->reliable_buf, netchan->reliable_length);
602 SZ_Write(&send, data, length);
604 SHOWPACKET(
"send %4"PRIz
" : s=%d ack=%d rack=%d",
606 netchan->outgoing_sequence,
607 netchan->incoming_sequence,
608 chan->incoming_reliable_sequence);
610 SHOWPACKET(
" reliable=%d", chan->reliable_sequence);
615 for (i = 0; i < numpackets; i++) {
617 &netchan->remote_address);
620 netchan->outgoing_sequence++;
621 netchan->reliable_ack_pending = qfalse;
624 return send.cursize * numpackets;
634 netchan_new_t *chan = (netchan_new_t *)netchan;
635 uint32_t sequence, sequence_ack, reliable_ack;
636 qboolean reliable_message, fragmented_message, more_fragments;
637 uint16_t fragment_offset;
647 if (netchan->sock == NS_SERVER)
649 if (netchan->qport) {
653 reliable_message = sequence >> 31;
654 reliable_ack = sequence_ack >> 31;
655 fragmented_message = (sequence >> 30) & 1;
657 sequence &= 0x3FFFFFFF;
658 sequence_ack &= 0x3FFFFFFF;
661 more_fragments = qfalse;
662 if (fragmented_message) {
664 more_fragments = fragment_offset >> 15;
665 fragment_offset &= 0x7FFF;
668 SHOWPACKET(
"recv %4"PRIz
" : s=%d ack=%d rack=%d",
669 msg_read.cursize, sequence, sequence_ack, reliable_ack);
670 if (fragmented_message) {
671 SHOWPACKET(
" fragment_offset=%d more_fragments=%d",
672 fragment_offset, more_fragments);
674 if (reliable_message) {
675 SHOWPACKET(
" reliable=%d", chan->incoming_reliable_sequence ^ 1);
682 if (sequence <= netchan->incoming_sequence) {
683 SHOWDROP(
"%s: out of order packet %i at %i\n",
685 sequence, netchan->incoming_sequence);
692 netchan->dropped = sequence - (netchan->incoming_sequence + 1);
693 if (netchan->dropped > 0) {
694 SHOWDROP(
"%s: dropped %i packets at %i\n",
696 netchan->dropped, sequence);
703 chan->incoming_reliable_acknowledged = reliable_ack;
704 if (reliable_ack == chan->reliable_sequence) {
705 netchan->reliable_length = 0;
712 if (fragmented_message) {
713 if (chan->fragment_sequence != sequence) {
715 chan->fragment_sequence = sequence;
719 if (fragment_offset < chan->fragment_in.cursize) {
720 SHOWDROP(
"%s: out of order fragment at %i\n",
725 if (fragment_offset > chan->fragment_in.cursize) {
726 SHOWDROP(
"%s: dropped fragment(s) at %i\n",
732 if (chan->fragment_in.cursize + length > chan->fragment_in.maxsize) {
733 SHOWDROP(
"%s: oversize fragment at %i\n",
738 SZ_Write(&chan->fragment_in,
msg_read.data +
740 if (more_fragments) {
746 SZ_Write(&
msg_read, chan->fragment_in.data,
747 chan->fragment_in.cursize);
751 netchan->incoming_sequence = sequence;
752 netchan->incoming_acknowledged = sequence_ack;
757 if (reliable_message) {
758 netchan->reliable_ack_pending = qtrue;
759 chan->incoming_reliable_sequence ^= 1;
767 netchan->total_dropped += netchan->dropped;
768 netchan->total_received += netchan->dropped + 1;
780 netchan_new_t *chan = (netchan_new_t *)netchan;
782 if (netchan->message.cursize ||
783 netchan->reliable_ack_pending ||
784 chan->fragment_out.cursize ||
798 int qport,
size_t maxpacketlen)
804 sock == NS_SERVER ? TAG_SERVER : TAG_GENERAL);
805 netchan = (netchan_t *)chan;
806 netchan->sock = sock;
807 netchan->remote_address = *adr;
808 netchan->qport = qport;
809 netchan->maxpacketlen = maxpacketlen;
812 netchan->incoming_sequence = 0;
813 netchan->outgoing_sequence = 1;
820 SZ_Init(&netchan->message, chan->message_buf,
821 sizeof(chan->message_buf));
822 SZ_TagInit(&chan->fragment_in, chan->fragment_in_buf,
823 sizeof(chan->fragment_in_buf), SZ_NC_FRG_IN);
824 SZ_TagInit(&chan->fragment_out, chan->fragment_out_buf,
825 sizeof(chan->fragment_out_buf), SZ_NC_FRG_OUT);
836 const netadr_t *adr,
int qport,
size_t maxpacketlen,
int protocol)
840 clamp(maxpacketlen, MIN_PACKETLEN, MAX_PACKETLEN_WRITABLE);
850 Com_Error(ERR_FATAL,
"Netchan_Setup: bad type");
854 netchan->protocol = protocol;
855 netchan->type = type;