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