mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 00:59:44 -06:00
Merge pull request #5898 from ligfx/extractupnp
Common: extract UPnP namespace from NetPlayServer
This commit is contained in:
@ -74,13 +74,12 @@ NetPlayClient::~NetPlayClient()
|
||||
|
||||
// called from ---GUI--- thread
|
||||
NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlayUI* dialog,
|
||||
const std::string& name, bool traversal,
|
||||
const std::string& centralServer, u16 centralPort)
|
||||
const std::string& name, const NetTraversalConfig& traversal_config)
|
||||
: m_dialog(dialog), m_player_name(name)
|
||||
{
|
||||
ClearBuffers();
|
||||
|
||||
if (!traversal)
|
||||
if (!traversal_config.use_traversal)
|
||||
{
|
||||
// Direct Connection
|
||||
m_client = enet_host_create(nullptr, 1, 3, 0, 0);
|
||||
@ -124,7 +123,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnsureTraversalClient(centralServer, centralPort))
|
||||
if (!EnsureTraversalClient(traversal_config.traversal_host, traversal_config.traversal_port))
|
||||
return;
|
||||
m_client = g_MainNetHost.get();
|
||||
|
||||
|
@ -67,8 +67,7 @@ public:
|
||||
void SendAsync(sf::Packet&& packet);
|
||||
|
||||
NetPlayClient(const std::string& address, const u16 port, NetPlayUI* dialog,
|
||||
const std::string& name, bool traversal, const std::string& centralServer,
|
||||
u16 centralPort);
|
||||
const std::string& name, const NetTraversalConfig& traversal_config);
|
||||
~NetPlayClient();
|
||||
|
||||
void GetPlayerList(std::string& list, std::vector<int>& pid_list);
|
||||
|
@ -27,6 +27,20 @@ struct NetSettings
|
||||
ExpansionInterface::TEXIDevices m_EXIDevice[2];
|
||||
};
|
||||
|
||||
struct NetTraversalConfig
|
||||
{
|
||||
NetTraversalConfig() = default;
|
||||
NetTraversalConfig(bool use_traversal_, std::string traversal_host_, u16 traversal_port_)
|
||||
: use_traversal{use_traversal_}, traversal_host{std::move(traversal_host_)},
|
||||
traversal_port{traversal_port_}
|
||||
{
|
||||
}
|
||||
|
||||
bool use_traversal = false;
|
||||
std::string traversal_host;
|
||||
u16 traversal_port = 0;
|
||||
};
|
||||
|
||||
extern NetSettings g_NetPlaySettings;
|
||||
extern u64 g_netplay_initial_rtc;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/UPnP.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HW/Sram.h"
|
||||
#include "Core/NetPlayClient.h" //for NetPlayUI
|
||||
@ -57,16 +58,13 @@ NetPlayServer::~NetPlayServer()
|
||||
}
|
||||
|
||||
#ifdef USE_UPNP
|
||||
if (m_upnp_thread.joinable())
|
||||
m_upnp_thread.join();
|
||||
m_upnp_thread = std::thread(&NetPlayServer::unmapPortThread);
|
||||
m_upnp_thread.join();
|
||||
UPnP::StopPortmapping();
|
||||
#endif
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
NetPlayServer::NetPlayServer(const u16 port, bool traversal, const std::string& centralServer,
|
||||
u16 centralPort)
|
||||
NetPlayServer::NetPlayServer(const u16 port, const bool forward_port,
|
||||
const NetTraversalConfig& traversal_config)
|
||||
{
|
||||
//--use server time
|
||||
if (enet_initialize() != 0)
|
||||
@ -77,9 +75,10 @@ NetPlayServer::NetPlayServer(const u16 port, bool traversal, const std::string&
|
||||
m_pad_map.fill(-1);
|
||||
m_wiimote_map.fill(-1);
|
||||
|
||||
if (traversal)
|
||||
if (traversal_config.use_traversal)
|
||||
{
|
||||
if (!EnsureTraversalClient(centralServer, centralPort, port))
|
||||
if (!EnsureTraversalClient(traversal_config.traversal_host, traversal_config.traversal_port,
|
||||
port))
|
||||
return;
|
||||
|
||||
g_TraversalClient->m_Client = this;
|
||||
@ -105,6 +104,11 @@ NetPlayServer::NetPlayServer(const u16 port, bool traversal, const std::string&
|
||||
m_do_loop = true;
|
||||
m_thread = std::thread(&NetPlayServer::ThreadFunc, this);
|
||||
m_target_buffer_size = 5;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
if (forward_port)
|
||||
UPnP::TryPortmapping(port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -933,155 +937,3 @@ std::vector<std::pair<std::string, std::string>> NetPlayServer::GetInterfaceList
|
||||
result.emplace_back(std::make_pair("!local!", "127.0.0.1"));
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_UPNP
|
||||
#include <miniupnpc.h>
|
||||
#include <miniwget.h>
|
||||
#include <upnpcommands.h>
|
||||
|
||||
struct UPNPUrls NetPlayServer::m_upnp_urls;
|
||||
struct IGDdatas NetPlayServer::m_upnp_data;
|
||||
std::string NetPlayServer::m_upnp_ourip;
|
||||
u16 NetPlayServer::m_upnp_mapped = 0;
|
||||
std::thread NetPlayServer::m_upnp_thread;
|
||||
|
||||
// called from ---GUI--- thread
|
||||
void NetPlayServer::TryPortmapping(u16 port)
|
||||
{
|
||||
if (m_upnp_thread.joinable())
|
||||
m_upnp_thread.join();
|
||||
m_upnp_thread = std::thread(&NetPlayServer::mapPortThread, port);
|
||||
}
|
||||
|
||||
// UPnP thread: try to map a port
|
||||
void NetPlayServer::mapPortThread(const u16 port)
|
||||
{
|
||||
if (initUPnP() && UPnPMapPort(m_upnp_ourip, port))
|
||||
{
|
||||
NOTICE_LOG(NETPLAY, "Successfully mapped port %d to %s.", port, m_upnp_ourip.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_LOG(NETPLAY, "Failed to map port %d to %s.", port, m_upnp_ourip.c_str());
|
||||
}
|
||||
|
||||
// UPnP thread: try to unmap a port
|
||||
void NetPlayServer::unmapPortThread()
|
||||
{
|
||||
if (m_upnp_mapped > 0)
|
||||
UPnPUnmapPort(m_upnp_mapped);
|
||||
}
|
||||
|
||||
// called from ---UPnP--- thread
|
||||
// discovers the IGD
|
||||
bool NetPlayServer::initUPnP()
|
||||
{
|
||||
static bool s_inited = false;
|
||||
static bool s_error = false;
|
||||
|
||||
std::vector<UPNPDev*> igds;
|
||||
int descXMLsize = 0, upnperror = 0;
|
||||
char cIP[20];
|
||||
|
||||
// Don't init if already inited
|
||||
if (s_inited)
|
||||
return true;
|
||||
|
||||
// Don't init if it failed before
|
||||
if (s_error)
|
||||
return false;
|
||||
|
||||
memset(&m_upnp_urls, 0, sizeof(UPNPUrls));
|
||||
memset(&m_upnp_data, 0, sizeof(IGDdatas));
|
||||
|
||||
// Find all UPnP devices
|
||||
std::unique_ptr<UPNPDev, decltype(&freeUPNPDevlist)> devlist(nullptr, freeUPNPDevlist);
|
||||
#if MINIUPNPC_API_VERSION >= 14
|
||||
devlist.reset(upnpDiscover(2000, nullptr, nullptr, 0, 0, 2, &upnperror));
|
||||
#else
|
||||
devlist.reset(upnpDiscover(2000, nullptr, nullptr, 0, 0, &upnperror));
|
||||
#endif
|
||||
if (!devlist)
|
||||
{
|
||||
WARN_LOG(NETPLAY, "An error occurred trying to discover UPnP devices.");
|
||||
|
||||
s_error = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look for the IGD
|
||||
for (UPNPDev* dev = devlist.get(); dev; dev = dev->pNext)
|
||||
{
|
||||
if (strstr(dev->st, "InternetGatewayDevice"))
|
||||
igds.push_back(dev);
|
||||
}
|
||||
|
||||
for (const UPNPDev* dev : igds)
|
||||
{
|
||||
std::unique_ptr<char, decltype(&std::free)> descXML(nullptr, std::free);
|
||||
int statusCode = 200;
|
||||
#if MINIUPNPC_API_VERSION >= 16
|
||||
descXML.reset(static_cast<char*>(
|
||||
miniwget_getaddr(dev->descURL, &descXMLsize, cIP, sizeof(cIP), 0, &statusCode)));
|
||||
#else
|
||||
descXML.reset(
|
||||
static_cast<char*>(miniwget_getaddr(dev->descURL, &descXMLsize, cIP, sizeof(cIP), 0)));
|
||||
#endif
|
||||
if (descXML && statusCode == 200)
|
||||
{
|
||||
parserootdesc(descXML.get(), descXMLsize, &m_upnp_data);
|
||||
GetUPNPUrls(&m_upnp_urls, &m_upnp_data, dev->descURL, 0);
|
||||
|
||||
m_upnp_ourip = cIP;
|
||||
|
||||
NOTICE_LOG(NETPLAY, "Got info from IGD at %s.", dev->descURL);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN_LOG(NETPLAY, "Error getting info from IGD at %s.", dev->descURL);
|
||||
}
|
||||
}
|
||||
|
||||
s_inited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---UPnP--- thread
|
||||
// Attempt to portforward!
|
||||
bool NetPlayServer::UPnPMapPort(const std::string& addr, const u16 port)
|
||||
{
|
||||
if (m_upnp_mapped > 0)
|
||||
UPnPUnmapPort(m_upnp_mapped);
|
||||
|
||||
std::string port_str = StringFromFormat("%d", port);
|
||||
int result = UPNP_AddPortMapping(
|
||||
m_upnp_urls.controlURL, m_upnp_data.first.servicetype, port_str.c_str(), port_str.c_str(),
|
||||
addr.c_str(), (std::string("dolphin-emu UDP on ") + addr).c_str(), "UDP", nullptr, nullptr);
|
||||
|
||||
if (result != 0)
|
||||
return false;
|
||||
|
||||
m_upnp_mapped = port;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---UPnP--- thread
|
||||
// Attempt to stop portforwarding.
|
||||
// --
|
||||
// NOTE: It is important that this happens! A few very crappy routers
|
||||
// apparently do not delete UPnP mappings on their own, so if you leave them
|
||||
// hanging, the NVRAM will fill with portmappings, and eventually all UPnP
|
||||
// requests will fail silently, with the only recourse being a factory reset.
|
||||
// --
|
||||
bool NetPlayServer::UPnPUnmapPort(const u16 port)
|
||||
{
|
||||
std::string port_str = StringFromFormat("%d", port);
|
||||
UPNP_DeletePortMapping(m_upnp_urls.controlURL, m_upnp_data.first.servicetype, port_str.c_str(),
|
||||
"UDP", nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
void ThreadFunc();
|
||||
void SendAsyncToClients(sf::Packet&& packet);
|
||||
|
||||
NetPlayServer(const u16 port, bool traversal, const std::string& centralServer, u16 centralPort);
|
||||
NetPlayServer(u16 port, bool forward_port, const NetTraversalConfig& traversal_config);
|
||||
~NetPlayServer();
|
||||
|
||||
bool ChangeGame(const std::string& game);
|
||||
@ -58,10 +58,6 @@ public:
|
||||
|
||||
bool is_connected = false;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
void TryPortmapping(u16 port);
|
||||
#endif
|
||||
|
||||
private:
|
||||
class Client
|
||||
{
|
||||
@ -123,19 +119,4 @@ private:
|
||||
ENetHost* m_server = nullptr;
|
||||
TraversalClient* m_traversal_client = nullptr;
|
||||
NetPlayUI* m_dialog = nullptr;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
static void mapPortThread(const u16 port);
|
||||
static void unmapPortThread();
|
||||
|
||||
static bool initUPnP();
|
||||
static bool UPnPMapPort(const std::string& addr, const u16 port);
|
||||
static bool UPnPUnmapPort(const u16 port);
|
||||
|
||||
static struct UPNPUrls m_upnp_urls;
|
||||
static struct IGDdatas m_upnp_data;
|
||||
static std::string m_upnp_ourip;
|
||||
static u16 m_upnp_mapped;
|
||||
static std::thread m_upnp_thread;
|
||||
#endif
|
||||
};
|
||||
|
Reference in New Issue
Block a user