doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
win_net.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 #include "../../idlib/precompiled.h"
29 #pragma hdrstop
30 
31 #include <iptypes.h>
32 #include <iphlpapi.h>
33 
34 #include "win_local.h"
35 
36 static WSADATA winsockdata;
37 static bool winsockInitialized = false;
38 static bool usingSocks = false;
39 
40 idCVar net_ip( "net_ip", "localhost", CVAR_SYSTEM, "local IP address" );
41 idCVar net_port( "net_port", "0", CVAR_SYSTEM | CVAR_INTEGER, "local IP port number" );
42 idCVar net_forceLatency( "net_forceLatency", "0", CVAR_SYSTEM | CVAR_INTEGER, "milliseconds latency" );
43 idCVar net_forceDrop( "net_forceDrop", "0", CVAR_SYSTEM | CVAR_INTEGER, "percentage packet loss" );
44 
45 idCVar net_socksEnabled( "net_socksEnabled", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "" );
46 idCVar net_socksServer( "net_socksServer", "", CVAR_SYSTEM | CVAR_ARCHIVE, "" );
47 idCVar net_socksPort( "net_socksPort", "1080", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "" );
48 idCVar net_socksUsername( "net_socksUsername", "", CVAR_SYSTEM | CVAR_ARCHIVE, "" );
49 idCVar net_socksPassword( "net_socksPassword", "", CVAR_SYSTEM | CVAR_ARCHIVE, "" );
50 
51 
52 static struct sockaddr socksRelayAddr;
53 
54 static SOCKET ip_socket;
55 static SOCKET socks_socket;
56 static char socksBuf[4096];
57 
58 typedef struct {
59  unsigned long ip;
60  unsigned long mask;
62 
63 #define MAX_INTERFACES 32
66 
67 //=============================================================================
68 
69 
70 /*
71 ====================
72 NET_ErrorString
73 ====================
74 */
75 char *NET_ErrorString( void ) {
76  int code;
77 
78  code = WSAGetLastError();
79  switch( code ) {
80  case WSAEINTR: return "WSAEINTR";
81  case WSAEBADF: return "WSAEBADF";
82  case WSAEACCES: return "WSAEACCES";
83  case WSAEDISCON: return "WSAEDISCON";
84  case WSAEFAULT: return "WSAEFAULT";
85  case WSAEINVAL: return "WSAEINVAL";
86  case WSAEMFILE: return "WSAEMFILE";
87  case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
88  case WSAEINPROGRESS: return "WSAEINPROGRESS";
89  case WSAEALREADY: return "WSAEALREADY";
90  case WSAENOTSOCK: return "WSAENOTSOCK";
91  case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
92  case WSAEMSGSIZE: return "WSAEMSGSIZE";
93  case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
94  case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
95  case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
96  case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
97  case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
98  case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
99  case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
100  case WSAEADDRINUSE: return "WSAEADDRINUSE";
101  case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
102  case WSAENETDOWN: return "WSAENETDOWN";
103  case WSAENETUNREACH: return "WSAENETUNREACH";
104  case WSAENETRESET: return "WSAENETRESET";
105  case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
106  case WSAECONNRESET: return "WSAECONNRESET";
107  case WSAENOBUFS: return "WSAENOBUFS";
108  case WSAEISCONN: return "WSAEISCONN";
109  case WSAENOTCONN: return "WSAENOTCONN";
110  case WSAESHUTDOWN: return "WSAESHUTDOWN";
111  case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
112  case WSAETIMEDOUT: return "WSAETIMEDOUT";
113  case WSAECONNREFUSED: return "WSAECONNREFUSED";
114  case WSAELOOP: return "WSAELOOP";
115  case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
116  case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
117  case WSASYSNOTREADY: return "WSASYSNOTREADY";
118  case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
119  case WSANOTINITIALISED: return "WSANOTINITIALISED";
120  case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
121  case WSATRY_AGAIN: return "WSATRY_AGAIN";
122  case WSANO_RECOVERY: return "WSANO_RECOVERY";
123  case WSANO_DATA: return "WSANO_DATA";
124  default: return "NO ERROR";
125  }
126 }
127 
128 /*
129 ====================
130 Net_NetadrToSockadr
131 ====================
132 */
133 void Net_NetadrToSockadr( const netadr_t *a, struct sockaddr *s ) {
134  memset( s, 0, sizeof(*s) );
135 
136  if( a->type == NA_BROADCAST ) {
137  ((struct sockaddr_in *)s)->sin_family = AF_INET;
138  ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
139  }
140  else if( a->type == NA_IP || a->type == NA_LOOPBACK ) {
141  ((struct sockaddr_in *)s)->sin_family = AF_INET;
142  ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
143  }
144 
145  ((struct sockaddr_in *)s)->sin_port = htons( (short)a->port );
146 }
147 
148 
149 /*
150 ====================
151 Net_SockadrToNetadr
152 ====================
153 */
154 void Net_SockadrToNetadr( struct sockaddr *s, netadr_t *a ) {
155  unsigned int ip;
156  if (s->sa_family == AF_INET) {
157  ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
158  *(unsigned int *)&a->ip = ip;
159  a->port = htons( ((struct sockaddr_in *)s)->sin_port );
160  // we store in network order, that loopback test is host order..
161  ip = ntohl( ip );
162  if ( ip == INADDR_LOOPBACK ) {
163  a->type = NA_LOOPBACK;
164  } else {
165  a->type = NA_IP;
166  }
167  }
168 }
169 
170 /*
171 =============
172 Net_ExtractPort
173 =============
174 */
175 static bool Net_ExtractPort( const char *src, char *buf, int bufsize, int *port ) {
176  char *p;
177  strncpy( buf, src, bufsize );
178  p = buf; p += Min( bufsize - 1, (int)strlen( src ) ); *p = '\0';
179  p = strchr( buf, ':' );
180  if ( !p ) {
181  return false;
182  }
183  *p = '\0';
184  *port = strtol( p+1, NULL, 10 );
185  if ( errno == ERANGE ) {
186  return false;
187  }
188  return true;
189 }
190 
191 /*
192 =============
193 Net_StringToSockaddr
194 =============
195 */
196 static bool Net_StringToSockaddr( const char *s, struct sockaddr *sadr, bool doDNSResolve ) {
197  struct hostent *h;
198  char buf[256];
199  int port;
200 
201  memset( sadr, 0, sizeof( *sadr ) );
202 
203  ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
204  ((struct sockaddr_in *)sadr)->sin_port = 0;
205 
206  if( s[0] >= '0' && s[0] <= '9' ) {
207  unsigned long ret = inet_addr(s);
208  if ( ret != INADDR_NONE ) {
209  *(int *)&((struct sockaddr_in *)sadr)->sin_addr = ret;
210  } else {
211  // check for port
212  if ( !Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
213  return false;
214  }
215  ret = inet_addr( buf );
216  if ( ret == INADDR_NONE ) {
217  return false;
218  }
219  *(int *)&((struct sockaddr_in *)sadr)->sin_addr = ret;
220  ((struct sockaddr_in *)sadr)->sin_port = htons( port );
221  }
222  } else if ( doDNSResolve ) {
223  // try to remove the port first, otherwise the DNS gets confused into multiple timeouts
224  // failed or not failed, buf is expected to contain the appropriate host to resolve
225  if ( Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
226  ((struct sockaddr_in *)sadr)->sin_port = htons( port );
227  }
228  h = gethostbyname( buf );
229  if ( h == 0 ) {
230  return false;
231  }
232  *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
233  }
234 
235  return true;
236 }
237 
238 /*
239 ====================
240 NET_IPSocket
241 ====================
242 */
243 int NET_IPSocket( const char *net_interface, int port, netadr_t *bound_to ) {
244  SOCKET newsocket;
245  struct sockaddr_in address;
246  unsigned long _true = 1;
247  int i = 1;
248  int err;
249 
250  if( net_interface ) {
251  common->DPrintf( "Opening IP socket: %s:%i\n", net_interface, port );
252  } else {
253  common->DPrintf( "Opening IP socket: localhost:%i\n", port );
254  }
255 
256  if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
257  err = WSAGetLastError();
258  if( err != WSAEAFNOSUPPORT ) {
259  common->Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
260  }
261  return 0;
262  }
263 
264  // make it non-blocking
265  if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
266  common->Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
267  return 0;
268  }
269 
270  // make it broadcast capable
271  if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
272  common->Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
273  return 0;
274  }
275 
276  if( !net_interface || !net_interface[0] || !idStr::Icmp( net_interface, "localhost" ) ) {
277  address.sin_addr.s_addr = INADDR_ANY;
278  }
279  else {
280  Net_StringToSockaddr( net_interface, (struct sockaddr *)&address, true );
281  }
282 
283  if( port == PORT_ANY ) {
284  address.sin_port = 0;
285  }
286  else {
287  address.sin_port = htons( (short)port );
288  }
289 
290  address.sin_family = AF_INET;
291 
292  if( bind( newsocket, (const struct sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) {
293  common->Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
294  closesocket( newsocket );
295  return 0;
296  }
297 
298  // if the port was PORT_ANY, we need to query again to know the real port we got bound to
299  // ( this used to be in idPort::InitForPort )
300  if ( bound_to ) {
301  int len = sizeof( address );
302  getsockname( newsocket, (sockaddr *)&address, &len );
303  Net_SockadrToNetadr( (sockaddr *)&address, bound_to );
304  }
305 
306  return newsocket;
307 }
308 
309 /*
310 ====================
311 NET_OpenSocks
312 ====================
313 */
314 void NET_OpenSocks( int port ) {
315  struct sockaddr_in address;
316  int err;
317  struct hostent *h;
318  int len;
319  bool rfc1929;
320  unsigned char buf[64];
321 
322  usingSocks = false;
323 
324  common->Printf( "Opening connection to SOCKS server.\n" );
325 
326  if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
327  err = WSAGetLastError();
328  common->Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
329  return;
330  }
331 
332  h = gethostbyname( net_socksServer.GetString() );
333  if ( h == NULL ) {
334  err = WSAGetLastError();
335  common->Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
336  return;
337  }
338  if ( h->h_addrtype != AF_INET ) {
339  common->Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
340  return;
341  }
342  address.sin_family = AF_INET;
343  address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
344  address.sin_port = htons( (short)net_socksPort.GetInteger() );
345 
346  if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
347  err = WSAGetLastError();
348  common->Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
349  return;
350  }
351 
352  // send socks authentication handshake
354  rfc1929 = true;
355  }
356  else {
357  rfc1929 = false;
358  }
359 
360  buf[0] = 5; // SOCKS version
361  // method count
362  if ( rfc1929 ) {
363  buf[1] = 2;
364  len = 4;
365  }
366  else {
367  buf[1] = 1;
368  len = 3;
369  }
370  buf[2] = 0; // method #1 - method id #00: no authentication
371  if ( rfc1929 ) {
372  buf[2] = 2; // method #2 - method id #02: username/password
373  }
374  if ( send( socks_socket, (const char *)buf, len, 0 ) == SOCKET_ERROR ) {
375  err = WSAGetLastError();
376  common->Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
377  return;
378  }
379 
380  // get the response
381  len = recv( socks_socket, (char *)buf, 64, 0 );
382  if ( len == SOCKET_ERROR ) {
383  err = WSAGetLastError();
384  common->Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
385  return;
386  }
387  if ( len != 2 || buf[0] != 5 ) {
388  common->Printf( "NET_OpenSocks: bad response\n" );
389  return;
390  }
391  switch( buf[1] ) {
392  case 0: // no authentication
393  break;
394  case 2: // username/password authentication
395  break;
396  default:
397  common->Printf( "NET_OpenSocks: request denied\n" );
398  return;
399  }
400 
401  // do username/password authentication if needed
402  if ( buf[1] == 2 ) {
403  int ulen;
404  int plen;
405 
406  // build the request
407  ulen = strlen( net_socksUsername.GetString() );
408  plen = strlen( net_socksPassword.GetString() );
409 
410  buf[0] = 1; // username/password authentication version
411  buf[1] = ulen;
412  if ( ulen ) {
413  memcpy( &buf[2], net_socksUsername.GetString(), ulen );
414  }
415  buf[2 + ulen] = plen;
416  if ( plen ) {
417  memcpy( &buf[3 + ulen], net_socksPassword.GetString(), plen );
418  }
419 
420  // send it
421  if ( send( socks_socket, (const char *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
422  err = WSAGetLastError();
423  common->Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
424  return;
425  }
426 
427  // get the response
428  len = recv( socks_socket, (char *)buf, 64, 0 );
429  if ( len == SOCKET_ERROR ) {
430  err = WSAGetLastError();
431  common->Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
432  return;
433  }
434  if ( len != 2 || buf[0] != 1 ) {
435  common->Printf( "NET_OpenSocks: bad response\n" );
436  return;
437  }
438  if ( buf[1] != 0 ) {
439  common->Printf( "NET_OpenSocks: authentication failed\n" );
440  return;
441  }
442  }
443 
444  // send the UDP associate request
445  buf[0] = 5; // SOCKS version
446  buf[1] = 3; // command: UDP associate
447  buf[2] = 0; // reserved
448  buf[3] = 1; // address type: IPV4
449  *(int *)&buf[4] = INADDR_ANY;
450  *(short *)&buf[8] = htons( (short)port ); // port
451  if ( send( socks_socket, (const char *)buf, 10, 0 ) == SOCKET_ERROR ) {
452  err = WSAGetLastError();
453  common->Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
454  return;
455  }
456 
457  // get the response
458  len = recv( socks_socket, (char *)buf, 64, 0 );
459  if( len == SOCKET_ERROR ) {
460  err = WSAGetLastError();
461  common->Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
462  return;
463  }
464  if( len < 2 || buf[0] != 5 ) {
465  common->Printf( "NET_OpenSocks: bad response\n" );
466  return;
467  }
468  // check completion code
469  if( buf[1] != 0 ) {
470  common->Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
471  return;
472  }
473  if( buf[3] != 1 ) {
474  common->Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
475  return;
476  }
477  ((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET;
478  ((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4];
479  ((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8];
480  memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 );
481 
482  usingSocks = true;
483 }
484 
485 /*
486 ==================
487 Net_WaitForUDPPacket
488 ==================
489 */
490 bool Net_WaitForUDPPacket( int netSocket, int timeout ) {
491  int ret;
492  fd_set set;
493  struct timeval tv;
494 
495  if ( !netSocket ) {
496  return false;
497  }
498 
499  if ( timeout <= 0 ) {
500  return true;
501  }
502 
503  FD_ZERO( &set );
504  FD_SET( netSocket, &set );
505 
506  tv.tv_sec = 0;
507  tv.tv_usec = timeout * 1000;
508 
509  ret = select( netSocket + 1, &set, NULL, NULL, &tv );
510 
511  if ( ret == -1 ) {
512  common->DPrintf( "Net_WaitForUPDPacket select(): %s\n", strerror( errno ) );
513  return false;
514  }
515 
516  // timeout with no data
517  if ( ret == 0 ) {
518  return false;
519  }
520 
521  return true;
522 }
523 
524 /*
525 ==================
526 Net_GetUDPPacket
527 ==================
528 */
529 bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) {
530  int ret;
531  struct sockaddr from;
532  int fromlen;
533  int err;
534 
535  if( !netSocket ) {
536  return false;
537  }
538 
539  fromlen = sizeof(from);
540  ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *)&from, &fromlen );
541  if ( ret == SOCKET_ERROR ) {
542  err = WSAGetLastError();
543 
544  if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
545  return false;
546  }
547  char buf[1024];
548  sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() );
549  OutputDebugString( buf );
550  return false;
551  }
552 
553  if ( netSocket == ip_socket ) {
554  memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 );
555  }
556 
557  if ( usingSocks && netSocket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
558  if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) {
559  return false;
560  }
561  net_from.type = NA_IP;
562  net_from.ip[0] = data[4];
563  net_from.ip[1] = data[5];
564  net_from.ip[2] = data[6];
565  net_from.ip[3] = data[7];
566  net_from.port = *(short *)&data[8];
567  memmove( data, &data[10], ret - 10 );
568  } else {
569  Net_SockadrToNetadr( &from, &net_from );
570  }
571 
572  if( ret == maxSize ) {
573  char buf[1024];
574  sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) );
575  OutputDebugString( buf );
576  return false;
577  }
578 
579  size = ret;
580 
581  return true;
582 }
583 
584 /*
585 ==================
586 Net_SendUDPPacket
587 ==================
588 */
589 void Net_SendUDPPacket( int netSocket, int length, const void *data, const netadr_t to ) {
590  int ret;
591  struct sockaddr addr;
592 
593  if( !netSocket ) {
594  return;
595  }
596 
597  Net_NetadrToSockadr( &to, &addr );
598 
599  if( usingSocks && to.type == NA_IP ) {
600  socksBuf[0] = 0; // reserved
601  socksBuf[1] = 0;
602  socksBuf[2] = 0; // fragment (not fragmented)
603  socksBuf[3] = 1; // address type: IPV4
604  *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
605  *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port;
606  memcpy( &socksBuf[10], data, length );
607  ret = sendto( netSocket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) );
608  } else {
609  ret = sendto( netSocket, (const char *)data, length, 0, &addr, sizeof(addr) );
610  }
611  if( ret == SOCKET_ERROR ) {
612  int err = WSAGetLastError();
613 
614  // wouldblock is silent
615  if( err == WSAEWOULDBLOCK ) {
616  return;
617  }
618 
619  // some PPP links do not allow broadcasts and return an error
620  if( ( err == WSAEADDRNOTAVAIL ) && ( to.type == NA_BROADCAST ) ) {
621  return;
622  }
623 
624  char buf[1024];
625  sprintf( buf, "Net_SendUDPPacket: %s\n", NET_ErrorString() );
626  OutputDebugString( buf );
627  }
628 }
629 
630 /*
631 ====================
632 Sys_InitNetworking
633 ====================
634 */
635 void Sys_InitNetworking( void ) {
636  int r;
637 
638  r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
639  if( r ) {
640  common->Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
641  return;
642  }
643 
644  winsockInitialized = true;
645  common->Printf( "Winsock Initialized\n" );
646 
647  PIP_ADAPTER_INFO pAdapterInfo;
648  PIP_ADAPTER_INFO pAdapter = NULL;
649  DWORD dwRetVal = 0;
650  PIP_ADDR_STRING pIPAddrString;
651  ULONG ulOutBufLen;
652  bool foundloopback;
653 
654  num_interfaces = 0;
655  foundloopback = false;
656 
657  pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof( IP_ADAPTER_INFO ) );
658  if( !pAdapterInfo ) {
659  common->FatalError( "Sys_InitNetworking: Couldn't malloc( %d )", sizeof( IP_ADAPTER_INFO ) );
660  }
661  ulOutBufLen = sizeof( IP_ADAPTER_INFO );
662 
663  // Make an initial call to GetAdaptersInfo to get
664  // the necessary size into the ulOutBufLen variable
665  if( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
666  free( pAdapterInfo );
667  pAdapterInfo = (IP_ADAPTER_INFO *)malloc( ulOutBufLen );
668  if( !pAdapterInfo ) {
669  common->FatalError( "Sys_InitNetworking: Couldn't malloc( %ld )", ulOutBufLen );
670  }
671  }
672 
673  if( ( dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) ) != NO_ERROR ) {
674  // happens if you have no network connection
675  common->Printf( "Sys_InitNetworking: GetAdaptersInfo failed (%ld).\n", dwRetVal );
676  } else {
677  pAdapter = pAdapterInfo;
678  while( pAdapter ) {
679  common->Printf( "Found interface: %s %s - ", pAdapter->AdapterName, pAdapter->Description );
680  pIPAddrString = &pAdapter->IpAddressList;
681  while( pIPAddrString ) {
682  unsigned long ip_a, ip_m;
683  if( !idStr::Icmp( "127.0.0.1", pIPAddrString->IpAddress.String ) ) {
684  foundloopback = true;
685  }
686  ip_a = ntohl( inet_addr( pIPAddrString->IpAddress.String ) );
687  ip_m = ntohl( inet_addr( pIPAddrString->IpMask.String ) );
688  //skip null netmasks
689  if( !ip_m ) {
690  common->Printf( "%s NULL netmask - skipped\n", pIPAddrString->IpAddress.String );
691  pIPAddrString = pIPAddrString->Next;
692  continue;
693  }
694  common->Printf( "%s/%s\n", pIPAddrString->IpAddress.String, pIPAddrString->IpMask.String );
695  netint[num_interfaces].ip = ip_a;
696  netint[num_interfaces].mask = ip_m;
697  num_interfaces++;
698  if( num_interfaces >= MAX_INTERFACES ) {
699  common->Printf( "Sys_InitNetworking: MAX_INTERFACES(%d) hit.\n", MAX_INTERFACES );
700  free( pAdapterInfo );
701  return;
702  }
703  pIPAddrString = pIPAddrString->Next;
704  }
705  pAdapter = pAdapter->Next;
706  }
707  }
708  // for some retarded reason, win32 doesn't count loopback as an adapter...
709  if( !foundloopback && num_interfaces < MAX_INTERFACES ) {
710  common->Printf( "Sys_InitNetworking: adding loopback interface\n" );
711  netint[num_interfaces].ip = ntohl( inet_addr( "127.0.0.1" ) );
712  netint[num_interfaces].mask = ntohl( inet_addr( "255.0.0.0" ) );
713  num_interfaces++;
714  }
715  free( pAdapterInfo );
716 }
717 
718 
719 /*
720 ====================
721 Sys_ShutdownNetworking
722 ====================
723 */
725  if ( !winsockInitialized ) {
726  return;
727  }
728  WSACleanup();
729  winsockInitialized = false;
730 }
731 
732 /*
733 =============
734 Sys_StringToNetAdr
735 =============
736 */
737 bool Sys_StringToNetAdr( const char *s, netadr_t *a, bool doDNSResolve ) {
738  struct sockaddr sadr;
739 
740  if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) {
741  return false;
742  }
743 
744  Net_SockadrToNetadr( &sadr, a );
745  return true;
746 }
747 
748 /*
749 =============
750 Sys_NetAdrToString
751 =============
752 */
753 const char *Sys_NetAdrToString( const netadr_t a ) {
754  static int index = 0;
755  static char buf[ 4 ][ 64 ]; // flip/flop
756  char *s;
757 
758  s = buf[index];
759  index = (index + 1) & 3;
760 
761  if ( a.type == NA_LOOPBACK ) {
762  if ( a.port ) {
763  idStr::snPrintf( s, 64, "localhost:%i", a.port );
764  } else {
765  idStr::snPrintf( s, 64, "localhost" );
766  }
767  } else if ( a.type == NA_IP ) {
768  idStr::snPrintf( s, 64, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port );
769  }
770  return s;
771 }
772 
773 /*
774 ==================
775 Sys_IsLANAddress
776 ==================
777 */
778 bool Sys_IsLANAddress( const netadr_t adr ) {
779 #if ID_NOLANADDRESS
780  common->Printf( "Sys_IsLANAddress: ID_NOLANADDRESS\n" );
781  return false;
782 #endif
783  if( adr.type == NA_LOOPBACK ) {
784  return true;
785  }
786 
787  if( adr.type != NA_IP ) {
788  return false;
789  }
790 
791  if( num_interfaces ) {
792  int i;
793  unsigned long *p_ip;
794  unsigned long ip;
795  p_ip = (unsigned long *)&adr.ip[0];
796  ip = ntohl( *p_ip );
797 
798  for( i=0; i < num_interfaces; i++ ) {
799  if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) {
800  return true;
801  }
802  }
803  }
804  return false;
805 }
806 
807 /*
808 ===================
809 Sys_CompareNetAdrBase
810 
811 Compares without the port
812 ===================
813 */
814 bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) {
815  if ( a.type != b.type ) {
816  return false;
817  }
818 
819  if ( a.type == NA_LOOPBACK ) {
820  return true;
821  }
822 
823  if ( a.type == NA_IP ) {
824  if ( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] ) {
825  return true;
826  }
827  return false;
828  }
829 
830  common->Printf( "Sys_CompareNetAdrBase: bad address type\n" );
831  return false;
832 }
833 
834 //=============================================================================
835 
836 
837 #define MAX_UDP_MSG_SIZE 1400
838 
839 typedef struct udpMsg_s {
842  int size;
843  int time;
844  struct udpMsg_s * next;
845 } udpMsg_t;
846 
847 class idUDPLag {
848 public:
849  idUDPLag( void );
850  ~idUDPLag( void );
851 
857 };
858 
861 }
862 
864  udpMsgAllocator.Shutdown();
865 }
866 
868 
869 /*
870 ==================
871 idPort::idPort
872 ==================
873 */
874 idPort::idPort() {
875  netSocket = 0;
876  memset( &bound_to, 0, sizeof( bound_to ) );
877 }
878 
879 /*
880 ==================
881 idPort::~idPort
882 ==================
883 */
884 idPort::~idPort() {
885  Close();
886 }
887 
888 /*
889 ==================
890 InitForPort
891 ==================
892 */
893 bool idPort::InitForPort( int portNumber ) {
894  int len = sizeof( struct sockaddr_in );
895 
896  netSocket = NET_IPSocket( net_ip.GetString(), portNumber, &bound_to );
897  if ( netSocket <= 0 ) {
898  netSocket = 0;
899  memset( &bound_to, 0, sizeof( bound_to ) );
900  return false;
901  }
902 
903 #if 0
904  if ( net_socksEnabled.GetBool() ) {
905  NET_OpenSocks( portNumber );
906  }
907 #endif
908 
909  udpPorts[ bound_to.port ] = new idUDPLag;
910 
911  return true;
912 }
913 
914 /*
915 ==================
916 idPort::Close
917 ==================
918 */
919 void idPort::Close() {
920  if ( netSocket ) {
921  if ( udpPorts[ bound_to.port ] ) {
922  delete udpPorts[ bound_to.port ];
923  udpPorts[ bound_to.port ] = NULL;
924  }
925  closesocket( netSocket );
926  netSocket = 0;
927  memset( &bound_to, 0, sizeof( bound_to ) );
928  }
929 }
930 
931 /*
932 ==================
933 idPort::GetPacket
934 ==================
935 */
936 bool idPort::GetPacket( netadr_t &from, void *data, int &size, int maxSize ) {
937  udpMsg_t *msg;
938  bool ret;
939 
940  while( 1 ) {
941 
942  ret = Net_GetUDPPacket( netSocket, from, (char *)data, size, maxSize );
943  if ( !ret ) {
944  break;
945  }
946 
947  if ( net_forceDrop.GetInteger() > 0 ) {
948  if ( rand() < net_forceDrop.GetInteger() * RAND_MAX / 100 ) {
949  continue;
950  }
951  }
952 
953  packetsRead++;
954  bytesRead += size;
955 
956  if ( net_forceLatency.GetInteger() > 0 ) {
957 
958  assert( size <= MAX_UDP_MSG_SIZE );
959  msg = udpPorts[ bound_to.port ]->udpMsgAllocator.Alloc();
960  memcpy( msg->data, data, size );
961  msg->size = size;
962  msg->address = from;
963  msg->time = Sys_Milliseconds();
964  msg->next = NULL;
965  if ( udpPorts[ bound_to.port ]->recieveLast ) {
966  udpPorts[ bound_to.port ]->recieveLast->next = msg;
967  } else {
968  udpPorts[ bound_to.port ]->recieveFirst = msg;
969  }
970  udpPorts[ bound_to.port ]->recieveLast = msg;
971  } else {
972  break;
973  }
974  }
975 
976  if ( net_forceLatency.GetInteger() > 0 || ( udpPorts[ bound_to.port] && udpPorts[ bound_to.port ]->recieveFirst ) ) {
977 
978  msg = udpPorts[ bound_to.port ]->recieveFirst;
979  if ( msg && msg->time <= Sys_Milliseconds() - net_forceLatency.GetInteger() ) {
980  memcpy( data, msg->data, msg->size );
981  size = msg->size;
982  from = msg->address;
983  udpPorts[ bound_to.port ]->recieveFirst = udpPorts[ bound_to.port ]->recieveFirst->next;
984  if ( !udpPorts[ bound_to.port ]->recieveFirst ) {
985  udpPorts[ bound_to.port ]->recieveLast = NULL;
986  }
987  udpPorts[ bound_to.port ]->udpMsgAllocator.Free( msg );
988  return true;
989  }
990  return false;
991 
992  } else {
993  return ret;
994  }
995 }
996 
997 /*
998 ==================
999 idPort::GetPacketBlocking
1000 ==================
1001 */
1002 bool idPort::GetPacketBlocking( netadr_t &from, void *data, int &size, int maxSize, int timeout ) {
1003 
1004  Net_WaitForUDPPacket( netSocket, timeout );
1005 
1006  if ( GetPacket( from, data, size, maxSize ) ) {
1007  return true;
1008  }
1009 
1010  return false;
1011 }
1012 
1013 /*
1014 ==================
1015 idPort::SendPacket
1016 ==================
1017 */
1018 void idPort::SendPacket( const netadr_t to, const void *data, int size ) {
1019  udpMsg_t *msg;
1020 
1021  if ( to.type == NA_BAD ) {
1022  common->Warning( "idPort::SendPacket: bad address type NA_BAD - ignored" );
1023  return;
1024  }
1025 
1026  packetsWritten++;
1027  bytesWritten += size;
1028 
1029  if ( net_forceDrop.GetInteger() > 0 ) {
1030  if ( rand() < net_forceDrop.GetInteger() * RAND_MAX / 100 ) {
1031  return;
1032  }
1033  }
1034 
1035  if ( net_forceLatency.GetInteger() > 0 || ( udpPorts[ bound_to.port ] && udpPorts[ bound_to.port ]->sendFirst ) ) {
1036 
1037  assert( size <= MAX_UDP_MSG_SIZE );
1038  msg = udpPorts[ bound_to.port ]->udpMsgAllocator.Alloc();
1039  memcpy( msg->data, data, size );
1040  msg->size = size;
1041  msg->address = to;
1042  msg->time = Sys_Milliseconds();
1043  msg->next = NULL;
1044  if ( udpPorts[ bound_to.port ]->sendLast ) {
1045  udpPorts[ bound_to.port ]->sendLast->next = msg;
1046  } else {
1047  udpPorts[ bound_to.port ]->sendFirst = msg;
1048  }
1049  udpPorts[ bound_to.port ]->sendLast = msg;
1050 
1051  for ( msg = udpPorts[ bound_to.port ]->sendFirst; msg && msg->time <= Sys_Milliseconds() - net_forceLatency.GetInteger(); msg = udpPorts[ bound_to.port ]->sendFirst ) {
1052  Net_SendUDPPacket( netSocket, msg->size, msg->data, msg->address );
1053  udpPorts[ bound_to.port ]->sendFirst = udpPorts[ bound_to.port ]->sendFirst->next;
1054  if ( !udpPorts[ bound_to.port ]->sendFirst ) {
1055  udpPorts[ bound_to.port ]->sendLast = NULL;
1056  }
1057  udpPorts[ bound_to.port ]->udpMsgAllocator.Free( msg );
1058  }
1059 
1060  } else {
1061  Net_SendUDPPacket( netSocket, size, data, to );
1062  }
1063 }
1064 
1065 
1066 //=============================================================================
1067 
1068 /*
1069 ==================
1070 idTCP::idTCP
1071 ==================
1072 */
1073 idTCP::idTCP() {
1074  fd = 0;
1075  memset( &address, 0, sizeof( address ) );
1076 }
1077 
1078 /*
1079 ==================
1080 idTCP::~idTCP
1081 ==================
1082 */
1083 idTCP::~idTCP() {
1084  Close();
1085 }
1086 
1087 /*
1088 ==================
1089 idTCP::Init
1090 ==================
1091 */
1092 bool idTCP::Init( const char *host, short port ) {
1093  unsigned long _true = 1;
1094  struct sockaddr sadr;
1095 
1096  if ( !Sys_StringToNetAdr( host, &address, true ) ) {
1097  common->Printf( "Couldn't resolve server name \"%s\"\n", host );
1098  return false;
1099  }
1100  address.type = NA_IP;
1101  if ( !address.port ) {
1102  address.port = port;
1103  }
1104  common->Printf( "\"%s\" resolved to %i.%i.%i.%i:%i\n", host,
1105  address.ip[0], address.ip[1], address.ip[2], address.ip[3], address.port );
1106  Net_NetadrToSockadr( &address, &sadr );
1107 
1108  if ( fd ) {
1109  common->Warning( "idTCP::Init: already initialized?" );
1110  }
1111 
1112  if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) {
1113  fd = 0;
1114  common->Printf( "ERROR: idTCP::Init: socket: %s\n", NET_ErrorString() );
1115  return false;
1116  }
1117 
1118  if ( connect( fd, &sadr, sizeof(sadr)) == SOCKET_ERROR ) {
1119  common->Printf( "ERROR: idTCP::Init: connect: %s\n", NET_ErrorString() );
1120  closesocket( fd );
1121  fd = 0;
1122  return false;
1123  }
1124 
1125  // make it non-blocking
1126  if( ioctlsocket( fd, FIONBIO, &_true ) == SOCKET_ERROR ) {
1127  common->Printf( "ERROR: idTCP::Init: ioctl FIONBIO: %s\n", NET_ErrorString() );
1128  closesocket( fd );
1129  fd = 0;
1130  return false;
1131  }
1132 
1133  common->DPrintf( "Opened TCP connection\n" );
1134  return true;
1135 }
1136 
1137 /*
1138 ==================
1139 idTCP::Close
1140 ==================
1141 */
1142 void idTCP::Close() {
1143  if ( fd ) {
1144  closesocket( fd );
1145  }
1146  fd = 0;
1147 }
1148 
1149 /*
1150 ==================
1151 idTCP::Read
1152 ==================
1153 */
1154 int idTCP::Read( void *data, int size ) {
1155  int nbytes;
1156 
1157  if ( !fd ) {
1158  common->Printf("idTCP::Read: not initialized\n");
1159  return -1;
1160  }
1161 
1162  if ( ( nbytes = recv( fd, (char *)data, size, 0 ) ) == SOCKET_ERROR ) {
1163  if ( WSAGetLastError() == WSAEWOULDBLOCK ) {
1164  return 0;
1165  }
1166  common->Printf( "ERROR: idTCP::Read: %s\n", NET_ErrorString() );
1167  Close();
1168  return -1;
1169  }
1170 
1171  // a successful read of 0 bytes indicates remote has closed the connection
1172  if ( nbytes == 0 ) {
1173  common->DPrintf( "idTCP::Read: read 0 bytes - assume connection closed\n" );
1174  return -1;
1175  }
1176 
1177  return nbytes;
1178 }
1179 
1180 /*
1181 ==================
1182 idTCP::Write
1183 ==================
1184 */
1185 int idTCP::Write( void *data, int size ) {
1186  int nbytes;
1187 
1188  if ( !fd ) {
1189  common->Printf("idTCP::Write: not initialized\n");
1190  return -1;
1191  }
1192 
1193  if ( ( nbytes = send( fd, (char *)data, size, 0 ) ) == SOCKET_ERROR ) {
1194  common->Printf( "ERROR: idTCP::Write: %s\n", NET_ErrorString() );
1195  Close();
1196  return -1;
1197  }
1198 
1199  return nbytes;
1200 }
#define MAX_UDP_MSG_SIZE
Definition: win_net.cpp:837
bool Init(const char *host, short port)
Definition: posix_net.cpp:634
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
Definition: Str.cpp:1465
int Write(void *data, int size)
Definition: posix_net.cpp:742
void Close()
Definition: posix_net.cpp:474
assert(prefInfo.fullscreenBtn)
unsigned char ip[4]
Definition: sys_public.h:406
netadrtype_t type
Definition: sys_public.h:405
GLenum GLint GLuint mask
Definition: glext.h:5864
idCVar net_socksEnabled("net_socksEnabled","0", CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_BOOL,"")
int NET_IPSocket(const char *net_interface, int port, netadr_t *bound_to)
Definition: win_net.cpp:243
idCVar net_port("net_port","0", CVAR_SYSTEM|CVAR_INTEGER,"local IP port number")
void Sys_ShutdownNetworking(void)
Definition: win_net.cpp:724
udpMsg_t * sendFirst
Definition: win_net.cpp:852
int num_interfaces
Definition: win_net.cpp:64
long tv_sec
Definition: timeval.h:37
byte data[MAX_UDP_MSG_SIZE]
Definition: win_net.cpp:840
idCVar net_socksPassword("net_socksPassword","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
DWORD
Definition: win_qgl.cpp:61
int Sys_Milliseconds(void)
unsigned short port
Definition: sys_public.h:407
idCVar net_ip("net_ip","localhost", CVAR_SYSTEM,"local IP address")
struct udpMsg_s * next
Definition: win_net.cpp:844
void Close()
Definition: posix_net.cpp:686
GLdouble s
Definition: glext.h:2935
GLuint src
Definition: glext.h:5390
net_interface netint[MAX_INTERFACES]
Definition: win_net.cpp:65
GLenum GLsizei len
Definition: glext.h:3472
int i
Definition: process.py:33
int Icmp(const char *text) const
Definition: Str.h:667
bool Net_WaitForUDPPacket(int netSocket, int timeout)
Definition: win_net.cpp:490
bool Net_GetUDPPacket(int netSocket, netadr_t &net_from, char *data, int &size, int maxSize)
Definition: win_net.cpp:529
bool GetPacket(netadr_t &from, void *data, int &size, int maxSize)
Definition: posix_net.cpp:487
int packetsRead
Definition: sys_public.h:427
int packetsWritten
Definition: sys_public.h:430
udpMsg_t * sendLast
Definition: win_net.cpp:853
idCVar net_socksServer("net_socksServer","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
long tv_usec
Definition: timeval.h:38
void SendPacket(const netadr_t to, const void *data, int size)
Definition: posix_net.cpp:572
int fd
Definition: sys_public.h:456
unsigned long mask
Definition: posix_net.cpp:56
GLuint index
Definition: glext.h:3476
int size
Definition: win_net.cpp:842
idCVar net_forceDrop("net_forceDrop","0", CVAR_SYSTEM|CVAR_INTEGER,"percentage packet loss")
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
#define select(args...)
Definition: amigaos.h:39
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
int GetInteger(void) const
Definition: CVarSystem.h:143
#define MAX_INTERFACES
Definition: win_net.cpp:63
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
#define PORT_ANY
Definition: sys_public.h:410
void Net_SockadrToNetadr(struct sockaddr *s, netadr_t *a)
Definition: win_net.cpp:154
idBlockAlloc< udpMsg_t, 64 > udpMsgAllocator
Definition: win_net.cpp:856
bool Sys_IsLANAddress(const netadr_t adr)
Definition: win_net.cpp:778
bool InitForPort(int portNumber)
Definition: posix_net.cpp:598
void Sys_InitNetworking(void)
Definition: win_net.cpp:635
int Read(void *data, int size)
Definition: posix_net.cpp:698
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
virtual void Printf(const char *fmt,...) id_attribute((format(printf
GLenum const GLvoid * addr
Definition: glext.h:5393
idUDPLag(void)
Definition: win_net.cpp:859
void Net_SendUDPPacket(int netSocket, int length, const void *data, const netadr_t to)
Definition: win_net.cpp:589
GLubyte GLubyte b
Definition: glext.h:4662
const char * GetString(void) const
Definition: CVarSystem.h:141
GLdouble GLdouble GLdouble r
Definition: glext.h:2951
static WindowRef ValidModeCallbackProc inCallback OSStatus err
bool GetBool(void) const
Definition: CVarSystem.h:142
virtual ~idPort()
Definition: posix_net.cpp:465
~idUDPLag(void)
Definition: win_net.cpp:863
udpMsg_t * recieveFirst
Definition: win_net.cpp:854
unsigned char byte
Definition: Lib.h:75
GLsizeiptr size
Definition: glext.h:3112
netadr_t bound_to
Definition: sys_public.h:434
void Net_NetadrToSockadr(const netadr_t *a, struct sockaddr *s)
Definition: win_net.cpp:133
void NET_OpenSocks(int port)
Definition: win_net.cpp:314
const char * Sys_NetAdrToString(const netadr_t a)
Definition: win_net.cpp:753
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
GLuint address
Definition: glext.h:5165
bool Sys_CompareNetAdrBase(const netadr_t a, const netadr_t b)
Definition: win_net.cpp:814
struct udpMsg_s udpMsg_t
bool Sys_StringToNetAdr(const char *s, netadr_t *a, bool doDNSResolve)
Definition: win_net.cpp:737
int bytesWritten
Definition: sys_public.h:431
idUDPLag * udpPorts[65536]
Definition: win_net.cpp:867
bool GetPacketBlocking(netadr_t &from, void *data, int &size, int maxSize, int timeout)
Definition: posix_net.cpp:520
idCVar net_socksUsername("net_socksUsername","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
char * NET_ErrorString(void)
Definition: win_net.cpp:75
virtual ~idTCP()
Definition: posix_net.cpp:625
virtual void DPrintf(const char *fmt,...) id_attribute((format(printf
GLfloat GLfloat p
Definition: glext.h:4674
udpMsg_t * recieveLast
Definition: win_net.cpp:855
int time
Definition: win_net.cpp:843
unsigned long ip
Definition: posix_net.cpp:55
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
ID_INLINE T Min(T x, T y)
Definition: Lib.h:159
int netSocket
Definition: sys_public.h:435
void OutputDebugString(const char *text)
Definition: macosx_sys.mm:243
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
idCVar net_forceLatency("net_forceLatency","0", CVAR_SYSTEM|CVAR_INTEGER,"milliseconds latency")
idCVar net_socksPort("net_socksPort","1080", CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_INTEGER,"")
netadr_t address
Definition: win_net.cpp:841
int bytesRead
Definition: sys_public.h:428