DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

win_net.cpp (25510B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition 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 BFG Edition 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 #pragma hdrstop
     29 #include "../../idlib/precompiled.h"
     30 
     31 /*
     32 ================================================================================================
     33 Contains the NetworkSystem implementation specific to Win32.
     34 ================================================================================================
     35 */
     36 
     37 #include <iptypes.h>
     38 #include <iphlpapi.h>
     39 
     40 static WSADATA	winsockdata;
     41 static bool	winsockInitialized = false;
     42 static bool usingSocks = false;
     43 
     44 //lint -e569	ioctl macros trigger this
     45 
     46 // force these libs to be included, so users of idLib don't need to add them to every project
     47 #pragma comment(lib, "iphlpapi.lib" )
     48 #pragma comment(lib, "wsock32.lib" )
     49 
     50 
     51 /*
     52 ================================================================================================
     53 
     54 	Network CVars
     55 
     56 ================================================================================================
     57 */
     58 
     59 idCVar net_socksServer( "net_socksServer", "", CVAR_ARCHIVE, "" );
     60 idCVar net_socksPort( "net_socksPort", "1080", CVAR_ARCHIVE | CVAR_INTEGER, "" );
     61 idCVar net_socksUsername( "net_socksUsername", "", CVAR_ARCHIVE, "" );
     62 idCVar net_socksPassword( "net_socksPassword", "", CVAR_ARCHIVE, "" );
     63 
     64 idCVar net_ip( "net_ip", "localhost", 0, "local IP address" );
     65 
     66 static struct sockaddr_in	socksRelayAddr;
     67 
     68 static SOCKET	ip_socket;
     69 static SOCKET	socks_socket;
     70 static char		socksBuf[4096];
     71 
     72 typedef struct {
     73 	unsigned long ip;
     74 	unsigned long mask;
     75 	char addr[16];
     76 } net_interface;
     77 
     78 #define 		MAX_INTERFACES	32
     79 int				num_interfaces = 0;
     80 net_interface	netint[MAX_INTERFACES];
     81 
     82 /*
     83 ================================================================================================
     84 
     85 	Free Functions
     86 
     87 ================================================================================================
     88 */
     89 
     90 /*
     91 ========================
     92 NET_ErrorString
     93 ========================
     94 */
     95 char *NET_ErrorString() {
     96 	int		code;
     97 
     98 	code = WSAGetLastError();
     99 	switch( code ) {
    100 	case WSAEINTR: return "WSAEINTR";
    101 	case WSAEBADF: return "WSAEBADF";
    102 	case WSAEACCES: return "WSAEACCES";
    103 	case WSAEDISCON: return "WSAEDISCON";
    104 	case WSAEFAULT: return "WSAEFAULT";
    105 	case WSAEINVAL: return "WSAEINVAL";
    106 	case WSAEMFILE: return "WSAEMFILE";
    107 	case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
    108 	case WSAEINPROGRESS: return "WSAEINPROGRESS";
    109 	case WSAEALREADY: return "WSAEALREADY";
    110 	case WSAENOTSOCK: return "WSAENOTSOCK";
    111 	case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
    112 	case WSAEMSGSIZE: return "WSAEMSGSIZE";
    113 	case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
    114 	case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
    115 	case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
    116 	case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
    117 	case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
    118 	case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
    119 	case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
    120 	case WSAEADDRINUSE: return "WSAEADDRINUSE";
    121 	case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
    122 	case WSAENETDOWN: return "WSAENETDOWN";
    123 	case WSAENETUNREACH: return "WSAENETUNREACH";
    124 	case WSAENETRESET: return "WSAENETRESET";
    125 	case WSAECONNABORTED: return "WSAECONNABORTED";
    126 	case WSAECONNRESET: return "WSAECONNRESET";
    127 	case WSAENOBUFS: return "WSAENOBUFS";
    128 	case WSAEISCONN: return "WSAEISCONN";
    129 	case WSAENOTCONN: return "WSAENOTCONN";
    130 	case WSAESHUTDOWN: return "WSAESHUTDOWN";
    131 	case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
    132 	case WSAETIMEDOUT: return "WSAETIMEDOUT";
    133 	case WSAECONNREFUSED: return "WSAECONNREFUSED";
    134 	case WSAELOOP: return "WSAELOOP";
    135 	case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
    136 	case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
    137 	case WSASYSNOTREADY: return "WSASYSNOTREADY";
    138 	case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
    139 	case WSANOTINITIALISED: return "WSANOTINITIALISED";
    140 	case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
    141 	case WSATRY_AGAIN: return "WSATRY_AGAIN";
    142 	case WSANO_RECOVERY: return "WSANO_RECOVERY";
    143 	case WSANO_DATA: return "WSANO_DATA";
    144 	default: return "NO ERROR";
    145 	}
    146 }
    147 
    148 /*
    149 ========================
    150 Net_NetadrToSockadr
    151 ========================
    152 */
    153 void Net_NetadrToSockadr( const netadr_t *a, sockaddr_in *s ) {
    154 	memset( s, 0, sizeof(*s) );
    155 
    156 	if ( a->type == NA_BROADCAST ) {
    157 		s->sin_family = AF_INET;
    158 		s->sin_addr.s_addr = INADDR_BROADCAST;
    159 	} else if ( a->type == NA_IP || a->type == NA_LOOPBACK ) {
    160 		s->sin_family = AF_INET;
    161 		s->sin_addr.s_addr = *(int *)a->ip;
    162 	}
    163 
    164 	s->sin_port = htons( (short)a->port );
    165 }
    166 
    167 /*
    168 ========================
    169 Net_SockadrToNetadr
    170 ========================
    171 */
    172 void Net_SockadrToNetadr( sockaddr_in *s, netadr_t *a ) {
    173 	unsigned int ip;
    174 	if ( s->sin_family == AF_INET ) {
    175 		ip = s->sin_addr.s_addr;
    176 		*(unsigned int *)a->ip = ip;
    177 		a->port = htons( s->sin_port );
    178 		// we store in network order, that loopback test is host order..
    179 		ip = ntohl( ip );
    180 		if ( ip == INADDR_LOOPBACK ) {
    181 			a->type = NA_LOOPBACK;
    182 		} else {
    183 			a->type = NA_IP;
    184 		}
    185 	}
    186 }
    187 
    188 /*
    189 ========================
    190 Net_ExtractPort
    191 ========================
    192 */
    193 static bool Net_ExtractPort( const char *src, char *buf, int bufsize, int *port ) {
    194 	char *p;
    195 	strncpy( buf, src, bufsize );
    196 	p = buf; p += Min( bufsize - 1, idStr::Length( src ) ); *p = '\0';
    197 	p = strchr( buf, ':' );
    198 	if ( !p ) {
    199 		return false;
    200 	}
    201 	*p = '\0';
    202 	*port = strtol( p+1, NULL, 10 );
    203 	if ( errno == ERANGE ) {
    204 		return false;
    205 	}
    206 	return true;
    207 }
    208 
    209 /*
    210 ========================
    211 Net_StringToSockaddr
    212 ========================
    213 */
    214 static bool Net_StringToSockaddr( const char *s, sockaddr_in *sadr, bool doDNSResolve ) {
    215 	struct hostent	*h;
    216 	char buf[256];
    217 	int port;
    218 	
    219 	memset( sadr, 0, sizeof( *sadr ) );
    220 
    221 	sadr->sin_family = AF_INET;
    222 	sadr->sin_port = 0;
    223 
    224 	if( s[0] >= '0' && s[0] <= '9' ) {
    225 		unsigned long ret = inet_addr(s);
    226 		if ( ret != INADDR_NONE ) {
    227 			*(int *)&sadr->sin_addr = ret;
    228 		} else {
    229 			// check for port
    230 			if ( !Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
    231 				return false;
    232 			}
    233 			ret = inet_addr( buf );
    234 			if ( ret == INADDR_NONE ) {
    235 				return false;
    236 			}
    237 			*(int *)&sadr->sin_addr = ret;
    238 			sadr->sin_port = htons( port );
    239 		}
    240 	} else if ( doDNSResolve ) {
    241 		// try to remove the port first, otherwise the DNS gets confused into multiple timeouts
    242 		// failed or not failed, buf is expected to contain the appropriate host to resolve
    243 		if ( Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
    244 			sadr->sin_port = htons( port );			
    245 		}
    246 		h = gethostbyname( buf );
    247 		if ( h == 0 ) {
    248 			return false;
    249 		}
    250 		*(int *)&sadr->sin_addr = *(int *)h->h_addr_list[0];
    251 	}
    252 	
    253 	return true;
    254 }
    255 
    256 /*
    257 ========================
    258 NET_IPSocket
    259 ========================
    260 */
    261 int NET_IPSocket( const char *net_interface, int port, netadr_t *bound_to ) {
    262 	SOCKET				newsocket;
    263 	sockaddr_in			address;
    264 	unsigned long		_true = 1;
    265 	int					i = 1;
    266 	int					err;
    267 
    268 	if ( port != PORT_ANY ) {
    269 		if( net_interface ) {
    270 			idLib::Printf( "Opening IP socket: %s:%i\n", net_interface, port );
    271 		} else {
    272 			idLib::Printf( "Opening IP socket: localhost:%i\n", port );
    273 		}
    274 	}
    275 
    276 	if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
    277 		err = WSAGetLastError();
    278 		if( err != WSAEAFNOSUPPORT ) {
    279 			idLib::Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
    280 		}
    281 		return 0;
    282 	}
    283 
    284 	// make it non-blocking
    285 	if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
    286 		idLib::Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
    287 		closesocket( newsocket );
    288 		return 0;
    289 	}
    290 
    291 	// make it broadcast capable
    292 	if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
    293 		idLib::Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
    294 		closesocket( newsocket );
    295 		return 0;
    296 	}
    297 
    298 	if( !net_interface || !net_interface[0] || !idStr::Icmp( net_interface, "localhost" ) ) {
    299 		address.sin_addr.s_addr = INADDR_ANY;
    300 	}
    301 	else {
    302 		Net_StringToSockaddr( net_interface, &address, true );
    303 	}
    304 
    305 	if( port == PORT_ANY ) {
    306 		address.sin_port = 0;
    307 	}
    308 	else {
    309 		address.sin_port = htons( (short)port );
    310 	}
    311 
    312 	address.sin_family = AF_INET;
    313 
    314 	if( bind( newsocket, (const sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) {
    315 		idLib::Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
    316 		closesocket( newsocket );
    317 		return 0;
    318 	}
    319 
    320 	// if the port was PORT_ANY, we need to query again to know the real port we got bound to
    321 	// ( this used to be in idUDP::InitForPort )
    322 	if ( bound_to ) {
    323 		int len = sizeof( address );
    324 		getsockname( newsocket, (sockaddr *)&address, &len );
    325 		Net_SockadrToNetadr( &address, bound_to );
    326 	}
    327 
    328 	return newsocket;
    329 }
    330 
    331 /*
    332 ========================
    333 NET_OpenSocks
    334 ========================
    335 */
    336 void NET_OpenSocks( int port ) {
    337 	sockaddr_in			address;
    338 	struct hostent		*h;
    339 	int					len;
    340 	bool				rfc1929;
    341 	unsigned char		buf[64];
    342 
    343 	usingSocks = false;
    344 
    345 	idLib::Printf( "Opening connection to SOCKS server.\n" );
    346 
    347 	if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
    348 		idLib::Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
    349 		return;
    350 	}
    351 
    352 	h = gethostbyname( net_socksServer.GetString() );
    353 	if ( h == NULL ) {
    354 		idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
    355 		return;
    356 	}
    357 	if ( h->h_addrtype != AF_INET ) {
    358 		idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
    359 		return;
    360 	}
    361 	address.sin_family = AF_INET;
    362 	address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
    363 	address.sin_port = htons( (short)net_socksPort.GetInteger() );
    364 
    365 	if ( connect( socks_socket, (sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
    366 		idLib::Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
    367 		return;
    368 	}
    369 
    370 	// send socks authentication handshake
    371 	if ( *net_socksUsername.GetString() || *net_socksPassword.GetString() ) {
    372 		rfc1929 = true;
    373 	}
    374 	else {
    375 		rfc1929 = false;
    376 	}
    377 
    378 	buf[0] = 5;		// SOCKS version
    379 	// method count
    380 	if ( rfc1929 ) {
    381 		buf[1] = 2;
    382 		len = 4;
    383 	}
    384 	else {
    385 		buf[1] = 1;
    386 		len = 3;
    387 	}
    388 	buf[2] = 0;		// method #1 - method id #00: no authentication
    389 	if ( rfc1929 ) {
    390 		buf[2] = 2;		// method #2 - method id #02: username/password
    391 	}
    392 	if ( send( socks_socket, (const char *)buf, len, 0 ) == SOCKET_ERROR ) {
    393 		idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
    394 		return;
    395 	}
    396 
    397 	// get the response
    398 	len = recv( socks_socket, (char *)buf, 64, 0 );
    399 	if ( len == SOCKET_ERROR ) {
    400 		idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
    401 		return;
    402 	}
    403 	if ( len != 2 || buf[0] != 5 ) {
    404 		idLib::Printf( "NET_OpenSocks: bad response\n" );
    405 		return;
    406 	}
    407 	switch( buf[1] ) {
    408 	case 0:	// no authentication
    409 		break;
    410 	case 2: // username/password authentication
    411 		break;
    412 	default:
    413 		idLib::Printf( "NET_OpenSocks: request denied\n" );
    414 		return;
    415 	}
    416 
    417 	// do username/password authentication if needed
    418 	if ( buf[1] == 2 ) {
    419 		int		ulen;
    420 		int		plen;
    421 
    422 		// build the request
    423 		ulen = idStr::Length( net_socksUsername.GetString() );
    424 		plen = idStr::Length( net_socksPassword.GetString() );
    425 
    426 		buf[0] = 1;		// username/password authentication version
    427 		buf[1] = ulen;
    428 		if ( ulen ) {
    429 			memcpy( &buf[2], net_socksUsername.GetString(), ulen );
    430 		}
    431 		buf[2 + ulen] = plen;
    432 		if ( plen ) {
    433 			memcpy( &buf[3 + ulen], net_socksPassword.GetString(), plen );
    434 		}
    435 
    436 		// send it
    437 		if ( send( socks_socket, (const char *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
    438 			idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
    439 			return;
    440 		}
    441 
    442 		// get the response
    443 		len = recv( socks_socket, (char *)buf, 64, 0 );
    444 		if ( len == SOCKET_ERROR ) {
    445 			idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
    446 			return;
    447 		}
    448 		if ( len != 2 || buf[0] != 1 ) {
    449 			idLib::Printf( "NET_OpenSocks: bad response\n" );
    450 			return;
    451 		}
    452 		if ( buf[1] != 0 ) {
    453 			idLib::Printf( "NET_OpenSocks: authentication failed\n" );
    454 			return;
    455 		}
    456 	}
    457 
    458 	// send the UDP associate request
    459 	buf[0] = 5;		// SOCKS version
    460 	buf[1] = 3;		// command: UDP associate
    461 	buf[2] = 0;		// reserved
    462 	buf[3] = 1;		// address type: IPV4
    463 	*(int *)&buf[4] = INADDR_ANY;
    464 	*(short *)&buf[8] = htons( (short)port );		// port
    465 	if ( send( socks_socket, (const char *)buf, 10, 0 ) == SOCKET_ERROR ) {
    466 		idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
    467 		return;
    468 	}
    469 
    470 	// get the response
    471 	len = recv( socks_socket, (char *)buf, 64, 0 );
    472 	if( len == SOCKET_ERROR ) {
    473 		idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
    474 		return;
    475 	}
    476 	if( len < 2 || buf[0] != 5 ) {
    477 		idLib::Printf( "NET_OpenSocks: bad response\n" );
    478 		return;
    479 	}
    480 	// check completion code
    481 	if( buf[1] != 0 ) {
    482 		idLib::Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
    483 		return;
    484 	}
    485 	if( buf[3] != 1 ) {
    486 		idLib::Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
    487 		return;
    488 	}
    489 	socksRelayAddr.sin_family = AF_INET;
    490 	socksRelayAddr.sin_addr.s_addr = *(int *)&buf[4];
    491 	socksRelayAddr.sin_port = *(short *)&buf[8];
    492 	memset( socksRelayAddr.sin_zero, 0, sizeof( socksRelayAddr.sin_zero ) );
    493 
    494 	usingSocks = true;
    495 }
    496 
    497 /*
    498 ========================
    499 Net_WaitForData
    500 ========================
    501 */
    502 bool Net_WaitForData( int netSocket, int timeout ) {
    503 	int					ret;
    504 	fd_set				set;
    505 	struct timeval		tv;
    506 
    507 	if ( !netSocket ) {
    508 		return false;
    509 	}
    510 
    511 	if ( timeout < 0 ) {
    512 		return true;
    513 	}
    514 
    515 	FD_ZERO( &set );
    516 	FD_SET( static_cast<unsigned int>( netSocket ), &set );
    517 
    518 	tv.tv_sec = 0;
    519 	tv.tv_usec = timeout * 1000;
    520 
    521 	ret = select( netSocket + 1, &set, NULL, NULL, &tv );
    522 
    523 	if ( ret == -1 ) {
    524 		idLib::Printf( "Net_WaitForData select(): %s\n", strerror( errno ) );
    525 		return false;
    526 	}
    527 
    528 	// timeout with no data
    529 	if ( ret == 0 ) {
    530 		return false;
    531 	}
    532 
    533 	return true;
    534 }
    535 
    536 /*
    537 ========================
    538 Net_GetUDPPacket
    539 ========================
    540 */
    541 bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) {
    542 	int 			ret;
    543 	sockaddr_in		from;
    544 	int				fromlen;
    545 	int				err;
    546 
    547 	if ( !netSocket ) {
    548 		return false;
    549 	}
    550 
    551 	fromlen = sizeof(from);
    552 	ret = recvfrom( netSocket, data, maxSize, 0, (sockaddr *)&from, &fromlen );
    553 	if ( ret == SOCKET_ERROR ) {
    554 		err = WSAGetLastError();
    555 
    556 		if ( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
    557 			return false;
    558 		}
    559 		char	buf[1024];
    560 		sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() );
    561 		idLib::Printf( buf );
    562 		return false;
    563 	}
    564 
    565 	if ( static_cast<unsigned int>( netSocket ) == ip_socket ) {
    566 		memset( from.sin_zero, 0, sizeof( from.sin_zero ) );
    567 	}
    568 
    569 	if ( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
    570 		if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) {
    571 			return false;
    572 		}
    573 		net_from.type = NA_IP;
    574 		net_from.ip[0] = data[4];
    575 		net_from.ip[1] = data[5];
    576 		net_from.ip[2] = data[6];
    577 		net_from.ip[3] = data[7];
    578 		net_from.port = *(short *)&data[8];
    579 		memmove( data, &data[10], ret - 10 );
    580 	} else {
    581 		Net_SockadrToNetadr( &from, &net_from );
    582 	}
    583 
    584 	if ( ret > maxSize ) {
    585 		char	buf[1024];
    586 		sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) );
    587 		idLib::Printf( buf );
    588 		return false;
    589 	}
    590 
    591 	size = ret;
    592 
    593 	return true;
    594 }
    595 
    596 /*
    597 ========================
    598 Net_SendUDPPacket
    599 ========================
    600 */
    601 void Net_SendUDPPacket( int netSocket, int length, const void *data, const netadr_t to ) {
    602 	int				ret;
    603 	sockaddr_in		addr;
    604 
    605 	if ( !netSocket ) {
    606 		return;
    607 	}
    608 
    609 	Net_NetadrToSockadr( &to, &addr );
    610 
    611 	if ( usingSocks && to.type == NA_IP ) {
    612 		socksBuf[0] = 0;	// reserved
    613 		socksBuf[1] = 0;
    614 		socksBuf[2] = 0;	// fragment (not fragmented)
    615 		socksBuf[3] = 1;	// address type: IPV4
    616 		*(int *)&socksBuf[4] = addr.sin_addr.s_addr;
    617 		*(short *)&socksBuf[8] = addr.sin_port;
    618 		memcpy( &socksBuf[10], data, length );
    619 		ret = sendto( netSocket, socksBuf, length+10, 0, (sockaddr *)&socksRelayAddr, sizeof(socksRelayAddr) );
    620 	} else {
    621 		ret = sendto( netSocket, (const char *)data, length, 0, (sockaddr *)&addr, sizeof(addr) );
    622 	}
    623 	if ( ret == SOCKET_ERROR ) {
    624 		int err = WSAGetLastError();
    625 
    626 		// some PPP links do not allow broadcasts and return an error
    627 		if ( ( err == WSAEADDRNOTAVAIL ) && ( to.type == NA_BROADCAST ) ) {
    628 			return;
    629 		}
    630 
    631 		// NOTE: WSAEWOULDBLOCK used to be silently ignored,
    632 		// but that means the packet will be dropped so I don't feel it's a good thing to ignore
    633 		idLib::Printf( "UDP sendto error - packet dropped: %s\n", NET_ErrorString() );
    634 	}
    635 }
    636 
    637 /*
    638 ========================
    639 Sys_InitNetworking
    640 ========================
    641 */
    642 void Sys_InitNetworking() {
    643 	int		r;
    644 
    645 	if ( winsockInitialized ) {
    646 		return;
    647 	}
    648 	r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
    649 	if( r ) {
    650 		idLib::Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
    651 		return;
    652 	}
    653 
    654 	winsockInitialized = true;
    655 	idLib::Printf( "Winsock Initialized\n" );
    656 
    657 	PIP_ADAPTER_INFO pAdapterInfo;
    658 	PIP_ADAPTER_INFO pAdapter = NULL;
    659 	DWORD dwRetVal = 0;
    660 	PIP_ADDR_STRING pIPAddrString;
    661 	ULONG ulOutBufLen;
    662 	bool foundloopback;
    663 
    664 	num_interfaces = 0;
    665 	foundloopback = false;
    666 
    667 	pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof( IP_ADAPTER_INFO ) );
    668 	if( !pAdapterInfo ) {
    669 		idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %d )", sizeof( IP_ADAPTER_INFO ) );
    670 	}
    671 	ulOutBufLen = sizeof( IP_ADAPTER_INFO );
    672 
    673 	// Make an initial call to GetAdaptersInfo to get
    674 	// the necessary size into the ulOutBufLen variable
    675 	if( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
    676 		free( pAdapterInfo );
    677 		pAdapterInfo = (IP_ADAPTER_INFO *)malloc( ulOutBufLen ); 
    678 		if( !pAdapterInfo ) {
    679 			idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %ld )", ulOutBufLen );
    680 		}
    681 	}
    682 
    683 	if( ( dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) ) != NO_ERROR ) {
    684 		// happens if you have no network connection
    685 		idLib::Printf( "Sys_InitNetworking: GetAdaptersInfo failed (%ld).\n", dwRetVal );
    686 	} else {
    687 		pAdapter = pAdapterInfo;
    688 		while( pAdapter ) {
    689 			idLib::Printf( "Found interface: %s %s - ", pAdapter->AdapterName, pAdapter->Description );
    690 			pIPAddrString = &pAdapter->IpAddressList;
    691 			while( pIPAddrString ) {
    692 				unsigned long ip_a, ip_m;
    693 				if( !idStr::Icmp( "127.0.0.1", pIPAddrString->IpAddress.String ) ) {
    694 					foundloopback = true;
    695 				}
    696 				ip_a = ntohl( inet_addr( pIPAddrString->IpAddress.String ) );
    697 				ip_m = ntohl( inet_addr( pIPAddrString->IpMask.String ) );
    698 				//skip null netmasks
    699 				if( !ip_m ) {
    700 					idLib::Printf( "%s NULL netmask - skipped\n", pIPAddrString->IpAddress.String );
    701 					pIPAddrString = pIPAddrString->Next;
    702 					continue;
    703 				}
    704 				idLib::Printf( "%s/%s\n", pIPAddrString->IpAddress.String, pIPAddrString->IpMask.String );
    705 				netint[num_interfaces].ip = ip_a;
    706 				netint[num_interfaces].mask = ip_m;
    707 				idStr::Copynz( netint[num_interfaces].addr, pIPAddrString->IpAddress.String, sizeof( netint[num_interfaces].addr ) );
    708 				num_interfaces++;
    709 				if( num_interfaces >= MAX_INTERFACES ) {
    710 					idLib::Printf( "Sys_InitNetworking: MAX_INTERFACES(%d) hit.\n", MAX_INTERFACES );
    711 					free( pAdapterInfo );
    712 					return;
    713 				}
    714 				pIPAddrString = pIPAddrString->Next;
    715 			}
    716 			pAdapter = pAdapter->Next;
    717 		}
    718 	}
    719 	// for some retarded reason, win32 doesn't count loopback as an adapter...
    720 	if( !foundloopback && num_interfaces < MAX_INTERFACES ) {
    721 		idLib::Printf( "Sys_InitNetworking: adding loopback interface\n" );
    722 		netint[num_interfaces].ip = ntohl( inet_addr( "127.0.0.1" ) );
    723 		netint[num_interfaces].mask = ntohl( inet_addr( "255.0.0.0" ) );
    724 		num_interfaces++;
    725 	}
    726 	free( pAdapterInfo );
    727 }
    728 
    729 /*
    730 ========================
    731 Sys_ShutdownNetworking
    732 ========================
    733 */
    734 void Sys_ShutdownNetworking() {
    735 	if ( !winsockInitialized ) {
    736 		return;
    737 	}
    738 	WSACleanup();
    739 	winsockInitialized = false;
    740 }
    741 
    742 /*
    743 ========================
    744 Sys_StringToNetAdr
    745 ========================
    746 */
    747 bool Sys_StringToNetAdr( const char *s, netadr_t *a, bool doDNSResolve ) {
    748 	sockaddr_in sadr;
    749 	
    750 	if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) {
    751 		return false;
    752 	}
    753 	
    754 	Net_SockadrToNetadr( &sadr, a );
    755 	return true;
    756 }
    757 
    758 /*
    759 ========================
    760 Sys_NetAdrToString
    761 ========================
    762 */
    763 const char *Sys_NetAdrToString( const netadr_t a ) {
    764 	static int index = 0;
    765 	static char buf[ 4 ][ 64 ];	// flip/flop
    766 	char *s;
    767 
    768 	s = buf[index];
    769 	index = (index + 1) & 3;
    770 
    771 	if ( a.type == NA_LOOPBACK ) {
    772 		if ( a.port ) {
    773 			idStr::snPrintf( s, 64, "localhost:%i", a.port );
    774 		} else {
    775 			idStr::snPrintf( s, 64, "localhost" );
    776 		}
    777 	} else if ( a.type == NA_IP ) {
    778 		idStr::snPrintf( s, 64, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port );
    779 	}
    780 	return s;
    781 }
    782 
    783 /*
    784 ========================
    785 Sys_IsLANAddress
    786 ========================
    787 */
    788 bool Sys_IsLANAddress( const netadr_t adr ) {
    789 	if ( adr.type == NA_LOOPBACK ) {
    790 		return true;
    791 	}
    792 
    793 	if ( adr.type != NA_IP ) {
    794 		return false;
    795 	}
    796 
    797 	if ( num_interfaces ) {
    798 		int i;
    799 		unsigned long *p_ip;
    800 		unsigned long ip;
    801 		p_ip = (unsigned long *)&adr.ip[0];
    802 		ip = ntohl( *p_ip );
    803 
    804 		for( i = 0; i < num_interfaces; i++ ) {
    805 			if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) {
    806 				return true;
    807 			}
    808 		}
    809 	}
    810 	return false;
    811 }
    812 
    813 /*
    814 ========================
    815 Sys_CompareNetAdrBase
    816 
    817 Compares without the port.
    818 ========================
    819 */
    820 bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) {
    821 	if ( a.type != b.type ) {
    822 		return false;
    823 	}
    824 
    825 	if ( a.type == NA_LOOPBACK ) {
    826 		if ( a.port == b.port ) {
    827 			return true;
    828 		}
    829 
    830 		return false;
    831 	}
    832 
    833 	if ( a.type == NA_IP ) {
    834 		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] ) {
    835 			return true;
    836 		}
    837 		return false;
    838 	}
    839 
    840 	idLib::Printf( "Sys_CompareNetAdrBase: bad address type\n" );
    841 	return false;
    842 }
    843 
    844 /*
    845 ========================
    846 Sys_GetLocalIPCount
    847 ========================
    848 */
    849 int	Sys_GetLocalIPCount() {
    850 	return num_interfaces;
    851 }
    852 
    853 /*
    854 ========================
    855 Sys_GetLocalIP
    856 ========================
    857 */
    858 const char * Sys_GetLocalIP( int i ) {
    859 	if ( ( i < 0 ) || ( i >= num_interfaces ) ) {
    860 		return NULL;
    861 	}
    862 	return netint[i].addr;
    863 }
    864 
    865 /*
    866 ================================================================================================
    867 
    868 	idUDP
    869 
    870 ================================================================================================
    871 */
    872 
    873 /*
    874 ========================
    875 idUDP::idUDP
    876 ========================
    877 */
    878 idUDP::idUDP() {
    879 	netSocket = 0;
    880 	memset( &bound_to, 0, sizeof( bound_to ) );
    881 	silent = false;
    882 	packetsRead = 0;
    883 	bytesRead = 0;
    884 	packetsWritten = 0;
    885 	bytesWritten = 0;
    886 }
    887 
    888 /*
    889 ========================
    890 idUDP::~idUDP
    891 ========================
    892 */
    893 idUDP::~idUDP() {
    894 	Close();
    895 }
    896 
    897 /*
    898 ========================
    899 idUDP::InitForPort
    900 ========================
    901 */
    902 bool idUDP::InitForPort( int portNumber ) {
    903 	netSocket = NET_IPSocket( net_ip.GetString(), portNumber, &bound_to );
    904 	if ( netSocket <= 0 ) {
    905 		netSocket = 0;
    906 		memset( &bound_to, 0, sizeof( bound_to ) );
    907 		return false;
    908 	}
    909 
    910 	return true;
    911 }
    912 
    913 /*
    914 ========================
    915 idUDP::Close
    916 ========================
    917 */
    918 void idUDP::Close() {
    919 	if ( netSocket ) {
    920 		closesocket( netSocket );
    921 		netSocket = 0;
    922 		memset( &bound_to, 0, sizeof( bound_to ) );
    923 	}
    924 }
    925 
    926 /*
    927 ========================
    928 idUDP::GetPacket
    929 ========================
    930 */
    931 bool idUDP::GetPacket( netadr_t &from, void *data, int &size, int maxSize ) {
    932 	bool ret;
    933 
    934 	while ( 1 ) {
    935 
    936 		ret = Net_GetUDPPacket( netSocket, from, (char *)data, size, maxSize );
    937 		if ( !ret ) {
    938 			break;
    939 		}
    940 
    941 		packetsRead++;
    942 		bytesRead += size;
    943 
    944 		break;
    945 	}
    946 
    947 	return ret;
    948 }
    949 
    950 /*
    951 ========================
    952 idUDP::GetPacketBlocking
    953 ========================
    954 */
    955 bool idUDP::GetPacketBlocking( netadr_t &from, void *data, int &size, int maxSize, int timeout ) {
    956 
    957 	if ( !Net_WaitForData( netSocket, timeout ) ) {
    958 		return false;
    959 	}
    960 
    961 	if ( GetPacket( from, data, size, maxSize ) ) {
    962 		return true;
    963 	}
    964 
    965 	return false;
    966 }
    967 
    968 /*
    969 ========================
    970 idUDP::SendPacket
    971 ========================
    972 */
    973 void idUDP::SendPacket( const netadr_t to, const void *data, int size ) {
    974 	if ( to.type == NA_BAD ) {
    975 		idLib::Warning( "idUDP::SendPacket: bad address type NA_BAD - ignored" );
    976 		return;
    977 	}
    978 
    979 	packetsWritten++;
    980 	bytesWritten += size;
    981 
    982 	if ( silent ) {
    983 		return;
    984 	}
    985 
    986 	Net_SendUDPPacket( netSocket, size, data, to );
    987 }