Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4a4d42ece | ||
|
|
189e861362 | ||
|
|
fd022b67d3 | ||
|
|
14d27b4cf5 | ||
|
|
17cb084968 | ||
|
|
ad8ef228d5 | ||
|
|
8d2252c4ac | ||
|
|
365b3ccd61 | ||
|
|
74140a8511 | ||
|
|
a9bf4ffd70 | ||
|
|
164d8b5467 | ||
|
|
f1ebefa59c | ||
|
|
3e060fae54 | ||
|
|
f97c04a8cc | ||
|
|
85cd20005c |
+1
-1
Submodule GS-IPv6-Forwarder updated: ae5e4aecb6...bff3c3cf00
@@ -14,6 +14,28 @@
|
|||||||
</Feature>
|
</Feature>
|
||||||
</Product>
|
</Product>
|
||||||
|
|
||||||
|
<!-- Enable the Windows Firewall service if it is disabled. Disabling the Windows Firewall service
|
||||||
|
will paradoxically block *all* incoming network traffic and prevent GameStream, MIST, MISS,
|
||||||
|
and other local servers from working at all. The proper way to disable Windows Firewall is via
|
||||||
|
the Windows Firewall control panel applet. -->
|
||||||
|
<Fragment>
|
||||||
|
<Property Id="MPSSVC_START">
|
||||||
|
<RegistrySearch Id="MpsSvcStart"
|
||||||
|
Root="HKLM"
|
||||||
|
Key="System\CurrentControlSet\Services\MpsSvc"
|
||||||
|
Name="Start"
|
||||||
|
Type="raw" />
|
||||||
|
</Property>
|
||||||
|
|
||||||
|
<SetProperty Id="EnableMpsSvc" Value='"[SystemFolder]sc.exe" config MpsSvc start= auto' Sequence="execute" Before="InstallInitialize"/>
|
||||||
|
<CustomAction Id="EnableMpsSvc" BinaryKey="WixCA" DllEntry="WixQuietExec"
|
||||||
|
Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||||
|
|
||||||
|
<SetProperty Id="StartMpsSvc" Value='"[SystemFolder]net.exe" start MpsSvc' Sequence="execute" Before="InstallInitialize"/>
|
||||||
|
<CustomAction Id="StartMpsSvc" BinaryKey="WixCA" DllEntry="WixQuietExec"
|
||||||
|
Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||||
|
</Fragment>
|
||||||
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
<Directory Id="ProgramFilesFolder">
|
<Directory Id="ProgramFilesFolder">
|
||||||
@@ -69,5 +91,14 @@
|
|||||||
<RegistryValue Root="HKCU" Key="Software\Moonlight Internet Streaming Tester" Name="Installed" Type="integer" Value="1" KeyPath="yes" />
|
<RegistryValue Root="HKCU" Key="Software\Moonlight Internet Streaming Tester" Name="Installed" Type="integer" Value="1" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
|
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<Custom Action="EnableMpsSvc" Before="StartMpsSvc">
|
||||||
|
<![CDATA[MPSSVC_START <> "#2"]]>
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="StartMpsSvc" Before="StopServices">
|
||||||
|
<![CDATA[MPSSVC_START <> "#2"]]>
|
||||||
|
</Custom>
|
||||||
|
</InstallExecuteSequence>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Wix>
|
</Wix>
|
||||||
|
|||||||
+290
-138
@@ -5,15 +5,16 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <WinInet.h>
|
#include <WinHttp.h>
|
||||||
#include <wtsapi32.h>
|
#include <wtsapi32.h>
|
||||||
#include <powerbase.h>
|
#include <powerbase.h>
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
#pragma comment(lib, "miniupnpc.lib")
|
#pragma comment(lib, "miniupnpc.lib")
|
||||||
#pragma comment(lib, "libnatpmp.lib")
|
#pragma comment(lib, "libnatpmp.lib")
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
#pragma comment(lib, "iphlpapi.lib")
|
#pragma comment(lib, "iphlpapi.lib")
|
||||||
#pragma comment(lib, "wininet.lib")
|
#pragma comment(lib, "winhttp.lib")
|
||||||
#pragma comment(lib, "wtsapi32.lib")
|
#pragma comment(lib, "wtsapi32.lib")
|
||||||
#pragma comment(lib, "powrprof.lib")
|
#pragma comment(lib, "powrprof.lib")
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
#define NATPMP_STATICLIB
|
#define NATPMP_STATICLIB
|
||||||
#include <natpmp.h>
|
#include <natpmp.h>
|
||||||
|
|
||||||
|
#define LOOPBACK_SERVER_PORT_OFFSET -10000
|
||||||
|
|
||||||
static struct port_entry {
|
static struct port_entry {
|
||||||
int proto;
|
int proto;
|
||||||
int port;
|
int port;
|
||||||
@@ -456,7 +459,7 @@ PortTestStatus TestPort(PSOCKADDR_STORAGE addr, int proto, int port, bool withSe
|
|||||||
sizeof(SOCKADDR_IN) : sizeof(SOCKADDR_IN6);
|
sizeof(SOCKADDR_IN) : sizeof(SOCKADDR_IN6);
|
||||||
|
|
||||||
RtlCopyMemory(&sin6, addr, addrLen);
|
RtlCopyMemory(&sin6, addr, addrLen);
|
||||||
sin6.sin6_port = htons(port);
|
sin6.sin6_port = htons(port + (isLoopbackRelay ? LOOPBACK_SERVER_PORT_OFFSET : 0));
|
||||||
|
|
||||||
if (proto == IPPROTO_TCP) {
|
if (proto == IPPROTO_TCP) {
|
||||||
err = connect(clientSock, (struct sockaddr*)&sin6, addrLen);
|
err = connect(clientSock, (struct sockaddr*)&sin6, addrLen);
|
||||||
@@ -546,64 +549,100 @@ PortTestStatus TestPort(PSOCKADDR_STORAGE addr, int proto, int port, bool withSe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PortTestStatus TestHttpPort(PSOCKADDR_STORAGE addr, int port)
|
PortTestStatus TestHttpPort(PSOCKADDR_STORAGE addr, int port, bool isLoopbackRelay)
|
||||||
{
|
{
|
||||||
HINTERNET hInternet;
|
HINTERNET hSession = nullptr;
|
||||||
HINTERNET hRequest;
|
HINTERNET hConnection = nullptr;
|
||||||
char url[1024];
|
HINTERNET hRequest = nullptr;
|
||||||
|
PortTestStatus result;
|
||||||
|
|
||||||
hInternet = InternetOpenA("MIST", 0, nullptr, nullptr, 0);
|
hSession = WinHttpOpen(L"MIST", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||||
if (hInternet == nullptr) {
|
if (hSession == nullptr) {
|
||||||
fprintf(LOG_OUT, "InternetOpen() failed: %d\n", GetLastError());
|
fprintf(LOG_OUT, "WinHttpOpen() failed: %d\n", GetLastError());
|
||||||
return PortTestError;
|
result = PortTestError;
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
char addrStr[INET6_ADDRSTRLEN + 2];
|
// WinHTTP's default timeouts are very long. Set them to something more reasonable.
|
||||||
|
if (!WinHttpSetTimeouts(hSession, 0, 3000, 5000, 5000)) {
|
||||||
|
fprintf(LOG_OUT, "WinHttpSetTimeouts() failed: %d\n", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows 8.1 enabled TLSv1.2 for WinHTTP by default (8.0 enables it for Schannel but not WinHTTP)
|
||||||
|
// https://docs.microsoft.com/en-us/security/engineering/solving-tls1-problem
|
||||||
|
if (!IsWindows8Point1OrGreater()) {
|
||||||
|
DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
|
||||||
|
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
|
||||||
|
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
|
||||||
|
|
||||||
|
if (!WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols))) {
|
||||||
|
fprintf(LOG_OUT, "WinHttpSetOption(WINHTTP_OPTION_SECURE_PROTOCOLS) failed: %d\n", GetLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR urlEscapedAddr[INET6_ADDRSTRLEN + 2];
|
||||||
if (addr->ss_family == AF_INET) {
|
if (addr->ss_family == AF_INET) {
|
||||||
inet_ntop(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, addrStr, sizeof(addrStr));
|
InetNtopW(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, urlEscapedAddr, ARRAYSIZE(urlEscapedAddr));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// The address string must be escaped for usage in URLs
|
// The address string must be escaped for usage in URLs
|
||||||
addrStr[0] = '[';
|
urlEscapedAddr[0] = L'[';
|
||||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)addr)->sin6_addr, &addrStr[1], INET6_ADDRSTRLEN);
|
InetNtopW(AF_INET6, &((struct sockaddr_in6*)addr)->sin6_addr, &urlEscapedAddr[1], INET6_ADDRSTRLEN);
|
||||||
strcat_s(addrStr, "]");
|
wcscat_s(urlEscapedAddr, L"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(url, "%s://%s:%d/",
|
hConnection = WinHttpConnect(hSession, urlEscapedAddr, port + (isLoopbackRelay ? LOOPBACK_SERVER_PORT_OFFSET : 0), NULL);
|
||||||
port == 47989 ? "http" : "https",
|
if (hConnection == nullptr) {
|
||||||
addrStr,
|
fprintf(LOG_OUT, "WinHttpConnect() failed: %d\n", GetLastError());
|
||||||
port);
|
result = PortTestError;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
hRequest = InternetOpenUrlA(hInternet, url, nullptr, 0,
|
hRequest = WinHttpOpenRequest(hConnection, L"GET", L"/", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||||
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_RELOAD,
|
port == 47984 ? WINHTTP_FLAG_SECURE : 0);
|
||||||
NULL);
|
if (hConnection == nullptr) {
|
||||||
if (hRequest == nullptr) {
|
fprintf(LOG_OUT, "WinHttpOpenRequest() failed: %d\n", GetLastError());
|
||||||
if (GetLastError() == ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) {
|
result = PortTestError;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) || !WinHttpReceiveResponse(hRequest, NULL)) {
|
||||||
|
if (GetLastError() == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED) {
|
||||||
// This is expected for our HTTPS connection
|
// This is expected for our HTTPS connection
|
||||||
fprintf(LOG_OUT, "Success\n");
|
fprintf(LOG_OUT, "Success\n");
|
||||||
|
result = PortTestOk;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// CANNOT_CONNECT is the "expected" error
|
// CANNOT_CONNECT is the "expected" error
|
||||||
if (GetLastError() == ERROR_INTERNET_CANNOT_CONNECT) {
|
if (GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT) {
|
||||||
fprintf(LOG_OUT, "Failed\n");
|
fprintf(LOG_OUT, "Failed\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(LOG_OUT, "Failed: %d\n", GetLastError());
|
fprintf(LOG_OUT, "Failed: %d\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
InternetCloseHandle(hInternet);
|
result = PortTestError;
|
||||||
return PortTestError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(LOG_OUT, "Success\n");
|
fprintf(LOG_OUT, "Success\n");
|
||||||
InternetCloseHandle(hRequest);
|
result = PortTestOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
if (hRequest != nullptr) {
|
||||||
|
WinHttpCloseHandle(hRequest);
|
||||||
|
}
|
||||||
|
if (hConnection != nullptr) {
|
||||||
|
WinHttpCloseHandle(hConnection);
|
||||||
|
}
|
||||||
|
if (hSession != nullptr) {
|
||||||
|
WinHttpCloseHandle(hSession);
|
||||||
|
}
|
||||||
|
|
||||||
InternetCloseHandle(hInternet);
|
return result;
|
||||||
|
|
||||||
return PortTestOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestAllPorts(PSOCKADDR_STORAGE addr, char* portMsg, int portMsgLen, bool isLoopbackRelay, bool consolePrint, bool* allPortsFailed = nullptr)
|
bool TestAllPorts(PSOCKADDR_STORAGE addr, char* portMsg, int portMsgLen, bool isLoopbackRelay, bool consolePrint, bool* allPortsFailed = nullptr)
|
||||||
@@ -615,9 +654,7 @@ bool TestAllPorts(PSOCKADDR_STORAGE addr, char* portMsg, int portMsgLen, bool is
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(k_Ports); i++) {
|
for (int i = 0; i < ARRAYSIZE(k_Ports); i++) {
|
||||||
fprintf(LOG_OUT, "Testing %s %d...",
|
PortTestStatus status;
|
||||||
k_Ports[i].proto == IPPROTO_TCP ? "TCP" : "UDP",
|
|
||||||
k_Ports[i].port);
|
|
||||||
|
|
||||||
if (consolePrint) {
|
if (consolePrint) {
|
||||||
fprintf(CONSOLE_OUT, "\tTesting %s %d...\n",
|
fprintf(CONSOLE_OUT, "\tTesting %s %d...\n",
|
||||||
@@ -625,15 +662,18 @@ bool TestAllPorts(PSOCKADDR_STORAGE addr, char* portMsg, int portMsgLen, bool is
|
|||||||
k_Ports[i].port);
|
k_Ports[i].port);
|
||||||
}
|
}
|
||||||
|
|
||||||
PortTestStatus status = TestPort(addr, k_Ports[i].proto, k_Ports[i].port, k_Ports[i].withServer, isLoopbackRelay);
|
if (!k_Ports[i].withServer) {
|
||||||
|
|
||||||
if (status != PortTestError && !k_Ports[i].withServer) {
|
|
||||||
// Test using a real HTTP client if the port wasn't totally dead.
|
// Test using a real HTTP client if the port wasn't totally dead.
|
||||||
// This is required to confirm functionality with the loopback relay.
|
// This is required to confirm functionality with the loopback relay.
|
||||||
// TestHttpPort() can take significantly longer to timeout than TestPort(),
|
assert(k_Ports[i].proto == IPPROTO_TCP);
|
||||||
// so we only do this test if we believe we're likely to get a response.
|
|
||||||
fprintf(LOG_OUT, "Testing TCP %d with HTTP traffic...", k_Ports[i].port);
|
fprintf(LOG_OUT, "Testing TCP %d with HTTP traffic...", k_Ports[i].port);
|
||||||
status = TestHttpPort(addr, k_Ports[i].port);
|
status = TestHttpPort(addr, k_Ports[i].port, isLoopbackRelay);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(LOG_OUT, "Testing %s %d...",
|
||||||
|
k_Ports[i].proto == IPPROTO_TCP ? "TCP" : "UDP",
|
||||||
|
k_Ports[i].port);
|
||||||
|
status = TestPort(addr, k_Ports[i].proto, k_Ports[i].port, k_Ports[i].withServer, isLoopbackRelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != PortTestOk) {
|
if (status != PortTestOk) {
|
||||||
@@ -660,6 +700,81 @@ bool TestAllPorts(PSOCKADDR_STORAGE addr, char* portMsg, int portMsgLen, bool is
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsTestServerReachable(struct addrinfo* addrinfo, unsigned short port)
|
||||||
|
{
|
||||||
|
SOCKET s;
|
||||||
|
FD_SET writeFds, exceptFds;
|
||||||
|
int err;
|
||||||
|
struct timeval tv = {};
|
||||||
|
SOCKADDR_STORAGE addr;
|
||||||
|
char testServerStr[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
||||||
|
((PSOCKADDR_IN6)&addr)->sin6_port = htons(port);
|
||||||
|
|
||||||
|
if (addr.ss_family == AF_INET) {
|
||||||
|
inet_ntop(AF_INET, &((struct sockaddr_in*)&addr)->sin_addr, testServerStr, sizeof(testServerStr));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inet_ntop(AF_INET6, &((struct sockaddr_in6*)&addr)->sin6_addr, testServerStr, sizeof(testServerStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(LOG_OUT, "Testing reachability of relay server %s...", testServerStr);
|
||||||
|
|
||||||
|
s = socket(addrinfo->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (s == INVALID_SOCKET) {
|
||||||
|
fprintf(LOG_OUT, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG nbIo = 1;
|
||||||
|
err = ioctlsocket(s, FIONBIO, &nbIo);
|
||||||
|
if (err == SOCKET_ERROR) {
|
||||||
|
fprintf(LOG_OUT, "ioctlsocket() failed: %d\n", WSAGetLastError());
|
||||||
|
closesocket(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = connect(s, (PSOCKADDR)&addr, addrinfo->ai_addrlen);
|
||||||
|
if (err == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||||
|
fprintf(LOG_OUT, "Unreachable (%d)\n", WSAGetLastError());
|
||||||
|
closesocket(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&writeFds);
|
||||||
|
FD_ZERO(&exceptFds);
|
||||||
|
|
||||||
|
FD_SET(s, &writeFds);
|
||||||
|
FD_SET(s, &exceptFds);
|
||||||
|
|
||||||
|
tv.tv_sec = 3;
|
||||||
|
err = select(0, nullptr, &writeFds, &exceptFds, &tv);
|
||||||
|
if (err == SOCKET_ERROR) {
|
||||||
|
fprintf(LOG_OUT, "select() failed: %d\n", WSAGetLastError());
|
||||||
|
closesocket(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (err == 0) {
|
||||||
|
fprintf(LOG_OUT, "Unreachable (timeout)\n");
|
||||||
|
closesocket(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int optlen = sizeof(err);
|
||||||
|
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen);
|
||||||
|
closesocket(s);
|
||||||
|
|
||||||
|
if (err != 0 || FD_ISSET(s, &exceptFds)) {
|
||||||
|
fprintf(LOG_OUT, "Unreachable (%d)\n", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(LOG_OUT, "Reachable\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FindLocalInterfaceIPAddress(int family, PSOCKADDR_STORAGE addr)
|
bool FindLocalInterfaceIPAddress(int family, PSOCKADDR_STORAGE addr)
|
||||||
{
|
{
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
@@ -673,9 +788,16 @@ bool FindLocalInterfaceIPAddress(int family, PSOCKADDR_STORAGE addr)
|
|||||||
hint.ai_socktype = SOCK_STREAM;
|
hint.ai_socktype = SOCK_STREAM;
|
||||||
hint.ai_protocol = IPPROTO_TCP;
|
hint.ai_protocol = IPPROTO_TCP;
|
||||||
hint.ai_flags = AI_ADDRCONFIG;
|
hint.ai_flags = AI_ADDRCONFIG;
|
||||||
err = getaddrinfo("moonlight-stream.org", "https", &hint, &result);
|
err = getaddrinfo("moonlight-stream.org", "443", &hint, &result);
|
||||||
if (err != 0 || result == NULL) {
|
if (err != 0 || result == NULL) {
|
||||||
fprintf(LOG_OUT, "getaddrinfo() failed: %d\n", err);
|
// AI_ADDRCONFIG will mask unusable addresses, so we may get nothing
|
||||||
|
// We get WSANO_DATA or WSAHOST_NOT_FOUND depending on whether it's V4 or V6 :(
|
||||||
|
if (err == WSANO_DATA || err == WSAHOST_NOT_FOUND) {
|
||||||
|
fprintf(LOG_OUT, "NONE\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(LOG_OUT, "getaddrinfo() failed: %d\n", err);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,7 +1094,7 @@ bool CheckWANAccess(PSOCKADDR_IN wanAddr, PSOCKADDR_IN reportedWanAddr, bool* fo
|
|||||||
closenatpmp(&natpmp);
|
closenatpmp(&natpmp);
|
||||||
|
|
||||||
if (natPmpErr == 0) {
|
if (natPmpErr == 0) {
|
||||||
char addrStr[64];
|
char addrStr[INET_ADDRSTRLEN];
|
||||||
reportedWanAddr->sin_addr = response.pnu.publicaddress.addr;
|
reportedWanAddr->sin_addr = response.pnu.publicaddress.addr;
|
||||||
inet_ntop(AF_INET, &response.pnu.publicaddress.addr, addrStr, sizeof(addrStr));
|
inet_ntop(AF_INET, &response.pnu.publicaddress.addr, addrStr, sizeof(addrStr));
|
||||||
fprintf(LOG_OUT, "%s\n", addrStr);
|
fprintf(LOG_OUT, "%s\n", addrStr);
|
||||||
@@ -999,7 +1121,7 @@ bool CheckWANAccess(PSOCKADDR_IN wanAddr, PSOCKADDR_IN reportedWanAddr, bool* fo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char addrStr[64];
|
char addrStr[INET_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET, &wanAddr->sin_addr, addrStr, sizeof(addrStr));
|
inet_ntop(AF_INET, &wanAddr->sin_addr, addrStr, sizeof(addrStr));
|
||||||
fprintf(LOG_OUT, "%s\n", addrStr);
|
fprintf(LOG_OUT, "%s\n", addrStr);
|
||||||
|
|
||||||
@@ -1013,16 +1135,12 @@ bool CheckWANAccess(PSOCKADDR_IN wanAddr, PSOCKADDR_IN reportedWanAddr, bool* fo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPossibleCGN(PSOCKADDR_IN wanAddr)
|
bool IsCGN(PSOCKADDR_IN wanAddr)
|
||||||
{
|
{
|
||||||
DWORD addr = htonl(wanAddr->sin_addr.S_un.S_addr);
|
DWORD addr = htonl(wanAddr->sin_addr.S_un.S_addr);
|
||||||
|
|
||||||
// 10.0.0.0/8 - ISPs used to use this
|
|
||||||
if ((addr & 0xFF000000) == 0x0A000000) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 100.64.0.0/10 - RFC6598 official CGN address
|
// 100.64.0.0/10 - RFC6598 official CGN address
|
||||||
else if ((addr & 0xFFC00000) == 0x64400000) {
|
if ((addr & 0xFFC00000) == 0x64400000) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1202,9 +1320,24 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FindLocalInterfaceIPAddress(AF_INET, &ss) && !FindLocalInterfaceIPAddress(AF_INET6, &ss)) {
|
bool hasV4Connectivity, hasV6Connectivity;
|
||||||
DisplayMessage("Unable to perform GameStream connectivity check. Please check your Internet connection and try again.");
|
{
|
||||||
return -1;
|
SOCKADDR_STORAGE v4, v6;
|
||||||
|
|
||||||
|
hasV4Connectivity = FindLocalInterfaceIPAddress(AF_INET, &v4);
|
||||||
|
hasV6Connectivity = FindLocalInterfaceIPAddress(AF_INET6, &v6);
|
||||||
|
|
||||||
|
// Prefer v4 connectivity because that's what GFE uses natively
|
||||||
|
if (hasV4Connectivity) {
|
||||||
|
ss = v4;
|
||||||
|
}
|
||||||
|
else if (hasV6Connectivity) {
|
||||||
|
ss = v6;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DisplayMessage("Unable to perform GameStream connectivity check. Please check your Internet connection and try again.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(CONSOLE_OUT, "Testing GameStream connectivity on your local network...\n");
|
fprintf(CONSOLE_OUT, "Testing GameStream connectivity on your local network...\n");
|
||||||
@@ -1220,7 +1353,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
bool igdDisconnected;
|
bool igdDisconnected;
|
||||||
SOCKADDR_IN locallyReportedWanAddr;
|
SOCKADDR_IN locallyReportedWanAddr;
|
||||||
char wanAddrStr[INET_ADDRSTRLEN];
|
char wanAddrStr[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
if (ss.ss_family == AF_INET) {
|
if (ss.ss_family == AF_INET) {
|
||||||
bool rulesFound;
|
bool rulesFound;
|
||||||
@@ -1231,8 +1364,6 @@ int main(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(CONSOLE_OUT, "Testing GameStream connectivity over the Internet...\n");
|
|
||||||
|
|
||||||
// Detect a double NAT by detecting STUN and and UPnP mismatches
|
// Detect a double NAT by detecting STUN and and UPnP mismatches
|
||||||
if (sin.sin_addr.S_un.S_addr != locallyReportedWanAddr.sin_addr.S_un.S_addr) {
|
if (sin.sin_addr.S_un.S_addr != locallyReportedWanAddr.sin_addr.S_un.S_addr) {
|
||||||
fprintf(LOG_OUT, "Testing GameStream ports via UPnP/NAT-PMP reported WAN address\n");
|
fprintf(LOG_OUT, "Testing GameStream ports via UPnP/NAT-PMP reported WAN address\n");
|
||||||
@@ -1250,101 +1381,122 @@ int main(int argc, char* argv[])
|
|||||||
// Go directly to the relay check if we have only IPv6 connectivity
|
// Go directly to the relay check if we have only IPv6 connectivity
|
||||||
igdDisconnected = false;
|
igdDisconnected = false;
|
||||||
locallyReportedWanAddr = {};
|
locallyReportedWanAddr = {};
|
||||||
goto RelayCheck;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to connect via WAN IPv4 address
|
struct addrinfo hint = {};
|
||||||
fprintf(LOG_OUT, "Testing GameStream ports via STUN-reported WAN address\n");
|
struct addrinfo* result;
|
||||||
if (!TestAllPorts(&ss, portMsgBuf, sizeof(portMsgBuf), false, true)) {
|
|
||||||
RelayCheck:
|
|
||||||
struct addrinfo hint = {};
|
|
||||||
struct addrinfo* result;
|
|
||||||
|
|
||||||
// We can get here if the router doesn't support NAT reflection.
|
hint.ai_family = AF_UNSPEC;
|
||||||
// We'll need to call out to our loopback server to get a second opinion.
|
hint.ai_flags = AI_ADDRCONFIG;
|
||||||
|
err = getaddrinfo("loopback-v2.moonlight-stream.org", NULL, &hint, &result);
|
||||||
|
if (err != 0 || result == NULL) {
|
||||||
|
fprintf(LOG_OUT, "getaddrinfo() failed: %d\n", err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool testServerWasReachable = false;
|
||||||
|
bool allPortsFailedOnV4 = true;
|
||||||
|
|
||||||
hint.ai_family = AF_UNSPEC;
|
// First try the relay server over IPv4. If this passes, it's considered a full success
|
||||||
hint.ai_flags = AI_ADDRCONFIG;
|
fprintf(LOG_OUT, "Testing GameStream ports via IPv4 loopback server\n");
|
||||||
err = getaddrinfo("loopback.moonlight-stream.org", NULL, &hint, &result);
|
for (struct addrinfo* current = result; current != NULL; current = current->ai_next) {
|
||||||
if (err != 0 || result == NULL) {
|
if (current->ai_family == AF_INET) {
|
||||||
fprintf(LOG_OUT, "getaddrinfo() failed: %d\n", err);
|
fprintf(CONSOLE_OUT, "Testing GameStream connectivity over the Internet using a relay server...\n");
|
||||||
|
|
||||||
|
if (!IsTestServerReachable(current, 443)) {
|
||||||
|
fprintf(CONSOLE_OUT, "Skipping unreachable relay server...\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
testServerWasReachable = true;
|
||||||
|
|
||||||
|
if (TestAllPorts((PSOCKADDR_STORAGE)current->ai_addr, portMsgBuf, sizeof(portMsgBuf), true, true, &allPortsFailedOnV4)) {
|
||||||
|
freeaddrinfo(result);
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "This PC is ready to host over the Internet!\n\n"
|
||||||
|
"For the easiest setup, you should pair Moonlight to your gaming PC from your home network before trying to stream over the Internet.\n\n"
|
||||||
|
"If you can't, you can type the following address into Moonlight's Add PC dialog: %s", wanAddrStr);
|
||||||
|
DisplayMessage(msgBuf, nullptr, MpInfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Tested against a working server and it failed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
bool allPortsFailedOnV4 = true;
|
|
||||||
|
|
||||||
// First try the relay server over IPv4. If this passes, it's considered a full success
|
// If that fails, try the relay server over IPv6. If this passes, it will be a partial success
|
||||||
fprintf(LOG_OUT, "Testing GameStream ports via IPv4 loopback server\n");
|
fprintf(LOG_OUT, "Testing GameStream ports via IPv6 loopback server\n");
|
||||||
for (struct addrinfo* current = result; current != NULL; current = current->ai_next) {
|
for (struct addrinfo* current = result; current != NULL; current = current->ai_next) {
|
||||||
if (current->ai_family == AF_INET) {
|
if (current->ai_family == AF_INET6) {
|
||||||
fprintf(CONSOLE_OUT, "Testing GameStream connectivity over the Internet using a relay server...\n");
|
fprintf(CONSOLE_OUT, "Testing GameStream connectivity over the Internet using an IPv6 relay server...\n");
|
||||||
if (TestAllPorts((PSOCKADDR_STORAGE)current->ai_addr, portMsgBuf, sizeof(portMsgBuf), true, true, &allPortsFailedOnV4)) {
|
|
||||||
|
if (!IsTestServerReachable(current, 443)) {
|
||||||
|
fprintf(CONSOLE_OUT, "Skipping unreachable IPv6 relay server...\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
testServerWasReachable = true;
|
||||||
|
|
||||||
|
// Pass the portMsgBuf only if we've detected an IPv6-only setup. Otherwise, we want to preserve
|
||||||
|
// the failing ports from the IPv4 to display in the error dialog.
|
||||||
|
if (TestAllPorts((PSOCKADDR_STORAGE)current->ai_addr,
|
||||||
|
ss.ss_family == AF_INET6 ? portMsgBuf : NULL,
|
||||||
|
ss.ss_family == AF_INET6 ? sizeof(portMsgBuf) : 0, true, true)) {
|
||||||
|
// We will terminate the test at the IPv6 limited connectivity warning in the following cases:
|
||||||
|
// 1) Double-NAT/CGN - indicates the connection is fundamentally limited to IPv6 for end-to-end connectivity
|
||||||
|
// 2) IPv6-only - indicates the connection is fundamentally limited to IPv6 for all connectivity
|
||||||
|
// 3) All ports failed the test with our IPv4 relay - This is one final heuristic to weed out IPv4 misconfigurations. If we have some ports open,
|
||||||
|
// it clearly indicates IPv4 support is possible, just currently misconfigured.
|
||||||
|
//
|
||||||
|
// Our last (implicit) heuristic is that we actually managed to establish an IPv6 connection. This means that there was either
|
||||||
|
// no IPv6 firewall (hopefully not) or that we were able to talk to a PCP/IGDv6 gateway to allow us through. Hopefully if we have
|
||||||
|
// a gateway that is unresponsive to UPnP/NAT-PMP, we wouldn't even be able to establish this connection so we would inherently fall
|
||||||
|
// to the checks below for IPv4 issues.
|
||||||
|
if (IsDoubleNAT(&locallyReportedWanAddr) || igdDisconnected || IsCGN(&locallyReportedWanAddr) || ss.ss_family == AF_INET6 || allPortsFailedOnV4) {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "This PC has limited connectivity for Internet hosting. It will work only for clients on certain networks.\n\n"
|
||||||
|
"If you want to try streaming with this configuration, you must pair Moonlight to your gaming PC from your home network before trying to stream over the Internet.\n\n"
|
||||||
|
"To get full connectivity, please contact your ISP and ask for a \"public IPv4 address\" which they may offer for free upon request. For more information and workarounds, click the Help button.");
|
||||||
|
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#limited-connectivity-for-hosting-error", MpWarn);
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
goto AllTestsPassed;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
// Tested against a working server and it failed
|
||||||
// If that fails, try the relay server over IPv6. If this passes, it will be a partial success
|
break;
|
||||||
fprintf(LOG_OUT, "Testing GameStream ports via IPv6 loopback server\n");
|
|
||||||
for (struct addrinfo* current = result; current != NULL; current = current->ai_next) {
|
|
||||||
if (current->ai_family == AF_INET6) {
|
|
||||||
fprintf(CONSOLE_OUT, "Testing GameStream connectivity over the Internet using an IPv6 relay server...\n");
|
|
||||||
// Pass the portMsgBuf only if we've detected an IPv6-only setup. Otherwise, we want to preserve
|
|
||||||
// the failing ports from the IPv4 to display in the error dialog.
|
|
||||||
if (TestAllPorts((PSOCKADDR_STORAGE)current->ai_addr,
|
|
||||||
ss.ss_family == AF_INET6 ? portMsgBuf : NULL,
|
|
||||||
ss.ss_family == AF_INET6 ? sizeof(portMsgBuf) : 0, true, true)) {
|
|
||||||
// We will terminate the test at the IPv6 limited connectivity warning in the following cases:
|
|
||||||
// 1) Double-NAT/CGN - indicates the connection is fundamentally limited to IPv6 for end-to-end connectivity
|
|
||||||
// 2) IPv6-only - indicates the connection is fundamentally limited to IPv6 for all connectivity
|
|
||||||
// 3) All ports failed the test with our IPv4 relay - This is one final heuristic to weed out IPv4 misconfigurations. If we have some ports open,
|
|
||||||
// it clearly indicates IPv4 support is possible, just currently misconfigured.
|
|
||||||
//
|
|
||||||
// Our last (implicit) heuristic is that we actually managed to establish an IPv6 connection. This means that there was either
|
|
||||||
// no IPv6 firewall (hopefully not) or that we were able to talk to a PCP/IGDv6 gateway to allow us through. Hopefully if we have
|
|
||||||
// a gateway that is unresponsive to UPnP/NAT-PMP, we wouldn't even be able to establish this connection so we would inherently fall
|
|
||||||
// to the checks below for IPv4 issues.
|
|
||||||
if (IsDoubleNAT(&locallyReportedWanAddr) || igdDisconnected || IsPossibleCGN(&locallyReportedWanAddr) || ss.ss_family == AF_INET6 || allPortsFailedOnV4) {
|
|
||||||
snprintf(msgBuf, sizeof(msgBuf), "This PC has limited connectivity for Internet hosting. It will work only for clients on certain networks.\n\n"
|
|
||||||
"If you want to try streaming with this configuration, you must pair Moonlight to your gaming PC from your home network before trying to stream over the Internet.\n\n"
|
|
||||||
"To get full connectivity, please contact your ISP and ask for a \"public IP address\" which they may offer for free upon request. For more information and workarounds, click the Help button.");
|
|
||||||
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#limited-connectivity-for-hosting-error", MpWarn);
|
|
||||||
freeaddrinfo(result);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Many UPnP devices report IGD disconnected when double-NATed. If it was really offline,
|
freeaddrinfo(result);
|
||||||
// we probably would not have even gotten past STUN.
|
|
||||||
if (IsDoubleNAT(&locallyReportedWanAddr) || igdDisconnected) {
|
|
||||||
snprintf(msgBuf, sizeof(msgBuf), "Your router appears be connected to the Internet through another router. Click the Help button for guidance on fixing this issue.");
|
|
||||||
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#connected-through-another-router-error");
|
|
||||||
}
|
|
||||||
else if (IsPossibleCGN(&locallyReportedWanAddr)) {
|
|
||||||
snprintf(msgBuf, sizeof(msgBuf), "Your ISP is running a Carrier-Grade NAT that is preventing you from hosting services like Moonlight on the Internet.\n\n"
|
|
||||||
"Ask your ISP for a \"public IP address\" which they may offer for free upon request. For more information and workarounds, click the Help button.");
|
|
||||||
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#carrier-grade-nat-error");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf(msgBuf, sizeof(msgBuf), "Internet GameStream connectivity check failed.\n\n"
|
|
||||||
"First, try restarting your router. If that fails, check that UPnP is enabled in your router settings. For more information and workarounds, click the Help button.\n\n"
|
|
||||||
"The following ports were not forwarded properly:\n%s", portMsgBuf);
|
|
||||||
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#internet-gamestream-connectivity-check-error");
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
if (!testServerWasReachable) {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "None of Moonlight's connection testing servers were reachable from your PC. Check your Internet connection and try again later.");
|
||||||
|
DisplayMessage(msgBuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Many UPnP devices report IGD disconnected when double-NATed. If it was really offline,
|
||||||
|
// we probably would not have even gotten past STUN.
|
||||||
|
//
|
||||||
|
// We try to tell double-NAT from CGN by checking if IPv6 connectivity is available. If it
|
||||||
|
// is, we assume we're in a DS-Lite or similar configuration. If not, we'll assume it's a
|
||||||
|
// real double-NAT setup.
|
||||||
|
if (IsCGN(&locallyReportedWanAddr) || ((IsDoubleNAT(&locallyReportedWanAddr) || igdDisconnected) && hasV6Connectivity)) {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "Your ISP is running a Carrier-Grade NAT that is preventing you from hosting services like Moonlight on the Internet.\n\n"
|
||||||
|
"Ask your ISP for a \"public IPv4 address\" which they may offer for free upon request. For more information and workarounds, click the Help button.");
|
||||||
|
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#carrier-grade-nat-error");
|
||||||
|
}
|
||||||
|
else if ((IsDoubleNAT(&locallyReportedWanAddr) || igdDisconnected) /* && !hasV6Connectivity */) {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "Your router appears be connected to the Internet through another router. Click the Help button for guidance on fixing this issue.");
|
||||||
|
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#connected-through-another-router-error");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf(msgBuf, sizeof(msgBuf), "Internet GameStream connectivity check failed.\n\n"
|
||||||
|
"First, try restarting your router. If that fails, check that UPnP is enabled in your router settings. For more information and workarounds, click the Help button.\n\n"
|
||||||
|
"The following ports were not forwarded properly:\n%s", portMsgBuf);
|
||||||
|
DisplayMessage(msgBuf, "https://github.com/moonlight-stream/moonlight-docs/wiki/Internet-Streaming-Errors#internet-gamestream-connectivity-check-error");
|
||||||
}
|
}
|
||||||
|
|
||||||
AllTestsPassed:
|
return -1;
|
||||||
snprintf(msgBuf, sizeof(msgBuf), "This PC is ready to host over the Internet!\n\n"
|
|
||||||
"For the easiest setup, you should pair Moonlight to your gaming PC from your home network before trying to stream over the Internet.\n\n"
|
|
||||||
"If you can't, you can type the following address into Moonlight's Add PC dialog: %s", wanAddrStr);
|
|
||||||
DisplayMessage(msgBuf, nullptr, MpInfo);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
@@ -100,6 +100,9 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>..\libs\x86\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\libs\x86\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Manifest>
|
||||||
|
<AdditionalManifestFiles>mist.exe.manifest</AdditionalManifestFiles>
|
||||||
|
</Manifest>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -115,6 +118,9 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Manifest>
|
||||||
|
<AdditionalManifestFiles>mist.exe.manifest</AdditionalManifestFiles>
|
||||||
|
</Manifest>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -138,6 +144,9 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalLibraryDirectories>..\libs\x86\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\libs\x86\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Manifest>
|
||||||
|
<AdditionalManifestFiles>mist.exe.manifest</AdditionalManifestFiles>
|
||||||
|
</Manifest>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -157,6 +166,9 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Manifest>
|
||||||
|
<AdditionalManifestFiles>mist.exe.manifest</AdditionalManifestFiles>
|
||||||
|
</Manifest>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="mist.cpp" />
|
<ClCompile Include="mist.cpp" />
|
||||||
@@ -169,6 +181,9 @@
|
|||||||
<ClInclude Include="..\version.h" />
|
<ClInclude Include="..\version.h" />
|
||||||
<ClInclude Include="mist.h" />
|
<ClInclude Include="mist.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Manifest Include="mist.exe.manifest" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|||||||
@@ -35,4 +35,9 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Manifest Include="mist.exe.manifest">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Manifest>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VER_VERSION 4,4,0,0
|
#define VER_VERSION 5,1,0,0
|
||||||
#define VER_VERSION_STR "4.4.0.0"
|
#define VER_VERSION_STR "5.1.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