From 0f74eca2ee709065b89dd0a6f4eb8af6a1d90a6b Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 6 Dec 2021 12:28:52 +0100 Subject: [PATCH] Fix various issues and crashes --- include/Common.h | 25 +++++++++++- include/Cryptography.h | 4 +- include/Http.h | 12 +++--- include/TConsole.h | 6 +-- src/Common.cpp | 1 - src/Http.cpp | 8 ++-- src/TConfig.cpp | 1 + src/TConsole.cpp | 90 ++++++++++++++++++++++-------------------- src/main.cpp | 15 ++++--- 9 files changed, 96 insertions(+), 66 deletions(-) diff --git a/include/Common.h b/include/Common.h index 00a3fca..ed34b7f 100644 --- a/include/Common.h +++ b/include/Common.h @@ -82,9 +82,32 @@ public: static std::array VersionStrToInts(const std::string& str); static bool IsOutdated(const Version& Current, const Version& Newest); + static void InitializeConsole() { + if (!mConsole) { + mConsole = std::make_unique(); + } + } + + enum class Status { + Starting, + Good, + Bad, + }; + + using SystemStatusMap = std::unordered_map; + + static const SystemStatusMap& GetSubsystemStatuses() { + return mSystemStatusMap; + } + + static void SetSubsystemStatus(const std::string& Subsystem, Status status) { + mSystemStatusMap[Subsystem] = status; + } + private: + static inline SystemStatusMap mSystemStatusMap {}; static inline std::string mPPS; - static std::unique_ptr mConsole; + static inline std::unique_ptr mConsole; static inline std::mutex mShutdownHandlersMutex {}; static inline std::deque mShutdownHandlers {}; diff --git a/include/Cryptography.h b/include/Cryptography.h index 5d710a0..bef2e58 100644 --- a/include/Cryptography.h +++ b/include/Cryptography.h @@ -91,14 +91,14 @@ static auto w_printf_s = [](const char* fmt, ...) { va_end(args); }; -static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) { +static auto w_sprintf_s = [](char* buf, size_t, const char* fmt, ...) { va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); }; -static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) { +static auto w_sprintf_s_ret = [](char* buf, size_t, const char* fmt, ...) { int ret; va_list args; va_start(args, fmt); diff --git a/include/Http.h b/include/Http.h index 92d1279..3673edc 100644 --- a/include/Http.h +++ b/include/Http.h @@ -3,12 +3,16 @@ #include #include #include -#include #include #include #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#include +#pragma GCC diagnostic pop + namespace fs = std::filesystem; namespace Crypto { @@ -36,12 +40,6 @@ namespace Server { void operator()(); private: - /** - * the shared pointer is necessary because httplib is a blocking library and due lacking thread-safety - * will "forget" about its environment, when configured across multiple threads. - * So we need to able to start the server (make it "listen()") in a single Thread. - */ - std::shared_ptr mHttpLibServerInstancePtr; std::thread mThread; }; // todo: all of these functions are likely unsafe, diff --git a/include/TConsole.h b/include/TConsole.h index 618c586..c393842 100644 --- a/include/TConsole.h +++ b/include/TConsole.h @@ -16,19 +16,19 @@ public: void InitializeLuaConsole(TLuaEngine& Engine); void BackupOldLog(); Commandline& Internal() { return mCommandline; } - + private: void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false); void ChangeToLuaConsole(const std::string& LuaStateId); void ChangeToRegularConsole(); - + void Command_Lua(const std::string& cmd); void Command_Help(const std::string& cmd); void Command_Kick(const std::string& cmd); void Command_Say(const std::string& cmd); void Command_List(const std::string& cmd); void Command_Status(const std::string& cmd); - + Commandline mCommandline; std::vector mCachedLuaHistory; std::vector mCachedRegularHistory; diff --git a/src/Common.cpp b/src/Common.cpp index 31b8d6e..26f7619 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -13,7 +13,6 @@ #include "Http.h" Application::TSettings Application::Settings = {}; -std::unique_ptr Application::mConsole = std::make_unique(); void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) { std::unique_lock Lock(mShutdownHandlersMutex); diff --git a/src/Http.cpp b/src/Http.cpp index b59a8b3..813a26d 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -270,14 +270,14 @@ Http::Server::THttpServerInstance::THttpServerInstance() { void Http::Server::THttpServerInstance::operator()() { beammp_info("HTTPS Server started on port " + std::to_string(Application::Settings.HTTPServerPort)); + httplib::SSLServer HttpLibServerInstance { Application::Settings.SSLCertPath.c_str(), Application::Settings.SSLKeyPath.c_str() }; // todo: make this IP agnostic so people can set their own IP - mHttpLibServerInstancePtr = std::make_shared(Application::Settings.SSLCertPath.c_str(), Application::Settings.SSLKeyPath.c_str()); - mHttpLibServerInstancePtr->Get("/", [](const httplib::Request&, httplib::Response& res) { + HttpLibServerInstance.Get("/", [](const httplib::Request&, httplib::Response& res) { res.set_content("

Hello World!

BeamMP Server can now serve HTTP requests!

", "text/html"); }); - mHttpLibServerInstancePtr->Get("/health", [](const httplib::Request&, httplib::Response& res) { + HttpLibServerInstance.Get("/health", [](const httplib::Request&, httplib::Response& res) { res.set_content("0", "text/plain"); res.status = 200; }); - mHttpLibServerInstancePtr->listen("0.0.0.0", Application::Settings.HTTPServerPort); + HttpLibServerInstance.listen("0.0.0.0", Application::Settings.HTTPServerPort); } diff --git a/src/TConfig.cpp b/src/TConfig.cpp index fff6304..9817fc6 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -42,6 +42,7 @@ TConfig::TConfig(const std::string& ConfigFileName) ParseFromFile(mConfigFileName); } } + /** * @brief Writes out the loaded application state into ServerConfig.toml * diff --git a/src/TConsole.cpp b/src/TConsole.cpp index f0293bd..9acf574 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -38,7 +38,7 @@ std::string GetDate() { auto fraction = now - seconds; size_t ms = std::chrono::duration_cast(fraction).count(); char fracstr[5]; - std::sprintf(fracstr, "%0.3lu", ms); + std::sprintf(fracstr, "%03lu", ms); date += fracstr; date += "] "; } else { @@ -99,6 +99,11 @@ void TConsole::BackupOldLog() { void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) { if (!mIsLuaConsole) { + if (!mLuaEngine) { + beammp_error("Lua engine not initialized yet, please wait and try again"); + return; + } + mLuaEngine->EnsureStateExists(mDefaultStateId, "Console"); mStateId = LuaStateId; mIsLuaConsole = true; if (mStateId != mDefaultStateId) { @@ -106,8 +111,8 @@ void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) { } else { Application::Console().WriteRaw("Entered Lua console. To exit, type `exit()`"); } - //mCachedRegularHistory = mCommandline.history(); - //mCommandline.set_history(mCachedLuaHistory); + // mCachedRegularHistory = mCommandline.history(); + // mCommandline.set_history(mCachedLuaHistory); mCommandline.set_prompt("lua> "); } } @@ -120,8 +125,8 @@ void TConsole::ChangeToRegularConsole() { } else { Application::Console().WriteRaw("Left Lua console."); } - //mCachedLuaHistory = mCommandline.history(); - //mCommandline.set_history(mCachedRegularHistory); + // mCachedLuaHistory = mCommandline.history(); + // mCommandline.set_history(mCachedRegularHistory); mCommandline.set_prompt("> "); mStateId = mDefaultStateId; } @@ -322,45 +327,45 @@ TConsole::TConsole() { auto cmd = c.get_command(); cmd = TrimString(cmd); mCommandline.write(mCommandline.prompt() + cmd); - if (!mLuaEngine) { - beammp_info("Lua not started yet, please try again in a second"); - } else { - if (mIsLuaConsole) { - if (cmd == "exit()") { - ChangeToRegularConsole(); - } else { - auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared(cmd), "", "" }); - while (!Future->Ready) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout - } - if (Future->Error) { - beammp_lua_error(Future->ErrorMessage); - } - } + if (mIsLuaConsole) { + if (!mLuaEngine) { + beammp_info("Lua not started yet, please try again in a second"); + } else if (cmd == "exit()") { + ChangeToRegularConsole(); } else { - if (cmd == "exit") { - beammp_info("gracefully shutting down"); - Application::GracefullyShutdown(); - } else if (StringStartsWith(cmd, "lua")) { - Command_Lua(cmd); - } else if (StringStartsWith(cmd, "help")) { - RunAsCommand(cmd, true); - Command_Help(cmd); - } else if (StringStartsWith(cmd, "kick")) { - RunAsCommand(cmd, true); - Command_Kick(cmd); - } else if (StringStartsWith(cmd, "say")) { - RunAsCommand(cmd, true); - Command_Say(cmd); - } else if (StringStartsWith(cmd, "list")) { - RunAsCommand(cmd, true); - Command_List(cmd); - } else if (StringStartsWith(cmd, "status")) { - RunAsCommand(cmd, true); - Command_Status(cmd); - } else if (!cmd.empty()) { - RunAsCommand(cmd); + auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared(cmd), "", "" }); + while (!Future->Ready) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout } + if (Future->Error) { + beammp_lua_error(Future->ErrorMessage); + } + } + } else { + if (!mLuaEngine) { + beammp_error("Attempted to run a command before Lua engine started. Please wait and try again."); + } else if (cmd == "exit") { + beammp_info("gracefully shutting down"); + Application::GracefullyShutdown(); + } else if (StringStartsWith(cmd, "lua")) { + Command_Lua(cmd); + } else if (StringStartsWith(cmd, "help")) { + RunAsCommand(cmd, true); + Command_Help(cmd); + } else if (StringStartsWith(cmd, "kick")) { + RunAsCommand(cmd, true); + Command_Kick(cmd); + } else if (StringStartsWith(cmd, "say")) { + RunAsCommand(cmd, true); + Command_Say(cmd); + } else if (StringStartsWith(cmd, "list")) { + RunAsCommand(cmd, true); + Command_List(cmd); + } else if (StringStartsWith(cmd, "status")) { + RunAsCommand(cmd, true); + Command_Status(cmd); + } else if (!cmd.empty()) { + RunAsCommand(cmd); } } } catch (const std::exception& e) { @@ -380,5 +385,4 @@ void TConsole::WriteRaw(const std::string& str) { void TConsole::InitializeLuaConsole(TLuaEngine& Engine) { mLuaEngine = &Engine; - Engine.EnsureStateExists(mDefaultStateId, "Console"); } diff --git a/src/main.cpp b/src/main.cpp index 8e92f9c..ca29d12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,6 +77,7 @@ int main(int argc, char** argv) { int BeamMPServerMain(MainArguments Arguments) { setlocale(LC_ALL, "C"); + Application::InitializeConsole(); SetupSignalHandlers(); @@ -131,6 +132,7 @@ int BeamMPServerMain(MainArguments Arguments) { TConfig Config(ConfigPath); TLuaEngine LuaEngine; LuaEngine.SetServer(&Server); + Application::Console().InitializeLuaConsole(LuaEngine); if (Config.Failed()) { beammp_info("Closing in 10 seconds"); @@ -146,13 +148,12 @@ int BeamMPServerMain(MainArguments Arguments) { beammp_trace("Running in debug mode on a debug build"); Sentry.SetupUser(); Sentry.PrintWelcome(); - TResourceManager ResourceManager; + TResourceManager ResourceManager; TPPSMonitor PPSMonitor(Server); THeartbeatThread Heartbeat(ResourceManager, Server); TNetwork Network(Server, PPSMonitor, ResourceManager); LuaEngine.SetNetwork(&Network); PPSMonitor.SetNetwork(Network); - Application::Console().InitializeLuaConsole(LuaEngine); Application::CheckForUpdates(); if (Application::Settings.HTTPServerEnabled) { @@ -160,11 +161,15 @@ int BeamMPServerMain(MainArguments Arguments) { Http::Server::THttpServerInstance HttpServerInstance {}; } - beammp_debug("cert.pem is " + std::to_string(fs::file_size("cert.pem")) + " bytes"); - beammp_debug("key.pem is " + std::to_string(fs::file_size("key.pem")) + " bytes"); - RegisterThread("Main(Waiting)"); + auto Statuses = Application::GetSubsystemStatuses(); + for (const auto& NameStatusPair : Statuses) { + if (NameStatusPair.second != Application::Status::Good) { + beammp_info("not good: " + NameStatusPair.first); + } + } + while (!Shutdown) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); }