1,202 changes: 601 additions & 601 deletions Source/Core/Core/Core.vcxproj

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions Source/Core/Core/Src/NetPlay.h
Expand Up @@ -192,6 +192,10 @@ class NetPlayServer : public NetPlay
u64 CalculateMinimumBufferTime();
void AdjustPadBufferSize(unsigned int size);

#ifdef USE_UPNP
void TryPortmapping(u16 port);
#endif

private:
class Client : public Player
{
Expand All @@ -215,6 +219,22 @@ class NetPlayServer : public NetPlay
Common::Timer m_ping_timer;
u32 m_ping_key;
bool m_update_pings;

#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 u16 m_upnp_mapped;
static bool m_upnp_inited;
static bool m_upnp_error;
static std::thread m_upnp_thread;
#endif
};

class NetPlayClient : public NetPlay
Expand Down
167 changes: 166 additions & 1 deletion Source/Core/Core/Src/NetPlayServer.cpp
Expand Up @@ -11,7 +11,14 @@ NetPlayServer::~NetPlayServer()
{
m_do_loop = false;
m_thread.join();
}
}

#ifdef USE_UPNP
if (m_upnp_thread.joinable())
m_upnp_thread.join();
m_upnp_thread = std::thread(&NetPlayServer::unmapPortThread);
m_upnp_thread.join();
#endif
}

// called from ---GUI--- thread
Expand Down Expand Up @@ -632,3 +639,161 @@ void NetPlayServer::SendToClients(sf::Packet& packet, const PlayerId skip_pid)
if (i->second.pid && (i->second.pid != skip_pid))
i->second.socket.Send(packet);
}

#ifdef USE_UPNP
#include <miniwget.h>
#include <miniupnpc.h>
#include <upnpcommands.h>

struct UPNPUrls NetPlayServer::m_upnp_urls;
struct IGDdatas NetPlayServer::m_upnp_data;
u16 NetPlayServer::m_upnp_mapped = 0;
bool NetPlayServer::m_upnp_inited = false;
bool NetPlayServer::m_upnp_error = false;
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)
{
std::string ourIP = sf::IPAddress::GetLocalAddress().ToString();

if (!m_upnp_inited)
if (!initUPnP())
goto fail;

if (!UPnPMapPort(ourIP, port))
goto fail;

NOTICE_LOG(NETPLAY, "Successfully mapped port %d to %s.", port, ourIP.c_str());
return;
fail:
WARN_LOG(NETPLAY, "Failed to map port %d to %s.", port, ourIP.c_str());
return;
}

// 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()
{
UPNPDev *devlist, *dev;
std::vector<UPNPDev *> igds;
int descXMLsize = 0, upnperror = 0;
char *descXML;

// Don't init if already inited
if (m_upnp_inited)
return true;

// Don't init if it failed before
if (m_upnp_error)
return false;

memset(&m_upnp_urls, 0, sizeof(UPNPUrls));
memset(&m_upnp_data, 0, sizeof(IGDdatas));

// Find all UPnP devices
devlist = upnpDiscover(2000, NULL, NULL, 0, 0, &upnperror);
if (!devlist)
{
WARN_LOG(NETPLAY, "An error occured trying to discover UPnP devices.");

m_upnp_error = true;
m_upnp_inited = false;

return false;
}

// Look for the IGD
dev = devlist;
while (dev)
{
if (strstr(dev->st, "InternetGatewayDevice"))
igds.push_back(dev);
dev = dev->pNext;
}

std::vector<UPNPDev *>::iterator i;
for (i = igds.begin(); i != igds.end(); i++)
{
dev = *i;
descXML = (char *) miniwget(dev->descURL, &descXMLsize, 0);
if (descXML)
{
parserootdesc(descXML, descXMLsize, &m_upnp_data);
free(descXML);
descXML = 0;
GetUPNPUrls(&m_upnp_urls, &m_upnp_data, dev->descURL, 0);

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);
}
}

freeUPNPDevlist(devlist);

return true;
}

// called from ---UPnP--- thread
// Attempt to portforward!
bool NetPlayServer::UPnPMapPort(const std::string& addr, const u16 port)
{
char port_str[6] = { 0 };
int result;

if (m_upnp_mapped > 0)
UPnPUnmapPort(m_upnp_mapped);

sprintf(port_str, "%d", port);
result = UPNP_AddPortMapping(m_upnp_urls.controlURL, m_upnp_data.first.servicetype,
port_str, port_str, addr.c_str(),
(std::string("dolphin-emu TCP on ") + addr).c_str(),
"TCP", NULL, NULL);

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)
{
char port_str[6] = { 0 };

sprintf(port_str, "%d", port);
UPNP_DeletePortMapping(m_upnp_urls.controlURL, m_upnp_data.first.servicetype,
port_str, "TCP", NULL);

return true;
}
#endif

4 changes: 4 additions & 0 deletions Source/Core/DolphinWX/CMakeLists.txt
Expand Up @@ -164,6 +164,10 @@ else()
set(DOLPHIN_EXE ${DOLPHIN_EXE_BASE}-nogui)
endif()

if(USE_UPNP)
set(LIBS ${LIBS} miniupnpc)
endif()

if(ANDROID)
add_library(${DOLPHIN_EXE} SHARED ${SRCS})
target_link_libraries(${DOLPHIN_EXE}
Expand Down
747 changes: 375 additions & 372 deletions Source/Core/DolphinWX/Dolphin.vcxproj

Large diffs are not rendered by default.

612 changes: 308 additions & 304 deletions Source/Core/DolphinWX/Dolphin.vcxproj.filters

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Source/Core/DolphinWX/Src/NetWindow.cpp
Expand Up @@ -149,6 +149,10 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
top_szr->Add(port_lbl, 0, wxCENTER | wxRIGHT, 5);
top_szr->Add(m_host_port_text, 0);
#ifdef USE_UPNP
m_upnp_chk = new wxCheckBox(host_tab, wxID_ANY, _("Forward port (UPnP)"));
top_szr->Add(m_upnp_chk, 0, wxALL | wxALIGN_RIGHT, 5);
#endif

wxBoxSizer* const host_szr = new wxBoxSizer(wxVERTICAL);
host_szr->Add(top_szr, 0, wxALL | wxEXPAND, 5);
Expand Down Expand Up @@ -220,6 +224,10 @@ void NetPlaySetupDiag::OnHost(wxCommandEvent&)
, WxStrToStr(m_nickname_text->GetValue()), npd, game);
if (netplay_ptr->is_connected)
{
#ifdef USE_UPNP
if(m_upnp_chk->GetValue())
((NetPlayServer*)netplay_ptr)->TryPortmapping(port);
#endif
npd->Show();
Destroy();
}
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinWX/Src/NetWindow.h
Expand Up @@ -48,6 +48,9 @@ class NetPlaySetupDiag : public wxFrame
*m_connect_ip_text;

wxListBox* m_game_lbox;
#ifdef USE_UPNP
wxCheckBox* m_upnp_chk;
#endif

const CGameListCtrl* const m_game_list;
};
Expand Down
14 changes: 14 additions & 0 deletions Source/Dolphin_2010.sln
Expand Up @@ -112,6 +112,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "..\Externals\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests", "UnitTests\UnitTests.vcxproj", "{40C636FA-B5BF-4D67-ABC8-376B524A7551}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "..\Externals\miniupnpc\miniupnpc.vcxproj", "{A680190D-0764-485B-9CF3-A82C5EDD5715}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Expand Down Expand Up @@ -409,6 +411,18 @@ Global
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|Win32.Build.0 = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|x64.ActiveCfg = Release|x64
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|x64.Build.0 = Release|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Debug|Win32.ActiveCfg = Debug|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Debug|Win32.Build.0 = Debug|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Debug|x64.ActiveCfg = Debug|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Debug|x64.Build.0 = Debug|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.DebugFast|Win32.ActiveCfg = Debug|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.DebugFast|Win32.Build.0 = Debug|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.DebugFast|x64.ActiveCfg = Debug|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.DebugFast|x64.Build.0 = Debug|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Release|Win32.ActiveCfg = Release|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Release|Win32.Build.0 = Release|Win32
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Release|x64.ActiveCfg = Release|x64
{A680190D-0764-485B-9CF3-A82C5EDD5715}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
54 changes: 27 additions & 27 deletions Source/VSProps/Base.props
@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StructMemberAlignment>16Bytes</StructMemberAlignment>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<BaseAddress>0x00400000</BaseAddress>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;USE_UPNP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<StructMemberAlignment>16Bytes</StructMemberAlignment>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<BaseAddress>0x00400000</BaseAddress>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
30 changes: 15 additions & 15 deletions Source/VSProps/Dolphin.Win32.props
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>..\..\..\Binary\$(PlatformName)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>..\..\..\Binary\$(PlatformName)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
32 changes: 16 additions & 16 deletions Source/VSProps/Dolphin.x64.props
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>Dolphin.x64</_PropertySheetDisplayName>
<OutDir>..\..\..\Binary\$(PlatformName)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>Dolphin.x64</_PropertySheetDisplayName>
<OutDir>..\..\..\Binary\$(PlatformName)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>