mirror of
https://github.com/moonlight-stream/Internet-Hosting-Tool.git
synced 2025-07-01 15:26:54 +00:00
Work around IGDs that deduplicate entries based on the internal port
This is a violation of the UPnP IGD specification but we can relay through an alternate port as a workaround.
This commit is contained in:
parent
5f015acdaa
commit
05413a554c
@ -12,6 +12,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "relay.h"
|
||||||
#include "..\version.h"
|
#include "..\version.h"
|
||||||
|
|
||||||
#pragma comment(lib, "miniupnpc.lib")
|
#pragma comment(lib, "miniupnpc.lib")
|
||||||
@ -205,6 +206,21 @@ bool UPnPMapPort(struct UPNPUrls* urls, struct IGDdatas* data, int proto, const
|
|||||||
else if (indefinite) {
|
else if (indefinite) {
|
||||||
printf("STATIC ");
|
printf("STATIC ");
|
||||||
}
|
}
|
||||||
|
if (err == 718 && proto == IPPROTO_UDP) { // ConflictInMappingEntry
|
||||||
|
// Some UPnP implementations incorrectly deduplicate on the internal port instead
|
||||||
|
// of the external port, in violation of the UPnP IGD specification. Since GFE creates
|
||||||
|
// mappings on the same internal port as us, those routers break our mappings. To
|
||||||
|
// work around this issue, we run relays for each of the UDP ports on an alternate
|
||||||
|
// internal port. We'll try the alternate port if we get a conflict for a UDP entry.
|
||||||
|
// Given that these are already horribly non-spec compliant, we won't take any chances
|
||||||
|
// and we'll use an indefinite mapping too.
|
||||||
|
char altPortStr[6];
|
||||||
|
snprintf(altPortStr, sizeof(altPortStr), "%d", port + RELAY_PORT_OFFSET);
|
||||||
|
err = UPNP_AddPortMapping(
|
||||||
|
urls->controlURL, data->first.servicetype, portStr,
|
||||||
|
altPortStr, myAddr, myDesc, protoStr, nullptr, "0");
|
||||||
|
printf("ALTERNATE ");
|
||||||
|
}
|
||||||
if (err == UPNPCOMMAND_SUCCESS) {
|
if (err == UPNPCOMMAND_SUCCESS) {
|
||||||
printf("OK" NL);
|
printf("OK" NL);
|
||||||
return true;
|
return true;
|
||||||
@ -852,6 +868,13 @@ int Run()
|
|||||||
|
|
||||||
ResetLogFile();
|
ResetLogFile();
|
||||||
|
|
||||||
|
// Create the UDP alternate port relays
|
||||||
|
for (int i = 0; i < ARRAYSIZE(k_Ports); i++) {
|
||||||
|
if (k_Ports[i].proto == IPPROTO_UDP) {
|
||||||
|
StartUdpRelay(k_Ports[i].port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the thread to watch for GameStream state changes
|
// Create the thread to watch for GameStream state changes
|
||||||
CreateThread(nullptr, 0, GameStreamStateChangeThread, gsChangeEvent, 0, nullptr);
|
CreateThread(nullptr, 0, GameStreamStateChangeThread, gsChangeEvent, 0, nullptr);
|
||||||
|
|
||||||
|
@ -163,6 +163,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="miss.cpp" />
|
<ClCompile Include="miss.cpp" />
|
||||||
<ClCompile Include="pcp.cpp" />
|
<ClCompile Include="pcp.cpp" />
|
||||||
|
<ClCompile Include="relay.cpp" />
|
||||||
<ClCompile Include="tracer.cpp" />
|
<ClCompile Include="tracer.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -170,6 +171,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\version.h" />
|
<ClInclude Include="..\version.h" />
|
||||||
|
<ClInclude Include="relay.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
<ClCompile Include="pcp.cpp">
|
<ClCompile Include="pcp.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="relay.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="miss.rc">
|
<ResourceCompile Include="miss.rc">
|
||||||
@ -34,5 +37,8 @@
|
|||||||
<ClInclude Include="..\version.h">
|
<ClInclude Include="..\version.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="relay.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
112
miss/relay.cpp
Normal file
112
miss/relay.cpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <Ws2ipdef.h>
|
||||||
|
|
||||||
|
#include "relay.h"
|
||||||
|
|
||||||
|
typedef struct _UDP_TUPLE {
|
||||||
|
SOCKET socket;
|
||||||
|
unsigned short port;
|
||||||
|
} UDP_TUPLE, *PUDP_TUPLE;
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
UdpRelayThreadProc(LPVOID Context)
|
||||||
|
{
|
||||||
|
PUDP_TUPLE tuple = (PUDP_TUPLE)Context;
|
||||||
|
fd_set fds;
|
||||||
|
int err;
|
||||||
|
SOCKADDR_IN lastRemoteAddr;
|
||||||
|
|
||||||
|
RtlZeroMemory(&lastRemoteAddr, sizeof(lastRemoteAddr));
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char buffer[4096];
|
||||||
|
SOCKADDR_IN sourceAddr;
|
||||||
|
int sourceAddrLen;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
|
||||||
|
FD_SET(tuple->socket, &fds);
|
||||||
|
|
||||||
|
err = select(0, &fds, NULL, NULL, NULL);
|
||||||
|
if (err <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceAddrLen = sizeof(sourceAddr);
|
||||||
|
err = recvfrom(tuple->socket, buffer, sizeof(buffer), 0, (PSOCKADDR)&sourceAddr, &sourceAddrLen);
|
||||||
|
if (err == SOCKET_ERROR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKADDR_IN destinationAddr;
|
||||||
|
if (RtlEqualMemory(&sourceAddr.sin_addr, &in4addr_loopback, sizeof(sourceAddr.sin_addr))) {
|
||||||
|
// Traffic incoming from loopback interface - send it to the last remote address
|
||||||
|
destinationAddr = lastRemoteAddr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Traffic incoming from the remote host - remember the source
|
||||||
|
lastRemoteAddr = sourceAddr;
|
||||||
|
|
||||||
|
// Send it to the normal port via the loopback adapter
|
||||||
|
destinationAddr = sourceAddr;
|
||||||
|
destinationAddr.sin_addr = in4addr_loopback;
|
||||||
|
destinationAddr.sin_port = htons(tuple->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto(tuple->socket, buffer, err, 0, (PSOCKADDR)&destinationAddr, sizeof(destinationAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(tuple->socket);
|
||||||
|
free(tuple);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StartUdpRelay(unsigned short Port)
|
||||||
|
{
|
||||||
|
SOCKET sock;
|
||||||
|
SOCKADDR_IN addr;
|
||||||
|
HANDLE thread;
|
||||||
|
PUDP_TUPLE tuple;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
printf("socket() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the alternate port
|
||||||
|
RtlZeroMemory(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(Port + RELAY_PORT_OFFSET);
|
||||||
|
if (bind(sock, (PSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
|
printf("bind() failed: %d\n", WSAGetLastError());
|
||||||
|
closesocket(sock);
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple = (PUDP_TUPLE)malloc(sizeof(*tuple));
|
||||||
|
if (tuple == NULL) {
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple->socket = sock;
|
||||||
|
tuple->port = Port;
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, UdpRelayThreadProc, tuple, 0, NULL);
|
||||||
|
if (thread == NULL) {
|
||||||
|
printf("CreateThread() failed: %d\n", GetLastError());
|
||||||
|
closesocket(sock);
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
5
miss/relay.h
Normal file
5
miss/relay.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define RELAY_PORT_OFFSET -10000
|
||||||
|
|
||||||
|
int StartUdpRelay(unsigned short Port);
|
Loading…
x
Reference in New Issue
Block a user