* Revert RakNetSocket2 implementation.

It breaks Windows XP compatibility by depending on inet_ntop. Please fix!
This commit is contained in:
iProgramInCpp 2024-01-22 19:02:38 +02:00
parent 047fd3120f
commit b24a230058
3 changed files with 79 additions and 202 deletions

View file

@ -74,7 +74,7 @@ RakNetSocket2* RakNetSocket2Allocator::AllocRNS2(void)
s2 = RakNet::OP_NEW<RNS2_WindowsStore8>(_FILE_AND_LINE_); s2 = RakNet::OP_NEW<RNS2_WindowsStore8>(_FILE_AND_LINE_);
s2->SetSocketType(RNS2T_WINDOWS_STORE_8); s2->SetSocketType(RNS2T_WINDOWS_STORE_8);

View file

@ -1,16 +1,11 @@
/* /*
* Original work: Copyright (c) 2014, Oculus VR, Inc. * Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved. * All rights reserved.
* *
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
*
* Modified work: Copyright (c) 2016-2020, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/ */
#include "EmptyHeader.h" #include "EmptyHeader.h"
@ -20,102 +15,87 @@
#ifndef RAKNETSOCKET2_BERKLEY_NATIVE_CLIENT_CPP #ifndef RAKNETSOCKET2_BERKLEY_NATIVE_CLIENT_CPP
#define RAKNETSOCKET2_BERKLEY_NATIVE_CLIENT_CPP #define RAKNETSOCKET2_BERKLEY_NATIVE_CLIENT_CPP
// Every platform except windows store 8 and native client supports Berkley sockets // Every platform except windows store 8 and native client supports Berkley sockets
#if !defined(WINDOWS_STORE_RT) #if !defined(WINDOWS_STORE_RT)
#include "Itoa.h" #include "Itoa.h"
#include "WSAStartupSingleton.h" // used for WSAStartupSingleton
#if (defined(__GNUC__) || defined(__GCCXML__)) && !defined(__WIN32__)
#include <netdb.h>
#endif
// Shared on most platforms, but excluded from the listed // Shared on most platforms, but excluded from the listed
// #low - maybe change to char (&ip)[65] - then we can also use sizeof again
void DomainNameToIP_Berkley_IPV4And6( const char *domainName, char ip[65] ) void DomainNameToIP_Berkley_IPV4And6(const char* domainName, char ip[65])
{ {
#if RAKNET_SUPPORT_IPV6==1 #if RAKNET_SUPPORT_IPV6==1
struct addrinfo hints, *res, *p; struct addrinfo hints, * res, * p;
int status; int status;
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
if ((status = getaddrinfo(domainName, nullptr, &hints, &res)) != 0) { if ((status = getaddrinfo(domainName, NULL, &hints, &res)) != 0) {
// #high - review/update callers - some unnecessarily initialize ip unnecessarily memset(ip, 0, sizeof(ip));
ip[0] = '\0';
return; return;
} }
p=res; p = res;
// for(p = res;p != nullptr; p = p->ai_next) { // for(p = res;p != NULL; p = p->ai_next) {
void *addr; void* addr;
// char *ipver; // char *ipver;
// get the pointer to the address itself, // get the pointer to the address itself,
// different fields in IPv4 and IPv6: // different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) if (p->ai_family == AF_INET)
{ {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; struct sockaddr_in* ipv4 = (struct sockaddr_in*)p->ai_addr;
addr = &(ipv4->sin_addr); addr = &(ipv4->sin_addr);
inet_ntop(AF_INET, &ipv4->sin_addr, ip, 65); strcpy(ip, inet_ntoa(ipv4->sin_addr));
} }
else else
{ {
// TODO - test // TODO - test
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)p->ai_addr;
addr = &(ipv6->sin6_addr); addr = &(ipv6->sin6_addr);
// inet_ntop function does not exist on windows // inet_ntop function does not exist on windows
// http://www.mail-archive.com/users@ipv6.org/msg02107.html // http://www.mail-archive.com/users@ipv6.org/msg02107.html
getnameinfo((struct sockaddr *)ipv6, sizeof(struct sockaddr_in6), ip, sizeof(ip), nullptr, 0, NI_NUMERICHOST); getnameinfo((struct sockaddr*)ipv6, sizeof(struct sockaddr_in6), ip, 1, NULL, 0, NI_NUMERICHOST);
} }
freeaddrinfo(res); // free the linked list freeaddrinfo(res); // free the linked list
// } // }
#else #else
(void) domainName; (void)domainName;
(void) ip; (void)ip;
#endif // #if RAKNET_SUPPORT_IPV6==1 #endif // #if RAKNET_SUPPORT_IPV6==1
} }
void DomainNameToIP_Berkley_IPV4( const char *domainName, char ip[65] ) void DomainNameToIP_Berkley_IPV4(const char* domainName, char ip[65])
{ {
static struct in_addr addr;
memset(&addr, 0, sizeof(in_addr));
// Use inet_addr instead? What is the difference? // Use inet_addr instead? What is the difference?
struct addrinfo *addressinfo = nullptr; struct hostent* phe = gethostbyname(domainName);
// needed for getaddrinfo
WSAStartupSingleton::AddRef(); if (phe == 0 || phe->h_addr_list[0] == 0)
int error = getaddrinfo(domainName, nullptr, nullptr, &addressinfo);
WSAStartupSingleton::Deref();
if ( error != 0 || addressinfo == 0 )
{ {
//cerr << "Yow! Bad host lookup." << endl; //cerr << "Yow! Bad host lookup." << endl;
// #high - review/update callers - some unnecessarily initialize ip unnecessarily memset(ip, 0, 65 * sizeof(char));
ip[0] = '\0';
return; return;
} }
// get the (first) IPv4 address if (phe->h_addr_list[0] == 0)
while (addressinfo != nullptr) { {
if (addressinfo->ai_family == AF_INET) { memset(ip, 0, 65 * sizeof(char));
break; // found an IPv4 address
}
addressinfo = addressinfo->ai_next;
}
if (addressinfo == nullptr) {
return; return;
} }
struct sockaddr_in *sockaddr_ipv4 = (struct sockaddr_in *) addressinfo->ai_addr; memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr));
strcpy(ip, inet_ntoa(addr));
inet_ntop(AF_INET, &sockaddr_ipv4->sin_addr, ip, 65);
} }
void DomainNameToIP_Berkley( const char *domainName, char ip[65] ) void DomainNameToIP_Berkley(const char* domainName, char ip[65])
{ {
#if RAKNET_SUPPORT_IPV6==1 #if RAKNET_SUPPORT_IPV6==1
return DomainNameToIP_Berkley_IPV4And6(domainName, ip); return DomainNameToIP_Berkley_IPV4And6(domainName, ip);
@ -131,4 +111,4 @@ void DomainNameToIP_Berkley( const char *domainName, char ip[65] )
#endif // file header #endif // file header
#endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS

View file

@ -3,13 +3,12 @@
* All rights reserved. * All rights reserved.
* *
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
*/ */
#include "EmptyHeader.h" #include "EmptyHeader.h"
#include "../../compat/PlatformDefinitions.h"
#ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
@ -18,138 +17,47 @@
#if !defined(WINDOWS_STORE_RT) && !defined(__native_client__) #if !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
#if MC_TARGET_OS_IOS
// Lifed from SLikeNet because *just* iOS 6 was bitching and moaning 25% of the time
// iOS 6 SDK makes phones hate this for some reason
// gethostbyname didn't return NULL on iPhone 5 running iOS 6.1.4 on iOS 5 SDK,
// but did return NULL when running on the same hardware on iOS 6.1 SDK
#ifndef _WIN32
#include <sys/types.h> // used for getifaddrs()
#include <ifaddrs.h> // used for getifaddrs()
#endif // _WIN32
#include <string> // used for std::string
// based on https://stackoverflow.com/questions/212528/get-the-ip-address-of-the-machine#265978
void GetMyIP_Linux(SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS], const bool includeIPv6)
{
struct ifaddrs* pAddresses = nullptr;
// #med - add error check to getifaddrs()-call
getifaddrs(&pAddresses);
struct ifaddrs* pCurAdapter = pAddresses;
size_t outAddressIndex = 0;
while ((pCurAdapter != nullptr) && (outAddressIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS)) {
// skip interfaces which don't have any address assigned (according to the manual, this would only apply for BSD, but still we'd check for null here just in case)
if (pCurAdapter->ifa_addr != nullptr) {
// skip loopback adapters
if ((pCurAdapter->ifa_flags & IFF_LOOPBACK) == 0) {
if (pCurAdapter->ifa_addr->sa_family == AF_INET) {
const sockaddr_in* const curSocketAddress = reinterpret_cast<const sockaddr_in*>(pCurAdapter->ifa_addr);
char buffer[INET_ADDRSTRLEN] = { 0 };
// #med - add return value check
inet_ntop(AF_INET, &(curSocketAddress->sin_addr), buffer, INET_ADDRSTRLEN);
const std::string ipv4String(buffer);
// #med - review, is this really necessary?
// skip source only addresses (aka: 0.0.0.0/8 - see RFC1700 p.4)
if (ipv4String.find("0.") != 0) {
// store the adapter's address
addresses[outAddressIndex++].address.addr4 = *curSocketAddress;
}
}
#if RAKNET_SUPPORT_IPV6 == 1
else if (includeIPv6 && pCurAdapter->ifa_addr->sa_family == AF_INET6) {
const sockaddr_in6* const curSocketAddress = reinterpret_cast<const sockaddr_in6*>(pCurAdapter->ifa_addr);
char buffer[INET6_ADDRSTRLEN] = { 0 };
// #med - add return value check
inet_ntop(AF_INET6, &(curSocketAddress->sin6_addr), buffer, INET6_ADDRSTRLEN);
const std::string ipv6String(buffer);
// detect and skip non-external addresses
bool isLocal = false;
bool isSpecial = false;
if (ipv6String.find("fe") == 0) {
const char c = ipv6String[2];
if (c == '8' || c == '9' || c == 'a' || c == 'b') {
isLocal = true;
}
}
else if (ipv6String.find("2001:0:") == 0) {
isSpecial = true;
}
if (!(isLocal || isSpecial)) {
// store the adapter's address
addresses[outAddressIndex++].address.addr6 = *curSocketAddress;
}
}
#endif // RAKNET_SUPPORT_IPV6 == 1
// else skip the address (neither IPv4 nor IPv6 address)
}
}
pCurAdapter = pCurAdapter->ifa_next;
}
if (pAddresses != nullptr)
freeifaddrs(pAddresses);
while (outAddressIndex < MAXIMUM_NUMBER_OF_INTERNAL_IDS) {
addresses[outAddressIndex++] = UNASSIGNED_SYSTEM_ADDRESS;
}
}
#else // !MC_TARGET_OS_IOS
#if RAKNET_SUPPORT_IPV6==1 #if RAKNET_SUPPORT_IPV6==1
void PrepareAddrInfoHints2(addrinfo *hints) void PrepareAddrInfoHints2(addrinfo* hints)
{ {
memset(hints, 0, sizeof (addrinfo)); // make sure the struct is empty memset(hints, 0, sizeof(addrinfo)); // make sure the struct is empty
hints->ai_socktype = SOCK_DGRAM; // UDP sockets hints->ai_socktype = SOCK_DGRAM; // UDP sockets
hints->ai_flags = AI_PASSIVE; // fill in my IP for me hints->ai_flags = AI_PASSIVE; // fill in my IP for me
} }
void GetMyIP_Windows_Linux_IPV4And6( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) void GetMyIP_Windows_Linux_IPV4And6(SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS])
{ {
int idx=0; int idx = 0;
char ac[ 80 ]; char ac[80];
int err = gethostname( ac, sizeof( ac ) ); int err = gethostname(ac, sizeof(ac));
RakAssert(err != -1); RakAssert(err != -1);
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *servinfo=0, *aip; // will point to the results struct addrinfo* servinfo = 0, * aip; // will point to the results
PrepareAddrInfoHints2(&hints); PrepareAddrInfoHints2(&hints);
getaddrinfo(ac, "", &hints, &servinfo); getaddrinfo(ac, "", &hints, &servinfo);
for (idx=0, aip = servinfo; aip != NULL && idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; aip = aip->ai_next, idx++) for (idx = 0, aip = servinfo; aip != NULL && idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; aip = aip->ai_next, idx++)
{ {
if (aip->ai_family == AF_INET) if (aip->ai_family == AF_INET)
{ {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)aip->ai_addr; struct sockaddr_in* ipv4 = (struct sockaddr_in*)aip->ai_addr;
memcpy(&addresses[idx].address.addr4,ipv4,sizeof(sockaddr_in)); memcpy(&addresses[idx].address.addr4, ipv4, sizeof(sockaddr_in));
} }
else else
{ {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)aip->ai_addr; struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)aip->ai_addr;
memcpy(&addresses[idx].address.addr4,ipv6,sizeof(sockaddr_in6)); memcpy(&addresses[idx].address.addr4, ipv6, sizeof(sockaddr_in6));
} }
} }
freeaddrinfo(servinfo); // free the linked-list freeaddrinfo(servinfo); // free the linked-list
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS) while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{ {
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS; addresses[idx] = UNASSIGNED_SYSTEM_ADDRESS;
idx++; idx++;
} }
} }
@ -159,36 +67,35 @@ void GetMyIP_Windows_Linux_IPV4And6( SystemAddress addresses[MAXIMUM_NUMBER_OF_I
#if (defined(__GNUC__) || defined(__GCCXML__)) && !defined(__WIN32__) #if (defined(__GNUC__) || defined(__GCCXML__)) && !defined(__WIN32__)
#include <netdb.h> #include <netdb.h>
#endif #endif
void GetMyIP_Windows_Linux_IPV4( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) void GetMyIP_Windows_Linux_IPV4(SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS])
{ {
int idx=0; int idx = 0;
char ac[ 80 ]; char ac[80];
int err = gethostname( ac, sizeof( ac ) ); int err = gethostname(ac, sizeof(ac));
(void) err; (void)err;
RakAssert(err != -1); RakAssert(err != -1);
struct hostent *phe = gethostbyname( ac );
if ( phe == 0 ) struct hostent* phe = gethostbyname(ac);
if (phe == 0)
{ {
printf("gethostbyname hostname: %s, errno: %d\n", ac, h_errno); RakAssert(phe != 0);
RakAssert(phe!=0); return;
return ;
} }
for ( idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx ) for (idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx)
{ {
if (phe->h_addr_list[ idx ] == 0) if (phe->h_addr_list[idx] == 0)
break; break;
memcpy(&addresses[idx].address.addr4.sin_addr,phe->h_addr_list[ idx ],sizeof(struct in_addr)); memcpy(&addresses[idx].address.addr4.sin_addr, phe->h_addr_list[idx], sizeof(struct in_addr));
} }
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS) while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{ {
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS; addresses[idx] = UNASSIGNED_SYSTEM_ADDRESS;
idx++; idx++;
} }
@ -196,24 +103,14 @@ void GetMyIP_Windows_Linux_IPV4( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTER
#endif // RAKNET_SUPPORT_IPV6==1 #endif // RAKNET_SUPPORT_IPV6==1
#endif // MC_TARGET_OS_IOS
void GetMyIP_Windows_Linux(SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS])
void GetMyIP_Windows_Linux( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] )
{ {
#if RAKNET_SUPPORT_IPV6==1 #if RAKNET_SUPPORT_IPV6==1
#if MC_TARGET_OS_IOS GetMyIP_Windows_Linux_IPV4And6(addresses);
GetMyIP_Linux(addresses, true); #else
#else GetMyIP_Windows_Linux_IPV4(addresses);
GetMyIP_Windows_Linux_IPV4And6(addresses); #endif
#endif
#else
#if MC_TARGET_OS_IOS
GetMyIP_Linux(addresses, false);
#else
GetMyIP_Windows_Linux_IPV4(addresses);
#endif
#endif
} }
@ -221,4 +118,4 @@ void GetMyIP_Windows_Linux( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_I
#endif // file header #endif // file header
#endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS