From da120f69e02acaec3cc98b5e4297f2fd47f0cd5f Mon Sep 17 00:00:00 2001 From: Exynox Date: Sat, 9 Dec 2023 17:02:17 +0200 Subject: [PATCH] Made various network parameters manually configurable. --- src/game/src/config.cpp | 163 +++++++++++++++++++++------------------- src/game/src/config.h | 10 +-- src/game/src/main.cpp | 19 ++++- 3 files changed, 107 insertions(+), 85 deletions(-) diff --git a/src/game/src/config.cpp b/src/game/src/config.cpp index 1765f7d..cab2dc9 100644 --- a/src/game/src/config.cpp +++ b/src/game/src/config.cpp @@ -21,12 +21,24 @@ using std::string; -BYTE g_bChannel = 0; +// Networking +char g_szPublicBindIP[16] = "0.0.0.0"; +char g_szPublicIP[16] = "0"; WORD mother_port = 50080; -int passes_per_sec = 25; -WORD db_port = 0; + +char g_szInternalBindIP[16] = "0.0.0.0"; +char g_szInternalIP[16] = "0"; WORD p2p_port = 50900; + char db_addr[ADDRESS_MAX_LEN + 1]; +WORD db_port = 0; + +char teen_addr[ADDRESS_MAX_LEN + 1] = {0}; +WORD teen_port = 0; +// End of networking + +BYTE g_bChannel = 0; +int passes_per_sec = 25; int save_event_second_cycle = passes_per_sec * 120; // 3ΊΠ int ping_event_second_cycle = passes_per_sec * 60; bool g_bNoMoreClient = false; @@ -49,8 +61,6 @@ BYTE guild_mark_min_level = 3; bool no_wander = false; int g_iUserLimit = 32768; -char g_szPublicIP[16] = "0"; -char g_szInternalIP[16] = "0"; bool g_bSkillDisable = false; int g_iFullUserCount = 1200; int g_iBusyUserCount = 650; @@ -89,9 +99,6 @@ string g_stBlockDate = "30000705"; extern string g_stLocale; -char teen_addr[ADDRESS_MAX_LEN + 1] = {0}; -WORD teen_port = 0; - int SPEEDHACK_LIMIT_COUNT = 50; int SPEEDHACK_LIMIT_BONUS = 80; int g_iSyncHackLimitCount = 20; // 10 -> 20 2013 09 11 CYH @@ -208,16 +215,44 @@ static void FN_log_adminpage() dev_log(LOG_DEB0, "ADMIN_PAGE_PASSWORD = %s", g_stAdminPagePassword.c_str()); } +/** + * Checks if a given IPv4 address is in the Private Address Space as per RFC1918 + * @param address + * @return True if address is private, false otherwise + */ +bool IsPrivateIP(const in_addr &address) +{ + const auto CLASS_A_PRIVATE = inet_addr("10.0.0.0"); + const auto CLASS_A_PRIVATE_NETMASK = inet_addr("255.0.0.0"); + if ((address.s_addr & CLASS_A_PRIVATE_NETMASK) == CLASS_A_PRIVATE) + return true; + const auto CLASS_B_PRIVATE = inet_addr("172.16.0.0"); + const auto CLASS_B_PRIVATE_NETMASK = inet_addr("255.240.0.0"); + if ((address.s_addr & CLASS_B_PRIVATE_NETMASK) == CLASS_B_PRIVATE) + return true; + + const auto CLASS_C_PRIVATE = inet_addr("192.168.0.0"); + const auto CLASS_C_PRIVATE_NETMASK = inet_addr("255.255.0.0"); + if ((address.s_addr & CLASS_C_PRIVATE_NETMASK) == CLASS_C_PRIVATE) + return true; + + return false; +} + +/** + * Retrieves the first private and public IP addresses and allocates them + * to g_szInternalIP and g_szPublicIP respectively + * @return True on success, false on system failure. + */ bool GetIPInfo() { -#ifndef __WIN32__ - struct ifaddrs* ifaddrp = NULL; + ifaddrs* ifaddrp = nullptr; if (0 != getifaddrs(&ifaddrp)) return false; - for( struct ifaddrs* ifap=ifaddrp ; NULL != ifap ; ifap = ifap->ifa_next ) + for (ifaddrs* ifap = ifaddrp; ifap != nullptr; ifap = ifap->ifa_next) { struct sockaddr_in * sai = (struct sockaddr_in *) ifap->ifa_addr; @@ -225,68 +260,23 @@ bool GetIPInfo() sai->sin_addr.s_addr == 0 || // ignore if address is 0.0.0.0 sai->sin_addr.s_addr == 16777343) // ignore if address is 127.0.0.1 continue; -#else - WSADATA wsa_data; - char host_name[100]; - HOSTENT* host_ent; - int n = 0; - if (WSAStartup(0x0101, &wsa_data)) { - return false; - } - - gethostname(host_name, sizeof(host_name)); - host_ent = gethostbyname(host_name); - if (host_ent == NULL) { - return false; - } - for ( ; host_ent->h_addr_list[n] != NULL; ++n) { - struct sockaddr_in addr; - struct sockaddr_in* sai = &addr; - memcpy(&sai->sin_addr.s_addr, host_ent->h_addr_list[n], host_ent->h_length); -#endif - - char * netip = inet_ntoa(sai->sin_addr); - - if (!strncmp(netip, "192.168", 7)) // ignore if address is starting with 192 + if (IsPrivateIP(sai->sin_addr) && g_szInternalIP[0] == '0') { - strlcpy(g_szInternalIP, netip, sizeof(g_szInternalIP)); -#ifndef __WIN32__ - fprintf(stderr, "INTERNAL_IP: %s interface %s\n", netip, ifap->ifa_name); -#else - fprintf(stderr, "INTERNAL_IP: %s\n", netip); -#endif - } - else if (!strncmp(netip, "10.", 3)) - { - strlcpy(g_szInternalIP, netip, sizeof(g_szInternalIP)); -#ifndef __WIN32__ - fprintf(stderr, "INTERNAL_IP: %s interface %s\n", netip, ifap->ifa_name); -#else - fprintf(stderr, "INTERNAL_IP: %s\n", netip); -#endif + char * ip = inet_ntoa(sai->sin_addr); + strlcpy(g_szInternalIP, ip, sizeof(g_szInternalIP)); + fprintf(stderr, "Internal IP automatically configured: %s interface %s\n", ip, ifap->ifa_name); } else if (g_szPublicIP[0] == '0') { - strlcpy(g_szPublicIP, netip, sizeof(g_szPublicIP)); -#ifndef __WIN32__ - fprintf(stderr, "PUBLIC_IP: %s interface %s\n", netip, ifap->ifa_name); -#else - fprintf(stderr, "PUBLIC_IP: %s\n", netip); -#endif + char * ip = inet_ntoa(sai->sin_addr); + strlcpy(g_szPublicIP, ip, sizeof(g_szPublicIP)); + fprintf(stderr, "Public IP automatically configured: %s interface %s\n", ip, ifap->ifa_name); } } -#ifndef __WIN32__ - freeifaddrs( ifaddrp ); -#else - WSACleanup(); -#endif - - if (g_szPublicIP[0] != '0') - return true; - else - return false; + freeifaddrs(ifaddrp); + return true; } void config_init(const string& st_localeServiceName) @@ -318,7 +308,7 @@ void config_init(const string& st_localeServiceName) if (!GetIPInfo()) { - fprintf(stderr, "Can not get public ip address\n"); + fprintf(stderr, "Failure in retrieving IP address information!\n"); exit(1); } @@ -699,12 +689,6 @@ void config_init(const string& st_localeServiceName) continue; } - TOKEN("port") - { - str_to_number(mother_port, value_string); - continue; - } - TOKEN("log_keep_days") { int i = 0; @@ -719,6 +703,36 @@ void config_init(const string& st_localeServiceName) continue; } + TOKEN("public_ip") + { + strlcpy(g_szPublicIP, value_string, sizeof(g_szPublicIP)); + continue; + } + + TOKEN("public_bind_ip") + { + strlcpy(g_szPublicBindIP, value_string, sizeof(g_szPublicBindIP)); + continue; + } + + TOKEN("port") + { + str_to_number(mother_port, value_string); + continue; + } + + TOKEN("internal_ip") + { + strlcpy(g_szInternalIP, value_string, sizeof(g_szInternalIP)); + continue; + } + + TOKEN("internal_bind_ip") + { + strlcpy(g_szInternalBindIP, value_string, sizeof(g_szInternalBindIP)); + continue; + } + TOKEN("p2p_port") { str_to_number(p2p_port, value_string); @@ -970,11 +984,6 @@ void config_init(const string& st_localeServiceName) g_strWebMallURL = value_string; } - TOKEN("bind_ip") - { - strlcpy(g_szPublicIP, value_string, sizeof(g_szPublicIP)); - } - TOKEN("view_range") { str_to_number(VIEW_RANGE, value_string); diff --git a/src/game/src/config.h b/src/game/src/config.h index 639b5f4..685b95a 100644 --- a/src/game/src/config.h +++ b/src/game/src/config.h @@ -9,9 +9,12 @@ enum void config_init(const std::string& st_localeServiceName); // default "" is CONFIG -extern char sql_addr[256]; - +extern char g_szPublicBindIP[16]; +extern char g_szPublicIP[16]; extern WORD mother_port; + +extern char g_szInternalBindIP[16]; +extern char g_szInternalIP[16]; extern WORD p2p_port; extern char db_addr[ADDRESS_MAX_LEN + 1]; @@ -49,9 +52,6 @@ extern std::string g_stHostname; extern std::string g_stLocale; extern std::string g_stLocaleFilename; -extern char g_szPublicIP[16]; -extern char g_szInternalIP[16]; - extern int (*is_twobyte) (const char * str); extern int (*check_name) (const char * str); diff --git a/src/game/src/main.cpp b/src/game/src/main.cpp index 9a2972a..5192696 100644 --- a/src/game/src/main.cpp +++ b/src/game/src/main.cpp @@ -615,6 +615,17 @@ int start(int argc, char **argv) signal_timer_disable(); // Initialize the network stack + + // Check if the public and internal IP addresses were configured + if (g_szInternalIP[0] == '0') { + fprintf(stderr, "Public IP address could not be automatically detected. Manually set the IP and try again."); + return 0; + } + if (g_szPublicIP[0] == '0') { + fprintf(stderr, "Public IP address could not be automatically detected. Manually set the IP and try again."); + return 0; + } + // Create a new libevent base and listen for new connections ev_base = event_base_new(); if (!ev_base) { @@ -632,8 +643,8 @@ int start(int argc, char **argv) // Main TCP listener sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(g_szPublicIP); - sin.sin_port = htons(mother_port); + sin.sin_addr.s_addr = inet_addr(g_szPublicBindIP); + sin.sin_port = htons(mother_port); tcp_listener = evconnlistener_new_bind( ev_base, @@ -645,11 +656,12 @@ int start(int argc, char **argv) sys_err("TCP listener initialization FAILED!"); return 0; } + fprintf(stdout, "TCP listening on %s:%u\n", g_szPublicBindIP, mother_port); evconnlistener_set_error_cb(tcp_listener, AcceptError); // Game P2P listener sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(g_szPublicIP); + sin.sin_addr.s_addr = inet_addr(g_szInternalBindIP); sin.sin_port = htons(p2p_port); p2p_listener = evconnlistener_new_bind( @@ -662,6 +674,7 @@ int start(int argc, char **argv) sys_err("P2P listener initialization FAILED!"); return 0; } + fprintf(stdout, "P2P listening on %s:%u\n", g_szInternalBindIP, p2p_port); evconnlistener_set_error_cb(p2p_listener, AcceptError); // Create client connections