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 }