Skip to content

Commit 81b45c2

Browse files
committed
DemonwareOverride: automatically port forward via upnp
1 parent 8f258db commit 81b45c2

File tree

4 files changed

+93
-17
lines changed

4 files changed

+93
-17
lines changed

CMakeLists.txt

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ endif()
5757

5858
include(FetchContent)
5959

60+
# Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP
61+
if(POLICY CMP0135)
62+
cmake_policy(SET CMP0135 NEW)
63+
endif()
6064
message(STATUS "Fetching zydis (v4.0.0)...")
6165
FetchContent_Declare(zydis
6266
GIT_REPOSITORY
@@ -93,16 +97,27 @@ FetchContent_Declare(flac
9397
)
9498
FetchContent_MakeAvailable(flac)
9599

100+
message(STATUS "Fetching miniupnpc (miniupnpd_2_3_7)...")
101+
FetchContent_Declare(miniupnpc
102+
GIT_REPOSITORY
103+
"https://github.com/miniupnp/miniupnp"
104+
GIT_TAG
105+
miniupnpd_2_3_7
106+
SOURCE_SUBDIR
107+
miniupnpc
108+
)
109+
FetchContent_MakeAvailable(miniupnpc)
110+
96111
# Target: spdlog
97112
set(spdlog_SOURCES
113+
cmake.toml
98114
"external/spdlog/src/async.cpp"
99115
"external/spdlog/src/bundled_fmtlib_format.cpp"
100116
"external/spdlog/src/cfg.cpp"
101117
"external/spdlog/src/color_sinks.cpp"
102118
"external/spdlog/src/file_sinks.cpp"
103119
"external/spdlog/src/spdlog.cpp"
104120
"external/spdlog/src/stdout_sinks.cpp"
105-
cmake.toml
106121
)
107122

108123
add_library(spdlog STATIC)
@@ -121,9 +136,21 @@ target_include_directories(spdlog PUBLIC
121136

122137
# Target: outrun2006tweaks
123138
set(outrun2006tweaks_SOURCES
139+
cmake.toml
140+
"external/ModUtils/MemoryMgr.h"
141+
"external/ModUtils/Patterns.cpp"
142+
"external/ModUtils/Patterns.h"
143+
"external/xxHash/xxhash.c"
144+
"external/xxHash/xxhash.h"
124145
"src/Proxy.cpp"
146+
"src/Proxy.def"
147+
"src/Proxy.hpp"
148+
"src/Resource.rc"
125149
"src/dllmain.cpp"
150+
"src/game.hpp"
151+
"src/game_addrs.hpp"
126152
"src/hook_mgr.cpp"
153+
"src/hook_mgr.hpp"
127154
"src/hooks_audio.cpp"
128155
"src/hooks_bugfixes.cpp"
129156
"src/hooks_flac.cpp"
@@ -134,20 +161,8 @@ set(outrun2006tweaks_SOURCES
134161
"src/hooks_misc.cpp"
135162
"src/hooks_textures.cpp"
136163
"src/hooks_uiscaling.cpp"
137-
"src/Proxy.def"
138-
"src/Resource.rc"
139-
"external/ModUtils/Patterns.cpp"
140-
"external/xxHash/xxhash.c"
141-
"src/Proxy.hpp"
142-
"src/game.hpp"
143-
"src/game_addrs.hpp"
144-
"src/hook_mgr.hpp"
145164
"src/plugin.hpp"
146165
"src/resource.h"
147-
"external/ModUtils/Patterns.h"
148-
"external/ModUtils/MemoryMgr.h"
149-
"external/xxHash/xxhash.h"
150-
cmake.toml
151166
)
152167

153168
add_library(outrun2006tweaks SHARED)
@@ -190,6 +205,7 @@ target_link_libraries(outrun2006tweaks PUBLIC
190205
version.lib
191206
xinput9_1_0.lib
192207
Hid.lib
208+
libminiupnpc-static
193209
)
194210

195211
target_link_options(outrun2006tweaks PUBLIC
@@ -216,4 +232,3 @@ set_target_properties(outrun2006tweaks PROPERTIES
216232
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO
217233
"${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}"
218234
)
219-

cmake.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ zydis = { git = "https://github.com/zyantific/zydis", tag = "v4.0.0" }
4747
safetyhook = { git = "https://github.com/cursey/safetyhook", tag = "629558c64009a7291ba6ed5cfb49187086a27a47" }
4848
ogg = { git = "https://github.com/xiph/ogg", tag = "v1.3.5" }
4949
flac = { git = "https://github.com/xiph/flac", tag = "1.4.3" }
50+
miniupnpc = { git = "https://github.com/miniupnp/miniupnp", tag = "miniupnpd_2_3_7", subdir = "miniupnpc" }
5051

5152
[target.outrun2006tweaks]
5253
type = "shared"
@@ -64,7 +65,8 @@ link-libraries = [
6465
"FLAC",
6566
"version.lib",
6667
"xinput9_1_0.lib",
67-
"Hid.lib"
68+
"Hid.lib",
69+
"libminiupnpc-static"
6870
]
6971

7072
[target.outrun2006tweaks.properties]

cmkr.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ include_guard()
22

33
# Change these defaults to point to your infrastructure if desired
44
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
5-
set(CMKR_TAG "v0.2.18" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
5+
set(CMKR_TAG "v0.2.34" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
66
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
77

88
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake

src/hooks_misc.cpp

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include "plugin.hpp"
66
#include "game_addrs.hpp"
77
#include <random>
8+
#include <miniupnpc.h>
9+
#include <upnpcommands.h>
10+
#include <WinSock2.h>
811

912
class DemonwareServerOverride : public Hook
1013
{
@@ -16,6 +19,60 @@ class DemonwareServerOverride : public Hook
1619
return ret;
1720
}
1821

22+
inline static SafetyHookInline InitNetwork = {};
23+
static void __cdecl InitNetwork_dest()
24+
{
25+
InitNetwork.call();
26+
27+
WSADATA tmp;
28+
WSAStartup(0x202, &tmp);
29+
30+
int upnpError = UPNPDISCOVER_SUCCESS;
31+
UPNPDev* upnpDevice = upnpDiscover(2000, NULL, NULL, 0, 0, 2, &upnpError);
32+
33+
bool anyError = false;
34+
int ret = 0;
35+
if (upnpError != UPNPDISCOVER_SUCCESS || !upnpDevice)
36+
{
37+
spdlog::error("UPnP: upnpDiscover failed with error {}", upnpError);
38+
return;
39+
}
40+
41+
struct UPNPUrls urls;
42+
struct IGDdatas data;
43+
char lanaddr[16];
44+
char wanaddr[16];
45+
46+
ret = UPNP_GetValidIGD(upnpDevice, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr));
47+
if (ret != 1 && ret != 2 && ret != 3) // UPNP_GetValidIGD returning 1/2/3 should be fine
48+
{
49+
spdlog::error("UPnP: UPNP_GetValidIGD failed with error {}", ret);
50+
return;
51+
}
52+
53+
std::list<int> portNums = { 41455, 41456, 41457 };
54+
55+
for (auto port : portNums)
56+
{
57+
for (int i = 0; i < 2; i++)
58+
{
59+
ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
60+
std::to_string(port).c_str(), std::to_string(port).c_str(),
61+
lanaddr, "OutRun2006", i == 0 ? "TCP" : "UDP", NULL, NULL);
62+
if (ret != UPNPCOMMAND_SUCCESS)
63+
{
64+
spdlog::error("UPnP: UPNP_AddPortMapping failed for port {}/{}, error code {}", port, i, ret);
65+
anyError = true;
66+
}
67+
}
68+
}
69+
70+
if (ret == 0 && !anyError)
71+
{
72+
spdlog::info("UPnP: port mappings succeeded");
73+
}
74+
}
75+
1976
public:
2077
std::string_view description() override
2178
{
@@ -29,8 +86,10 @@ class DemonwareServerOverride : public Hook
2986

3087
bool apply() override
3188
{
32-
constexpr int bdPlatformSocket__getHostByName_Addr = 0x1349B0;
89+
constexpr int InitNetwork_Addr = 0x5ACB0;
90+
InitNetwork = safetyhook::create_inline(Module::exe_ptr(InitNetwork_Addr), InitNetwork_dest);
3391

92+
constexpr int bdPlatformSocket__getHostByName_Addr = 0x1349B0;
3493
bdPlatformSocket__getHostByName_hook = safetyhook::create_inline(Module::exe_ptr(bdPlatformSocket__getHostByName_Addr), destination);
3594

3695
// DW has a very simple check to see if hostname is an IP: if first digit is a number, it's an IP addr

0 commit comments

Comments
 (0)