Skip to content

Commit

Permalink
DemonwareOverride: automatically port forward via upnp
Browse files Browse the repository at this point in the history
  • Loading branch information
emoose committed Aug 6, 2024
1 parent 8f258db commit 81b45c2
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 17 deletions.
43 changes: 29 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ endif()

include(FetchContent)

# Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
message(STATUS "Fetching zydis (v4.0.0)...")
FetchContent_Declare(zydis
GIT_REPOSITORY
Expand Down Expand Up @@ -93,16 +97,27 @@ FetchContent_Declare(flac
)
FetchContent_MakeAvailable(flac)

message(STATUS "Fetching miniupnpc (miniupnpd_2_3_7)...")
FetchContent_Declare(miniupnpc
GIT_REPOSITORY
"https://github.com/miniupnp/miniupnp"
GIT_TAG
miniupnpd_2_3_7
SOURCE_SUBDIR
miniupnpc
)
FetchContent_MakeAvailable(miniupnpc)

# Target: spdlog
set(spdlog_SOURCES
cmake.toml
"external/spdlog/src/async.cpp"
"external/spdlog/src/bundled_fmtlib_format.cpp"
"external/spdlog/src/cfg.cpp"
"external/spdlog/src/color_sinks.cpp"
"external/spdlog/src/file_sinks.cpp"
"external/spdlog/src/spdlog.cpp"
"external/spdlog/src/stdout_sinks.cpp"
cmake.toml
)

add_library(spdlog STATIC)
Expand All @@ -121,9 +136,21 @@ target_include_directories(spdlog PUBLIC

# Target: outrun2006tweaks
set(outrun2006tweaks_SOURCES
cmake.toml
"external/ModUtils/MemoryMgr.h"
"external/ModUtils/Patterns.cpp"
"external/ModUtils/Patterns.h"
"external/xxHash/xxhash.c"
"external/xxHash/xxhash.h"
"src/Proxy.cpp"
"src/Proxy.def"
"src/Proxy.hpp"
"src/Resource.rc"
"src/dllmain.cpp"
"src/game.hpp"
"src/game_addrs.hpp"
"src/hook_mgr.cpp"
"src/hook_mgr.hpp"
"src/hooks_audio.cpp"
"src/hooks_bugfixes.cpp"
"src/hooks_flac.cpp"
Expand All @@ -134,20 +161,8 @@ set(outrun2006tweaks_SOURCES
"src/hooks_misc.cpp"
"src/hooks_textures.cpp"
"src/hooks_uiscaling.cpp"
"src/Proxy.def"
"src/Resource.rc"
"external/ModUtils/Patterns.cpp"
"external/xxHash/xxhash.c"
"src/Proxy.hpp"
"src/game.hpp"
"src/game_addrs.hpp"
"src/hook_mgr.hpp"
"src/plugin.hpp"
"src/resource.h"
"external/ModUtils/Patterns.h"
"external/ModUtils/MemoryMgr.h"
"external/xxHash/xxhash.h"
cmake.toml
)

add_library(outrun2006tweaks SHARED)
Expand Down Expand Up @@ -190,6 +205,7 @@ target_link_libraries(outrun2006tweaks PUBLIC
version.lib
xinput9_1_0.lib
Hid.lib
libminiupnpc-static
)

target_link_options(outrun2006tweaks PUBLIC
Expand All @@ -216,4 +232,3 @@ set_target_properties(outrun2006tweaks PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO
"${CMAKE_BINARY_DIR}/lib/${CMKR_TARGET}"
)

4 changes: 3 additions & 1 deletion cmake.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ zydis = { git = "https://github.com/zyantific/zydis", tag = "v4.0.0" }
safetyhook = { git = "https://github.com/cursey/safetyhook", tag = "629558c64009a7291ba6ed5cfb49187086a27a47" }
ogg = { git = "https://github.com/xiph/ogg", tag = "v1.3.5" }
flac = { git = "https://github.com/xiph/flac", tag = "1.4.3" }
miniupnpc = { git = "https://github.com/miniupnp/miniupnp", tag = "miniupnpd_2_3_7", subdir = "miniupnpc" }

[target.outrun2006tweaks]
type = "shared"
Expand All @@ -64,7 +65,8 @@ link-libraries = [
"FLAC",
"version.lib",
"xinput9_1_0.lib",
"Hid.lib"
"Hid.lib",
"libminiupnpc-static"
]

[target.outrun2006tweaks.properties]
Expand Down
2 changes: 1 addition & 1 deletion cmkr.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ include_guard()

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

# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
Expand Down
61 changes: 60 additions & 1 deletion src/hooks_misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "plugin.hpp"
#include "game_addrs.hpp"
#include <random>
#include <miniupnpc.h>
#include <upnpcommands.h>
#include <WinSock2.h>

class DemonwareServerOverride : public Hook
{
Expand All @@ -16,6 +19,60 @@ class DemonwareServerOverride : public Hook
return ret;
}

inline static SafetyHookInline InitNetwork = {};
static void __cdecl InitNetwork_dest()
{
InitNetwork.call();

WSADATA tmp;
WSAStartup(0x202, &tmp);

int upnpError = UPNPDISCOVER_SUCCESS;
UPNPDev* upnpDevice = upnpDiscover(2000, NULL, NULL, 0, 0, 2, &upnpError);

bool anyError = false;
int ret = 0;
if (upnpError != UPNPDISCOVER_SUCCESS || !upnpDevice)
{
spdlog::error("UPnP: upnpDiscover failed with error {}", upnpError);
return;
}

struct UPNPUrls urls;
struct IGDdatas data;
char lanaddr[16];
char wanaddr[16];

ret = UPNP_GetValidIGD(upnpDevice, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr));
if (ret != 1 && ret != 2 && ret != 3) // UPNP_GetValidIGD returning 1/2/3 should be fine
{
spdlog::error("UPnP: UPNP_GetValidIGD failed with error {}", ret);
return;
}

std::list<int> portNums = { 41455, 41456, 41457 };

for (auto port : portNums)
{
for (int i = 0; i < 2; i++)
{
ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
std::to_string(port).c_str(), std::to_string(port).c_str(),
lanaddr, "OutRun2006", i == 0 ? "TCP" : "UDP", NULL, NULL);
if (ret != UPNPCOMMAND_SUCCESS)
{
spdlog::error("UPnP: UPNP_AddPortMapping failed for port {}/{}, error code {}", port, i, ret);
anyError = true;
}
}
}

if (ret == 0 && !anyError)
{
spdlog::info("UPnP: port mappings succeeded");
}
}

public:
std::string_view description() override
{
Expand All @@ -29,8 +86,10 @@ class DemonwareServerOverride : public Hook

bool apply() override
{
constexpr int bdPlatformSocket__getHostByName_Addr = 0x1349B0;
constexpr int InitNetwork_Addr = 0x5ACB0;
InitNetwork = safetyhook::create_inline(Module::exe_ptr(InitNetwork_Addr), InitNetwork_dest);

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

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

0 comments on commit 81b45c2

Please sign in to comment.