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