mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-06-17 14:21:30 +00:00
Test each address returned in the getaddrinfo() call and stop blindly preferring IPv4
Fixes NAT64 on iOS 12 and probably other obscure configurations
This commit is contained in:
+1
-1
@@ -213,7 +213,7 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
|
|||||||
|
|
||||||
Limelog("Resolving host name...");
|
Limelog("Resolving host name...");
|
||||||
ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
|
ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
|
||||||
err = resolveHostName(serverInfo->address, &RemoteAddr, &RemoteAddrLen);
|
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47984, &RemoteAddr, &RemoteAddrLen);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
Limelog("failed: %d\n", err);
|
Limelog("failed: %d\n", err);
|
||||||
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
|
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
|
||||||
|
|||||||
+38
-26
@@ -1,6 +1,8 @@
|
|||||||
#include "PlatformSockets.h"
|
#include "PlatformSockets.h"
|
||||||
#include "Limelight-internal.h"
|
#include "Limelight-internal.h"
|
||||||
|
|
||||||
|
#define TEST_PORT_TIMEOUT_SEC 3
|
||||||
|
|
||||||
#define RCV_BUFFER_SIZE_MIN 32767
|
#define RCV_BUFFER_SIZE_MIN 32767
|
||||||
#define RCV_BUFFER_SIZE_STEP 16384
|
#define RCV_BUFFER_SIZE_STEP 16384
|
||||||
|
|
||||||
@@ -282,43 +284,53 @@ int enableNoDelay(SOCKET s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int resolveHostName(const char* host, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen)
|
int resolveHostName(const char* host, int family, int tcpTestPort, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen)
|
||||||
{
|
{
|
||||||
#ifndef __vita__
|
#ifndef __vita__
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res, *currentAddr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
// We must first try IPv4-only because GFE doesn't listen on IPv6,
|
|
||||||
// so we'll only want to use an IPv6 address if it's the only address we have.
|
|
||||||
// For NAT64 networks, the IPv4 address resolution will fail but the IPv6 address
|
|
||||||
// will give us working connectivity to the host. All other networks will use IPv4
|
|
||||||
// addresses.
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = family;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
err = getaddrinfo(host, NULL, &hints, &res);
|
err = getaddrinfo(host, NULL, &hints, &res);
|
||||||
if (err != 0 || res == NULL) {
|
if (err != 0) {
|
||||||
memset(&hints, 0, sizeof(hints));
|
Limelog("getaddrinfo(%s) failed: %d\n", host, err);
|
||||||
hints.ai_family = AF_UNSPEC;
|
return err;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
}
|
||||||
err = getaddrinfo(host, NULL, &hints, &res);
|
else if (res == NULL) {
|
||||||
if (err != 0) {
|
Limelog("getaddrinfo(%s) returned success without addresses\n", host);
|
||||||
Limelog("getaddrinfo() failed: %d\n", err);
|
return -1;
|
||||||
return err;
|
}
|
||||||
}
|
|
||||||
|
for (currentAddr = res; currentAddr != NULL; currentAddr = currentAddr->ai_next) {
|
||||||
if (res == NULL) {
|
// Use the test port to ensure this address is working
|
||||||
Limelog("getaddrinfo() returned success without addresses\n");
|
if (tcpTestPort != 0) {
|
||||||
return -1;
|
SOCKET testSocket = connectTcpSocket((struct sockaddr_storage*)currentAddr->ai_addr,
|
||||||
|
currentAddr->ai_addrlen,
|
||||||
|
tcpTestPort,
|
||||||
|
TEST_PORT_TIMEOUT_SEC);
|
||||||
|
if (testSocket == INVALID_SOCKET) {
|
||||||
|
// Try the next address
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
closeSocket(testSocket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(addr, currentAddr->ai_addr, currentAddr->ai_addrlen);
|
||||||
|
*addrLen = currentAddr->ai_addrlen;
|
||||||
|
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the first address in the list
|
Limelog("No working addresses found for host: %s\n", host);
|
||||||
memcpy(addr, res->ai_addr, res->ai_addrlen);
|
|
||||||
*addrLen = res->ai_addrlen;
|
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return 0;
|
return -1;
|
||||||
#else
|
#else
|
||||||
struct hostent *phost = gethostbyname(host);
|
struct hostent *phost = gethostbyname(host);
|
||||||
if (!phost) {
|
if (!phost) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ typedef socklen_t SOCKADDR_LEN;
|
|||||||
#define URLSAFESTRING_LEN (INET6_ADDRSTRLEN+2)
|
#define URLSAFESTRING_LEN (INET6_ADDRSTRLEN+2)
|
||||||
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
|
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
|
||||||
|
|
||||||
int resolveHostName(const char* host, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen);
|
int resolveHostName(const char* host, int family, int tcpTestPort, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen);
|
||||||
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
||||||
SOCKET bindUdpSocket(int addrfamily, int bufferSize);
|
SOCKET bindUdpSocket(int addrfamily, int bufferSize);
|
||||||
int enableNoDelay(SOCKET s);
|
int enableNoDelay(SOCKET s);
|
||||||
|
|||||||
+1
-7
@@ -52,18 +52,12 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un
|
|||||||
char buf[1024];
|
char buf[1024];
|
||||||
} resp;
|
} resp;
|
||||||
|
|
||||||
err = resolveHostName(stunServer, &stunAddr, &stunAddrLen);
|
err = resolveHostName(stunServer, AF_INET, 0, &stunAddr, &stunAddrLen);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
Limelog("Failed to resolve STUN server: %d\n", err);
|
Limelog("Failed to resolve STUN server: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must use IPv4 to talk to the STUN server to get our IPv4 address back
|
|
||||||
if (stunAddr.ss_family != AF_INET) {
|
|
||||||
Limelog("STUN server was not reachable over IPv4\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sock = bindUdpSocket(AF_INET, 2048);
|
sock = bindUdpSocket(AF_INET, 2048);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
err = LastSocketFail();
|
err = LastSocketFail();
|
||||||
|
|||||||
Reference in New Issue
Block a user