Skip to content

Commit

Permalink
Fix connection failure on iOS when connecting to a Tailscale IPv4 add…
Browse files Browse the repository at this point in the history
…ress from an IPv6-only mobile network such as T-Mobile.

T-Mobile handles IPv4 addresses, including the special 100.x.x.x Tailscale addresses, using 464xlat and NAT64. We need to force resolve the address using AF_INET instead of AF_UNSPEC in order to get a usable address to connect to. More info: https://en.wikipedia.org/wiki/IPv6_transition_mechanism#464XLAT
  • Loading branch information
andygrundman committed Dec 2, 2024
1 parent d3d3e6c commit bc67221
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
18 changes: 9 additions & 9 deletions src/Connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void LiStopConnection(void) {
Limelog("done\n");
}
LC_ASSERT(stage == STAGE_NONE);

if (RemoteAddrString != NULL) {
free(RemoteAddrString);
RemoteAddrString = NULL;
Expand Down Expand Up @@ -281,7 +281,7 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre

alreadyTerminated = false;
ConnectionInterrupted = false;

// Validate the audio configuration
if (MAGIC_BYTE_FROM_AUDIO_CONFIG(StreamConfig.audioConfiguration) != 0xCA ||
CHANNEL_COUNT_FROM_AUDIO_CONFIGURATION(StreamConfig.audioConfiguration) > AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT) {
Expand Down Expand Up @@ -328,7 +328,7 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
Limelog("Disabling reference frame invalidation for 4K streaming with GFE\n");
VideoCallbacks.capabilities &= ~CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC;
}

Limelog("Initializing platform...");
ListenerCallbacks.stageStarting(STAGE_PLATFORM_INIT);
err = initializePlatform();
Expand All @@ -348,13 +348,13 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
if (RtspPortNumber != 48010) {
// If we have an alternate RTSP port, use that as our test port. The host probably
// isn't listening on 47989 or 47984 anyway, since they're using alternate ports.
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &AddrLen);
err = resolveHostName(serverInfo->address, AF_INET, RtspPortNumber, &RemoteAddr, &AddrLen);
if (err != 0) {
// Sleep for a second and try again. It's possible that we've attempt to connect
// before the host has gotten around to listening on the RTSP port. Give it some
// time before retrying.
PltSleepMs(1000);
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &AddrLen);
err = resolveHostName(serverInfo->address, AF_INET, RtspPortNumber, &RemoteAddr, &AddrLen);
}
}
else {
Expand All @@ -364,12 +364,12 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
// TCP 48010 is a last resort because:
// a) it's not always listening and there's a race between listen() on the host and our connect()
// b) it's not used at all by certain host versions which perform RTSP over ENet
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47984, &RemoteAddr, &AddrLen);
err = resolveHostName(serverInfo->address, AF_INET, 47984, &RemoteAddr, &AddrLen);
if (err != 0) {
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47989, &RemoteAddr, &AddrLen);
err = resolveHostName(serverInfo->address, AF_INET, 47989, &RemoteAddr, &AddrLen);
}
if (err != 0) {
err = resolveHostName(serverInfo->address, AF_UNSPEC, 48010, &RemoteAddr, &AddrLen);
err = resolveHostName(serverInfo->address, AF_INET, 48010, &RemoteAddr, &AddrLen);
}
}
if (err != 0) {
Expand Down Expand Up @@ -517,7 +517,7 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
LC_ASSERT(stage == STAGE_INPUT_STREAM_START);
ListenerCallbacks.stageComplete(STAGE_INPUT_STREAM_START);
Limelog("done\n");

// Wiggle the mouse a bit to wake the display up
LiSendMouseMoveEvent(1, 1);
PltSleepMs(10);
Expand Down
14 changes: 14 additions & 0 deletions src/PlatformSockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,18 @@ int enableNoDelay(SOCKET s) {
return 0;
}

static void logWithSockaddr(const char *format, const char *arg, const struct sockaddr *addr, socklen_t len) {
char host[NI_MAXHOST], service[NI_MAXSERV];
int res = getnameinfo(addr, len, host, sizeof(host), service, sizeof(service),
NI_NUMERICHOST | NI_NUMERICSERV);
if (res == 0) {
Limelog(format, arg, host, service);
}
else {
Limelog("getnameinfo() failed: %s\n", gai_strerror(res));
}
}

int resolveHostName(const char* host, int family, int tcpTestPort, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen)
{
struct addrinfo hints, *res, *currentAddr;
Expand Down Expand Up @@ -638,6 +650,8 @@ int resolveHostName(const char* host, int family, int tcpTestPort, struct sockad
}
}

logWithSockaddr("Resolved %s to %s %s", host, currentAddr->ai_addr, sizeof(currentAddr->ai_addr));

memcpy(addr, currentAddr->ai_addr, currentAddr->ai_addrlen);
*addrLen = (SOCKADDR_LEN)currentAddr->ai_addrlen;

Expand Down

0 comments on commit bc67221

Please sign in to comment.