diff options
Diffstat (limited to 'drivers/unix/ip_unix.cpp')
-rw-r--r-- | drivers/unix/ip_unix.cpp | 113 |
1 files changed, 74 insertions, 39 deletions
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 08a8c19583..fc0b3faccc 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,21 +30,28 @@ #if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#include <string.h> #ifdef WINDOWS_ENABLED - #ifdef WINRT_ENABLED #include <ws2tcpip.h> #include <winsock2.h> #include <windows.h> #include <stdio.h> - #else - #define WINVER 0x0600 - #include <ws2tcpip.h> - #include <winsock2.h> - #include <windows.h> - #include <stdio.h> - #include <iphlpapi.h> - #endif + #ifndef UWP_ENABLED + #if defined(__MINGW32__ ) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4) + // MinGW-w64 on Ubuntu 12.04 (our Travis build env) has bugs in this code where + // some includes are missing in dependencies of iphlpapi.h for WINVER >= 0x0600 (Vista). + // We don't use this Vista code for now, so working it around by disabling it. + // MinGW-w64 >= 4.0 seems to be better judging by its headers. + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 // Windows XP, disable Vista API + #include <iphlpapi.h> + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0600 // Reenable Vista API + #else + #include <iphlpapi.h> + #endif // MINGW hack + #endif #else #include <netdb.h> #ifdef ANDROID_ENABLED @@ -62,16 +69,50 @@ #endif #endif -IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { +static IP_Address _sockaddr2ip(struct sockaddr* p_addr) { - struct hostent *he; - if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info - ERR_PRINT("gethostbyname failed!"); - return IP_Address(); - } IP_Address ip; + if (p_addr->sa_family == AF_INET) { + struct sockaddr_in* addr = (struct sockaddr_in*)p_addr; + ip.set_ipv4((uint8_t *)&(addr->sin_addr)); + } else { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + ip.set_ipv6(addr6->sin6_addr.s6_addr); + }; + + return ip; +}; - ip.host= *((unsigned long*)he->h_addr); +IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, Type p_type) { + + struct addrinfo hints; + struct addrinfo* result; + + memset(&hints, 0, sizeof(struct addrinfo)); + if (p_type == TYPE_IPV4) { + hints.ai_family = AF_INET; + } else if (p_type == TYPE_IPV6) { + hints.ai_family = AF_INET6; + hints.ai_flags = 0; + } else { + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + }; + + int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); + if (s != 0) { + ERR_PRINT("getaddrinfo failed!"); + return IP_Address(); + }; + + if (result == NULL || result->ai_addr == NULL) { + ERR_PRINT("Invalid response from getaddrinfo"); + return IP_Address(); + }; + + IP_Address ip = _sockaddr2ip(result->ai_addr); + + freeaddrinfo(result); return ip; @@ -79,7 +120,7 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { #if defined(WINDOWS_ENABLED) -#if defined(WINRT_ENABLED) +#if defined(UWP_ENABLED) void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { @@ -90,10 +131,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { for (int i = 0; i < hostnames->Size; i++) { - if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 && hostnames->GetAt(i)->IPInformation != nullptr) { + if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 || hostnames->GetAt(i)->Type == HostNameType::Ipv6 && hostnames->GetAt(i)->IPInformation != nullptr) { r_addresses->push_back(IP_Address(String(hostnames->GetAt(i)->CanonicalName->Data()))); - } } @@ -108,7 +148,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { while (true) { addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size); - int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST | + int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, @@ -134,14 +174,20 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; while (address != NULL) { - char addr_chr[INET_ADDRSTRLEN]; - SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); - IP_Address ip; - ip.host= *((unsigned long*)&ipv4->sin_addr); + if (address->Address.lpSockaddr->sa_family == AF_INET) { + + SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); + + ip.set_ipv4((uint8_t *)&(ipv4->sin_addr)); + } else { // ipv6 + + SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr); + + ip.set_ipv6(ipv6->sin6_addr.s6_addr); + }; - //inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN); r_addresses->push_back(ip); @@ -167,20 +213,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) continue; - if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 - // is a valid IP4 Address - - IP_Address ip; - ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr); - r_addresses->push_back(ip); - }/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6 - // is a valid IP6 Address - tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } */ + IP_Address ip = _sockaddr2ip(ifa->ifa_addr); + r_addresses->push_back(ip); } if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); |