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