|
|
1.1.1.3 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ 1.1 root 20: 21: #include "qcommon.h" 1.1.1.2 root 22: 1.1 root 23: /* 1.1.1.2 root 24: 1.1 root 25: packet header 26: ------------- 27: 31 sequence 28: 1 does this message contain a reliable payload 29: 31 acknowledge sequence 30: 1 acknowledge receipt of even/odd message 31: 16 qport 1.1.1.2 root 32: 1.1 root 33: The remote connection never knows if it missed a reliable message, the 34: local side detects that it has been dropped by seeing a sequence acknowledge 35: higher thatn the last reliable sequence, but without the correct evon/odd 36: bit for the reliable set. 1.1.1.2 root 37: 1.1 root 38: If the sender notices that a reliable message has been dropped, it will be 39: retransmitted. It will not be retransmitted again until a message after 40: the retransmit has been acknowledged and the reliable still failed to get there. 1.1.1.2 root 41: 1.1 root 42: if the sequence number is -1, the packet should be handled without a netcon 1.1.1.2 root 43: 1.1 root 44: The reliable message can be added to at any time by doing 45: MSG_Write* (&netchan->message, <data>). 1.1.1.2 root 46: 1.1 root 47: If the message buffer is overflowed, either by a single message, or by 48: multiple frames worth piling up while the last reliable transmit goes 49: unacknowledged, the netchan signals a fatal error. 1.1.1.2 root 50: 1.1 root 51: Reliable messages are always placed first in a packet, then the unreliable 52: message is included if there is sufficient room. 1.1.1.2 root 53: 1.1 root 54: To the receiver, there is no distinction between the reliable and unreliable 55: parts of the message, they are just processed out as a single larger message. 1.1.1.2 root 56: 1.1 root 57: Illogical packet sequence numbers cause the packet to be dropped, but do 58: not kill the connection. This, combined with the tight window of valid 59: reliable acknowledgement numbers provides protection against malicious 60: address spoofing. 61: 62: 63: The qport field is a workaround for bad address translating routers that 64: sometimes remap the client's source port on a packet during gameplay. 65: 66: If the base part of the net address matches and the qport matches, then the 67: channel matches even if the IP port differs. The IP port should be updated 68: to the new value before sending out any replies. 69: 70: 71: If there is no information that needs to be transfered on a given frame, 72: such as during the connection stage while waiting for the client to load, 73: then a packet only needs to be delivered if there is something in the 74: unacknowledged reliable 75: */ 1.1.1.2 root 76: 1.1 root 77: cvar_t *showpackets; 78: cvar_t *showdrop; 79: cvar_t *qport; 1.1.1.2 root 80: 1.1 root 81: netadr_t net_from; 82: sizebuf_t net_message; 83: byte net_message_buffer[MAX_MSGLEN]; 1.1.1.2 root 84: 1.1 root 85: /* 86: =============== 87: Netchan_Init 1.1.1.2 root 88: 1.1 root 89: =============== 90: */ 91: void Netchan_Init (void) 92: { 93: int port; 94: 95: // pick a port value that should be nice and random 96: port = Sys_Milliseconds() & 0xffff; 1.1.1.2 root 97: 1.1 root 98: showpackets = Cvar_Get ("showpackets", "0", 0); 99: showdrop = Cvar_Get ("showdrop", "0", 0); 100: qport = Cvar_Get ("qport", va("%i", port), CVAR_NOSET); 101: } 1.1.1.2 root 102: 1.1 root 103: /* 104: =============== 105: Netchan_OutOfBand 1.1.1.2 root 106: 1.1 root 107: Sends an out-of-band datagram 108: ================ 109: */ 110: void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data) 111: { 112: sizebuf_t send; 113: byte send_buf[MAX_MSGLEN]; 1.1.1.2 root 114: 1.1 root 115: // write the packet header 116: SZ_Init (&send, send_buf, sizeof(send_buf)); 117: 118: MSG_WriteLong (&send, -1); // -1 sequence means out of band 119: SZ_Write (&send, data, length); 1.1.1.2 root 120: 1.1 root 121: // send the datagram 122: NET_SendPacket (net_socket, send.cursize, send.data, adr); 123: } 1.1.1.2 root 124: 1.1 root 125: /* 126: =============== 127: Netchan_OutOfBandPrint 1.1.1.2 root 128: 1.1 root 129: Sends a text message in an out-of-band datagram 130: ================ 131: */ 132: void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...) 133: { 134: va_list argptr; 135: static char string[MAX_MSGLEN - 4]; 136: 137: va_start (argptr, format); 138: vsprintf (string, format,argptr); 139: va_end (argptr); 1.1.1.2 root 140: 1.1 root 141: Netchan_OutOfBand (net_socket, adr, strlen(string), (byte *)string); 142: } 1.1.1.2 root 143: 144: 1.1 root 145: /* 146: ============== 147: Netchan_Setup 1.1.1.2 root 148: 1.1 root 149: called to open a channel to a remote system 150: ============== 151: */ 152: void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport) 153: { 154: memset (chan, 0, sizeof(*chan)); 155: 156: chan->sock = sock; 157: chan->remote_address = adr; 158: chan->qport = qport; 159: chan->last_received = curtime; 160: chan->incoming_sequence = 0; 161: chan->outgoing_sequence = 1; 1.1.1.2 root 162: 1.1 root 163: SZ_Init (&chan->message, chan->message_buf, sizeof(chan->message_buf)); 164: chan->message.allowoverflow = true; 165: } 1.1.1.2 root 166: 167: 1.1 root 168: /* 169: =============== 170: Netchan_CanReliable 1.1.1.2 root 171: 1.1 root 172: Returns true if the last reliable message has acked 173: ================ 174: */ 175: qboolean Netchan_CanReliable (netchan_t *chan) 176: { 177: if (chan->reliable_length) 178: return false; // waiting for ack 179: return true; 180: } 181: 1.1.1.2 root 182: 1.1 root 183: qboolean Netchan_NeedReliable (netchan_t *chan) 184: { 185: qboolean send_reliable; 186: 187: // if the remote side dropped the last reliable message, resend it 188: send_reliable = false; 189: 190: if (chan->incoming_acknowledged > chan->last_reliable_sequence 191: && chan->incoming_reliable_acknowledged != chan->reliable_sequence) 192: send_reliable = true; 193: 194: // if the reliable transmit buffer is empty, copy the current message out 195: if (!chan->reliable_length && chan->message.cursize) 196: { 197: send_reliable = true; 198: } 199: 200: return send_reliable; 201: } 1.1.1.2 root 202: 1.1 root 203: /* 204: =============== 205: Netchan_Transmit 1.1.1.2 root 206: 1.1 root 207: tries to send an unreliable message to a connection, and handles the 208: transmition / retransmition of the reliable messages. 1.1.1.2 root 209: 1.1 root 210: A 0 length will still generate a packet and deal with the reliable messages. 211: ================ 212: */ 213: void Netchan_Transmit (netchan_t *chan, int length, byte *data) 214: { 215: sizebuf_t send; 216: byte send_buf[MAX_MSGLEN]; 217: qboolean send_reliable; 218: unsigned w1, w2; 1.1.1.2 root 219: 1.1 root 220: // check for message overflow 221: if (chan->message.overflowed) 222: { 223: chan->fatal_error = true; 224: Com_Printf ("%s:Outgoing message overflow\n" 225: , NET_AdrToString (chan->remote_address)); 226: return; 227: } 228: 229: send_reliable = Netchan_NeedReliable (chan); 230: 231: if (!chan->reliable_length && chan->message.cursize) 232: { 233: memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize); 234: chan->reliable_length = chan->message.cursize; 235: chan->message.cursize = 0; 236: chan->reliable_sequence ^= 1; 237: } 1.1.1.2 root 238: 239: 1.1 root 240: // write the packet header 241: SZ_Init (&send, send_buf, sizeof(send_buf)); 1.1.1.2 root 242: 1.1 root 243: w1 = ( chan->outgoing_sequence & ~(1<<31) ) | (send_reliable<<31); 244: w2 = ( chan->incoming_sequence & ~(1<<31) ) | (chan->incoming_reliable_sequence<<31); 1.1.1.2 root 245: 1.1 root 246: chan->outgoing_sequence++; 247: chan->last_sent = curtime; 1.1.1.2 root 248: 1.1 root 249: MSG_WriteLong (&send, w1); 250: MSG_WriteLong (&send, w2); 251: 252: // send the qport if we are a client 253: if (chan->sock == NS_CLIENT) 254: MSG_WriteShort (&send, qport->value); 1.1.1.2 root 255: 1.1 root 256: // copy the reliable message to the packet first 257: if (send_reliable) 258: { 259: SZ_Write (&send, chan->reliable_buf, chan->reliable_length); 260: chan->last_reliable_sequence = chan->outgoing_sequence; 261: } 262: 263: // add the unreliable part if space is available 264: if (send.maxsize - send.cursize >= length) 265: SZ_Write (&send, data, length); 266: else 267: Com_Printf ("Netchan_Transmit: dumped unreliable\n"); 1.1.1.2 root 268: 1.1 root 269: // send the datagram 270: NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); 1.1.1.2 root 271: 1.1 root 272: if (showpackets->value) 273: { 274: if (send_reliable) 275: Com_Printf ("send %4i : s=%i reliable=%i ack=%i rack=%i\n" 276: , send.cursize 277: , chan->outgoing_sequence - 1 278: , chan->reliable_sequence 279: , chan->incoming_sequence 280: , chan->incoming_reliable_sequence); 281: else 282: Com_Printf ("send %4i : s=%i ack=%i rack=%i\n" 283: , send.cursize 284: , chan->outgoing_sequence - 1 285: , chan->incoming_sequence 286: , chan->incoming_reliable_sequence); 287: } 288: } 1.1.1.2 root 289: 1.1 root 290: /* 291: ================= 292: Netchan_Process 1.1.1.2 root 293: 1.1 root 294: called when the current net_message is from remote_address 295: modifies net_message so that it points to the packet payload 296: ================= 297: */ 298: qboolean Netchan_Process (netchan_t *chan, sizebuf_t *msg) 299: { 300: unsigned sequence, sequence_ack; 301: unsigned reliable_ack, reliable_message; 302: int qport; 1.1.1.2 root 303: 1.1 root 304: // get sequence numbers 305: MSG_BeginReading (msg); 306: sequence = MSG_ReadLong (msg); 307: sequence_ack = MSG_ReadLong (msg); 308: 309: // read the qport if we are a server 310: if (chan->sock == NS_SERVER) 311: qport = MSG_ReadShort (msg); 1.1.1.2 root 312: 1.1 root 313: reliable_message = sequence >> 31; 314: reliable_ack = sequence_ack >> 31; 1.1.1.2 root 315: 1.1 root 316: sequence &= ~(1<<31); 317: sequence_ack &= ~(1<<31); 1.1.1.2 root 318: 1.1 root 319: if (showpackets->value) 320: { 321: if (reliable_message) 322: Com_Printf ("recv %4i : s=%i reliable=%i ack=%i rack=%i\n" 323: , msg->cursize 324: , sequence 325: , chan->incoming_reliable_sequence ^ 1 326: , sequence_ack 327: , reliable_ack); 328: else 329: Com_Printf ("recv %4i : s=%i ack=%i rack=%i\n" 330: , msg->cursize 331: , sequence 332: , sequence_ack 333: , reliable_ack); 334: } 1.1.1.2 root 335: 1.1 root 336: // 337: // discard stale or duplicated packets 338: // 339: if (sequence <= chan->incoming_sequence) 340: { 341: if (showdrop->value) 342: Com_Printf ("%s:Out of order packet %i at %i\n" 343: , NET_AdrToString (chan->remote_address) 344: , sequence 345: , chan->incoming_sequence); 346: return false; 347: } 1.1.1.2 root 348: 1.1 root 349: // 350: // dropped packets don't keep the message from being used 351: // 352: chan->dropped = sequence - (chan->incoming_sequence+1); 353: if (chan->dropped > 0) 354: { 355: if (showdrop->value) 356: Com_Printf ("%s:Dropped %i packets at %i\n" 357: , NET_AdrToString (chan->remote_address) 358: , chan->dropped 359: , sequence); 360: } 1.1.1.2 root 361: 1.1 root 362: // 363: // if the current outgoing reliable message has been acknowledged 364: // clear the buffer to make way for the next 365: // 366: if (reliable_ack == chan->reliable_sequence) 367: chan->reliable_length = 0; // it has been received 368: 369: // 370: // if this message contains a reliable message, bump incoming_reliable_sequence 371: // 372: chan->incoming_sequence = sequence; 373: chan->incoming_acknowledged = sequence_ack; 374: chan->incoming_reliable_acknowledged = reliable_ack; 375: if (reliable_message) 376: { 377: chan->incoming_reliable_sequence ^= 1; 378: } 1.1.1.2 root 379: 1.1 root 380: // 381: // the message can now be read from the current message pointer 382: // 383: chan->last_received = curtime; 1.1.1.2 root 384: 1.1 root 385: return true; 386: } 1.1.1.2 root 387:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.