From 71c2d4b859464b1ae0e3816276fa85cf4df4d52e Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Fri, 25 Mar 2022 12:55:35 +0100 Subject: [PATCH 01/35] Simplify "Backend heartbeat response" error (closes #97) --- deps/commandline | 2 +- include/Common.h | 1 + src/THeartbeatThread.cpp | 8 ++++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/deps/commandline b/deps/commandline index 71240f6..01434c1 160000 --- a/deps/commandline +++ b/deps/commandline @@ -1 +1 @@ -Subproject commit 71240f634b211d830679e7d2841b897c7c30dad9 +Subproject commit 01434c11aaf82d37a126dc70f5aa02cc523dbbb4 diff --git a/include/Common.h b/include/Common.h index 2cf15b9..4698f6e 100644 --- a/include/Common.h +++ b/include/Common.h @@ -12,6 +12,7 @@ extern TSentry Sentry; #include #include #include +#include #include "Compat.h" diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index 6efdd74..42e7b36 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -62,8 +62,8 @@ void THeartbeatThread::operator()() { beammp_trace(T); Doc.Parse(T.data(), T.size()); if (Doc.HasParseError() || !Doc.IsObject()) { - beammp_error("Backend response failed to parse as valid json"); - beammp_debug("Response was: `" + T + "`"); + beammp_debug("Failed to contact backend at " + Url + " (this is not an error)."); + beammp_trace("Response was: " + T); Sentry.SetContext("JSON Response", { { "reponse", T } }); SentryReportError(Url + Target, ResponseCode); } else if (ResponseCode != 200) { @@ -105,6 +105,10 @@ void THeartbeatThread::operator()() { beammp_error("Missing/invalid json members in backend response"); Sentry.LogError("Missing/invalid json members in backend response", __FILE__, std::to_string(__LINE__)); } + } else { + if (!Application::Settings.Private) { + beammp_warn("Backend failed to respond to a heartbeat. Your server may temporarily disappear from the server list. This is not an error, and will likely resolve itself soon. Direct connect will still work."); + } } if (Ok && !isAuth) { From f8c58f363aab2e7a6d4d2cd9edf0373e422b241a Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Fri, 25 Mar 2022 13:32:41 +0100 Subject: [PATCH 02/35] Change default MaxPlayers to 8 --- include/Common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Common.h b/include/Common.h index 4698f6e..88e2732 100644 --- a/include/Common.h +++ b/include/Common.h @@ -44,7 +44,7 @@ public: std::string SSLKeyPath { "./.ssl/HttpServer/key.pem" }; std::string SSLCertPath { "./.ssl/HttpServer/cert.pem" }; bool HTTPServerEnabled { false }; - int MaxPlayers { 10 }; + int MaxPlayers { 8 }; bool Private { true }; int MaxCars { 1 }; bool DebugModeEnabled { false }; From de82caef335403767ffd50cac7f69e6ff2131c75 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Fri, 25 Mar 2022 13:33:03 +0100 Subject: [PATCH 03/35] Add HideUpdateMessages setting ("ImScaredOfUpdates") and periodic update reminders (every 5th heartbeat) --- include/Common.h | 1 + src/Common.cpp | 2 +- src/TConfig.cpp | 28 ++++++++++++++++++---------- src/THeartbeatThread.cpp | 5 +++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/include/Common.h b/include/Common.h index 88e2732..5d224fb 100644 --- a/include/Common.h +++ b/include/Common.h @@ -54,6 +54,7 @@ public: bool SendErrorsMessageEnabled { true }; int HTTPServerPort { 8080 }; bool HTTPServerUseSSL { true }; + bool HideUpdateMessages { false }; [[nodiscard]] bool HasCustomIP() const { return !CustomIP.empty(); } }; diff --git a/src/Common.cpp b/src/Common.cpp index a113f74..99d0009 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -107,7 +107,7 @@ void Application::CheckForUpdates() { auto RemoteVersion = Version(VersionStrToInts(Response)); if (IsOutdated(MyVersion, RemoteVersion)) { std::string RealVersionString = RemoteVersion.AsString(); - beammp_warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION OUT! There's a new version (v" + RealVersionString + ") of the BeamMP-Server available! For more info visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server." + std::string(ANSI_RESET)); + beammp_warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION IS OUT! Please update to the new version (v" + RealVersionString + ") of the BeamMP-Server! Download it here: https://beammp.com/! For a guide on how to update, visit: https://wiki.beammp.com/en/home/server-maintenance#updating-the-server" + std::string(ANSI_RESET)); } else { beammp_info("Server up-to-date!"); } diff --git a/src/TConfig.cpp b/src/TConfig.cpp index f1c3126..1260cb7 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -17,12 +17,15 @@ static constexpr std::string_view StrName = "Name"; static constexpr std::string_view StrDescription = "Description"; static constexpr std::string_view StrResourceFolder = "ResourceFolder"; static constexpr std::string_view StrAuthKey = "AuthKey"; + +// Misc static constexpr std::string_view StrSendErrors = "SendErrors"; static constexpr std::string_view StrSendErrorsMessageEnabled = "SendErrorsShowMessage"; -static constexpr std::string_view StrHTTPServerEnabled = "HTTPServerEnabled"; -static constexpr std::string_view StrHTTPServerUseSSL = "UseSSL"; +static constexpr std::string_view StrHideUpdateMessages = "ImScaredOfUpdates"; // HTTP +static constexpr std::string_view StrHTTPServerEnabled = "HTTPServerEnabled"; +static constexpr std::string_view StrHTTPServerUseSSL = "UseSSL"; static constexpr std::string_view StrSSLKeyPath = "SSLKeyPath"; static constexpr std::string_view StrSSLCertPath = "SSLCertPath"; static constexpr std::string_view StrHTTPServerPort = "HTTPServerPort"; @@ -59,7 +62,6 @@ void SetComment(CommentsT& Comments, const std::string& Comment) { */ void TConfig::FlushToFile() { auto data = toml::parse(mConfigFileName); - data["General"] = toml::table(); data["General"][StrAuthKey.data()] = Application::Settings.Key; SetComment(data["General"][StrAuthKey.data()].comments(), " AuthKey has to be filled out in order to run the server"); data["General"][StrDebug.data()] = Application::Settings.DebugModeEnabled; @@ -71,10 +73,14 @@ void TConfig::FlushToFile() { data["General"][StrMap.data()] = Application::Settings.MapName; data["General"][StrDescription.data()] = Application::Settings.ServerDesc; data["General"][StrResourceFolder.data()] = Application::Settings.Resource; - data["General"][StrSendErrors.data()] = Application::Settings.SendErrors; - SetComment(data["General"][StrSendErrors.data()].comments(), " You can turn on/off the SendErrors message you get on startup here"); - data["General"][StrSendErrorsMessageEnabled.data()] = Application::Settings.SendErrorsMessageEnabled; - SetComment(data["General"][StrSendErrorsMessageEnabled.data()].comments(), " If SendErrors is `true`, the server will send helpful info about crashes and other issues back to the BeamMP developers. This info may include your config, who is on your server at the time of the error, and similar general information. This kind of data is vital in helping us diagnose and fix issues faster. This has no impact on server performance. You can opt-out of this system by setting this to `false`"); + // Misc + data["Misc"][StrHideUpdateMessages.data()] = Application::Settings.HideUpdateMessages; + SetComment(data["Misc"][StrHideUpdateMessages.data()].comments(), " Hides the periodic update message which notifies you of a new server version. You should really keep this on and always update as soon as possible. For more information visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server. An update message will always appear at startup regardless."); + data["Misc"][StrSendErrors.data()] = Application::Settings.SendErrors; + SetComment(data["Misc"][StrSendErrors.data()].comments(), " You can turn on/off the SendErrors message you get on startup here"); + data["Misc"][StrSendErrorsMessageEnabled.data()] = Application::Settings.SendErrorsMessageEnabled; + SetComment(data["Misc"][StrSendErrorsMessageEnabled.data()].comments(), " If SendErrors is `true`, the server will send helpful info about crashes and other issues back to the BeamMP developers. This info may include your config, who is on your server at the time of the error, and similar general information. This kind of data is vital in helping us diagnose and fix issues faster. This has no impact on server performance. You can opt-out of this system by setting this to `false`"); + // HTTP data["HTTP"][StrSSLKeyPath.data()] = Application::Settings.SSLKeyPath; data["HTTP"][StrSSLCertPath.data()] = Application::Settings.SSLCertPath; data["HTTP"][StrHTTPServerPort.data()] = Application::Settings.HTTPServerPort; @@ -82,7 +88,7 @@ void TConfig::FlushToFile() { SetComment(data["HTTP"][StrHTTPServerUseSSL.data()].comments(), " Recommended to keep enabled. With SSL the server will serve https and requires valid key and cert files"); data["HTTP"][StrHTTPServerEnabled.data()] = Application::Settings.HTTPServerEnabled; SetComment(data["HTTP"][StrHTTPServerEnabled.data()].comments(), " Enables the internal HTTP server"); - std::ofstream Stream(mConfigFileName); + std::ofstream Stream(mConfigFileName, std::ios::trunc | std::ios::out); Stream << data << std::flush; } @@ -158,8 +164,10 @@ void TConfig::ParseFromFile(std::string_view name) { TryReadValue(data, "General", StrDescription, Application::Settings.ServerDesc); TryReadValue(data, "General", StrResourceFolder, Application::Settings.Resource); TryReadValue(data, "General", StrAuthKey, Application::Settings.Key); - TryReadValue(data, "General", StrSendErrors, Application::Settings.SendErrors); - TryReadValue(data, "General", StrSendErrorsMessageEnabled, Application::Settings.SendErrorsMessageEnabled); + // Misc + TryReadValue(data, "Misc", StrSendErrors, Application::Settings.SendErrors); + TryReadValue(data, "Misc", StrHideUpdateMessages, Application::Settings.HideUpdateMessages); + TryReadValue(data, "Misc", StrSendErrorsMessageEnabled, Application::Settings.SendErrorsMessageEnabled); // HTTP TryReadValue(data, "HTTP", StrSSLKeyPath, Application::Settings.SSLKeyPath); TryReadValue(data, "HTTP", StrSSLCertPath, Application::Settings.SSLCertPath); diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index 42e7b36..d65380e 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -19,7 +19,9 @@ void THeartbeatThread::operator()() { static std::chrono::high_resolution_clock::time_point LastNormalUpdateTime = std::chrono::high_resolution_clock::now(); bool isAuth = false; + size_t UpdateReminderCounter = 0; while (!mShutdown) { + ++UpdateReminderCounter; Body = GenerateCall(); // a hot-change occurs when a setting has changed, to update the backend of that change. auto Now = std::chrono::high_resolution_clock::now(); @@ -128,6 +130,9 @@ void THeartbeatThread::operator()() { if (isAuth) { Application::SetSubsystemStatus("Heartbeat", Application::Status::Good); } + if (!Application::Settings.HideUpdateMessages && UpdateReminderCounter % 5) { + Application::CheckForUpdates(); + } } } From b97397132d7f603636e8cfcf21c573a6edf0bf39 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 15:59:31 +0200 Subject: [PATCH 04/35] TLuaEngine: improve result queue handling --- include/TLuaEngine.h | 6 ++++-- src/TLuaEngine.cpp | 42 ++++++++++++++++++++++-------------------- src/main.cpp | 2 +- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 9b0a884..9d3abd3 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -218,8 +219,9 @@ private: std::recursive_mutex mLuaEventsMutex; std::vector mTimedEvents; std::recursive_mutex mTimedEventsMutex; - std::queue> mResultsToCheck; - std::recursive_mutex mResultsToCheckMutex; + std::list> mResultsToCheck; + std::mutex mResultsToCheckMutex; + std::condition_variable mResultsToCheckCond; }; // std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr arg, bool Wait); diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 41ffb96..78724c9 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -44,7 +44,7 @@ void TLuaEngine::operator()() { CollectAndInitPlugins(); // now call all onInit's auto Futures = TriggerEvent("onInit", ""); - WaitForAll(Futures); + WaitForAll(Futures, std::chrono::seconds(5)); for (const auto& Future : Futures) { if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) { beammp_lua_error("Calling \"onInit\" on \"" + Future->StateId + "\" failed: " + Future->ErrorMessage); @@ -54,25 +54,21 @@ void TLuaEngine::operator()() { auto ResultCheckThread = std::thread([&] { RegisterThread("ResultCheckThread"); while (!mShutdown) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::unique_lock Lock(mResultsToCheckMutex); + mResultsToCheckCond.wait_for(Lock, std::chrono::milliseconds(20)); if (!mResultsToCheck.empty()) { - auto Res = mResultsToCheck.front(); - mResultsToCheck.pop(); - Lock.unlock(); - - if (!Res->Ready) { - Lock.lock(); - mResultsToCheck.push(Res); - Lock.unlock(); - } - if (Res->Error) { - if (Res->ErrorMessage != BeamMPFnNotFoundError) { - beammp_lua_error(Res->Function + ": " + Res->ErrorMessage); + mResultsToCheck.remove_if([](const std::shared_ptr& Ptr) -> bool { + if (Ptr->Ready) { + return true; + } else if (Ptr->Error) { + if (Ptr->ErrorMessage != BeamMPFnNotFoundError) { + beammp_lua_error(Ptr->Function + ": " + Ptr->ErrorMessage); + } + return true; } - } + return false; + }); } - std::this_thread::yield(); } }); // event loop @@ -91,7 +87,8 @@ void TLuaEngine::operator()() { std::unique_lock Lock2(mResultsToCheckMutex); for (auto& Handler : Handlers) { auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCall(Handler, {}); - mResultsToCheck.push(Res); + mResultsToCheck.push_back(Res); + mResultsToCheckCond.notify_one(); } } } @@ -144,7 +141,8 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) { void TLuaEngine::AddResultToCheck(const std::shared_ptr& Result) { std::unique_lock Lock(mResultsToCheckMutex); - mResultsToCheck.push(Result); + mResultsToCheck.push_back(Result); + mResultsToCheckCond.notify_one(); } void TLuaEngine::WaitForAll(std::vector>& Results, const std::optional& Max) { @@ -155,9 +153,12 @@ void TLuaEngine::WaitForAll(std::vector>& Results, c std::this_thread::sleep_for(std::chrono::milliseconds(10)); ms += 10; if (Max.has_value() && std::chrono::milliseconds(ms) > Max.value()) { - beammp_trace("'" + Result->Function + "' in '" + Result->StateId + "' did not finish executing in time (took: " + std::to_string(ms) + "ms)"); + beammp_trace("'" + Result->Function + "' in '" + Result->StateId + "' did not finish executing in time (took: " + std::to_string(ms) + "ms)."); Cancelled = true; } + else if (ms > 1000 * 60) { + beammp_lua_warn("'" + Result->Function +"' in '" + Result->StateId + "' is taking very long. The event it's handling is too important to discard the result of this handler, but may block this event and possibly the whole lua state."); + } } if (Cancelled) { beammp_lua_warn("'" + Result->Function + "' in '" + Result->StateId + "' failed to execute in time and was not waited for. It may still finish executing at a later time."); @@ -174,7 +175,8 @@ void TLuaEngine::WaitForAll(std::vector>& Results, c void TLuaEngine::ReportErrors(const std::vector>& Results) { std::unique_lock Lock2(mResultsToCheckMutex); for (const auto& Result : Results) { - mResultsToCheck.push(Result); + mResultsToCheck.push_back(Result); + mResultsToCheckCond.notify_one(); } } diff --git a/src/main.cpp b/src/main.cpp index 8b2f3c5..d076cc1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,7 +133,7 @@ int BeamMPServerMain(MainArguments Arguments) { }); Application::RegisterShutdownHandler([] { auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", ""); - TLuaEngine::WaitForAll(Futures); + TLuaEngine::WaitForAll(Futures, std::chrono::seconds(5)); }); TServer Server(Arguments.List); From 81dbf747d524a5ce5deaff08de3aaf40ede5e7ba Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 16:50:00 +0200 Subject: [PATCH 05/35] Kick client if we fail to send them a client event --- src/LuaAPI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index 14cd8f6..4a76cdc 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -112,7 +112,8 @@ bool LuaAPI::MP::TriggerClientEvent(int PlayerID, const std::string& EventName, } auto c = MaybeClient.value().lock(); if (!Engine->Network().Respond(*c, Packet, true)) { - beammp_lua_error("Respond failed"); + beammp_lua_error("Respond failed, dropping client " + std::to_string(PlayerID)); + Engine->Network().ClientKick(*c, "Disconnected after failing to receive packets"); return false; } } From d4b30a258375f01f50f5c9276322cfa880bb3540 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 20:13:59 +0200 Subject: [PATCH 06/35] CreateEventTimer: Implement CallStrategy There are two CallStrategies: - BestEffort (default): Will try to get your event to trigger at the specified interval, but will refuse to queue handlers if a handler takes too long. - Precise: Will enqueue event handlers at the exact interval specified. Can lead to the queue filling up if the handler takes longer than the interval. --- include/TLuaEngine.h | 20 ++++++++-- src/TLuaEngine.cpp | 92 ++++++++++++++++++++++++++++++++++---------- src/TNetwork.cpp | 1 + 3 files changed, 90 insertions(+), 23 deletions(-) diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 9d3abd3..5ca2222 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -73,6 +73,18 @@ private: class TLuaEngine : IThreaded { public: + enum CallStrategy : int { + BestEffort, + Precise, + }; + + struct QueuedFunction { + std::string FunctionName; + std::shared_ptr Result; + std::vector Args; + std::string EventName; // optional, may be empty + }; + TLuaEngine(); ~TLuaEngine() noexcept { beammp_debug("Lua Engine terminated"); @@ -146,7 +158,7 @@ public: return Results; // } std::set GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId); - void CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS); + void CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS, CallStrategy Strategy); void CancelEventTimers(const std::string& EventName, TLuaStateId StateId); sol::state_view GetStateForPlugin(const fs::path& PluginPath); TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath); @@ -167,6 +179,7 @@ private: ~StateThreadData() noexcept { beammp_debug("\"" + mStateId + "\" destroyed"); } [[nodiscard]] std::shared_ptr EnqueueScript(const TLuaChunk& Script); [[nodiscard]] std::shared_ptr EnqueueFunctionCall(const std::string& FunctionName, const std::vector& Args); + [[nodiscard]] std::shared_ptr EnqueueFunctionCallFromCustomEvent(const std::string& FunctionName, const std::vector& Args, const std::string& EventName, CallStrategy Strategy); void RegisterEvent(const std::string& EventName, const std::string& FunctionName); void AddPath(const fs::path& Path); // to be added to path and cpath void operator()() override; @@ -189,7 +202,7 @@ private: std::thread mThread; std::queue>> mStateExecuteQueue; std::recursive_mutex mStateExecuteQueueMutex; - std::queue, std::vector>> mStateFunctionQueue; + std::vector mStateFunctionQueue; std::mutex mStateFunctionQueueMutex; std::condition_variable mStateFunctionQueueCond; TLuaEngine* mEngine; @@ -203,6 +216,7 @@ private: std::chrono::high_resolution_clock::time_point LastCompletion {}; std::string EventName; TLuaStateId StateId; + CallStrategy Strategy; bool Expired(); void Reset(); }; diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 78724c9..1d684d8 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -81,22 +81,31 @@ void TLuaEngine::operator()() { std::unique_lock Lock(mTimedEventsMutex); for (auto& Timer : mTimedEvents) { if (Timer.Expired()) { + auto LastCompletionBeforeReset = Timer.LastCompletion; Timer.Reset(); auto Handlers = GetEventHandlersForState(Timer.EventName, Timer.StateId); std::unique_lock StateLock(mLuaStatesMutex); std::unique_lock Lock2(mResultsToCheckMutex); for (auto& Handler : Handlers) { - auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCall(Handler, {}); - mResultsToCheck.push_back(Res); - mResultsToCheckCond.notify_one(); + auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCallFromCustomEvent(Handler, {}, Timer.EventName, Timer.Strategy); + if (Res) { + mResultsToCheck.push_back(Res); + mResultsToCheckCond.notify_one(); + } else { + // "revert" reset + Timer.LastCompletion = LastCompletionBeforeReset; + // beammp_trace("Reverted reset of \"" + Timer.EventName + "\" timer"); + // no need to try to enqueue more handlers for this event (they will all fail) + break; + } } } } } - std::chrono::high_resolution_clock::duration Diff; - if ((Diff = std::chrono::high_resolution_clock::now() - Before) - < std::chrono::milliseconds(10)) { - std::this_thread::sleep_for(Diff); + const auto Expected = std::chrono::milliseconds(10); + if (auto Diff = std::chrono::high_resolution_clock::now() - Before; + Diff < Expected) { + std::this_thread::sleep_for(Expected - Diff); } else { beammp_trace("Event loop cannot keep up! Running " + std::to_string(Diff.count()) + "s behind"); } @@ -155,9 +164,8 @@ void TLuaEngine::WaitForAll(std::vector>& Results, c if (Max.has_value() && std::chrono::milliseconds(ms) > Max.value()) { beammp_trace("'" + Result->Function + "' in '" + Result->StateId + "' did not finish executing in time (took: " + std::to_string(ms) + "ms)."); Cancelled = true; - } - else if (ms > 1000 * 60) { - beammp_lua_warn("'" + Result->Function +"' in '" + Result->StateId + "' is taking very long. The event it's handling is too important to discard the result of this handler, but may block this event and possibly the whole lua state."); + } else if (ms > 1000 * 60) { + beammp_lua_warn("'" + Result->Function + "' in '" + Result->StateId + "' is taking very long. The event it's handling is too important to discard the result of this handler, but may block this event and possibly the whole lua state."); } } if (Cancelled) { @@ -504,11 +512,27 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi return Lua_GetPlayerIdentifiers(ID); }); MPTable.set_function("Sleep", &LuaAPI::MP::Sleep); - MPTable.set_function("CreateEventTimer", [&](const std::string& EventName, size_t IntervalMS) { + // const std::string& EventName, size_t IntervalMS, int strategy + MPTable.set_function("CreateEventTimer", [&](sol::variadic_args Args) { + if (Args.size() < 2 || Args.size() > 3) { + beammp_lua_error("CreateEventTimer expects 2 or 3 arguments."); + } + if (Args.get_type(0) != sol::type::string) { + beammp_lua_error("CreateEventTimer expects 1st argument to be a string"); + } + if (Args.get_type(1) != sol::type::number) { + beammp_lua_error("CreateEventTimer expects 2nd argument to be a number"); + } + if (Args.size() == 3 && Args.get_type(2) != sol::type::number) { + beammp_lua_error("CreateEventTimer expects 3rd argument to be a number (MP.CallStrategy)"); + } + auto EventName = Args.get(0); + auto IntervalMS = Args.get(1); + CallStrategy Strategy = Args.size() > 2 ? Args.get(2) : CallStrategy::BestEffort; if (IntervalMS < 25) { beammp_warn("Timer for \"" + EventName + "\" on \"" + mStateId + "\" is set to trigger at <25ms, which is likely too fast and won't cancel properly."); } - mEngine->CreateEventTimer(EventName, mStateId, IntervalMS); + mEngine->CreateEventTimer(EventName, mStateId, IntervalMS, Strategy); }); MPTable.set_function("CancelEventTimer", [&](const std::string& EventName) { mEngine->CancelEventTimers(EventName, mStateId); @@ -528,6 +552,10 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi "Name", 5, "Description", 6); + MPTable.create_named("CallStrategy", + "BestEffort", CallStrategy::BestEffort, + "Precise", CallStrategy::Precise); + auto FSTable = StateView.create_named_table("FS"); FSTable.set_function("CreateDirectory", &LuaAPI::FS::CreateDirectory); FSTable.set_function("Exists", &LuaAPI::FS::Exists); @@ -550,12 +578,34 @@ std::shared_ptr TLuaEngine::StateThreadData::EnqueueScript(const TLu return Result; } +std::shared_ptr TLuaEngine::StateThreadData::EnqueueFunctionCallFromCustomEvent(const std::string& FunctionName, const std::vector& Args, const std::string& EventName, CallStrategy Strategy) { + // TODO: Document all this + decltype(mStateFunctionQueue)::iterator Iter = mStateFunctionQueue.end(); + if (Strategy == CallStrategy::BestEffort) { + Iter = std::find_if(mStateFunctionQueue.begin(), mStateFunctionQueue.end(), + [&EventName](const QueuedFunction& Element) { + return Element.EventName == EventName; + }); + } + if (Iter == mStateFunctionQueue.end()) { + auto Result = std::make_shared(); + Result->StateId = mStateId; + Result->Function = FunctionName; + std::unique_lock Lock(mStateFunctionQueueMutex); + mStateFunctionQueue.push_back({ FunctionName, Result, Args, EventName }); + mStateFunctionQueueCond.notify_all(); + return Result; + } else { + return nullptr; + } +} + std::shared_ptr TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName, const std::vector& Args) { auto Result = std::make_shared(); Result->StateId = mStateId; Result->Function = FunctionName; std::unique_lock Lock(mStateFunctionQueueMutex); - mStateFunctionQueue.push({ FunctionName, Result, Args }); + mStateFunctionQueue.push_back({ FunctionName, Result, Args, "" }); mStateFunctionQueueCond.notify_all(); return Result; } @@ -618,12 +668,13 @@ void TLuaEngine::StateThreadData::operator()() { std::chrono::milliseconds(500), [&]() -> bool { return !mStateFunctionQueue.empty(); }); if (NotExpired) { - auto FnNameResultPair = std::move(mStateFunctionQueue.front()); - mStateFunctionQueue.pop(); + auto TheQueuedFunction = std::move(mStateFunctionQueue.front()); + mStateFunctionQueue.erase(mStateFunctionQueue.begin()); Lock.unlock(); - auto& FnName = std::get<0>(FnNameResultPair); - auto& Result = std::get<1>(FnNameResultPair); - auto Args = std::get<2>(FnNameResultPair); + auto& FnName = TheQueuedFunction.FunctionName; + auto& Result = TheQueuedFunction.Result; + auto Args = TheQueuedFunction.Args; + // TODO: Use TheQueuedFunction.EventName for errors, warnings, etc Result->StateId = mStateId; sol::state_view StateView(mState); auto Fn = StateView[FnName]; @@ -671,13 +722,14 @@ void TLuaEngine::StateThreadData::operator()() { } } -void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS) { +void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS, CallStrategy Strategy) { std::unique_lock Lock(mTimedEventsMutex); TimedEvent Event { std::chrono::high_resolution_clock::duration { std::chrono::milliseconds(IntervalMS) }, std::chrono::high_resolution_clock::now(), EventName, - StateId + StateId, + Strategy }; mTimedEvents.push_back(std::move(Event)); beammp_trace("created event timer for \"" + EventName + "\" on \"" + StateId + "\" with " + std::to_string(IntervalMS) + "ms interval"); diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index 1e0e5be..ef2064e 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -514,6 +514,7 @@ void TNetwork::Looper(const std::weak_ptr& c) { } } } + void TNetwork::TCPClient(const std::weak_ptr& c) { // TODO: the c.expired() might cause issues here, remove if you end up here with your debugger if (c.expired() || c.lock()->GetTCPSock() == -1) { From d01d79a49a6d01a5f1cc76abc55af47bdb705815 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 20:27:08 +0200 Subject: [PATCH 07/35] update changelog --- Changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Changelog.md b/Changelog.md index 982c893..ac45ff8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,11 @@ +# v3.0.2 + +- ADDED Periodic update message if a new server is released +- CHANGED Default MaxPlayers to 8 +- FIXED `MP.CreateEventTimer` filling up the queue (see https://wiki.beammp.com/en/Scripting/new-lua-scripting#mpcreateeventtimerevent_name-string-interval_ms-number-strategy-number-since-v302) +- FIXED `MP.TriggerClientEvent` not kicking the client if it failed +- FIXED Lua result queue handling not checking all results + # v3.0.1 - ADDED Backup URLs to UpdateCheck (will fail less often now) From 5e4c7eac510553fc59096790e25227a318a356a9 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 23:48:07 +0200 Subject: [PATCH 08/35] add send timeout to client tcp socket --- src/TNetwork.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index ef2064e..155f97f 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -154,6 +154,19 @@ void TNetwork::TCPServerMain() { beammp_warn(("Got an invalid client socket on connect! Skipping...")); continue; } + // set timeout + size_t SendTimeoutMS = 30 * 1000; +#if defined(BEAMMP_WINDOWS) + ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&ms), sizeof(ms)); +#else // POSIX + struct timeval optval; + optval.tv_sec = (int)(SendTimeoutMS / 1000); + optval.tv_usec = (SendTimeoutMS % 1000) * 1000; + ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&optval), sizeof(optval)); +#endif + if (ret < 0) { + throw std::runtime_error("setsockopt recv timeout: " + GetPlatformAgnosticErrorString()); + } std::thread ID(&TNetwork::Identify, this, client); ID.detach(); // TODO: Add to a queue and attempt to join periodically } catch (const std::exception& e) { From 4ff69528bd6a8143632ac11230df0df70acfcc0c Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 31 Mar 2022 23:56:02 +0200 Subject: [PATCH 09/35] fix some missing declaration --- src/TNetwork.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index 155f97f..0af4f49 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -157,12 +157,12 @@ void TNetwork::TCPServerMain() { // set timeout size_t SendTimeoutMS = 30 * 1000; #if defined(BEAMMP_WINDOWS) - ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&ms), sizeof(ms)); + int ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&ms), sizeof(ms)); #else // POSIX struct timeval optval; optval.tv_sec = (int)(SendTimeoutMS / 1000); optval.tv_usec = (SendTimeoutMS % 1000) * 1000; - ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&optval), sizeof(optval)); + int ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&optval), sizeof(optval)); #endif if (ret < 0) { throw std::runtime_error("setsockopt recv timeout: " + GetPlatformAgnosticErrorString()); From 1bab3276e9cf97ab3e5ad22a5eea88fe628376b9 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Tue, 5 Apr 2022 10:58:42 +0200 Subject: [PATCH 10/35] fix setsockopt SO_SNDTIMEO for windows, bump version number to 3.0.2, update commandline --- deps/commandline | 2 +- include/Common.h | 4 ++-- src/TNetwork.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/deps/commandline b/deps/commandline index 01434c1..b1da8bc 160000 --- a/deps/commandline +++ b/deps/commandline @@ -1 +1 @@ -Subproject commit 01434c11aaf82d37a126dc70f5aa02cc523dbbb4 +Subproject commit b1da8bcb696bfa9388dca46bf0f5dd9538fc70aa diff --git a/include/Common.h b/include/Common.h index 5d224fb..8861a77 100644 --- a/include/Common.h +++ b/include/Common.h @@ -7,12 +7,12 @@ extern TSentry Sentry; #include #include #include +#include #include #include #include #include #include -#include #include "Compat.h" @@ -121,7 +121,7 @@ private: static inline std::mutex mShutdownHandlersMutex {}; static inline std::deque mShutdownHandlers {}; - static inline Version mVersion { 3, 0, 1 }; + static inline Version mVersion { 3, 0, 2 }; }; std::string ThreadName(bool DebugModeOverride = false); diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index 0af4f49..03c90f1 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -154,10 +154,10 @@ void TNetwork::TCPServerMain() { beammp_warn(("Got an invalid client socket on connect! Skipping...")); continue; } - // set timeout - size_t SendTimeoutMS = 30 * 1000; + // set timeout (DWORD, aka uint32_t) + uint32_t SendTimeoutMS = 30 * 1000; #if defined(BEAMMP_WINDOWS) - int ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&ms), sizeof(ms)); + int ret = ::setsockopt(client.Socket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast(&SendTimeoutMS), sizeof(SendTimeoutMS)); #else // POSIX struct timeval optval; optval.tv_sec = (int)(SendTimeoutMS / 1000); From d8c33c03eea8551111d6d58c2ca2254e740d8b0b Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Tue, 5 Apr 2022 22:27:45 +0200 Subject: [PATCH 11/35] start work on new logger --- include/TConsole.h | 2 ++ src/TConsole.cpp | 26 ++++++++++++++++++++++++++ src/main.cpp | 6 ++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/TConsole.h b/include/TConsole.h index c393842..1d64660 100644 --- a/include/TConsole.h +++ b/include/TConsole.h @@ -15,6 +15,7 @@ public: void WriteRaw(const std::string& str); void InitializeLuaConsole(TLuaEngine& Engine); void BackupOldLog(); + void StartLoggingToFile(); Commandline& Internal() { return mCommandline; } private: @@ -37,4 +38,5 @@ private: bool mFirstTime { true }; std::string mStateId; const std::string mDefaultStateId = "BEAMMP_SERVER_CONSOLE"; + std::ofstream mLogFileStream; }; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 79d30a4..16b3c04 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -97,6 +97,32 @@ void TConsole::BackupOldLog() { } } +enum EscState { + None, + Escape, + FeSeqStart, + FeSeqMid, + SeqEnd +}; + +void TConsole::StartLoggingToFile() { + mLogFileStream.open("Server.log"); + Application::Console().Internal().on_write = [this](const std::string& ToWrite) { + // sanitize the string by removing all ANSI control codes (like color, etc) + std::string Sanitized; + Sanitized.reserve(ToWrite.size()); + EscState state; + for (size_t i = 0; i < ToWrite.size(); ++i) { + if (i + 1 < ToWrite.size() + && ToWrite[i] == 0x1b) { // starts ANSI escape sequence + if (ToWrite[i + 1] >= 0x40 || ToWrite[i + 1] <= 0x5F) { + } + } + mLogFileStream.write(ToWrite.c_str(), ToWrite.size()); + }; + }; +} + void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) { if (!mIsLuaConsole) { if (!mLuaEngine) { diff --git a/src/main.cpp b/src/main.cpp index d076cc1..905b994 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,10 +119,8 @@ int BeamMPServerMain(MainArguments Arguments) { } Application::SetSubsystemStatus("Main", Application::Status::Starting); - bool Success = Application::Console().Internal().enable_write_to_file("Server.log"); - if (!Success) { - beammp_error("unable to open file for writing: \"Server.log\""); - } + + Application::Console().StartLoggingToFile(); SetupSignalHandlers(); From 056d20292af145f034fca2c758086192a336886a Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 13:14:28 +0200 Subject: [PATCH 12/35] Make "unable to fetch version" a trace message --- deps/commandline | 2 +- src/Common.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/commandline b/deps/commandline index b1da8bc..01434c1 160000 --- a/deps/commandline +++ b/deps/commandline @@ -1 +1 @@ -Subproject commit b1da8bcb696bfa9388dca46bf0f5dd9538fc70aa +Subproject commit 01434c11aaf82d37a126dc70f5aa02cc523dbbb4 diff --git a/src/Common.cpp b/src/Common.cpp index 99d0009..9263862 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -123,7 +123,7 @@ void Application::CheckForUpdates() { } } if (Application::GetSubsystemStatuses().at("UpdateCheck") == Application::Status::Bad) { - beammp_warn("Unable to fetch version info from backend."); + beammp_trace("Unable to fetch version info from backend."); } } From 668cc496b6c218533e0ef768875bd4e4832ef40d Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 13:24:46 +0200 Subject: [PATCH 13/35] update commandline, unused are now errors --- CMakeLists.txt | 9 +++++---- deps/commandline | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a36c83..e72a070 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,10 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif () +message(STATUS "Adding local source dependencies") +# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG +add_subdirectory(deps) + message(STATUS "Setting compiler flags") if (WIN32) @@ -68,7 +72,7 @@ if (WIN32) include_directories(${VcpkgRoot}/include) link_directories(${VcpkgRoot}/lib) elseif (UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++ -Werror=unused") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fno-builtin") if (SANITIZE) @@ -78,9 +82,6 @@ elseif (UNIX) endif () -message(STATUS "Adding local source dependencies") -# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG -add_subdirectory(deps) set(CMAKE_CXX_STANDARD 17) diff --git a/deps/commandline b/deps/commandline index 01434c1..d6b1c32 160000 --- a/deps/commandline +++ b/deps/commandline @@ -1 +1 @@ -Subproject commit 01434c11aaf82d37a126dc70f5aa02cc523dbbb4 +Subproject commit d6b1c32c8af6ad5306f9f001305b3be9928ae4bb From 5ded713b4be568463917f5b09c71ff975adb1924 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 13:32:38 +0200 Subject: [PATCH 14/35] Application::CheckForUpdates: only print status the first time --- src/Common.cpp | 24 ++++++++++++++++-------- src/TConsole.cpp | 1 - 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Common.cpp b/src/Common.cpp index 9263862..34b28ea 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -97,6 +97,7 @@ void Application::SetSubsystemStatus(const std::string& Subsystem, Status status void Application::CheckForUpdates() { Application::SetSubsystemStatus("UpdateCheck", Application::Status::Starting); + static bool FirstTime = true; // checks current version against latest version std::regex VersionRegex { R"(\d+\.\d+\.\d+\n*)" }; for (const auto& url : GetBackendUrlsInOrder()) { @@ -109,22 +110,29 @@ void Application::CheckForUpdates() { std::string RealVersionString = RemoteVersion.AsString(); beammp_warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION IS OUT! Please update to the new version (v" + RealVersionString + ") of the BeamMP-Server! Download it here: https://beammp.com/! For a guide on how to update, visit: https://wiki.beammp.com/en/home/server-maintenance#updating-the-server" + std::string(ANSI_RESET)); } else { - beammp_info("Server up-to-date!"); + if (FirstTime) { + beammp_info("Server up-to-date!"); + } } Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good); break; } else { - beammp_debug("Failed to fetch version from: " + url); - beammp_trace("got " + Response); - auto Lock = Sentry.CreateExclusiveContext(); - Sentry.SetContext("get-response", { { "response", Response } }); - Sentry.LogError("failed to get server version", _file_basename, _line); - Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad); + if (FirstTime) { + beammp_debug("Failed to fetch version from: " + url); + beammp_trace("got " + Response); + auto Lock = Sentry.CreateExclusiveContext(); + Sentry.SetContext("get-response", { { "response", Response } }); + Sentry.LogError("failed to get server version", _file_basename, _line); + Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad); + } } } if (Application::GetSubsystemStatuses().at("UpdateCheck") == Application::Status::Bad) { - beammp_trace("Unable to fetch version info from backend."); + if (FirstTime) { + beammp_warn("Unable to fetch version info from backend."); + } } + FirstTime = false; } // thread name stuff diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 16b3c04..1c69791 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -111,7 +111,6 @@ void TConsole::StartLoggingToFile() { // sanitize the string by removing all ANSI control codes (like color, etc) std::string Sanitized; Sanitized.reserve(ToWrite.size()); - EscState state; for (size_t i = 0; i < ToWrite.size(); ++i) { if (i + 1 < ToWrite.size() && ToWrite[i] == 0x1b) { // starts ANSI escape sequence From 0761036c8caf0e3d1a881529309c2ff09008a03c Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 13:44:39 +0200 Subject: [PATCH 15/35] TConsole::StartLoggingToFile: implement --- include/TConsole.h | 1 + src/TConsole.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/TConsole.h b/include/TConsole.h index 1d64660..839f862 100644 --- a/include/TConsole.h +++ b/include/TConsole.h @@ -39,4 +39,5 @@ private: std::string mStateId; const std::string mDefaultStateId = "BEAMMP_SERVER_CONSOLE"; std::ofstream mLogFileStream; + std::mutex mLogFileStreamMtx; }; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 1c69791..13e8f2d 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -108,17 +108,11 @@ enum EscState { void TConsole::StartLoggingToFile() { mLogFileStream.open("Server.log"); Application::Console().Internal().on_write = [this](const std::string& ToWrite) { - // sanitize the string by removing all ANSI control codes (like color, etc) - std::string Sanitized; - Sanitized.reserve(ToWrite.size()); - for (size_t i = 0; i < ToWrite.size(); ++i) { - if (i + 1 < ToWrite.size() - && ToWrite[i] == 0x1b) { // starts ANSI escape sequence - if (ToWrite[i + 1] >= 0x40 || ToWrite[i + 1] <= 0x5F) { - } - } - mLogFileStream.write(ToWrite.c_str(), ToWrite.size()); - }; + // TODO: Sanitize by removing all ansi escape codes (vt100) + std::unique_lock Lock(mLogFileStreamMtx); + mLogFileStream.write(ToWrite.c_str(), ToWrite.size()); + mLogFileStream.write("\n", 1); + mLogFileStream.flush(); }; } From 0979c8b1e47885a898003c1573a03eb4a262f7b6 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:04:54 +0200 Subject: [PATCH 16/35] HTTPServer: Attempt to catch more errors --- include/Client.h | 2 +- src/Client.cpp | 1 + src/Http.cpp | 12 ++++++++++-- src/main.cpp | 9 ++++++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/Client.h b/include/Client.h index 93882f2..d513659 100644 --- a/include/Client.h +++ b/include/Client.h @@ -92,7 +92,7 @@ private: std::queue mPacketsSync; std::unordered_map mIdentifiers; bool mIsGuest = false; - std::mutex mVehicleDataMutex; + mutable std::mutex mVehicleDataMutex; TSetOfVehicleData mVehicleData; std::string mName = "Unknown Client"; SOCKET mSocket[2] { SOCKET(0), SOCKET(0) }; diff --git a/src/Client.cpp b/src/Client.cpp index d5736fe..4edbbc7 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -27,6 +27,7 @@ void TClient::ClearCars() { int TClient::GetOpenCarID() const { int OpenID = 0; bool found; + std::unique_lock lock(mVehicleDataMutex); do { found = true; for (auto& v : mVehicleData) { diff --git a/src/Http.cpp b/src/Http.cpp index 467fd3c..9a3b9b6 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -293,7 +293,7 @@ Http::Server::THttpServerInstance::THttpServerInstance() { mThread.detach(); } -void Http::Server::THttpServerInstance::operator()() { +void Http::Server::THttpServerInstance::operator()() try { beammp_info("HTTP(S) Server started on port " + std::to_string(Application::Settings.HTTPServerPort)); std::unique_ptr HttpLibServerInstance; if (Application::Settings.HTTPServerUseSSL) { @@ -370,6 +370,14 @@ void Http::Server::THttpServerInstance::operator()() { HttpLibServerInstance->Get({ 0x2f, 0x6b, 0x69, 0x74, 0x74, 0x79 }, [](const httplib::Request&, httplib::Response& res) { res.set_content(std::string(Magic), "text/plain"); }); + HttpLibServerInstance->set_logger([](const httplib::Request& Req, const httplib::Response& Res) { + beammp_debug("Http Server: " + Req.method + " " + Req.target + " -> " + std::to_string(Res.status)); + }); Application::SetSubsystemStatus("HTTPServer", Application::Status::Good); - HttpLibServerInstance->listen("0.0.0.0", Application::Settings.HTTPServerPort); + auto ret = HttpLibServerInstance->listen("0.0.0.0", Application::Settings.HTTPServerPort); + if (!ret) { + beammp_error("Failed to start http server (failed to listen). Please ensure the http server is configured properly in the ServerConfig.toml, or turn it off if you don't need it."); + } +} catch (const std::exception& e) { + beammp_error("Failed to start http server. Please ensure the http server is configured properly in the ServerConfig.toml, or turn it off if you don't need it. Error: " + std::string(e.what())); } diff --git a/src/main.cpp b/src/main.cpp index 905b994..5e5a96d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,7 +119,7 @@ int BeamMPServerMain(MainArguments Arguments) { } Application::SetSubsystemStatus("Main", Application::Status::Starting); - + Application::Console().StartLoggingToFile(); SetupSignalHandlers(); @@ -170,6 +170,10 @@ int BeamMPServerMain(MainArguments Arguments) { Application::SetSubsystemStatus("Main", Application::Status::Good); RegisterThread("Main(Waiting)"); + std::set IgnoreSubsystems { + "UpdateCheck" // Ignore as not to confuse users (non-vital system) + }; + bool FullyStarted = false; while (!Shutdown) { if (!FullyStarted) { @@ -178,6 +182,9 @@ int BeamMPServerMain(MainArguments Arguments) { std::string SystemsBadList {}; auto Statuses = Application::GetSubsystemStatuses(); for (const auto& NameStatusPair : Statuses) { + if (IgnoreSubsystems.count(NameStatusPair.first) > 0) { + continue; // ignore + } if (NameStatusPair.second == Application::Status::Starting) { FullyStarted = false; } else if (NameStatusPair.second == Application::Status::Bad) { From 974dda9f8b6550cc961066f2392715075d873cfc Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:12:26 +0200 Subject: [PATCH 17/35] HTTPServer: Add config value to specify listen IP Change default IP to localhost, Set default SSL to false due to this. --- include/Common.h | 3 ++- src/Http.cpp | 2 +- src/TConfig.cpp | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/Common.h b/include/Common.h index 8861a77..39714d0 100644 --- a/include/Common.h +++ b/include/Common.h @@ -53,7 +53,8 @@ public: bool SendErrors { true }; bool SendErrorsMessageEnabled { true }; int HTTPServerPort { 8080 }; - bool HTTPServerUseSSL { true }; + std::string HTTPServerIP { "127.0.0.1" }; + bool HTTPServerUseSSL { false }; bool HideUpdateMessages { false }; [[nodiscard]] bool HasCustomIP() const { return !CustomIP.empty(); } }; diff --git a/src/Http.cpp b/src/Http.cpp index 9a3b9b6..aeb66d5 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -374,7 +374,7 @@ void Http::Server::THttpServerInstance::operator()() try { beammp_debug("Http Server: " + Req.method + " " + Req.target + " -> " + std::to_string(Res.status)); }); Application::SetSubsystemStatus("HTTPServer", Application::Status::Good); - auto ret = HttpLibServerInstance->listen("0.0.0.0", Application::Settings.HTTPServerPort); + auto ret = HttpLibServerInstance->listen(Application::Settings.HTTPServerIP.c_str(), Application::Settings.HTTPServerPort); if (!ret) { beammp_error("Failed to start http server (failed to listen). Please ensure the http server is configured properly in the ServerConfig.toml, or turn it off if you don't need it."); } diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 1260cb7..f21954e 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -29,6 +29,7 @@ static constexpr std::string_view StrHTTPServerUseSSL = "UseSSL"; static constexpr std::string_view StrSSLKeyPath = "SSLKeyPath"; static constexpr std::string_view StrSSLCertPath = "SSLCertPath"; static constexpr std::string_view StrHTTPServerPort = "HTTPServerPort"; +static constexpr std::string_view StrHTTPServerIP = "HTTPServerIP"; TConfig::TConfig(const std::string& ConfigFileName) : mConfigFileName(ConfigFileName) { @@ -84,8 +85,10 @@ void TConfig::FlushToFile() { data["HTTP"][StrSSLKeyPath.data()] = Application::Settings.SSLKeyPath; data["HTTP"][StrSSLCertPath.data()] = Application::Settings.SSLCertPath; data["HTTP"][StrHTTPServerPort.data()] = Application::Settings.HTTPServerPort; + SetComment(data["HTTP"][StrHTTPServerIP.data()].comments(), " Which IP to listen on. Pick 0.0.0.0 for a public-facing server with no specific IP, and 127.0.0.1 or 'localhost' for a local server."); + data["HTTP"][StrHTTPServerIP.data()] = Application::Settings.HTTPServerIP; data["HTTP"][StrHTTPServerUseSSL.data()] = Application::Settings.HTTPServerUseSSL; - SetComment(data["HTTP"][StrHTTPServerUseSSL.data()].comments(), " Recommended to keep enabled. With SSL the server will serve https and requires valid key and cert files"); + SetComment(data["HTTP"][StrHTTPServerUseSSL.data()].comments(), " Recommended to have enabled for servers which face the internet. With SSL the server will serve https and requires valid key and cert files"); data["HTTP"][StrHTTPServerEnabled.data()] = Application::Settings.HTTPServerEnabled; SetComment(data["HTTP"][StrHTTPServerEnabled.data()].comments(), " Enables the internal HTTP server"); std::ofstream Stream(mConfigFileName, std::ios::trunc | std::ios::out); @@ -172,6 +175,7 @@ void TConfig::ParseFromFile(std::string_view name) { TryReadValue(data, "HTTP", StrSSLKeyPath, Application::Settings.SSLKeyPath); TryReadValue(data, "HTTP", StrSSLCertPath, Application::Settings.SSLCertPath); TryReadValue(data, "HTTP", StrHTTPServerPort, Application::Settings.HTTPServerPort); + TryReadValue(data, "HTTP", StrHTTPServerIP, Application::Settings.HTTPServerIP); TryReadValue(data, "HTTP", StrHTTPServerEnabled, Application::Settings.HTTPServerEnabled); TryReadValue(data, "HTTP", StrHTTPServerUseSSL, Application::Settings.HTTPServerUseSSL); } catch (const std::exception& err) { @@ -210,6 +214,7 @@ void TConfig::PrintDebug() { beammp_debug(std::string(StrSSLKeyPath) + ": \"" + Application::Settings.SSLKeyPath + "\""); beammp_debug(std::string(StrSSLCertPath) + ": \"" + Application::Settings.SSLCertPath + "\""); beammp_debug(std::string(StrHTTPServerPort) + ": \"" + std::to_string(Application::Settings.HTTPServerPort) + "\""); + beammp_debug(std::string(StrHTTPServerIP) + ": \"" + Application::Settings.HTTPServerIP + "\""); // special! beammp_debug("Key Length: " + std::to_string(Application::Settings.Key.length()) + ""); } From 11c53e0b3a8b65648dce5bd5db5b9c38e65fcb29 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:13:51 +0200 Subject: [PATCH 18/35] Remove unused error, as Sentry's code fails to build otherwise Thanks, sentry. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e72a070..f6a813f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ if (WIN32) include_directories(${VcpkgRoot}/include) link_directories(${VcpkgRoot}/lib) elseif (UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++ -Werror=unused") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fno-builtin") if (SANITIZE) From 7f41a2a57476fb0e7b7b79a54223c403094f3057 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:18:10 +0200 Subject: [PATCH 19/35] Update Changelog to reflect latest changes --- Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index ac45ff8..7ff6d04 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,8 +1,10 @@ # v3.0.2 - ADDED Periodic update message if a new server is released +- ADDED Config setting for the IP the http server listens on - CHANGED Default MaxPlayers to 8 -- FIXED `MP.CreateEventTimer` filling up the queue (see https://wiki.beammp.com/en/Scripting/new-lua-scripting#mpcreateeventtimerevent_name-string-interval_ms-number-strategy-number-since-v302) +- CHANGED Default http server listen IP to localhost +- FIXED `MP.CreateEventTimer` filling up the queue (see ) - FIXED `MP.TriggerClientEvent` not kicking the client if it failed - FIXED Lua result queue handling not checking all results From f4eb492d91a1dc06ee87ed296cd51db844e7d109 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:24:02 +0200 Subject: [PATCH 20/35] Actions: try to use master as vcpkgGitCommitId --- .github/workflows/cmake-windows.yml | 2 +- .github/workflows/release-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index aa9b43b..fc9b1c7 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -20,7 +20,7 @@ jobs: with: vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl' vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' - vcpkgGitCommitId: '8dddc6c899ce6fdbeab38b525a31e7f23cb2d5bb' + vcpkgGitCommitId: 'master' vcpkgTriplet: 'x64-windows-static' - name: Create Build Environment diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 8d2063a..5c39160 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -85,7 +85,7 @@ jobs: with: vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl' vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' - vcpkgGitCommitId: '8dddc6c899ce6fdbeab38b525a31e7f23cb2d5bb' + vcpkgGitCommitId: 'master' vcpkgTriplet: 'x64-windows-static' - name: Create Build Environment From 34b39aad4d7acabfc69b5d7e6de23a41dcdc6a2b Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:30:44 +0200 Subject: [PATCH 21/35] add message to shutdown suggesting Ctrl+C if it takes too long This is an ongoing issue that needs to be resolved properly, but I'm not sure what's hanging it. --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 5e5a96d..e220636 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,6 +126,7 @@ int BeamMPServerMain(MainArguments Arguments) { bool Shutdown = false; Application::RegisterShutdownHandler([&Shutdown] { + beammp_info("If this takes too long, you can press Ctrl+C repeatedly to force a shutdown."); Application::SetSubsystemStatus("Main", Application::Status::ShuttingDown); Shutdown = true; }); From ca52d233c0693be01947e3d70f91789d6504e162 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:34:05 +0200 Subject: [PATCH 22/35] Use another git commit id for vcpkg this should really be done properly, yikes --- .github/workflows/cmake-windows.yml | 2 +- .github/workflows/release-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index fc9b1c7..b882766 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -20,7 +20,7 @@ jobs: with: vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl' vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' - vcpkgGitCommitId: 'master' + vcpkgGitCommitId: 'a106de33bbee694e3be6243718aa2a549a692832' vcpkgTriplet: 'x64-windows-static' - name: Create Build Environment diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 5c39160..2f8e3f3 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -85,7 +85,7 @@ jobs: with: vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl' vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' - vcpkgGitCommitId: 'master' + vcpkgGitCommitId: 'a106de33bbee694e3be6243718aa2a549a692832' vcpkgTriplet: 'x64-windows-static' - name: Create Build Environment From 3b2016d09f818864cfb7b3007e4fcd2757315913 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 14:58:07 +0200 Subject: [PATCH 23/35] Windows moment Windows deprecated when --- src/TConsole.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 13e8f2d..f6eb1fa 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -97,14 +97,6 @@ void TConsole::BackupOldLog() { } } -enum EscState { - None, - Escape, - FeSeqStart, - FeSeqMid, - SeqEnd -}; - void TConsole::StartLoggingToFile() { mLogFileStream.open("Server.log"); Application::Console().Internal().on_write = [this](const std::string& ToWrite) { From 8d7505956d86fbbd5b1f7496af2b413b360afa09 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 16:26:30 +0200 Subject: [PATCH 24/35] let's try vcpkg --- CMakeLists.txt | 132 +++++++++++++++++-------------------------- deps/CMakeLists.txt | 7 +-- include/TConfig.h | 2 +- include/TLuaEngine.h | 2 +- src/TSentry.cpp | 2 +- vcpkg.cmake | 18 ++++++ vcpkg.json | 17 ++++++ 7 files changed, 91 insertions(+), 89 deletions(-) create mode 100644 vcpkg.cmake create mode 100644 vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index f6a813f..680cd8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,17 @@ cmake_minimum_required(VERSION 3.0) +if (WIN32) + set(VCPKG_TARGET_TRIPLET "x64-windows-static") +elseif(UNIX) + set(VCPKG_TARGET_TRIPLET "x64-linux") +endif() + +option(USE_VCPKG "USE_VCPKG" ON) + +if(USE_VCPKG) + include(vcpkg.cmake) +endif() + message(STATUS "You can find build instructions and a list of dependencies in the README at \ https://github.com/BeamMP/BeamMP-Server") @@ -10,15 +22,6 @@ project(BeamMP-Server set(HTTPLIB_REQUIRE_OPENSSL ON) -include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include") -include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include") -include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp") -include_directories("${PROJECT_SOURCE_DIR}/deps/commandline") -include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include") -include_directories("${PROJECT_SOURCE_DIR}/deps/cpp-httplib") -include_directories("${PROJECT_SOURCE_DIR}/deps/json/single_include") -include_directories("${PROJECT_SOURCE_DIR}/deps") - add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT) if(APPLE) @@ -36,26 +39,6 @@ if (WIN32) STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) endif() -include_directories("include/sentry-native/include") -set(SENTRY_BUILD_SHARED_LIBS OFF) -if (MSVC) - set(SENTRY_BUILD_RUNTIMESTATIC ON) -endif() -message(STATUS "Checking for Sentry URL") -# this is set by the build system. -# IMPORTANT: if you're building from source, just leave this empty -if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL) - message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \ - This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.") - set(BEAMMP_SECRET_SENTRY_URL "") - set(SENTRY_BACKEND none) -else() - string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN) - message(STATUS "Sentry URL is length ${URL_LEN}") - set(SENTRY_BACKEND breakpad) -endif() -add_subdirectory("deps/sentry-native") - if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif () @@ -81,7 +64,19 @@ elseif (UNIX) endif (SANITIZE) endif () - +message(STATUS "Checking for Sentry URL") +# this is set by the build system. +# IMPORTANT: if you're building from source, just leave this empty +if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL) + message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \ + This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.") + set(BEAMMP_SECRET_SENTRY_URL "") + set(SENTRY_BACKEND none) +else() + string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN) + message(STATUS "Sentry URL is length ${URL_LEN}") + set(SENTRY_BACKEND breakpad) +endif() set(CMAKE_CXX_STANDARD 17) @@ -113,57 +108,34 @@ add_executable(BeamMP-Server target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}") include_directories(BeamMP-Server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_include_directories(BeamMP-Server PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/commandline") +include(FindThreads) -if (APPLE) - message(STATUS "NOT looking for Lua on APPLE") -else() - message(STATUS "Looking for Lua") - find_package(Lua REQUIRED VERSION 5.3) -endif() +find_package(OpenSSL REQUIRED) +find_package(ZLIB REQUIRED) +find_package(CURL CONFIG REQUIRED) +find_package(Lua REQUIRED 5.3) +find_package(nlohmann_json CONFIG REQUIRED) +find_package(RapidJSON CONFIG REQUIRED) +find_package(sentry CONFIG REQUIRED) +find_package(sol2 CONFIG REQUIRED) +find_package(toml11 CONFIG REQUIRED) +find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") -target_include_directories(BeamMP-Server PUBLIC - ${LUA_INCLUDE_DIR} - ${CURL_INCLUDE_DIRS} - "include/tomlplusplus" - "include/sentry-native/include" - "include/curl/include") +target_include_directories(BeamMP-Server PRIVATE + ${CPP_HTTPLIB_INCLUDE_DIRS} + ${LUA_INCLUDE_DIR} +) -message(STATUS "Looking for SSL") +target_link_libraries(BeamMP-Server PRIVATE OpenSSL::SSL OpenSSL::Crypto + ZLIB::ZLIB + CURL::libcurl + ${LUA_LIBRARIES} + Threads::Threads + commandline + nlohmann_json::nlohmann_json + rapidjson + sentry::sentry + sol2::sol2 + toml11::toml11 +) -if (APPLE) - set(OPENSSL_LIBRARIES ssl crypto) -else() - find_package(OpenSSL REQUIRED) -endif() - -target_link_libraries(BeamMP-Server sol2::sol2 ${LUA_LIBRARIES}) -message(STATUS "CURL IS ${CURL_LIBRARIES}") - -if (UNIX) - target_link_libraries(BeamMP-Server - z - pthread - ${LUA_LIBRARIES} - crypto - ${OPENSSL_LIBRARIES} - commandline - sentry - ssl) -elseif (WIN32) - include(FindLua) - message(STATUS "Looking for libz") - find_package(ZLIB REQUIRED) - message(STATUS "Looking for RapidJSON") - find_package(RapidJSON CONFIG REQUIRED) - target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS}) - target_link_libraries(BeamMP-Server - ws2_32 - ZLIB::ZLIB - ${LUA_LIBRARIES} - ${OPENSSL_LIBRARIES} - commandline - sentry) -endif () diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 4e556b0..6f87000 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,9 +1,4 @@ -include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include") -include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include") -include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp") -include_directories("${PROJECT_SOURCE_DIR}/deps/commandline") -include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include") include_directories("${PROJECT_SOURCE_DIR}/deps") +include_directories("${PROJECT_SOURCE_DIR}/deps/commandline") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/commandline") -add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2") diff --git a/include/TConfig.h b/include/TConfig.h index 3fcc597..b05f422 100644 --- a/include/TConfig.h +++ b/include/TConfig.h @@ -5,7 +5,7 @@ #include #define TOML11_PRESERVE_COMMENTS_BY_DEFAULT -#include // header-only version of TOML++ +#include // header-only version of TOML++ namespace fs = std::filesystem; diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 5ca2222..876d910 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/TSentry.cpp b/src/TSentry.cpp index da05c10..7f2b416 100644 --- a/src/TSentry.cpp +++ b/src/TSentry.cpp @@ -72,7 +72,7 @@ void TSentry::Log(SentryLevel level, const std::string& logger, const std::strin SetContext("threads", { { "thread-name", ThreadName(true) } }); auto Msg = sentry_value_new_message_event(sentry_level_t(level), logger.c_str(), text.c_str()); sentry_capture_event(Msg); - sentry_remove_transaction(); + sentry_set_transaction(nullptr); } void TSentry::LogError(const std::string& text, const std::string& file, const std::string& line) { diff --git a/vcpkg.cmake b/vcpkg.cmake new file mode 100644 index 0000000..56b51e5 --- /dev/null +++ b/vcpkg.cmake @@ -0,0 +1,18 @@ +include(FetchContent) + +message(STATUS "Getting, checking and running vcpkg, this may take a while") + +FetchContent_Declare( + vcpkg + GIT_REPOSITORY https://github.com/microsoft/vcpkg.git +) + +FetchContent_GetProperties(vcpkg) + +if(NOT vcpkg_POPULATED) + FetchContent_Populate(vcpkg) + execute_process(COMMAND ./${vcpkg_SOURCE_DIR}/bootstrap-vcpkg.sh) +endif() + +set(CMAKE_TOOLCHAIN_FILE ${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake +CACHE STRING "Vcpkg toolchain file") diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..f28fa5b --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "beammp-server", + "version-string": "3.0.2", + "homepage": "https://beammp.com", + "dependencies": [ + "sentry-native", + "lua", + "zlib", + "rapidjson", + "nlohmann-json", + "openssl", + "curl", + "sol2", + "cpp-httplib", + "toml11" + ] +} From a5153e4bc111d5b08acc4504277ae555af7225e9 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 28 Apr 2022 16:28:23 +0200 Subject: [PATCH 25/35] Remove unneeded submodules --- .gitmodules | 24 ------------------------ deps/asio | 1 - deps/cpp-httplib | 1 - deps/json | 1 - deps/libzip | 1 - deps/rapidjson | 1 - deps/sentry-native | 1 - deps/sol2 | 1 - deps/toml11 | 1 - 9 files changed, 32 deletions(-) delete mode 160000 deps/asio delete mode 160000 deps/cpp-httplib delete mode 160000 deps/json delete mode 160000 deps/libzip delete mode 160000 deps/rapidjson delete mode 160000 deps/sentry-native delete mode 160000 deps/sol2 delete mode 160000 deps/toml11 diff --git a/.gitmodules b/.gitmodules index b54a97b..5cfa6fa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,27 +1,3 @@ [submodule "deps/commandline"] path = deps/commandline url = https://github.com/lionkor/commandline -[submodule "deps/asio"] - path = deps/asio - url = https://github.com/chriskohlhoff/asio -[submodule "deps/rapidjson"] - path = deps/rapidjson - url = https://github.com/Tencent/rapidjson -[submodule "deps/toml11"] - path = deps/toml11 - url = https://github.com/ToruNiina/toml11 -[submodule "deps/sentry-native"] - path = deps/sentry-native - url = https://github.com/getsentry/sentry-native -[submodule "deps/sol2"] - path = deps/sol2 - url = https://github.com/ThePhD/sol2 -[submodule "deps/libzip"] - path = deps/libzip - url = https://github.com/nih-at/libzip -[submodule "deps/cpp-httplib"] - path = deps/cpp-httplib - url = https://github.com/yhirose/cpp-httplib -[submodule "deps/json"] - path = deps/json - url = https://github.com/nlohmann/json diff --git a/deps/asio b/deps/asio deleted file mode 160000 index d038fb3..0000000 --- a/deps/asio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d038fb3c2fb56fb91ff1d17b0715cff7887aa09e diff --git a/deps/cpp-httplib b/deps/cpp-httplib deleted file mode 160000 index b324921..0000000 --- a/deps/cpp-httplib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b324921c1aeff2976544128e4bb2a0979a4aa595 diff --git a/deps/json b/deps/json deleted file mode 160000 index eb21824..0000000 --- a/deps/json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eb2182414749825be086c825edb5229e5c28503d diff --git a/deps/libzip b/deps/libzip deleted file mode 160000 index 76df02f..0000000 --- a/deps/libzip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 76df02f86b9746e139fd9fc934a70e3a21bbc557 diff --git a/deps/rapidjson b/deps/rapidjson deleted file mode 160000 index 00dbcf2..0000000 --- a/deps/rapidjson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 00dbcf2c6e03c47d6c399338b6de060c71356464 diff --git a/deps/sentry-native b/deps/sentry-native deleted file mode 160000 index 90966cc..0000000 --- a/deps/sentry-native +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 90966cc1022b8155681b6899539b35466baccf2c diff --git a/deps/sol2 b/deps/sol2 deleted file mode 160000 index c068aef..0000000 --- a/deps/sol2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c068aefbeddb3dd1f1fd38d42843ecb49a3b4cdb diff --git a/deps/toml11 b/deps/toml11 deleted file mode 160000 index fda0a2b..0000000 --- a/deps/toml11 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fda0a2b9abd16e356f777c40a675131821c71b00 From d8526f06495b4685e02a96b62d23a62eb0cd11a1 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 29 May 2022 14:30:57 +0200 Subject: [PATCH 26/35] TNetwork::SplitLoad: Use managed memory --- src/TNetwork.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index 03c90f1..d9edc81 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -756,11 +756,11 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) { void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name) { std::ifstream f(Name.c_str(), std::ios::binary); uint32_t Split = 0x7735940; // 125MB - char* Data; + std::vector Data; if (Size > Split) - Data = new char[Split]; + Data.resize(Split); else - Data = new char[Size]; + Data.resize(Size); SOCKET TCPSock; if (D) TCPSock = c.GetDownSock(); @@ -771,8 +771,8 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std size_t Diff = Size - Sent; if (Diff > Split) { f.seekg(Sent, std::ios_base::beg); - f.read(Data, Split); - if (!TCPSendRaw(c, TCPSock, Data, Split)) { + f.read(Data.data(), Split); + if (!TCPSendRaw(c, TCPSock, Data.data(), Split)) { if (c.GetStatus() > -1) c.SetStatus(-1); break; @@ -780,8 +780,8 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std Sent += Split; } else { f.seekg(Sent, std::ios_base::beg); - f.read(Data, Diff); - if (!TCPSendRaw(c, TCPSock, Data, int32_t(Diff))) { + f.read(Data.data(), Diff); + if (!TCPSendRaw(c, TCPSock, Data.data(), int32_t(Diff))) { if (c.GetStatus() > -1) c.SetStatus(-1); break; @@ -789,8 +789,6 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std Sent += Diff; } } - delete[] Data; - f.close(); } bool TNetwork::TCPSendRaw(TClient& C, SOCKET socket, char* Data, int32_t Size) { From 1970d97ea415a43a9d1d97f4a704fd0656a57d4f Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 29 May 2022 14:37:41 +0200 Subject: [PATCH 27/35] Revert "Remove unneeded submodules" This reverts commit a5153e4bc111d5b08acc4504277ae555af7225e9. --- .gitmodules | 24 ++++++++++++++++++++++++ deps/asio | 1 + deps/cpp-httplib | 1 + deps/json | 1 + deps/libzip | 1 + deps/rapidjson | 1 + deps/sentry-native | 1 + deps/sol2 | 1 + deps/toml11 | 1 + 9 files changed, 32 insertions(+) create mode 160000 deps/asio create mode 160000 deps/cpp-httplib create mode 160000 deps/json create mode 160000 deps/libzip create mode 160000 deps/rapidjson create mode 160000 deps/sentry-native create mode 160000 deps/sol2 create mode 160000 deps/toml11 diff --git a/.gitmodules b/.gitmodules index 5cfa6fa..b54a97b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,27 @@ [submodule "deps/commandline"] path = deps/commandline url = https://github.com/lionkor/commandline +[submodule "deps/asio"] + path = deps/asio + url = https://github.com/chriskohlhoff/asio +[submodule "deps/rapidjson"] + path = deps/rapidjson + url = https://github.com/Tencent/rapidjson +[submodule "deps/toml11"] + path = deps/toml11 + url = https://github.com/ToruNiina/toml11 +[submodule "deps/sentry-native"] + path = deps/sentry-native + url = https://github.com/getsentry/sentry-native +[submodule "deps/sol2"] + path = deps/sol2 + url = https://github.com/ThePhD/sol2 +[submodule "deps/libzip"] + path = deps/libzip + url = https://github.com/nih-at/libzip +[submodule "deps/cpp-httplib"] + path = deps/cpp-httplib + url = https://github.com/yhirose/cpp-httplib +[submodule "deps/json"] + path = deps/json + url = https://github.com/nlohmann/json diff --git a/deps/asio b/deps/asio new file mode 160000 index 0000000..d038fb3 --- /dev/null +++ b/deps/asio @@ -0,0 +1 @@ +Subproject commit d038fb3c2fb56fb91ff1d17b0715cff7887aa09e diff --git a/deps/cpp-httplib b/deps/cpp-httplib new file mode 160000 index 0000000..b324921 --- /dev/null +++ b/deps/cpp-httplib @@ -0,0 +1 @@ +Subproject commit b324921c1aeff2976544128e4bb2a0979a4aa595 diff --git a/deps/json b/deps/json new file mode 160000 index 0000000..eb21824 --- /dev/null +++ b/deps/json @@ -0,0 +1 @@ +Subproject commit eb2182414749825be086c825edb5229e5c28503d diff --git a/deps/libzip b/deps/libzip new file mode 160000 index 0000000..76df02f --- /dev/null +++ b/deps/libzip @@ -0,0 +1 @@ +Subproject commit 76df02f86b9746e139fd9fc934a70e3a21bbc557 diff --git a/deps/rapidjson b/deps/rapidjson new file mode 160000 index 0000000..00dbcf2 --- /dev/null +++ b/deps/rapidjson @@ -0,0 +1 @@ +Subproject commit 00dbcf2c6e03c47d6c399338b6de060c71356464 diff --git a/deps/sentry-native b/deps/sentry-native new file mode 160000 index 0000000..90966cc --- /dev/null +++ b/deps/sentry-native @@ -0,0 +1 @@ +Subproject commit 90966cc1022b8155681b6899539b35466baccf2c diff --git a/deps/sol2 b/deps/sol2 new file mode 160000 index 0000000..c068aef --- /dev/null +++ b/deps/sol2 @@ -0,0 +1 @@ +Subproject commit c068aefbeddb3dd1f1fd38d42843ecb49a3b4cdb diff --git a/deps/toml11 b/deps/toml11 new file mode 160000 index 0000000..fda0a2b --- /dev/null +++ b/deps/toml11 @@ -0,0 +1 @@ +Subproject commit fda0a2b9abd16e356f777c40a675131821c71b00 From 758d5b2c968d0301d01fe3fb1e573e547bedfd03 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 29 May 2022 14:37:50 +0200 Subject: [PATCH 28/35] Revert "let's try vcpkg" This reverts commit 8d7505956d86fbbd5b1f7496af2b413b360afa09. --- CMakeLists.txt | 132 ++++++++++++++++++++++++++----------------- deps/CMakeLists.txt | 7 ++- include/TConfig.h | 2 +- include/TLuaEngine.h | 2 +- src/TSentry.cpp | 2 +- vcpkg.cmake | 18 ------ vcpkg.json | 17 ------ 7 files changed, 89 insertions(+), 91 deletions(-) delete mode 100644 vcpkg.cmake delete mode 100644 vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 680cd8b..f6a813f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,5 @@ cmake_minimum_required(VERSION 3.0) -if (WIN32) - set(VCPKG_TARGET_TRIPLET "x64-windows-static") -elseif(UNIX) - set(VCPKG_TARGET_TRIPLET "x64-linux") -endif() - -option(USE_VCPKG "USE_VCPKG" ON) - -if(USE_VCPKG) - include(vcpkg.cmake) -endif() - message(STATUS "You can find build instructions and a list of dependencies in the README at \ https://github.com/BeamMP/BeamMP-Server") @@ -22,6 +10,15 @@ project(BeamMP-Server set(HTTPLIB_REQUIRE_OPENSSL ON) +include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include") +include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include") +include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp") +include_directories("${PROJECT_SOURCE_DIR}/deps/commandline") +include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include") +include_directories("${PROJECT_SOURCE_DIR}/deps/cpp-httplib") +include_directories("${PROJECT_SOURCE_DIR}/deps/json/single_include") +include_directories("${PROJECT_SOURCE_DIR}/deps") + add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT) if(APPLE) @@ -39,6 +36,26 @@ if (WIN32) STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) endif() +include_directories("include/sentry-native/include") +set(SENTRY_BUILD_SHARED_LIBS OFF) +if (MSVC) + set(SENTRY_BUILD_RUNTIMESTATIC ON) +endif() +message(STATUS "Checking for Sentry URL") +# this is set by the build system. +# IMPORTANT: if you're building from source, just leave this empty +if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL) + message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \ + This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.") + set(BEAMMP_SECRET_SENTRY_URL "") + set(SENTRY_BACKEND none) +else() + string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN) + message(STATUS "Sentry URL is length ${URL_LEN}") + set(SENTRY_BACKEND breakpad) +endif() +add_subdirectory("deps/sentry-native") + if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif () @@ -64,19 +81,7 @@ elseif (UNIX) endif (SANITIZE) endif () -message(STATUS "Checking for Sentry URL") -# this is set by the build system. -# IMPORTANT: if you're building from source, just leave this empty -if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL) - message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \ - This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.") - set(BEAMMP_SECRET_SENTRY_URL "") - set(SENTRY_BACKEND none) -else() - string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN) - message(STATUS "Sentry URL is length ${URL_LEN}") - set(SENTRY_BACKEND breakpad) -endif() + set(CMAKE_CXX_STANDARD 17) @@ -108,34 +113,57 @@ add_executable(BeamMP-Server target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}") include_directories(BeamMP-Server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -include(FindThreads) +target_include_directories(BeamMP-Server PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/commandline") -find_package(OpenSSL REQUIRED) -find_package(ZLIB REQUIRED) -find_package(CURL CONFIG REQUIRED) -find_package(Lua REQUIRED 5.3) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(RapidJSON CONFIG REQUIRED) -find_package(sentry CONFIG REQUIRED) -find_package(sol2 CONFIG REQUIRED) -find_package(toml11 CONFIG REQUIRED) -find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") +if (APPLE) + message(STATUS "NOT looking for Lua on APPLE") +else() + message(STATUS "Looking for Lua") + find_package(Lua REQUIRED VERSION 5.3) +endif() -target_include_directories(BeamMP-Server PRIVATE - ${CPP_HTTPLIB_INCLUDE_DIRS} - ${LUA_INCLUDE_DIR} -) +target_include_directories(BeamMP-Server PUBLIC + ${LUA_INCLUDE_DIR} + ${CURL_INCLUDE_DIRS} + "include/tomlplusplus" + "include/sentry-native/include" + "include/curl/include") -target_link_libraries(BeamMP-Server PRIVATE OpenSSL::SSL OpenSSL::Crypto - ZLIB::ZLIB - CURL::libcurl - ${LUA_LIBRARIES} - Threads::Threads - commandline - nlohmann_json::nlohmann_json - rapidjson - sentry::sentry - sol2::sol2 - toml11::toml11 -) +message(STATUS "Looking for SSL") +if (APPLE) + set(OPENSSL_LIBRARIES ssl crypto) +else() + find_package(OpenSSL REQUIRED) +endif() + +target_link_libraries(BeamMP-Server sol2::sol2 ${LUA_LIBRARIES}) +message(STATUS "CURL IS ${CURL_LIBRARIES}") + +if (UNIX) + target_link_libraries(BeamMP-Server + z + pthread + ${LUA_LIBRARIES} + crypto + ${OPENSSL_LIBRARIES} + commandline + sentry + ssl) +elseif (WIN32) + include(FindLua) + message(STATUS "Looking for libz") + find_package(ZLIB REQUIRED) + message(STATUS "Looking for RapidJSON") + find_package(RapidJSON CONFIG REQUIRED) + target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS}) + target_link_libraries(BeamMP-Server + ws2_32 + ZLIB::ZLIB + ${LUA_LIBRARIES} + ${OPENSSL_LIBRARIES} + commandline + sentry) +endif () diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 6f87000..4e556b0 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,4 +1,9 @@ -include_directories("${PROJECT_SOURCE_DIR}/deps") +include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include") +include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include") +include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp") include_directories("${PROJECT_SOURCE_DIR}/deps/commandline") +include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include") +include_directories("${PROJECT_SOURCE_DIR}/deps") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/commandline") +add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2") diff --git a/include/TConfig.h b/include/TConfig.h index b05f422..3fcc597 100644 --- a/include/TConfig.h +++ b/include/TConfig.h @@ -5,7 +5,7 @@ #include #define TOML11_PRESERVE_COMMENTS_BY_DEFAULT -#include // header-only version of TOML++ +#include // header-only version of TOML++ namespace fs = std::filesystem; diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 876d910..5ca2222 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/TSentry.cpp b/src/TSentry.cpp index 7f2b416..da05c10 100644 --- a/src/TSentry.cpp +++ b/src/TSentry.cpp @@ -72,7 +72,7 @@ void TSentry::Log(SentryLevel level, const std::string& logger, const std::strin SetContext("threads", { { "thread-name", ThreadName(true) } }); auto Msg = sentry_value_new_message_event(sentry_level_t(level), logger.c_str(), text.c_str()); sentry_capture_event(Msg); - sentry_set_transaction(nullptr); + sentry_remove_transaction(); } void TSentry::LogError(const std::string& text, const std::string& file, const std::string& line) { diff --git a/vcpkg.cmake b/vcpkg.cmake deleted file mode 100644 index 56b51e5..0000000 --- a/vcpkg.cmake +++ /dev/null @@ -1,18 +0,0 @@ -include(FetchContent) - -message(STATUS "Getting, checking and running vcpkg, this may take a while") - -FetchContent_Declare( - vcpkg - GIT_REPOSITORY https://github.com/microsoft/vcpkg.git -) - -FetchContent_GetProperties(vcpkg) - -if(NOT vcpkg_POPULATED) - FetchContent_Populate(vcpkg) - execute_process(COMMAND ./${vcpkg_SOURCE_DIR}/bootstrap-vcpkg.sh) -endif() - -set(CMAKE_TOOLCHAIN_FILE ${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake -CACHE STRING "Vcpkg toolchain file") diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index f28fa5b..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "beammp-server", - "version-string": "3.0.2", - "homepage": "https://beammp.com", - "dependencies": [ - "sentry-native", - "lua", - "zlib", - "rapidjson", - "nlohmann-json", - "openssl", - "curl", - "sol2", - "cpp-httplib", - "toml11" - ] -} From 06f8ba5a0eae98d35cd8b7d27973cadb99d9d3e1 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 21:11:34 +0200 Subject: [PATCH 29/35] update sentry-native to 0.4.18 --- deps/sentry-native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/sentry-native b/deps/sentry-native index 90966cc..ff5bfcf 160000 --- a/deps/sentry-native +++ b/deps/sentry-native @@ -1 +1 @@ -Subproject commit 90966cc1022b8155681b6899539b35466baccf2c +Subproject commit ff5bfcf0eb2c47d03eb57a51bdf2e6ad4b8ece10 From 420e6c353376260542e387c87e636d49dc7dbc2f Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 21:40:19 +0200 Subject: [PATCH 30/35] roll back to an ancient version of sentry sentry-native deprecated compiling without error somewhere around one of the next version --- CMakeLists.txt | 2 +- deps/sentry-native | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6a813f..7ada026 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ if (WIN32) endif() include_directories("include/sentry-native/include") -set(SENTRY_BUILD_SHARED_LIBS OFF) +set(BUILD_SHARED_LIBS OFF) if (MSVC) set(SENTRY_BUILD_RUNTIMESTATIC ON) endif() diff --git a/deps/sentry-native b/deps/sentry-native index ff5bfcf..90966cc 160000 --- a/deps/sentry-native +++ b/deps/sentry-native @@ -1 +1 @@ -Subproject commit ff5bfcf0eb2c47d03eb57a51bdf2e6ad4b8ece10 +Subproject commit 90966cc1022b8155681b6899539b35466baccf2c From 98681254e63211b45e576dde55ac17be363cf801 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 21:50:23 +0200 Subject: [PATCH 31/35] update toml11 --- deps/toml11 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/toml11 b/deps/toml11 index fda0a2b..1400dd2 160000 --- a/deps/toml11 +++ b/deps/toml11 @@ -1 +1 @@ -Subproject commit fda0a2b9abd16e356f777c40a675131821c71b00 +Subproject commit 1400dd223fb4297337266fcb5d04b700338aea71 From 696e080e1c20ab99f9afc081870974891a436b01 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 21:57:24 +0200 Subject: [PATCH 32/35] fix #105 --- src/TConfig.cpp | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/TConfig.cpp b/src/TConfig.cpp index f21954e..4a414da 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -91,8 +91,14 @@ void TConfig::FlushToFile() { SetComment(data["HTTP"][StrHTTPServerUseSSL.data()].comments(), " Recommended to have enabled for servers which face the internet. With SSL the server will serve https and requires valid key and cert files"); data["HTTP"][StrHTTPServerEnabled.data()] = Application::Settings.HTTPServerEnabled; SetComment(data["HTTP"][StrHTTPServerEnabled.data()].comments(), " Enables the internal HTTP server"); + std::stringstream Ss; + Ss << data; std::ofstream Stream(mConfigFileName, std::ios::trunc | std::ios::out); - Stream << data << std::flush; + Stream << "# This is the BeamMP-Server config file.\n" + "# Help & Documentation: `https://wiki.beammp.com/en/home/server-maintenance`\n" + "# IMPORTANT: Fill in the AuthKey with the key you got from `https://beammp.com/k/dashboard` on the left under \"Keys\"\n" + << Ss.str(); + Stream.flush(); } void TConfig::CreateConfigFile(std::string_view name) { @@ -112,27 +118,6 @@ void TConfig::CreateConfigFile(std::string_view name) { } FlushToFile(); - - size_t FileSize = fs::file_size(name); - std::fstream ofs { std::string(name), std::ios::in | std::ios::out }; - if (ofs.good()) { - std::string Contents {}; - Contents.resize(FileSize); - ofs.readsome(Contents.data(), FileSize); - ofs.seekp(0); - ofs << "# This is the BeamMP-Server config file.\n" - "# Help & Documentation: `https://wiki.beammp.com/en/home/server-maintenance`\n" - "# IMPORTANT: Fill in the AuthKey with the key you got from `https://beammp.com/k/dashboard` on the left under \"Keys\"\n" - << '\n' - << Contents; - beammp_error("There was no \"" + std::string(mConfigFileName) + "\" file (this is normal for the first time running the server), so one was generated for you. It was automatically filled with the settings from your Server.cfg, if you have one. Please open ServerConfig.toml and ensure your AuthKey and other settings are filled in and correct, then restart the server. The old Server.cfg file will no longer be used and causes a warning if it exists from now on."); - mFailed = true; - ofs.close(); - } else { - beammp_error("Couldn't create " + std::string(name) + ". Check permissions, try again, and contact support if it continues not to work."); - Application::SetSubsystemStatus("Config", Application::Status::Bad); - mFailed = true; - } } void TConfig::TryReadValue(toml::value& Table, const std::string& Category, const std::string_view& Key, std::string& OutValue) { From 38eeec39b49872d0d79ebd49f98d0e65d2ab25cb Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 22:27:05 +0200 Subject: [PATCH 33/35] another attempt to fix #105 --- Changelog.md | 1 + src/TConfig.cpp | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7ff6d04..0486505 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ - FIXED `MP.CreateEventTimer` filling up the queue (see ) - FIXED `MP.TriggerClientEvent` not kicking the client if it failed - FIXED Lua result queue handling not checking all results +- FIXED bug which caused ServerConfig.toml to generate incorrectly # v3.0.1 diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 4a414da..65c7ba0 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -92,13 +92,20 @@ void TConfig::FlushToFile() { data["HTTP"][StrHTTPServerEnabled.data()] = Application::Settings.HTTPServerEnabled; SetComment(data["HTTP"][StrHTTPServerEnabled.data()].comments(), " Enables the internal HTTP server"); std::stringstream Ss; - Ss << data; - std::ofstream Stream(mConfigFileName, std::ios::trunc | std::ios::out); - Stream << "# This is the BeamMP-Server config file.\n" - "# Help & Documentation: `https://wiki.beammp.com/en/home/server-maintenance`\n" - "# IMPORTANT: Fill in the AuthKey with the key you got from `https://beammp.com/k/dashboard` on the left under \"Keys\"\n" - << Ss.str(); - Stream.flush(); + Ss << "# This is the BeamMP-Server config file.\n" + "# Help & Documentation: `https://wiki.beammp.com/en/home/server-maintenance`\n" + "# IMPORTANT: Fill in the AuthKey with the key you got from `https://beammp.com/k/dashboard` on the left under \"Keys\"\n" + << data; + auto File = std::fopen(mConfigFileName.c_str(), "w+"); + if (!File) { + beammp_error("Failed to create/write to config file: " + GetPlatformAgnosticErrorString()); + throw std::runtime_error("Failed to create/write to config file"); + } + auto Str = Ss.str(); + auto N = std::fwrite(Str.data(), sizeof(char), Str.size(), File); + if (N != Str.size()) { + beammp_error("Failed to write to config file properly, config file might be misshapen"); + } } void TConfig::CreateConfigFile(std::string_view name) { @@ -113,10 +120,6 @@ void TConfig::CreateConfigFile(std::string_view name) { beammp_error("an error occurred and was ignored during config transfer: " + std::string(e.what())); } - { // create file context - std::ofstream ofs(name.data()); - } - FlushToFile(); } From 6c1d02a425037122bc6140b3c85ca8b21c126ca8 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 22:29:12 +0200 Subject: [PATCH 34/35] add fclose --- src/TConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 65c7ba0..8d445c9 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -106,6 +106,7 @@ void TConfig::FlushToFile() { if (N != Str.size()) { beammp_error("Failed to write to config file properly, config file might be misshapen"); } + std::fclose(File); } void TConfig::CreateConfigFile(std::string_view name) { From f8d622352f4e4ebcee73400c499deeefd0f76d30 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 9 Jul 2022 22:42:38 +0200 Subject: [PATCH 35/35] generate toml from scratch --- src/TConfig.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 8d445c9..531fd59 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -62,7 +62,8 @@ void SetComment(CommentsT& Comments, const std::string& Comment) { * whether it is in TConfig.cpp or the configuration file. */ void TConfig::FlushToFile() { - auto data = toml::parse(mConfigFileName); + // auto data = toml::parse(mConfigFileName); + auto data = toml::value {}; data["General"][StrAuthKey.data()] = Application::Settings.Key; SetComment(data["General"][StrAuthKey.data()].comments(), " AuthKey has to be filled out in order to run the server"); data["General"][StrDebug.data()] = Application::Settings.DebugModeEnabled;