From de4226fdc9ba606bbb79ad209b412d92138c88ef Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Mon, 3 Mar 2025 00:04:03 -0600 Subject: [PATCH] [World] Check if port in use to avoid double booting mistakes (#4740) * Stuff * Potentially fix aura crash * Reload crash fix * Revert "Reload crash fix" This reverts commit 96e1e76306059fc2a624e0152eca4beaee49a0f8. * Fix * Update entity.cpp * Update dbcore.cpp * [World] Check if port in use to avoid double booting mistakes * Revert "Stuff" This reverts commit 2162c00eddfd13c7ff9fbe53cada1ea36373880c. * Revert "Potentially fix aura crash" This reverts commit 7c242723f40a0d013371c36e205a9917849ee862. * Revert "Fix" This reverts commit 8419e284d48bac823c861c480719eb3d3b8290a9. * Revert "Update entity.cpp" This reverts commit 8a1f4545a4e1c96a848866fb5b6185c66db09097. * Revert "Update dbcore.cpp" This reverts commit f0278d95910ccf9e1667eb0e1a0f2608aa7b6058. --- common/ip_util.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++ common/ip_util.h | 1 + world/main.cpp | 11 +++++++ 3 files changed, 85 insertions(+) diff --git a/common/ip_util.cpp b/common/ip_util.cpp index 47689a2fa..1a4701c64 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -259,3 +259,76 @@ bool IpUtil::IsIPAddress(const std::string &ip_address) } +#include +#ifdef _WIN32 +#include + #pragma comment(lib, "ws2_32.lib") // Link against Winsock library +#else +#include +#include +#include +#include +#endif + +#include +#include +#ifdef _WIN32 +#include + #include // For inet_pton + #pragma comment(lib, "ws2_32.lib") // Link against Winsock library +#else +#include +#include +#include +#include // For inet_pton +#include +#endif + +bool IpUtil::IsPortInUse(const std::string& ip, int port) { + bool in_use = false; + +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + std::cerr << "WSAStartup failed\n"; + return true; // Assume in use on failure + } +#endif + + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { +#ifdef _WIN32 + WSACleanup(); +#endif + return true; // Assume in use on failure + } + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + // Convert IP address from string to binary format + if (inet_pton(AF_INET, ip.c_str(), &addr.sin_addr) <= 0) { + std::cerr << "Invalid IP address format: " << ip << std::endl; +#ifdef _WIN32 + closesocket(sock); + WSACleanup(); +#else + close(sock); +#endif + return true; // Assume in use on failure + } + + if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + in_use = true; // Bind failed, port is in use + } + +#ifdef _WIN32 + closesocket(sock); + WSACleanup(); +#else + close(sock); +#endif + + return in_use; +} diff --git a/common/ip_util.h b/common/ip_util.h index 3f67492a4..3d96f219c 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -37,6 +37,7 @@ public: int port ); static bool IsIPAddress(const std::string &ip_address); + static bool IsPortInUse(const std::string& ip, int port); }; diff --git a/world/main.cpp b/world/main.cpp index f0cb8e702..91af43edd 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -89,6 +89,7 @@ #include "../common/events/player_event_logs.h" #include "../common/skill_caps.h" #include "../common/repositories/character_parcels_repository.h" +#include "../common/ip_util.h" SkillCaps skill_caps; ZoneStore zone_store; @@ -188,6 +189,16 @@ int main(int argc, char **argv) launcher_list.LoadList(); zoneserver_list.Init(); + if (IpUtil::IsPortInUse(Config->WorldIP, Config->WorldTCPPort)) { + LogError("World port [{}] already in use", Config->WorldTCPPort); + return 1; + } + + if (IpUtil::IsPortInUse(Config->TelnetIP, Config->TelnetTCPPort)) { + LogError("Telnet port [{}] already in use", Config->TelnetTCPPort); + return 1; + } + std::unique_ptr console; if (Config->TelnetEnabled) { LogInfo("Console (TCP) listener started on [{}:{}]", Config->TelnetIP, Config->TelnetTCPPort);