#pragma once // Copyright (C) 2007-2021 EQ2Emulator Development Team, GPL v3 License #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lworld.hpp" #include "client.hpp" #include "login_database.hpp" #include "../common/log.hpp" #include "../common/unix.hpp" #include "../common/crc16.hpp" #include "../common/types.hpp" #include "../common/debug.hpp" #include "../common/queue.hpp" #include "../common/timer.hpp" #include "../common/version.hpp" #include "../common/separator.hpp" #include "../common/web_server.hpp" #include "../common/json_parser.hpp" #include "../common/data_buffer.hpp" #include "../common/config_reader.hpp" #include "../common/misc_functions.hpp" #include "../common/common_defines.hpp" #include "../common/packet/packet_struct.hpp" #include "../common/packet/packet_functions.hpp" #include "../common/stream/eq_stream_factory.hpp" void CatchSignal(int sig_num); enum eServerMode { Standalone, Master, Slave, Mesh }; class NetConnection { public: // Constructor - initializes all network connection parameters and default values NetConnection() { port = 5999; listening_socket = 0; memset(masteraddress, 0, sizeof(masteraddress)); uplinkport = 0; memset(uplinkaccount, 0, sizeof(uplinkaccount)); memset(uplinkpassword, 0, sizeof(uplinkpassword)); LoginMode = Standalone; Uplink_WrongVersion = false; numclients = 0; numservers = 0; allowAccountCreation = true; // Full expansion support flag - controls available expansions expansionFlag = 0x7CFF; // Cities availability flag - controls which starting cities are available citiesFlag = 0xFF; // Default subscription level - controls character creation restrictions defaultSubscriptionLevel = 0xFFFFFFFF; // Enabled races flag - controls which races are selectable enabledRaces = 0xFFFF; web_loginport = 0; login_webserver = nullptr; login_running = false; login_uptime = getCurrentTimestamp(); } // Destructor - cleans up web server resources ~NetConnection() { safe_delete(login_webserver); } // Updates console window title with server status information void UpdateWindowTitle(char* iNewTitle = 0) { // Linux systems don't support console title updates like Windows // This is a no-op on Linux systems } // Reads and parses the login server configuration from JSON file bool ReadLoginConfig() { JsonParser parser(MAIN_CONFIG_FILE); if (!parser.IsLoaded()) { LogWrite(INIT__ERROR, 0, "Init", "Failed to find %s in server directory..", MAIN_CONFIG_FILE); return false; } std::string serverport = parser.getValue("loginconfig.serverport"); std::string serverip = parser.getValue("loginconfig.serverip"); if (!parser.convertStringToUnsignedShort(serverport, port)) { LogWrite(INIT__ERROR, 0, "Init", "Failed to translate loginconfig.serverport.."); return false; } if (serverip.size() > 0) { eqsf.listen_ip_address = new char[serverip.size() + 1]; strcpy(eqsf.listen_ip_address, serverip.c_str()); } else { safe_delete(eqsf.listen_ip_address); eqsf.listen_ip_address = nullptr; } std::string acctcreate_str = parser.getValue("loginconfig.accountcreation"); int16 allow_acct = 0; parser.convertStringToUnsignedShort(acctcreate_str, allow_acct); allowAccountCreation = allow_acct > 0 ? true : false; std::string expflag_str = parser.getValue("loginconfig.expansionflag"); parser.convertStringToUnsignedInt(expflag_str, expansionFlag); std::string citiesflag_str = parser.getValue("loginconfig.citiesflag"); parser.convertStringToUnsignedChar(citiesflag_str, citiesFlag); std::string defaultsublevel_str = parser.getValue("loginconfig.defaultsubscriptionlevel"); parser.convertStringToUnsignedInt(defaultsublevel_str, defaultSubscriptionLevel); std::string enableraces_str = parser.getValue("loginconfig.enabledraces"); parser.convertStringToUnsignedInt(enableraces_str, enabledRaces); web_loginaddress = parser.getValue("loginconfig.webloginaddress"); web_certfile = parser.getValue("loginconfig.webcertfile"); web_keyfile = parser.getValue("loginconfig.webkeyfile"); web_keypassword = parser.getValue("loginconfig.webkeypassword"); web_hardcodeuser = parser.getValue("loginconfig.webhardcodeuser"); web_hardcodepassword = parser.getValue("loginconfig.webhardcodepassword"); std::string webloginport_str = parser.getValue("loginconfig.webloginport"); parser.convertStringToUnsignedShort(webloginport_str, web_loginport); LogWrite(INIT__INFO, 0, "Init", "%s loaded..", MAIN_CONFIG_FILE); LogWrite(INIT__INFO, 0, "Init", "Database init begin.."); if (!database.Init()) { LogWrite(INIT__ERROR, 0, "Init", "Database init FAILED!"); LogStop(); return false; } LogWrite(INIT__INFO, 0, "Init", "Loading opcodes 2.0.."); EQOpcodeVersions = database.GetVersions(); std::map::iterator version_itr2; int16 version1 = 0; for (version_itr2 = EQOpcodeVersions.begin(); version_itr2 != EQOpcodeVersions.end(); version_itr2++) { version1 = version_itr2->first; EQOpcodeManager[version1] = new RegularOpcodeManager(); std::map eq = database.GetOpcodes(version1); if (!EQOpcodeManager[version1]->LoadOpcodes(&eq)) { LogWrite(INIT__ERROR, 0, "Init", "Loading opcodes failed. Make sure you have sourced the opcodes.sql file!"); return false; } } return true; } // Displays the EQ2Emulator welcome header with ASCII art and information void WelcomeHeader() { printf("Module: %s, Version: %s", EQ2EMU_MODULE, CURRENT_VERSION); printf("\n\nCopyright (C) 2007-2021 EQ2Emulator. https://www.eq2emu.com \n\n"); printf("EQ2Emulator is free software: you can redistribute it and/or modify\n"); printf("it under the terms of the GNU General Public License as published by\n"); printf("the Free Software Foundation, either version 3 of the License, or\n"); printf("(at your option) any later version.\n\n"); printf("EQ2Emulator is distributed in the hope that it will be useful,\n"); printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); printf("GNU General Public License for more details.\n\n"); printf(" /$$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$$ \n"); printf("| $$_____/ /$$__ $$ /$$__ $$| $$_____/ \n"); printf("| $$ | $$ \\ $$|__/ \\ $$| $$ /$$$$$$/$$$$ /$$ /$$\n"); printf("| $$$$$ | $$ | $$ /$$$$$$/| $$$$$ | $$_ $$_ $$| $$ | $$\n"); printf("| $$__/ | $$ | $$ /$$____/ | $$__/ | $$ \\ $$ \\ $$| $$ | $$\n"); printf("| $$ | $$/$$ $$| $$ | $$ | $$ | $$ | $$| $$ | $$\n"); printf("| $$$$$$$$| $$$$$$/| $$$$$$$$| $$$$$$$$| $$ | $$ | $$| $$$$$$/\n"); printf("|________/ \\____ $$$|________/|________/|__/ |__/ |__/ \\______/ \n"); printf(" \\__/ \n\n"); printf(" Website : https://eq2emu.com \n"); printf(" Wiki : https://wiki.eq2emu.com \n"); printf(" Git : https://git.eq2emu.com \n"); printf(" Discord : https://discord.gg/5Cavm9NYQf \n\n"); printf("For more detailed logging, modify 'Level' param the log_config.xml file.\n\n"); fflush(stdout); } // Initializes and starts the web server for login status and world information void InitWebServer(std::string web_ipaddr, int16 web_port, std::string cert_file, std::string key_file, std::string key_password, std::string hardcode_user, std::string hardcode_password) { if (web_ipaddr.size() > 0 && web_port > 0) { try { login_webserver = new WebServer(web_ipaddr, web_port, cert_file, key_file, key_password, hardcode_user, hardcode_password); login_webserver->register_route("/status", NetConnection::Web_loginhandle_status); login_webserver->register_route("/worlds", NetConnection::Web_loginhandle_worlds); login_webserver->run(); LogWrite(INIT__INFO, 0, "Init", "Login Web Server is listening on %s:%u..", web_ipaddr.c_str(), web_port); } catch (const std::exception& e) { LogWrite(INIT__ERROR, 0, "Init", "Login Web Server failed to listen on %s:%u due to reason %s", web_ipaddr.c_str(), web_port, e.what()); } } } // Accessor methods for configuration values int16 GetPort() { return port; } void SetPort(int16 in_port) { port = in_port; } eServerMode GetLoginMode() { return LoginMode; } char* GetMasterAddress() { return masteraddress; } int16 GetUplinkPort() { if (uplinkport != 0) return uplinkport; else return port; } char* GetUplinkAccount() { return uplinkaccount; } char* GetUplinkPassword() { return uplinkpassword; } bool IsAllowingAccountCreation() { return allowAccountCreation; } int32 GetExpansionFlag() { return expansionFlag; } int8 GetCitiesFlag() { return citiesFlag; } int32 GetDefaultSubscriptionLevel() { return defaultSubscriptionLevel; } int32 GetEnabledRaces() { return enabledRaces; } std::string GetWebLoginAddress() { return web_loginaddress; } int16 GetWebLoginPort() { return web_loginport; } std::string GetWebCertFile() { return web_certfile; } std::string GetWebKeyFile() { return web_keyfile; } std::string GetWebKeyPassword() { return web_keypassword; } std::string GetWebHardcodeUser() { return web_hardcodeuser; } std::string GetWebHardcodePassword() { return web_hardcodepassword; } // Web server route handlers for status and world information static void Web_loginhandle_status(const http::request& req, http::response& res); static void Web_loginhandle_worlds(const http::request& req, http::response& res); // Public server state variables char address[1024]; int32 numclients; int32 numservers; bool login_running; std::atomic login_uptime; protected: friend class LWorld; bool Uplink_WrongVersion; private: // Network connection parameters int16 port; int listening_socket; char masteraddress[300]; int16 uplinkport; char uplinkaccount[300]; char uplinkpassword[300]; eServerMode LoginMode; // Login server configuration flags bool allowAccountCreation; int32 expansionFlag; int8 citiesFlag; int32 defaultSubscriptionLevel; int32 enabledRaces; // Web server configuration std::string web_loginaddress; std::string web_certfile; std::string web_keyfile; std::string web_keypassword; std::string web_hardcodeuser; std::string web_hardcodepassword; int16 web_loginport; WebServer* login_webserver; }; // Global variables - external declarations extern EQStreamFactory eqsf; extern std::map EQOpcodeManager; extern NetConnection net; extern ClientList client_list; extern LWorldList world_list; extern LoginDatabase database; extern ConfigReader configReader; extern std::map EQOpcodeVersions; extern Timer statTimer; extern volatile bool RunLoops;