]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/sys/win32/win_net.cpp
hello world
[icculus/iodoom3.git] / neo / sys / win32 / win_net.cpp
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;
61 } net_interface;
62
63 #define                 MAX_INTERFACES  32
64 int                             num_interfaces = 0;
65 net_interface   netint[MAX_INTERFACES];
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
353         if ( *net_socksUsername.GetString() || *net_socksPassword.GetString() ) {
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 */
724 void Sys_ShutdownNetworking( void ) {
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 {
840         byte                            data[MAX_UDP_MSG_SIZE];
841         netadr_t                        address;
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
852         udpMsg_t *                      sendFirst;
853         udpMsg_t *                      sendLast;
854         udpMsg_t *                      recieveFirst;
855         udpMsg_t *                      recieveLast;
856         idBlockAlloc<udpMsg_t, 64> udpMsgAllocator;
857 };
858
859 idUDPLag::idUDPLag( void ) {
860         sendFirst = sendLast = recieveFirst = recieveLast = NULL;
861 }
862
863 idUDPLag::~idUDPLag( void ) {
864         udpMsgAllocator.Shutdown();
865 }
866
867 idUDPLag *udpPorts[65536];
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 }