From ef5111b60d12395d1f209ac2c562113f0cc17a62 Mon Sep 17 00:00:00 2001 From: nukeulater <18323679+nukeulater@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:40:15 +0200 Subject: [PATCH] add LAN address override configuration command, ComVar updates, removed redundant WAN config option --- .../GUI/imgui_integration/Console/ComVar.h | 123 +++++++++++++++--- .../Console/CommandCollection.cpp | 28 +++- .../Console/CommandCollection.h | 5 +- .../Console/CommandHandler.h | 2 +- xlive/H2MOD/Modules/Accounts/AccountLogin.cpp | 3 - xlive/H2MOD/Modules/Shell/Config.cpp | 24 +--- xlive/H2MOD/Modules/Shell/Config.h | 3 - xlive/XLive/xnet/Sockets/XSocket.h | 8 +- 8 files changed, 146 insertions(+), 50 deletions(-) diff --git a/xlive/H2MOD/GUI/imgui_integration/Console/ComVar.h b/xlive/H2MOD/GUI/imgui_integration/Console/ComVar.h index fc2822f88..083281940 100644 --- a/xlive/H2MOD/GUI/imgui_integration/Console/ComVar.h +++ b/xlive/H2MOD/GUI/imgui_integration/Console/ComVar.h @@ -8,13 +8,17 @@ extern std::string empty; const ComVar<_var_type> _var_name##__LINE__(_var_ptr); \ ConsoleCommand _var_name((ComVarBase*)&_var_name##__LINE__, _command_name, _description, _min_parameter_count, _max_parameter_count, _callback); +#define ComVarFromPtrIpv4(_var_name, _var_ptr, _command_name, _description, _min_parameter_count, _max_parameter_count, _callback) \ +const ComVarAddrIpv4 _var_name##__LINE__(_var_ptr); \ +ConsoleCommand _var_name((ComVarBase*)&_var_name##__LINE__, _command_name, _description, _min_parameter_count, _max_parameter_count, _callback); + class ComVarBase { public: ComVarBase() = default; virtual ~ComVarBase() = default; - virtual std::string GetValStr() const + virtual std::string AsString() const { return ""; } @@ -67,6 +71,12 @@ class CStrToValue return std::stol(str, nullptr, _Base); } + template<> + static unsigned long ToIntegral(const std::string& str, int _Base) + { + return std::stoul(str, nullptr, _Base); + } + template<> static long long ToIntegral(const std::string& str, int _Base) { @@ -106,9 +116,29 @@ class CStrToValue }; template -class ComVar : private CStrToValue, public ComVarBase +class ComVar : protected CStrToValue, public ComVarBase { +protected: T* m_var_ptr; + + template + std::string ToString() const + { + return std::to_string(*m_var_ptr); + } + + template<> + std::string ToString() const + { + return *m_var_ptr ? "true" : "false"; + } + + template<> + std::string ToString() const + { + return ToString(); + } + public: // for custom types, the class should implement the equal operator overload // othewise default is used @@ -173,36 +203,95 @@ class ComVar : private CStrToValue, public ComVarBase return success; } - template - std::string AsString() const + std::string AsString() const override { - return std::to_string(*m_var_ptr); + return ToString(); } - template<> - std::string AsString() const + T GetVal() const { - return *m_var_ptr ? "true" : "false"; + return *m_var_ptr; } - template<> - std::string AsString() const + void SetVal(T val) { - return AsString(); + *m_var_ptr = val; } +}; - std::string GetValStr() const override +class ComVarAddrIpv4 : public ComVar +{ +public: + ComVarAddrIpv4(unsigned long* ptr) + : ComVar(ptr) { - return AsString(); } - T GetVal() const + std::string AsString() const override { - return *m_var_ptr; + return std::string(std::to_string(*m_var_ptr & 0x000000FF)) + '.' + + std::string(std::to_string((*m_var_ptr & 0x0000FF00) >> 8)) + '.' + + std::string(std::to_string((*m_var_ptr & 0x00FF0000) >> 16)) + '.' + + std::string(std::to_string((*m_var_ptr & 0xFF000000) >> 24)); } - void SetVal(T val) + bool SetFromStr(const std::string& str, std::string& potentialException = empty) { - *m_var_ptr = val; + bool success = true; + try + { + std::string subip_address(""); + size_t cur_offset = 0; + + unsigned long new_address = 0; + + if (str.length() < std::string("0.0.0.0").length() + || str.length() > std::string("255.255.255.255").length() + || str.find_first_not_of("0123456789.") != std::string::npos) + { + throw std::runtime_error("invalid ipv4 address format"); + } + + /* + for (int i = 0; i < 3; i++) + { + size_t dot_occurrance = str.find_first_of('.', cur_offset); + if (dot_occurrance == std::string::npos + || dot_occurrance <= cur_offset + || dot_occurrance - cur_offset < 1) + { + throw std::runtime_error("invalid ipv4 address format"); + } + + subip_address = str.substr(cur_offset, dot_occurrance - cur_offset); + + if (ComVar::ToIntegral(subip_address, 10) != ComVar::ToIntegral(subip_address, 0)) + { + throw std::runtime_error("invalid ipv4 address format"); + } + + new_address |= (ComVar::ToIntegral(subip_address, 10) & 0xFF) << (i * 8); + cur_offset = dot_occurrance + 1; + } + + subip_address = str.substr(cur_offset, str.length() - cur_offset); + + if (ComVar::ToIntegral(subip_address, 10) != ComVar::ToIntegral(subip_address, 0)) + { + throw std::runtime_error("invalid ipv4 address format"); + } + + new_address |= ComVar::ToIntegral(subip_address, 10) & 0xFF << 24; + */ + + *m_var_ptr = inet_addr(str.c_str()); + } + catch (const std::exception& e) + { + success = false; + potentialException.assign(e.what()); + } + + return success; } }; \ No newline at end of file diff --git a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp index f60338218..89dafff0b 100644 --- a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp +++ b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp @@ -20,6 +20,7 @@ #include "H2MOD.h" #include "H2MOD/GUI/imgui_integration/imgui_handler.h" #include "H2MOD/Modules/MapManager/MapManager.h" +#include "H2MOD/Modules/Shell/Config.h" // for XNet connection logging #include "tag_files/tag_loader/tag_injection.h" @@ -45,6 +46,9 @@ ComVarFromPtr(rumble_var_cmd, real32, &g_rumble_factor, ComVarFromPtr(debug_render_horizontal_splitscreen, bool, &g_debug_render_horizontal_splitscreen, "var_debug_render_horizontal_splitscreen", "force horizontal spliscreen split", 0, 1, CommandCollection::BoolVarHandlerCmd); +ComVarFromPtrIpv4(h2config_set_lan_ipv4_address, &H2Config_ip_lan, + "var_lan_ip_address_override", "", 1, 1, CommandCollection::SetAddressIpv4HandlerCmd); + // don't forget to add '_cmd' after the name, // if you add a variable command created using `DECL_ComVarCommandPtr` macro std::vector CommandCollection::commandTable; @@ -59,6 +63,7 @@ void CommandCollection::InitializeCommands() InsertCommand(new ConsoleCommand(og_frame_limiter_var_cmd)); InsertCommand(new ConsoleCommand(rumble_var_cmd)); InsertCommand(new ConsoleCommand(debug_render_horizontal_splitscreen)); + InsertCommand(new ConsoleCommand(h2config_set_lan_ipv4_address)); InsertCommand(new ConsoleCommand("help", "outputs all commands, 0 - 1 parameter(s): (optional): command name", 0, 1, CommandCollection::HelpCmd)); InsertCommand(new ConsoleCommand("log_peers", "logs all peers to console, 0 parameter(s)", 0, 0, CommandCollection::LogPeersCmd)); InsertCommand(new ConsoleCommand("log_players", "logs all players to console, 0 parameter(s)", 0, 0, CommandCollection::LogPlayersCmd)); @@ -173,6 +178,25 @@ int CommandCollection::BoolVarHandlerCmd(const std::vector& tokens, return 0; } +int CommandCollection::SetAddressIpv4HandlerCmd(const std::vector& tokens, ConsoleCommandCtxData ctx) +{ + TextOutputCb* outputCb = ctx.outputCb; + + auto address = ctx.consoleCommand->GetVar(); + + std::string exception; + if (address->SetFromStr(tokens[1], exception)) + { + } + else + { + outputCb(StringFlag_None, command_error_bad_arg); + outputCb(StringFlag_None, " %s", exception.c_str()); + } + + return 0; +} + int CommandCollection::RumbleScaleCmd(const std::vector& tokens, ConsoleCommandCtxData ctx) { TextOutputCb* outputCb = ctx.outputCb; @@ -722,7 +746,7 @@ int CommandCollection::SpawnCmd(const std::vector& tokens, ConsoleC ObjectSpawn(objectDatum, count, pPosition, pRotation, 1.0f, sameTeam); - // outputCbFmt(StringFlag_None, "# spawned: %s, near player: %s with rotation: %i", objectName.c_str(), nearPlayerSpawn.GetValStr().c_str(), withRotation); + // outputCbFmt(StringFlag_None, "# spawned: %s, near player: %s with rotation: %i", objectName.c_str(), nearPlayerSpawn.AsString().c_str(), withRotation); return 0; } @@ -976,4 +1000,4 @@ int CommandCollection::_screenshot_cubemap(const std::vector& token ImGuiHandler::ToggleWindow("console"); // Close the console window so it doesn't appear in the cubemap screenshot screenshot_cubemap(tokens[1].c_str()); return 0; -} +} \ No newline at end of file diff --git a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.h b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.h index 5821827d9..221449547 100644 --- a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.h +++ b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.h @@ -15,6 +15,9 @@ namespace CommandCollection void InitializeCommands(); // commands + int BoolVarHandlerCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); + int SetAddressIpv4HandlerCmd(const std::vector& tokens, ConsoleCommandCtxData ctx); + int RumbleScaleCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); int NetworkMetricsCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); int SetD3D9ExStateCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); @@ -35,7 +38,7 @@ namespace CommandCollection int KickPeerCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); int SpawnCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); int InjectTagCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); - int BoolVarHandlerCmd(const std::vector& tokens, ConsoleCommandCtxData cbData); + int Crash(const std::vector& tokens, ConsoleCommandCtxData cbData); int map_name(const std::vector& tokens, ConsoleCommandCtxData cbData); int game_difficulty(const std::vector& tokens, ConsoleCommandCtxData cbData); diff --git a/xlive/H2MOD/GUI/imgui_integration/Console/CommandHandler.h b/xlive/H2MOD/GUI/imgui_integration/Console/CommandHandler.h index 3c927463b..2f14a7df8 100644 --- a/xlive/H2MOD/GUI/imgui_integration/Console/CommandHandler.h +++ b/xlive/H2MOD/GUI/imgui_integration/Console/CommandHandler.h @@ -95,7 +95,7 @@ class ConsoleCommand final { if (SetsVariable()) { - strncpy(outVar, m_var_ptr->GetValStr().c_str(), outSize - 1); + strncpy(outVar, m_var_ptr->AsString().c_str(), outSize - 1); } } diff --git a/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp b/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp index b516bd9e7..12b8c4971 100644 --- a/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp +++ b/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp @@ -194,9 +194,6 @@ static int InterpretMasterLogin(char* response_content, char* prev_login_token) addDebugText("Client External IP Address is: %s", tempstr1); unsigned long resolvedAddr; if ((resolvedAddr = inet_addr(tempstr1)) != INADDR_NONE) { - if (strlen(H2Config_str_wan) <= 0 && strlen(H2Config_str_lan) > 0) { - H2Config_ip_wan = resolvedAddr; - } xnaddr = resolvedAddr; } } diff --git a/xlive/H2MOD/Modules/Shell/Config.cpp b/xlive/H2MOD/Modules/Shell/Config.cpp index 52832a4b9..852c99663 100644 --- a/xlive/H2MOD/Modules/Shell/Config.cpp +++ b/xlive/H2MOD/Modules/Shell/Config.cpp @@ -35,10 +35,7 @@ std::string cartographerURL = "https://cartographer.online"; std::string cartographerMapRepoURL = "http://www.h2maps.net/Cartographer/CustomMaps"; unsigned short H2Config_base_port = 2000; -char H2Config_str_wan[16] = { "" }; -char H2Config_str_lan[16] = { "" }; -unsigned long H2Config_ip_wan = 0; -unsigned long H2Config_ip_lan = 0; +unsigned long H2Config_ip_lan = INADDR_ANY; _H2Config_language H2Config_language = { -1, 0 }; bool H2Config_custom_labels_capture_missing = false; bool H2Config_skip_intro = false; @@ -135,7 +132,7 @@ set_config_entry(CSimpleIniA* simple_ini, const char* section_key, const char* c try { - value_as_string = ComVar(value).GetValStr(); + value_as_string = ComVar(value).AsString(); } catch (...) { @@ -424,8 +421,8 @@ void SaveH2Config() { CONFIG_SET(&ini, "h2portable", &H2Portable); CONFIG_SET(&ini, "base_port", &H2Config_base_port); - CONFIG_SET(&ini, "wan_ip", H2Config_str_wan); - CONFIG_SET(&ini, "lan_ip", H2Config_str_lan); + ComVarAddrIpv4 address_lan(&H2Config_ip_lan); + CONFIG_SET(&ini, "lan_ip", address_lan.AsString().c_str()); CONFIG_SET(&ini, "upnp", &H2Config_upnp_enable); @@ -599,24 +596,13 @@ void ReadH2Config() { CONFIG_GET(&ini, "debug_log_level", "2", &H2Config_debug_log_level); CONFIG_GET(&ini, "debug_log_console", "false", &H2Config_debug_log_console); - const char* ip_wan = nullptr; - CONFIG_GET(&ini, "wan_ip", "", &ip_wan); - if (ip_wan - && strnlen_s(ip_wan, 15) >= 7 - && inet_addr(ip_wan) != INADDR_NONE) - { - strncpy(H2Config_str_wan, ip_wan, 15); - H2Config_ip_wan = inet_addr(H2Config_str_wan); - } - const char* ip_lan = nullptr; CONFIG_GET(&ini, "lan_ip", "", &ip_lan); if (ip_lan && strnlen_s(ip_lan, 15) >= 7 && inet_addr(ip_lan) != INADDR_NONE) { - strncpy(H2Config_str_lan, ip_lan, 15); - H2Config_ip_lan = inet_addr(H2Config_str_lan); + H2Config_ip_lan = inet_addr(ip_lan); } // client only diff --git a/xlive/H2MOD/Modules/Shell/Config.h b/xlive/H2MOD/Modules/Shell/Config.h index 8669465d7..3beea3de2 100644 --- a/xlive/H2MOD/Modules/Shell/Config.h +++ b/xlive/H2MOD/Modules/Shell/Config.h @@ -42,9 +42,6 @@ extern unsigned short H2Config_master_port_relay; extern bool H2Portable; extern bool H2Config_isConfigFileAppDataLocal; extern unsigned short H2Config_base_port; -extern char H2Config_str_wan[16]; -extern char H2Config_str_lan[16]; -extern unsigned long H2Config_ip_wan; extern unsigned long H2Config_ip_lan; extern _H2Config_language H2Config_language; diff --git a/xlive/XLive/xnet/Sockets/XSocket.h b/xlive/XLive/xnet/Sockets/XSocket.h index 5f575ed33..5d0814922 100644 --- a/xlive/XLive/xnet/Sockets/XSocket.h +++ b/xlive/XLive/xnet/Sockets/XSocket.h @@ -68,17 +68,17 @@ class XSocketManager bool CreateSocket(XBroadcastSocket* sock, WORD port, bool multicast); - WORD SystemLinkGetPort() + WORD SystemLinkGetPort() const { return m_broadcastLANSock.m_port; } - SOCKET SystemLinkGetLANSystemSockHandle() + SOCKET SystemLinkGetLANSystemSockHandle() const { return m_broadcastLANSock.m_systemSockHandle; } - SOCKET SystemLinkGetSystemSockHandle(int index) + SOCKET SystemLinkGetSystemSockHandle(int index) const { switch (index) { @@ -91,7 +91,7 @@ class XSocketManager return INVALID_SOCKET; } - bool SystemLinkAvailable() + bool SystemLinkAvailable() const { for (int i = 0; i < 2; i++) {