Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae2647f36e | ||
|
|
8e40ef80bd | ||
|
|
16bb727b99 | ||
|
|
9194b8e22b | ||
|
|
2805464e86 | ||
|
|
20e7374480 | ||
|
|
0fdbee831b | ||
|
|
b37b99e9c3 | ||
|
|
29bbdc5319 | ||
|
|
09cd50b12a | ||
|
|
d60eda6fa8 | ||
|
|
cda9bc6be7 | ||
|
|
0008fbbcdb |
+1
-1
Submodule GS-IPv6-Forwarder updated: 7b395a9f2f...60ec35a3c0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-3
@@ -47,9 +47,7 @@
|
|||||||
Account="NT AUTHORITY\LocalService"
|
Account="NT AUTHORITY\LocalService"
|
||||||
ErrorControl="ignore"
|
ErrorControl="ignore"
|
||||||
Interactive="no">
|
Interactive="no">
|
||||||
<ServiceConfig DelayedAutoStart="no" OnInstall="yes" OnReinstall="yes" ServiceSid="restricted">
|
<ServiceConfig DelayedAutoStart="no" OnInstall="yes" OnReinstall="yes" ServiceSid="unrestricted"/>
|
||||||
<RequiredPrivilege>SeChangeNotifyPrivilege</RequiredPrivilege>
|
|
||||||
</ServiceConfig>
|
|
||||||
</ServiceInstall>
|
</ServiceInstall>
|
||||||
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="MISS" Wait="yes" />
|
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="MISS" Wait="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|||||||
@@ -386,15 +386,6 @@ bool NATPMPMapPort(natpmp_t* natpmp, int proto, int port, bool enable, bool inde
|
|||||||
else if (response.pnu.newportmapping.mappedpublicport != port) {
|
else if (response.pnu.newportmapping.mappedpublicport != port) {
|
||||||
printf("CONFLICT" NL);
|
printf("CONFLICT" NL);
|
||||||
|
|
||||||
// Some buggy routers (Untangle) will change the *internal* port when
|
|
||||||
// adjusting a port mapping request that collides. This is why we also
|
|
||||||
// pass privateport back from the response and not from the port we originally
|
|
||||||
// asked for. Warn in this case.
|
|
||||||
if (response.pnu.newportmapping.privateport != port) {
|
|
||||||
printf("Buggy router changed the internal port when handling NAT-PMP conflict! (%d -> %d)" NL,
|
|
||||||
port, response.pnu.newportmapping.privateport);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It couldn't assign us the external port we requested and gave us an alternate external port.
|
// It couldn't assign us the external port we requested and gave us an alternate external port.
|
||||||
// We can't use this alternate mapping, so immediately release it.
|
// We can't use this alternate mapping, so immediately release it.
|
||||||
printf("Deleting unwanted NAT-PMP mapping for %s %d...", proto == IPPROTO_TCP ? "TCP" : "UDP", response.pnu.newportmapping.mappedpublicport);
|
printf("Deleting unwanted NAT-PMP mapping for %s %d...", proto == IPPROTO_TCP ? "TCP" : "UDP", response.pnu.newportmapping.mappedpublicport);
|
||||||
|
|||||||
+230
-2
@@ -178,6 +178,56 @@ void DisplayMessage(const char* message, const char* helpUrl = nullptr, MessageP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExecuteCommand(PCSTR command, PCHAR outputBuffer, DWORD outputBufferLength)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES attribs;
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
HANDLE outReadHandle;
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
|
||||||
|
ZeroMemory(&si, sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||||
|
si.wShowWindow = SW_HIDE;
|
||||||
|
|
||||||
|
ZeroMemory(&attribs, sizeof(attribs));
|
||||||
|
attribs.nLength = sizeof(attribs);
|
||||||
|
attribs.bInheritHandle = TRUE;
|
||||||
|
|
||||||
|
if (!CreatePipe(&outReadHandle, &si.hStdOutput, &attribs, 0))
|
||||||
|
{
|
||||||
|
fprintf(LOG_OUT, "CreatePipe() failed: %d\n", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
si.hStdError = si.hStdOutput;
|
||||||
|
|
||||||
|
if (!CreateProcess(NULL, (LPSTR)command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
||||||
|
{
|
||||||
|
fprintf(LOG_OUT, "CreateProcess() failed: %d\n", GetLastError());
|
||||||
|
CloseHandle(si.hStdOutput);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(si.hStdOutput);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
|
if (!ReadFile(outReadHandle, outputBuffer, outputBufferLength, &bytesRead, NULL))
|
||||||
|
{
|
||||||
|
fprintf(LOG_OUT, "ReadFile() failed: %d\n", GetLastError());
|
||||||
|
CloseHandle(outReadHandle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputBuffer[bytesRead] = 0;
|
||||||
|
CloseHandle(outReadHandle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsGameStreamEnabled()
|
bool IsGameStreamEnabled()
|
||||||
{
|
{
|
||||||
DWORD error;
|
DWORD error;
|
||||||
@@ -211,6 +261,20 @@ bool IsGameStreamEnabled()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsZeroTierInstalled()
|
||||||
|
{
|
||||||
|
DWORD error;
|
||||||
|
HKEY key;
|
||||||
|
|
||||||
|
error = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ZeroTier, Inc.\\ZeroTier One", 0, KEY_READ | KEY_WOW64_32KEY, &key);
|
||||||
|
if (error != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
enum PortTestStatus {
|
enum PortTestStatus {
|
||||||
PortTestOk,
|
PortTestOk,
|
||||||
PortTestError,
|
PortTestError,
|
||||||
@@ -554,6 +618,105 @@ bool FindLocalInterfaceIPAddress(int family, PSOCKADDR_STORAGE addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FindZeroTierInterfaceAddress(PSOCKADDR_STORAGE addr)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
IP_ADAPTER_ADDRESSES addresses;
|
||||||
|
char buffer[8192];
|
||||||
|
};
|
||||||
|
ULONG error;
|
||||||
|
ULONG length;
|
||||||
|
PIP_ADAPTER_ADDRESSES currentAdapter;
|
||||||
|
PIP_ADAPTER_UNICAST_ADDRESS currentAddress;
|
||||||
|
|
||||||
|
// Get all IPv4 interfaces
|
||||||
|
length = sizeof(buffer);
|
||||||
|
error = GetAdaptersAddresses(AF_INET,
|
||||||
|
GAA_FLAG_SKIP_ANYCAST |
|
||||||
|
GAA_FLAG_SKIP_MULTICAST |
|
||||||
|
GAA_FLAG_SKIP_DNS_SERVER |
|
||||||
|
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||||
|
NULL,
|
||||||
|
&addresses,
|
||||||
|
&length);
|
||||||
|
if (error != ERROR_SUCCESS) {
|
||||||
|
fprintf(LOG_OUT, "GetAdaptersAddresses() failed: %d\n", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAdapter = &addresses;
|
||||||
|
while (currentAdapter != NULL) {
|
||||||
|
// Look for ones that correspond to a ZeroTier device
|
||||||
|
if (wcsstr(currentAdapter->Description, L"ZeroTier")) {
|
||||||
|
// Check if this interface has the IP address we want
|
||||||
|
currentAddress = currentAdapter->FirstUnicastAddress;
|
||||||
|
while (currentAddress != NULL) {
|
||||||
|
if (currentAddress->Address.lpSockaddr->sa_family == AF_INET) {
|
||||||
|
RtlCopyMemory(addr, currentAddress->Address.lpSockaddr, currentAddress->Address.iSockaddrLength);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAddress = currentAddress->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAdapter = currentAdapter->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindDuplicateDefaultInterfaces(void)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
IP_ADAPTER_ADDRESSES addresses;
|
||||||
|
char buffer[8192];
|
||||||
|
};
|
||||||
|
ULONG error;
|
||||||
|
ULONG length;
|
||||||
|
MIB_IPFORWARDROW defaultRoute;
|
||||||
|
PIP_ADAPTER_ADDRESSES currentAdapter;
|
||||||
|
DWORD matchingInterfaces = 0;
|
||||||
|
|
||||||
|
error = GetBestRoute(0, 0, &defaultRoute);
|
||||||
|
if (error != NO_ERROR) {
|
||||||
|
fprintf(LOG_OUT, "GetBestRoute() failed: %d\n", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all IPv4 interfaces
|
||||||
|
length = sizeof(buffer);
|
||||||
|
error = GetAdaptersAddresses(AF_INET,
|
||||||
|
GAA_FLAG_SKIP_UNICAST |
|
||||||
|
GAA_FLAG_SKIP_ANYCAST |
|
||||||
|
GAA_FLAG_SKIP_MULTICAST |
|
||||||
|
GAA_FLAG_SKIP_DNS_SERVER |
|
||||||
|
GAA_FLAG_INCLUDE_GATEWAYS |
|
||||||
|
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||||
|
NULL,
|
||||||
|
&addresses,
|
||||||
|
&length);
|
||||||
|
if (error != ERROR_SUCCESS) {
|
||||||
|
fprintf(LOG_OUT, "GetAdaptersAddresses() failed: %d\n", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAdapter = &addresses;
|
||||||
|
while (currentAdapter != NULL) {
|
||||||
|
if (currentAdapter->OperStatus == IfOperStatusUp &&
|
||||||
|
currentAdapter->FirstGatewayAddress != NULL &&
|
||||||
|
currentAdapter->FirstGatewayAddress->Address.iSockaddrLength == sizeof(SOCKADDR_IN)) {
|
||||||
|
if (((PSOCKADDR_IN)currentAdapter->FirstGatewayAddress->Address.lpSockaddr)->sin_addr.S_un.S_addr == defaultRoute.dwForwardNextHop) {
|
||||||
|
matchingInterfaces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAdapter = currentAdapter->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingInterfaces > 1;
|
||||||
|
}
|
||||||
|
|
||||||
enum UPnPPortStatus {
|
enum UPnPPortStatus {
|
||||||
NOT_FOUND,
|
NOT_FOUND,
|
||||||
OK,
|
OK,
|
||||||
@@ -732,7 +895,7 @@ bool CheckWANAccess(PSOCKADDR_IN wanAddr, PSOCKADDR_IN reportedWanAddr, bool* fo
|
|||||||
fprintf(LOG_OUT, "Detecting WAN IP address via STUN...");
|
fprintf(LOG_OUT, "Detecting WAN IP address via STUN...");
|
||||||
fprintf(CONSOLE_OUT, "\tTesting STUN...\n");
|
fprintf(CONSOLE_OUT, "\tTesting STUN...\n");
|
||||||
|
|
||||||
if (!getExternalAddressPortIP4(IPPROTO_UDP, 0, wanAddr) && !getExternalAddressPortIP4(IPPROTO_TCP, 0, wanAddr)) {
|
if (!getExternalAddressPortIP4(0, wanAddr)) {
|
||||||
DisplayMessage("Unable to determine your public IP address. Please check your Internet connection or try again in a few minutes.");
|
DisplayMessage("Unable to determine your public IP address. Please check your Internet connection or try again in a few minutes.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -823,6 +986,29 @@ int main(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(CONSOLE_OUT, "Checking for anti-virus and firewall software...\n");
|
||||||
|
|
||||||
|
char wmicBuf[8192];
|
||||||
|
if (ExecuteCommand("WMIC /Node:localhost /Namespace:\\\\root\\SecurityCenter2 Path AntiVirusProduct Get displayName", wmicBuf, sizeof(wmicBuf))) {
|
||||||
|
fprintf(LOG_OUT, "AV products:\n%s", wmicBuf);
|
||||||
|
}
|
||||||
|
if (ExecuteCommand("WMIC /Node:localhost /Namespace:\\\\root\\SecurityCenter2 Path FirewallProduct Get displayName", wmicBuf, sizeof(wmicBuf))) {
|
||||||
|
fprintf(LOG_OUT, "Firewall products:\n%s", wmicBuf);
|
||||||
|
if (!strstr(wmicBuf, "No Instance(s) Available.") && !strstr(wmicBuf, "Invalid namespace")) {
|
||||||
|
DisplayMessage("Detected anti-virus and/or firewall software installed on this system. This software may interfere with NVIDIA GameStream.\n\n"
|
||||||
|
"Please try temporarily disabling your anti-virus or firewall software if you experience connection issues with Moonlight.",
|
||||||
|
"https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting", MpInfo, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(CONSOLE_OUT, "Checking network connections...\n");
|
||||||
|
|
||||||
|
if (FindDuplicateDefaultInterfaces()) {
|
||||||
|
DisplayMessage("This computer appears to have more than one connection to the same network (like both WiFi and Ethernet, for example).\n\n"
|
||||||
|
"Please disconnect the extra connection(s) to ensure hosting works reliably over the Internet. If you are connected via WiFi and Ethernet, try disabling your WiFi connection.",
|
||||||
|
"https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#multiple-connections-error", MpWarn, false);
|
||||||
|
}
|
||||||
|
|
||||||
union {
|
union {
|
||||||
SOCKADDR_STORAGE ss;
|
SOCKADDR_STORAGE ss;
|
||||||
SOCKADDR_IN sin;
|
SOCKADDR_IN sin;
|
||||||
@@ -845,6 +1031,49 @@ int main(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do a special limited test pass for ZeroTier
|
||||||
|
if (IsZeroTierInstalled()) {
|
||||||
|
fprintf(LOG_OUT, "Found ZeroTier installed\n");
|
||||||
|
|
||||||
|
if (!FindZeroTierInterfaceAddress(&ss)) {
|
||||||
|
DisplayMessage("ZeroTier appears to be installed on this PC, but it's not connected to a network.\n\n"
|
||||||
|
"If you are trying to host with ZeroTier, connect to your ZeroTier network and restart this test.\n\n"
|
||||||
|
"If not, click OK and this test will continue assuming you aren't using ZeroTier.",
|
||||||
|
"https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide#zerotier", MpInfo, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char zeroTierAddrStr[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &sin.sin_addr, zeroTierAddrStr, sizeof(zeroTierAddrStr));
|
||||||
|
|
||||||
|
fprintf(LOG_OUT, "Found ZeroTier connected with address: %s\n", zeroTierAddrStr);
|
||||||
|
|
||||||
|
if (strstr(zeroTierAddrStr, "169.254.")) {
|
||||||
|
DisplayMessage("ZeroTier is active, but this PC has not been authorized to connect to your ZeroTier network.\n\n"
|
||||||
|
"Make sure you check the Auth checkbox for all network members on the ZeroTier Networks webpage.",
|
||||||
|
"https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide#zerotier");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to connect via ZeroTier address
|
||||||
|
fprintf(CONSOLE_OUT, "Testing GameStream connectivity using ZeroTier...\n");
|
||||||
|
fprintf(LOG_OUT, "Testing GameStream ports via ZeroTier\n");
|
||||||
|
if (!TestAllPorts(&ss, portMsgBuf, sizeof(portMsgBuf), false, true)) {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf),
|
||||||
|
"ZeroTier connectivity check failed. This is almost always caused by a firewall on your computer blocking the connection.\n\nTry temporarily disabling your antivirus and firewall.");
|
||||||
|
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, our testing is complete for ZeroTier
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "This PC is ready to host over the Internet with ZeroTier!\n\n"
|
||||||
|
"Don't forget to connect to your ZeroTier network on your client before streaming over the Internet.\n\n"
|
||||||
|
"After connecting ZeroTier, type following address into Moonlight's Add PC dialog: %s", zeroTierAddrStr);
|
||||||
|
DisplayMessage(msgBuf, nullptr, MpInfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!FindLocalInterfaceIPAddress(AF_INET, &ss) && !FindLocalInterfaceIPAddress(AF_INET6, &ss)) {
|
if (!FindLocalInterfaceIPAddress(AF_INET, &ss) && !FindLocalInterfaceIPAddress(AF_INET6, &ss)) {
|
||||||
DisplayMessage("Unable to perform GameStream connectivity check. Please check your Internet connection and try again.");
|
DisplayMessage("Unable to perform GameStream connectivity check. Please check your Internet connection and try again.");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -861,7 +1090,6 @@ int main(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool igdDisconnected;
|
bool igdDisconnected;
|
||||||
SOCKADDR_IN locallyReportedWanAddr;
|
SOCKADDR_IN locallyReportedWanAddr;
|
||||||
char wanAddrStr[INET_ADDRSTRLEN];
|
char wanAddrStr[INET_ADDRSTRLEN];
|
||||||
|
|||||||
+3
-1
@@ -7,6 +7,8 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <Iphlpapi.h>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
|
|
||||||
#include "..\version.h"
|
#include "..\version.h"
|
||||||
@@ -14,4 +16,4 @@
|
|||||||
#define CONSOLE_OUT stdout
|
#define CONSOLE_OUT stdout
|
||||||
#define LOG_OUT stderr
|
#define LOG_OUT stderr
|
||||||
|
|
||||||
bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN wanAddr);
|
bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr);
|
||||||
+26
-38
@@ -38,7 +38,7 @@ typedef struct _STUN_MESSAGE {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN wanAddr)
|
bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||||
{
|
{
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
STUN_MESSAGE reqMsg;
|
STUN_MESSAGE reqMsg;
|
||||||
@@ -46,32 +46,41 @@ bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN
|
|||||||
int bytesRead;
|
int bytesRead;
|
||||||
int tries;
|
int tries;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
int err;
|
||||||
PSTUN_ATTRIBUTE_HEADER attribute;
|
PSTUN_ATTRIBUTE_HEADER attribute;
|
||||||
PSTUN_MAPPED_IPV4_ADDRESS_ATTRIBUTE ipv4Attrib;
|
PSTUN_MAPPED_IPV4_ADDRESS_ATTRIBUTE ipv4Attrib;
|
||||||
struct hostent *host;
|
struct addrinfo* result;
|
||||||
|
struct addrinfo hints;
|
||||||
union {
|
union {
|
||||||
STUN_MESSAGE hdr;
|
STUN_MESSAGE hdr;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
} resp;
|
} resp;
|
||||||
|
|
||||||
host = gethostbyname("stun.moonlight-stream.org");
|
memset(&hints, 0, sizeof(hints));
|
||||||
if (host == nullptr) {
|
hints.ai_family = AF_INET;
|
||||||
fprintf(LOG_OUT, "gethostbyname() failed: %d\n", WSAGetLastError());
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
err = getaddrinfo("stun.moonlight-stream.org", "3478", &hints, &result);
|
||||||
|
if (err != 0 || result == NULL) {
|
||||||
|
fprintf(LOG_OUT, "getaddrinfo() failed: %d\n", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock = socket(AF_INET, proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM, proto);
|
sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
fprintf(LOG_OUT, "socket() failed: %d\n", WSAGetLastError());
|
fprintf(LOG_OUT, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
freeaddrinfo(result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_in bindAddr = {};
|
struct sockaddr_in bindAddr = {};
|
||||||
bindAddr.sin_family = AF_INET;
|
bindAddr.sin_family = hints.ai_family;
|
||||||
bindAddr.sin_port = htons(localPort);
|
bindAddr.sin_port = htons(localPort);
|
||||||
if (bind(sock, (struct sockaddr*)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) {
|
if (bind(sock, (struct sockaddr*)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) {
|
||||||
fprintf(LOG_OUT, "bind() failed: %d\n", WSAGetLastError());
|
fprintf(LOG_OUT, "bind() failed: %d\n", WSAGetLastError());
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
freeaddrinfo(result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,36 +91,13 @@ bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN
|
|||||||
reqMsg.transactionId[i] = rand();
|
reqMsg.transactionId[i] = rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKADDR_IN stunAddr = {};
|
|
||||||
stunAddr.sin_family = AF_INET;
|
|
||||||
stunAddr.sin_port = htons(STUN_PORT);
|
|
||||||
stunAddr.sin_addr = *(struct in_addr*)host->h_addr;
|
|
||||||
|
|
||||||
// We'll connect() even for UDP so we can use send()/recv() and share more code
|
|
||||||
if (connect(sock, (struct sockaddr*)&stunAddr, sizeof(stunAddr)) == SOCKET_ERROR) {
|
|
||||||
fprintf(LOG_OUT, "connect() failed: %d\n", WSAGetLastError());
|
|
||||||
closesocket(sock);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For UDP, we'll do 3 iterations of 1 second each. For TCP,
|
|
||||||
// we'll do one iteration with a 3 second wait.
|
|
||||||
if (proto == IPPROTO_TCP) {
|
|
||||||
tries = 1;
|
|
||||||
timeout = STUN_RECV_TIMEOUT_SEC;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tries = STUN_RECV_TIMEOUT_SEC;
|
|
||||||
timeout = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesRead = 0;
|
bytesRead = 0;
|
||||||
for (i = 0; i < tries; i++) {
|
for (i = 0; i < STUN_RECV_TIMEOUT_SEC; i++) {
|
||||||
// Retransmit the request every second until the timeout elapses
|
// Retransmit the request every second to all resolved IP addresses until the timeout elapses
|
||||||
if (send(sock, (char *)&reqMsg, sizeof(reqMsg), 0) == SOCKET_ERROR) {
|
for (struct addrinfo* current = result; current != NULL; current = current->ai_next) {
|
||||||
fprintf(LOG_OUT, "send() failed: %d\n", WSAGetLastError());
|
if (sendto(sock, (char*)&reqMsg, sizeof(reqMsg), 0, current->ai_addr, current->ai_addrlen) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
fprintf(LOG_OUT, "sendto() failed: %d\n", WSAGetLastError());
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
@@ -119,7 +105,7 @@ bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN
|
|||||||
FD_SET(sock, &fds);
|
FD_SET(sock, &fds);
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = timeout;
|
tv.tv_sec = 1;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
int selectRes = select(0, &fds, nullptr, nullptr, &tv);
|
int selectRes = select(0, &fds, nullptr, nullptr, &tv);
|
||||||
@@ -130,14 +116,16 @@ bool getExternalAddressPortIP4(int proto, unsigned short localPort, PSOCKADDR_IN
|
|||||||
else if (selectRes == SOCKET_ERROR) {
|
else if (selectRes == SOCKET_ERROR) {
|
||||||
fprintf(LOG_OUT, "select() failed: %d\n", WSAGetLastError());
|
fprintf(LOG_OUT, "select() failed: %d\n", WSAGetLastError());
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
freeaddrinfo(result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error handling is below
|
// Error handling is below
|
||||||
bytesRead = recv(sock, resp.buf, sizeof(resp.buf), 0);
|
bytesRead = recvfrom(sock, resp.buf, sizeof(resp.buf), 0, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
|
||||||
if (bytesRead == 0) {
|
if (bytesRead == 0) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VER_VERSION 4,1,0,0
|
#define VER_VERSION 4,3,0,0
|
||||||
#define VER_VERSION_STR "4.1.0.0"
|
#define VER_VERSION_STR "4.3.0.0"
|
||||||
|
|
||||||
#define VER_COMPANYNAME_STR "Moonlight Game Streaming Project"
|
#define VER_COMPANYNAME_STR "Moonlight Game Streaming Project"
|
||||||
#define VER_PRODUCTNAME_STR "Moonlight Internet Hosting Tool"
|
#define VER_PRODUCTNAME_STR "Moonlight Internet Hosting Tool"
|
||||||
|
|||||||
Reference in New Issue
Block a user