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