1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 #include "q_shared.h"
24 #include "qcommon.h"
25
26 /*
27
28 packet header
29 -------------
30 4 outgoing sequence. high bit will be set if this is a fragmented message
31 [2 qport (only for client to server)]
32 [2 fragment start byte]
33 [2 fragment length. if < FRAGMENT_SIZE, this is the last fragment]
34
35 if the sequence number is -1, the packet should be handled as an out-of-band
36 message instead of as part of a netcon.
37
38 All fragments will have the same sequence numbers.
39
40 The qport field is a workaround for bad address translating routers that
41 sometimes remap the client's source port on a packet during gameplay.
42
43 If the base part of the net address matches and the qport matches, then the
44 channel matches even if the IP port differs. The IP port should be updated
45 to the new value before sending out any replies.
46
47 */
48
49
50 #define MAX_PACKETLEN 1400 // max size of a network packet
51
52 #define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
53 #define PACKET_HEADER 10 // two ints and a short
54
55 #define FRAGMENT_BIT (1<<31)
56
57 cvar_t *showpackets;
58 cvar_t *showdrop;
59 cvar_t *qport;
60
61 static char *netsrcString[2] = {
62 "client",
63 "server"
64 };
65
66 /*
67 ===============
68 Netchan_Init
69
70 ===============
71 */
Netchan_Init(int port)72 void Netchan_Init( int port ) {
73 port &= 0xffff;
74 showpackets = Cvar_Get ("showpackets", "0", CVAR_TEMP );
75 showdrop = Cvar_Get ("showdrop", "0", CVAR_TEMP );
76 qport = Cvar_Get ("net_qport", va("%i", port), CVAR_INIT );
77 }
78
79 /*
80 ==============
81 Netchan_Setup
82
83 called to open a channel to a remote system
84 ==============
85 */
Netchan_Setup(netsrc_t sock,netchan_t * chan,netadr_t adr,int qport)86 void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
87 Com_Memset (chan, 0, sizeof(*chan));
88
89 chan->sock = sock;
90 chan->remoteAddress = adr;
91 chan->qport = qport;
92 chan->incomingSequence = 0;
93 chan->outgoingSequence = 1;
94 }
95
96 // TTimo: unused, commenting out to make gcc happy
97 #if 0
98 /*
99 ==============
100 Netchan_ScramblePacket
101
102 A probably futile attempt to make proxy hacking somewhat
103 more difficult.
104 ==============
105 */
106 #define SCRAMBLE_START 6
107 static void Netchan_ScramblePacket( msg_t *buf ) {
108 unsigned seed;
109 int i, j, c, mask, temp;
110 int seq[MAX_PACKETLEN];
111
112 seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
113 c = buf->cursize;
114 if ( c <= SCRAMBLE_START ) {
115 return;
116 }
117 if ( c > MAX_PACKETLEN ) {
118 Com_Error( ERR_DROP, "MAX_PACKETLEN" );
119 }
120
121 // generate a sequence of "random" numbers
122 for (i = 0 ; i < c ; i++) {
123 seed = (119 * seed + 1);
124 seq[i] = seed;
125 }
126
127 // transpose each character
128 for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
129 }
130 mask >>= 1;
131 for (i = SCRAMBLE_START ; i < c ; i++) {
132 j = SCRAMBLE_START + ( seq[i] & mask );
133 temp = buf->data[j];
134 buf->data[j] = buf->data[i];
135 buf->data[i] = temp;
136 }
137
138 // byte xor the data after the header
139 for (i = SCRAMBLE_START ; i < c ; i++) {
140 buf->data[i] ^= seq[i];
141 }
142 }
143
144 static void Netchan_UnScramblePacket( msg_t *buf ) {
145 unsigned seed;
146 int i, j, c, mask, temp;
147 int seq[MAX_PACKETLEN];
148
149 seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
150 c = buf->cursize;
151 if ( c <= SCRAMBLE_START ) {
152 return;
153 }
154 if ( c > MAX_PACKETLEN ) {
155 Com_Error( ERR_DROP, "MAX_PACKETLEN" );
156 }
157
158 // generate a sequence of "random" numbers
159 for (i = 0 ; i < c ; i++) {
160 seed = (119 * seed + 1);
161 seq[i] = seed;
162 }
163
164 // byte xor the data after the header
165 for (i = SCRAMBLE_START ; i < c ; i++) {
166 buf->data[i] ^= seq[i];
167 }
168
169 // transpose each character in reverse order
170 for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
171 }
172 mask >>= 1;
173 for (i = c-1 ; i >= SCRAMBLE_START ; i--) {
174 j = SCRAMBLE_START + ( seq[i] & mask );
175 temp = buf->data[j];
176 buf->data[j] = buf->data[i];
177 buf->data[i] = temp;
178 }
179 }
180 #endif
181
182 /*
183 =================
184 Netchan_TransmitNextFragment
185
186 Send one fragment of the current message
187 =================
188 */
Netchan_TransmitNextFragment(netchan_t * chan)189 void Netchan_TransmitNextFragment( netchan_t *chan ) {
190 msg_t send;
191 byte send_buf[MAX_PACKETLEN];
192 int fragmentLength;
193
194 // write the packet header
195 MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
196
197 MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
198
199 // send the qport if we are a client
200 if ( chan->sock == NS_CLIENT ) {
201 MSG_WriteShort( &send, qport->integer );
202 }
203
204 // copy the reliable message to the packet first
205 fragmentLength = FRAGMENT_SIZE;
206 if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
207 fragmentLength = chan->unsentLength - chan->unsentFragmentStart;
208 }
209
210 MSG_WriteShort( &send, chan->unsentFragmentStart );
211 MSG_WriteShort( &send, fragmentLength );
212 MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength );
213
214 // send the datagram
215 NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
216
217 if ( showpackets->integer ) {
218 Com_Printf ("%s send %4i : s=%i fragment=%i,%i\n"
219 , netsrcString[ chan->sock ]
220 , send.cursize
221 , chan->outgoingSequence
222 , chan->unsentFragmentStart, fragmentLength);
223 }
224
225 chan->unsentFragmentStart += fragmentLength;
226
227 // this exit condition is a little tricky, because a packet
228 // that is exactly the fragment length still needs to send
229 // a second packet of zero length so that the other side
230 // can tell there aren't more to follow
231 if ( chan->unsentFragmentStart == chan->unsentLength && fragmentLength != FRAGMENT_SIZE ) {
232 chan->outgoingSequence++;
233 chan->unsentFragments = qfalse;
234 }
235 }
236
237
238 /*
239 ===============
240 Netchan_Transmit
241
242 Sends a message to a connection, fragmenting if necessary
243 A 0 length will still generate a packet.
244 ================
245 */
Netchan_Transmit(netchan_t * chan,int length,const byte * data)246 void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
247 msg_t send;
248 byte send_buf[MAX_PACKETLEN];
249
250 if ( length > MAX_MSGLEN ) {
251 Com_Error( ERR_DROP, "Netchan_Transmit: length = %i", length );
252 }
253 chan->unsentFragmentStart = 0;
254
255 // fragment large reliable messages
256 if ( length >= FRAGMENT_SIZE ) {
257 chan->unsentFragments = qtrue;
258 chan->unsentLength = length;
259 Com_Memcpy( chan->unsentBuffer, data, length );
260
261 // only send the first fragment now
262 Netchan_TransmitNextFragment( chan );
263
264 return;
265 }
266
267 // write the packet header
268 MSG_InitOOB (&send, send_buf, sizeof(send_buf));
269
270 MSG_WriteLong( &send, chan->outgoingSequence );
271 chan->outgoingSequence++;
272
273 // send the qport if we are a client
274 if ( chan->sock == NS_CLIENT ) {
275 MSG_WriteShort( &send, qport->integer );
276 }
277
278 MSG_WriteData( &send, data, length );
279
280 // send the datagram
281 NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
282
283 if ( showpackets->integer ) {
284 Com_Printf( "%s send %4i : s=%i ack=%i\n"
285 , netsrcString[ chan->sock ]
286 , send.cursize
287 , chan->outgoingSequence - 1
288 , chan->incomingSequence );
289 }
290 }
291
292 /*
293 =================
294 Netchan_Process
295
296 Returns qfalse if the message should not be processed due to being
297 out of order or a fragment.
298
299 Msg must be large enough to hold MAX_MSGLEN, because if this is the
300 final fragment of a multi-part message, the entire thing will be
301 copied out.
302 =================
303 */
Netchan_Process(netchan_t * chan,msg_t * msg)304 qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
305 int sequence;
306 int qport;
307 int fragmentStart, fragmentLength;
308 qboolean fragmented;
309
310 // XOR unscramble all data in the packet after the header
311 // Netchan_UnScramblePacket( msg );
312
313 // get sequence numbers
314 MSG_BeginReadingOOB( msg );
315 sequence = MSG_ReadLong( msg );
316
317 // check for fragment information
318 if ( sequence & FRAGMENT_BIT ) {
319 sequence &= ~FRAGMENT_BIT;
320 fragmented = qtrue;
321 } else {
322 fragmented = qfalse;
323 }
324
325 // read the qport if we are a server
326 if ( chan->sock == NS_SERVER ) {
327 qport = MSG_ReadShort( msg );
328 }
329
330 // read the fragment information
331 if ( fragmented ) {
332 fragmentStart = MSG_ReadShort( msg );
333 fragmentLength = MSG_ReadShort( msg );
334 } else {
335 fragmentStart = 0; // stop warning message
336 fragmentLength = 0;
337 }
338
339 if ( showpackets->integer ) {
340 if ( fragmented ) {
341 Com_Printf( "%s recv %4i : s=%i fragment=%i,%i\n"
342 , netsrcString[ chan->sock ]
343 , msg->cursize
344 , sequence
345 , fragmentStart, fragmentLength );
346 } else {
347 Com_Printf( "%s recv %4i : s=%i\n"
348 , netsrcString[ chan->sock ]
349 , msg->cursize
350 , sequence );
351 }
352 }
353
354 //
355 // discard out of order or duplicated packets
356 //
357 if ( sequence <= chan->incomingSequence ) {
358 if ( showdrop->integer || showpackets->integer ) {
359 Com_Printf( "%s:Out of order packet %i at %i\n"
360 , NET_AdrToString( chan->remoteAddress )
361 , sequence
362 , chan->incomingSequence );
363 }
364 return qfalse;
365 }
366
367 //
368 // dropped packets don't keep the message from being used
369 //
370 chan->dropped = sequence - (chan->incomingSequence+1);
371 if ( chan->dropped > 0 ) {
372 if ( showdrop->integer || showpackets->integer ) {
373 Com_Printf( "%s:Dropped %i packets at %i\n"
374 , NET_AdrToString( chan->remoteAddress )
375 , chan->dropped
376 , sequence );
377 }
378 }
379
380
381 //
382 // if this is the final framgent of a reliable message,
383 // bump incoming_reliable_sequence
384 //
385 if ( fragmented ) {
386 // TTimo
387 // make sure we add the fragments in correct order
388 // either a packet was dropped, or we received this one too soon
389 // we don't reconstruct the fragments. we will wait till this fragment gets to us again
390 // (NOTE: we could probably try to rebuild by out of order chunks if needed)
391 if ( sequence != chan->fragmentSequence ) {
392 chan->fragmentSequence = sequence;
393 chan->fragmentLength = 0;
394 }
395
396 // if we missed a fragment, dump the message
397 if ( fragmentStart != chan->fragmentLength ) {
398 if ( showdrop->integer || showpackets->integer ) {
399 Com_Printf( "%s:Dropped a message fragment\n"
400 , NET_AdrToString( chan->remoteAddress ));
401 }
402 // we can still keep the part that we have so far,
403 // so we don't need to clear chan->fragmentLength
404 return qfalse;
405 }
406
407 // copy the fragment to the fragment buffer
408 if ( fragmentLength < 0 || msg->readcount + fragmentLength > msg->cursize ||
409 chan->fragmentLength + fragmentLength > sizeof( chan->fragmentBuffer ) ) {
410 if ( showdrop->integer || showpackets->integer ) {
411 Com_Printf ("%s:illegal fragment length\n"
412 , NET_AdrToString (chan->remoteAddress ) );
413 }
414 return qfalse;
415 }
416
417 Com_Memcpy( chan->fragmentBuffer + chan->fragmentLength,
418 msg->data + msg->readcount, fragmentLength );
419
420 chan->fragmentLength += fragmentLength;
421
422 // if this wasn't the last fragment, don't process anything
423 if ( fragmentLength == FRAGMENT_SIZE ) {
424 return qfalse;
425 }
426
427 if ( chan->fragmentLength > msg->maxsize ) {
428 Com_Printf( "%s:fragmentLength %i > msg->maxsize\n"
429 , NET_AdrToString (chan->remoteAddress ),
430 chan->fragmentLength );
431 return qfalse;
432 }
433
434 // copy the full message over the partial fragment
435
436 // make sure the sequence number is still there
437 *(int *)msg->data = LittleLong( sequence );
438
439 Com_Memcpy( msg->data + 4, chan->fragmentBuffer, chan->fragmentLength );
440 msg->cursize = chan->fragmentLength + 4;
441 chan->fragmentLength = 0;
442 msg->readcount = 4; // past the sequence number
443 msg->bit = 32; // past the sequence number
444
445 // TTimo
446 // clients were not acking fragmented messages
447 chan->incomingSequence = sequence;
448
449 return qtrue;
450 }
451
452 //
453 // the message can now be read from the current message pointer
454 //
455 chan->incomingSequence = sequence;
456
457 return qtrue;
458 }
459
460
461 //==============================================================================
462
463
464 /*
465 =============================================================================
466
467 LOOPBACK BUFFERS FOR LOCAL PLAYER
468
469 =============================================================================
470 */
471
472 // there needs to be enough loopback messages to hold a complete
473 // gamestate of maximum size
474 #define MAX_LOOPBACK 16
475
476 typedef struct {
477 byte data[MAX_PACKETLEN];
478 int datalen;
479 } loopmsg_t;
480
481 typedef struct {
482 loopmsg_t msgs[MAX_LOOPBACK];
483 int get, send;
484 } loopback_t;
485
486 loopback_t loopbacks[2];
487
488
NET_GetLoopPacket(netsrc_t sock,netadr_t * net_from,msg_t * net_message)489 qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message)
490 {
491 int i;
492 loopback_t *loop;
493
494 loop = &loopbacks[sock];
495
496 if (loop->send - loop->get > MAX_LOOPBACK)
497 loop->get = loop->send - MAX_LOOPBACK;
498
499 if (loop->get >= loop->send)
500 return qfalse;
501
502 i = loop->get & (MAX_LOOPBACK-1);
503 loop->get++;
504
505 Com_Memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
506 net_message->cursize = loop->msgs[i].datalen;
507 Com_Memset (net_from, 0, sizeof(*net_from));
508 net_from->type = NA_LOOPBACK;
509 return qtrue;
510
511 }
512
513
NET_SendLoopPacket(netsrc_t sock,int length,const void * data,netadr_t to)514 void NET_SendLoopPacket (netsrc_t sock, int length, const void *data, netadr_t to)
515 {
516 int i;
517 loopback_t *loop;
518
519 loop = &loopbacks[sock^1];
520
521 i = loop->send & (MAX_LOOPBACK-1);
522 loop->send++;
523
524 Com_Memcpy (loop->msgs[i].data, data, length);
525 loop->msgs[i].datalen = length;
526 }
527
528 //=============================================================================
529
530 typedef struct packetQueue_s {
531 struct packetQueue_s *next;
532 int length;
533 byte *data;
534 netadr_t to;
535 int release;
536 } packetQueue_t;
537
538 packetQueue_t *packetQueue = NULL;
539
NET_QueuePacket(int length,const void * data,netadr_t to,int offset)540 static void NET_QueuePacket( int length, const void *data, netadr_t to,
541 int offset )
542 {
543 packetQueue_t *new, *next = packetQueue;
544
545 if(offset > 999)
546 offset = 999;
547
548 new = S_Malloc(sizeof(packetQueue_t));
549 new->data = S_Malloc(length);
550 Com_Memcpy(new->data, data, length);
551 new->length = length;
552 new->to = to;
553 new->release = Sys_Milliseconds() + offset;
554 new->next = NULL;
555
556 if(!packetQueue) {
557 packetQueue = new;
558 return;
559 }
560 while(next) {
561 if(!next->next) {
562 next->next = new;
563 return;
564 }
565 next = next->next;
566 }
567 }
568
NET_FlushPacketQueue(void)569 void NET_FlushPacketQueue(void)
570 {
571 packetQueue_t *last;
572 int now;
573
574 while(packetQueue) {
575 now = Sys_Milliseconds();
576 if(packetQueue->release >= now)
577 break;
578 Sys_SendPacket(packetQueue->length, packetQueue->data,
579 packetQueue->to);
580 last = packetQueue;
581 packetQueue = packetQueue->next;
582 Z_Free(last->data);
583 Z_Free(last);
584 }
585 }
586
NET_SendPacket(netsrc_t sock,int length,const void * data,netadr_t to)587 void NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to ) {
588
589 // sequenced packets are shown in netchan, so just show oob
590 if ( showpackets->integer && *(int *)data == -1 ) {
591 Com_Printf ("send packet %4i\n", length);
592 }
593
594 if ( to.type == NA_LOOPBACK ) {
595 NET_SendLoopPacket (sock, length, data, to);
596 return;
597 }
598 if ( to.type == NA_BOT ) {
599 return;
600 }
601 if ( to.type == NA_BAD ) {
602 return;
603 }
604
605 if ( sock == NS_CLIENT && cl_packetdelay->integer > 0 ) {
606 NET_QueuePacket( length, data, to, cl_packetdelay->integer );
607 }
608 else if ( sock == NS_SERVER && sv_packetdelay->integer > 0 ) {
609 NET_QueuePacket( length, data, to, sv_packetdelay->integer );
610 }
611 else {
612 Sys_SendPacket( length, data, to );
613 }
614 }
615
616 /*
617 ===============
618 NET_OutOfBandPrint
619
620 Sends a text message in an out-of-band datagram
621 ================
622 */
NET_OutOfBandPrint(netsrc_t sock,netadr_t adr,const char * format,...)623 void QDECL NET_OutOfBandPrint( netsrc_t sock, netadr_t adr, const char *format, ... ) {
624 va_list argptr;
625 char string[MAX_MSGLEN];
626
627
628 // set the header
629 string[0] = -1;
630 string[1] = -1;
631 string[2] = -1;
632 string[3] = -1;
633
634 va_start( argptr, format );
635 Q_vsnprintf( string+4, sizeof(string)-4, format, argptr );
636 va_end( argptr );
637
638 // send the datagram
639 NET_SendPacket( sock, strlen( string ), string, adr );
640 }
641
642 /*
643 ===============
644 NET_OutOfBandPrint
645
646 Sends a data message in an out-of-band datagram (only used for "connect")
647 ================
648 */
NET_OutOfBandData(netsrc_t sock,netadr_t adr,byte * format,int len)649 void QDECL NET_OutOfBandData( netsrc_t sock, netadr_t adr, byte *format, int len ) {
650 byte string[MAX_MSGLEN*2];
651 int i;
652 msg_t mbuf;
653
654 // set the header
655 string[0] = 0xff;
656 string[1] = 0xff;
657 string[2] = 0xff;
658 string[3] = 0xff;
659
660 for(i=0;i<len;i++) {
661 string[i+4] = format[i];
662 }
663
664 mbuf.data = string;
665 mbuf.cursize = len+4;
666 Huff_Compress( &mbuf, 12);
667 // send the datagram
668 NET_SendPacket( sock, mbuf.cursize, mbuf.data, adr );
669 }
670
671 /*
672 =============
673 NET_StringToAdr
674
675 Traps "localhost" for loopback, passes everything else to system
676 return 0 on address not found, 1 on address found with port, 2 on address found without port.
677 =============
678 */
NET_StringToAdr(const char * s,netadr_t * a,netadrtype_t family)679 int NET_StringToAdr( const char *s, netadr_t *a, netadrtype_t family )
680 {
681 char base[MAX_STRING_CHARS], *search;
682 char *port = NULL;
683
684 if (!strcmp (s, "localhost")) {
685 Com_Memset (a, 0, sizeof(*a));
686 a->type = NA_LOOPBACK;
687 // as NA_LOOPBACK doesn't require ports report port was given.
688 return 1;
689 }
690
691 Q_strncpyz( base, s, sizeof( base ) );
692
693 if(*base == '[' || Q_CountChar(base, ':') > 1)
694 {
695 // This is an ipv6 address, handle it specially.
696 search = strchr(base, ']');
697 if(search)
698 {
699 *search = '\0';
700 search++;
701
702 if(*search == ':')
703 port = search + 1;
704 }
705
706 if(*base == '[')
707 search = base + 1;
708 else
709 search = base;
710 }
711 else
712 {
713 // look for a port number
714 port = strchr( base, ':' );
715
716 if ( port ) {
717 *port = '\0';
718 port++;
719 }
720
721 search = base;
722 }
723
724 if(!Sys_StringToAdr(search, a, family))
725 {
726 a->type = NA_BAD;
727 return 0;
728 }
729
730 if(port)
731 {
732 a->port = BigShort((short) atoi(port));
733 return 1;
734 }
735 else
736 {
737 a->port = BigShort(PORT_SERVER);
738 return 2;
739 }
740 }
741