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