mirror of
https://github.com/libretro/Mesen.git
synced 2025-03-06 15:17:49 +00:00
Added UPnP port forwarding support
This commit is contained in:
parent
6b00a1f5c8
commit
0fd2fb23c5
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#pragma comment(lib,"ws2_32.lib") //Winsock Library
|
||||
#include "stdafx.h"
|
||||
#include "UPnPPortMapper.h"
|
||||
#include <winsock2.h>
|
||||
|
||||
class Socket
|
||||
@ -11,6 +12,7 @@ private:
|
||||
bool _cleanupWSA = false;
|
||||
char* _sendBuffer;
|
||||
int _bufferPosition;
|
||||
int32_t _UPnPPort = -1;
|
||||
|
||||
public:
|
||||
Socket()
|
||||
@ -51,6 +53,10 @@ public:
|
||||
|
||||
~Socket()
|
||||
{
|
||||
if(_UPnPPort != -1) {
|
||||
UPnPPortMapper::RemoveNATPortMapping(_UPnPPort, IPProtocol::TCP);
|
||||
}
|
||||
|
||||
if(_socket != INVALID_SOCKET) {
|
||||
Close();
|
||||
}
|
||||
@ -84,7 +90,7 @@ public:
|
||||
|
||||
void Close()
|
||||
{
|
||||
std::cout << "Client disconnected!\r\n";
|
||||
std::cout << "Socket closed." << std::endl;
|
||||
shutdown(_socket, SD_SEND);
|
||||
closesocket(_socket);
|
||||
SetConnectionErrorFlag();
|
||||
@ -102,6 +108,10 @@ public:
|
||||
serverInf.sin_addr.s_addr = INADDR_ANY;
|
||||
serverInf.sin_port = htons(port);
|
||||
|
||||
if(UPnPPortMapper::AddNATPortMapping(port, port, IPProtocol::TCP)) {
|
||||
_UPnPPort = port;
|
||||
}
|
||||
|
||||
if(bind(_socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) {
|
||||
std::cout << "Unable to bind socket." << std::endl;
|
||||
SetConnectionErrorFlag();
|
||||
@ -193,7 +203,6 @@ public:
|
||||
|
||||
int Recv(char *buf, int len, int flags)
|
||||
{
|
||||
static ofstream received("received.log", ios::out | ios::binary);
|
||||
int returnVal = recv(_socket, buf, len, flags);
|
||||
|
||||
int nError = WSAGetLastError();
|
||||
|
132
Utilities/UPnPPortMapper.h
Normal file
132
Utilities/UPnPPortMapper.h
Normal file
@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <natupnp.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
enum class IPProtocol
|
||||
{
|
||||
TCP = 0,
|
||||
UDP = 1
|
||||
};
|
||||
|
||||
class UPnPPortMapper
|
||||
{
|
||||
public:
|
||||
static bool AddNATPortMapping(WORD internalPort, WORD externalPort, IPProtocol protocol)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
IUPnPNAT *nat = nullptr;
|
||||
HRESULT hResult = CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
|
||||
|
||||
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
|
||||
|
||||
if(SUCCEEDED(hResult) && nat) {
|
||||
IStaticPortMappingCollection *spmc = nullptr;
|
||||
hResult = nat->get_StaticPortMappingCollection(&spmc);
|
||||
if(SUCCEEDED(hResult) && spmc) {
|
||||
IStaticPortMapping *spm = nullptr;
|
||||
hResult = spmc->get_Item(externalPort, proto, &spm);
|
||||
if(spm != nullptr) {
|
||||
//An identical mapping already exists, remove it
|
||||
if(RemoveNATPortMapping(externalPort, protocol)) {
|
||||
std::cout << "Removed existing UPnP mapping." << std::endl;
|
||||
spm->Release();
|
||||
spm = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if(!SUCCEEDED(hResult) || spm == nullptr) {
|
||||
std::cout << "Attempting to automatically forward port via UPnP..." << std::endl;
|
||||
|
||||
wstring localIP = GetLocalIP();
|
||||
BSTR desc = SysAllocString(L"NESEmu for NetPlay");
|
||||
BSTR clientStr = SysAllocString(localIP.c_str());
|
||||
hResult = spmc->Add(externalPort, proto, internalPort, clientStr, true, desc, &spm);
|
||||
SysFreeString(clientStr);
|
||||
SysFreeString(desc);
|
||||
|
||||
if(SUCCEEDED(hResult) && spm) {
|
||||
//Successfully added a new port mapping
|
||||
std::cout << std::dec << "Forwarded port " << externalPort << " to IP ";
|
||||
std::wcout << localIP.c_str() << std::endl;
|
||||
spm->Release();
|
||||
result = true;
|
||||
}
|
||||
spmc->Release();
|
||||
} else {
|
||||
std::cout << "Unable to add UPnP port mapping." << std::endl;
|
||||
}
|
||||
}
|
||||
nat->Release();
|
||||
}
|
||||
|
||||
SysFreeString(proto);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool RemoveNATPortMapping(WORD externalPort, IPProtocol protocol)
|
||||
{
|
||||
IUPnPNAT *nat = nullptr;
|
||||
IStaticPortMappingCollection *spmc;
|
||||
bool result = false;
|
||||
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
HRESULT hResult = ::CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
|
||||
|
||||
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
|
||||
|
||||
if(SUCCEEDED(hResult) && nat) {
|
||||
hResult = nat->get_StaticPortMappingCollection(&spmc);
|
||||
if(SUCCEEDED(hResult) && spmc) {
|
||||
spmc->Remove(externalPort, proto);
|
||||
spmc->Release();
|
||||
result = true;
|
||||
}
|
||||
nat->Release();
|
||||
}
|
||||
|
||||
SysFreeString(proto);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static wstring GetLocalIP()
|
||||
{
|
||||
wstring localIP;
|
||||
|
||||
ADDRINFOW *result = nullptr;
|
||||
ADDRINFOW hints;
|
||||
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
wchar_t hostName[255];
|
||||
DWORD hostSize = 255;
|
||||
GetComputerName(hostName, &hostSize);
|
||||
|
||||
if(GetAddrInfoW(hostName, nullptr, &hints, &result) == 0) {
|
||||
wchar_t ipAddr[255];
|
||||
DWORD ipSize = 255;
|
||||
if(WSAAddressToString(result->ai_addr, result->ai_addrlen, nullptr, ipAddr, &ipSize) == 0) {
|
||||
localIP = ipAddr;
|
||||
}
|
||||
FreeAddrInfoW(result);
|
||||
}
|
||||
return localIP;
|
||||
}
|
||||
|
||||
|
||||
};
|
@ -73,7 +73,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ConfigManager.h" />
|
||||
<ClInclude Include="FolderUtilities.h" />
|
||||
<ClInclude Include="NATPortMapper.h" />
|
||||
<ClInclude Include="UPnPPortMapper.h" />
|
||||
<ClInclude Include="SimpleLock.h" />
|
||||
<ClInclude Include="Socket.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
|
@ -48,7 +48,7 @@
|
||||
<ClInclude Include="SimpleLock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NATPortMapper.h">
|
||||
<ClInclude Include="UPnPPortMapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user