mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 18:24:16 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c44a307bc | |||
| 754053e73f | |||
| 29f8d29e33 | |||
| e043361abb | |||
| fca5bbcec9 | |||
| 2a588954be | |||
| cd4129e05d | |||
| c42c748b37 |
@@ -8,6 +8,8 @@ project(BeamMP-Server
|
|||||||
HOMEPAGE_URL https://beammp.com
|
HOMEPAGE_URL https://beammp.com
|
||||||
LANGUAGES CXX C)
|
LANGUAGES CXX C)
|
||||||
|
|
||||||
|
set(HTTPLIB_REQUIRE_OPENSSL ON)
|
||||||
|
|
||||||
include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include")
|
include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include")
|
||||||
include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include")
|
include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include")
|
||||||
include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp")
|
include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp")
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
# v3.0.1
|
||||||
|
|
||||||
|
- ADDED Backup URLs to UpdateCheck (will fail less often now)
|
||||||
|
- FIXED a bug where, when run with --working-directory, the Server.log would still be in the original directory
|
||||||
|
- FIXED a bug which could cause the plugin reload thread to spin at 100% if the reloaded plugin's onInit didn't terminate
|
||||||
|
|
||||||
# v3.0.0
|
# v3.0.0
|
||||||
|
|
||||||
- CHANGED entire plugin Lua implementation (rewrite)
|
- CHANGED entire plugin Lua implementation (rewrite)
|
||||||
|
|||||||
Vendored
+1
-1
Submodule deps/commandline updated: 3d11606d02...0d3e1073c1
+9
-4
@@ -74,10 +74,15 @@ public:
|
|||||||
|
|
||||||
static TSettings Settings;
|
static TSettings Settings;
|
||||||
|
|
||||||
|
static std::vector<std::string> GetBackendUrlsInOrder() {
|
||||||
|
return {
|
||||||
|
"backend.beammp.com",
|
||||||
|
"backup1.beammp.com",
|
||||||
|
"backup2.beammp.com"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static std::string GetBackendUrlForAuth() { return "auth.beammp.com"; }
|
static std::string GetBackendUrlForAuth() { return "auth.beammp.com"; }
|
||||||
static std::string GetBackendHostname() { return "backend.beammp.com"; }
|
|
||||||
static std::string GetBackup1Hostname() { return "backup1.beammp.com"; }
|
|
||||||
static std::string GetBackup2Hostname() { return "backup2.beammp.com"; }
|
|
||||||
static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; }
|
static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; }
|
||||||
static void CheckForUpdates();
|
static void CheckForUpdates();
|
||||||
static std::array<uint8_t, 3> VersionStrToInts(const std::string& str);
|
static std::array<uint8_t, 3> VersionStrToInts(const std::string& str);
|
||||||
@@ -114,7 +119,7 @@ private:
|
|||||||
static inline std::mutex mShutdownHandlersMutex {};
|
static inline std::mutex mShutdownHandlersMutex {};
|
||||||
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
||||||
|
|
||||||
static inline Version mVersion { 3, 0, 0 };
|
static inline Version mVersion { 3, 0, 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ThreadName(bool DebugModeOverride = false);
|
std::string ThreadName(bool DebugModeOverride = false);
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ constexpr size_t RSA_DEFAULT_KEYLENGTH { 2048 };
|
|||||||
|
|
||||||
namespace Http {
|
namespace Http {
|
||||||
std::string GET(const std::string& host, int port, const std::string& target, unsigned int* status = nullptr);
|
std::string GET(const std::string& host, int port, const std::string& target, unsigned int* status = nullptr);
|
||||||
std::string POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr);
|
std::string POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr, const httplib::Headers& headers = {});
|
||||||
namespace Status {
|
namespace Status {
|
||||||
std::string ToString(int code);
|
std::string ToString(int code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ private:
|
|||||||
void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false);
|
void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false);
|
||||||
void ChangeToLuaConsole(const std::string& LuaStateId);
|
void ChangeToLuaConsole(const std::string& LuaStateId);
|
||||||
void ChangeToRegularConsole();
|
void ChangeToRegularConsole();
|
||||||
void HandleLuaInternalCommand(const std::string& cmd);
|
|
||||||
|
|
||||||
void Command_Lua(const std::string& cmd);
|
void Command_Lua(const std::string& cmd);
|
||||||
void Command_Help(const std::string& cmd);
|
void Command_Help(const std::string& cmd);
|
||||||
|
|||||||
+3
-13
@@ -32,8 +32,8 @@ static constexpr size_t TLuaArgTypes_Bool = 3;
|
|||||||
class TLuaPlugin;
|
class TLuaPlugin;
|
||||||
|
|
||||||
struct TLuaResult {
|
struct TLuaResult {
|
||||||
bool Ready;
|
std::atomic_bool Ready;
|
||||||
bool Error;
|
std::atomic_bool Error;
|
||||||
std::string ErrorMessage;
|
std::string ErrorMessage;
|
||||||
sol::object Result { sol::lua_nil };
|
sol::object Result { sol::lua_nil };
|
||||||
TLuaStateId StateId;
|
TLuaStateId StateId;
|
||||||
@@ -89,7 +89,6 @@ public:
|
|||||||
std::unique_lock Lock(mResultsToCheckMutex);
|
std::unique_lock Lock(mResultsToCheckMutex);
|
||||||
return mResultsToCheck.size();
|
return mResultsToCheck.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLuaStateCount() {
|
size_t GetLuaStateCount() {
|
||||||
std::unique_lock Lock(mLuaStatesMutex);
|
std::unique_lock Lock(mLuaStatesMutex);
|
||||||
return mLuaStates.size();
|
return mLuaStates.size();
|
||||||
@@ -150,15 +149,10 @@ public:
|
|||||||
void CancelEventTimers(const std::string& EventName, TLuaStateId StateId);
|
void CancelEventTimers(const std::string& EventName, TLuaStateId StateId);
|
||||||
sol::state_view GetStateForPlugin(const fs::path& PluginPath);
|
sol::state_view GetStateForPlugin(const fs::path& PluginPath);
|
||||||
TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath);
|
TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath);
|
||||||
|
void AddResultToCheck(const std::shared_ptr<TLuaResult>& Result);
|
||||||
|
|
||||||
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
|
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
|
||||||
|
|
||||||
// Debugging functions (slow)
|
|
||||||
std::unordered_map<std::string /*event name */, std::vector<std::string> /* handlers */> Debug_GetEventsForState(TLuaStateId StateId);
|
|
||||||
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueueForState(TLuaStateId StateId);
|
|
||||||
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Debug_GetStateFunctionQueueForState(TLuaStateId StateId);
|
|
||||||
std::vector<TLuaResult> Debug_GetResultsToCheckForState(TLuaStateId StateId);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CollectAndInitPlugins();
|
void CollectAndInitPlugins();
|
||||||
void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config);
|
void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config);
|
||||||
@@ -177,10 +171,6 @@ private:
|
|||||||
void operator()() override;
|
void operator()() override;
|
||||||
sol::state_view State() { return sol::state_view(mState); }
|
sol::state_view State() { return sol::state_view(mState); }
|
||||||
|
|
||||||
// Debug functions, slow
|
|
||||||
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueue();
|
|
||||||
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Debug_GetStateFunctionQueue();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
||||||
sol::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
sol::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
||||||
|
|||||||
+23
-17
@@ -99,25 +99,31 @@ void Application::CheckForUpdates() {
|
|||||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Starting);
|
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Starting);
|
||||||
// checks current version against latest version
|
// checks current version against latest version
|
||||||
std::regex VersionRegex { R"(\d+\.\d+\.\d+\n*)" };
|
std::regex VersionRegex { R"(\d+\.\d+\.\d+\n*)" };
|
||||||
auto Response = Http::GET(GetBackendHostname(), 443, "/v/s");
|
for (const auto& url : GetBackendUrlsInOrder()) {
|
||||||
bool Matches = std::regex_match(Response, VersionRegex);
|
auto Response = Http::GET(GetBackendUrlsInOrder().at(0), 443, "/v/s");
|
||||||
if (Matches) {
|
bool Matches = std::regex_match(Response, VersionRegex);
|
||||||
auto MyVersion = ServerVersion();
|
if (Matches) {
|
||||||
auto RemoteVersion = Version(VersionStrToInts(Response));
|
auto MyVersion = ServerVersion();
|
||||||
if (IsOutdated(MyVersion, RemoteVersion)) {
|
auto RemoteVersion = Version(VersionStrToInts(Response));
|
||||||
std::string RealVersionString = RemoteVersion.AsString();
|
if (IsOutdated(MyVersion, RemoteVersion)) {
|
||||||
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));
|
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));
|
||||||
|
} else {
|
||||||
|
beammp_info("Server up-to-date!");
|
||||||
|
}
|
||||||
|
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good);
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
beammp_info("Server up-to-date!");
|
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);
|
||||||
}
|
}
|
||||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good);
|
}
|
||||||
} else {
|
if (Application::GetSubsystemStatuses().at("UpdateCheck") == Application::Status::Bad) {
|
||||||
beammp_warn("Unable to fetch version from backend.");
|
beammp_warn("Unable to fetch version info from backend.");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -4,6 +4,7 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
|
#include "httplib.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <random>
|
#include <random>
|
||||||
@@ -33,17 +34,20 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status, const httplib::Headers& headers) {
|
||||||
httplib::SSLClient client(host, port);
|
httplib::SSLClient client(host, port);
|
||||||
|
client.set_read_timeout(std::chrono::seconds(10));
|
||||||
|
beammp_assert(client.is_valid());
|
||||||
client.enable_server_certificate_verification(false);
|
client.enable_server_certificate_verification(false);
|
||||||
client.set_address_family(AF_INET);
|
client.set_address_family(AF_INET);
|
||||||
auto res = client.Post(target.c_str(), body.c_str(), body.size(), ContentType.c_str());
|
auto res = client.Post(target.c_str(), headers, body.c_str(), body.size(), ContentType.c_str());
|
||||||
if (res) {
|
if (res) {
|
||||||
if (status) {
|
if (status) {
|
||||||
*status = res->status;
|
*status = res->status;
|
||||||
}
|
}
|
||||||
return res->body;
|
return res->body;
|
||||||
} else {
|
} else {
|
||||||
|
beammp_debug("POST failed: " + httplib::to_string(res.error()));
|
||||||
return Http::ErrorString;
|
return Http::ErrorString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-59
@@ -107,10 +107,10 @@ void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) {
|
|||||||
mStateId = LuaStateId;
|
mStateId = LuaStateId;
|
||||||
mIsLuaConsole = true;
|
mIsLuaConsole = true;
|
||||||
if (mStateId != mDefaultStateId) {
|
if (mStateId != mDefaultStateId) {
|
||||||
Application::Console().WriteRaw("Attached to Lua state '" + mStateId + "'. For help, type `:help`. To detach, type `:detach`");
|
Application::Console().WriteRaw("Entered Lua console for state '" + mStateId + "'. To exit, type `exit()`");
|
||||||
mCommandline.set_prompt("lua @" + LuaStateId + "> ");
|
mCommandline.set_prompt("lua @" + LuaStateId + "> ");
|
||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Attached to Lua. For help, type `:help`. To detach, type `:detach`");
|
Application::Console().WriteRaw("Entered Lua console. To exit, type `exit()`");
|
||||||
mCommandline.set_prompt("lua> ");
|
mCommandline.set_prompt("lua> ");
|
||||||
}
|
}
|
||||||
mCachedRegularHistory = mCommandline.history();
|
mCachedRegularHistory = mCommandline.history();
|
||||||
@@ -122,9 +122,9 @@ void TConsole::ChangeToRegularConsole() {
|
|||||||
if (mIsLuaConsole) {
|
if (mIsLuaConsole) {
|
||||||
mIsLuaConsole = false;
|
mIsLuaConsole = false;
|
||||||
if (mStateId != mDefaultStateId) {
|
if (mStateId != mDefaultStateId) {
|
||||||
Application::Console().WriteRaw("Detached from Lua state '" + mStateId + "'.");
|
Application::Console().WriteRaw("Left Lua console for state '" + mStateId + "'.");
|
||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Detached from Lua.");
|
Application::Console().WriteRaw("Left Lua console.");
|
||||||
}
|
}
|
||||||
mCachedLuaHistory = mCommandline.history();
|
mCachedLuaHistory = mCommandline.history();
|
||||||
mCommandline.set_history(mCachedRegularHistory);
|
mCommandline.set_history(mCachedRegularHistory);
|
||||||
@@ -364,58 +364,6 @@ void TConsole::RunAsCommand(const std::string& cmd, bool IgnoreNotACommand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::HandleLuaInternalCommand(const std::string& cmd) {
|
|
||||||
if (cmd == "detach") {
|
|
||||||
ChangeToRegularConsole();
|
|
||||||
} else if (cmd == "queued") {
|
|
||||||
auto QueuedFunctions = LuaAPI::MP::Engine->Debug_GetStateFunctionQueueForState(mStateId);
|
|
||||||
Application::Console().WriteRaw("Pending functions in State '" + mStateId + "'");
|
|
||||||
std::unordered_map<std::string, size_t> FunctionsCount;
|
|
||||||
std::vector<std::string> FunctionsInOrder;
|
|
||||||
while (!QueuedFunctions.empty()) {
|
|
||||||
auto Tuple = QueuedFunctions.front();
|
|
||||||
QueuedFunctions.pop();
|
|
||||||
FunctionsInOrder.push_back(std::get<0>(Tuple));
|
|
||||||
FunctionsCount[std::get<0>(Tuple)] += 1;
|
|
||||||
}
|
|
||||||
std::set<std::string> Uniques;
|
|
||||||
for (const auto& Function : FunctionsInOrder) {
|
|
||||||
if (Uniques.count(Function) == 0) {
|
|
||||||
Uniques.insert(Function);
|
|
||||||
if (FunctionsCount.at(Function) > 1) {
|
|
||||||
Application::Console().WriteRaw(" " + Function + " (" + std::to_string(FunctionsCount.at(Function)) + "x)");
|
|
||||||
} else {
|
|
||||||
Application::Console().WriteRaw(" " + Function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Application::Console().WriteRaw("Executed functions waiting to be checked in State '" + mStateId + "'");
|
|
||||||
for (const auto& Function : LuaAPI::MP::Engine->Debug_GetResultsToCheckForState(mStateId)) {
|
|
||||||
Application::Console().WriteRaw(" '" + Function.Function + "' (Ready? " + (Function.Ready ? "Yes" : "No") + ", Error? " + (Function.Error ? "Yes: '" + Function.ErrorMessage + "'" : "No") + ")");
|
|
||||||
}
|
|
||||||
} else if (cmd == "events") {
|
|
||||||
auto Events = LuaAPI::MP::Engine->Debug_GetEventsForState(mStateId);
|
|
||||||
Application::Console().WriteRaw("Registered Events + Handlers for State '" + mStateId + "'");
|
|
||||||
for (const auto& EventHandlerPair : Events) {
|
|
||||||
Application::Console().WriteRaw(" Event '" + EventHandlerPair.first + "'");
|
|
||||||
for (const auto& Handler : EventHandlerPair.second) {
|
|
||||||
Application::Console().WriteRaw(" " + Handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (cmd == "help") {
|
|
||||||
Application::Console().WriteRaw(R"(BeamMP Lua Debugger
|
|
||||||
All commands must be prefixed with a `:`. Non-prefixed commands are interpreted as Lua.
|
|
||||||
|
|
||||||
Commands
|
|
||||||
:detach detaches (exits) from this Lua console
|
|
||||||
:help displays this help
|
|
||||||
:events shows a list of currently registered events
|
|
||||||
:queued shows a list of all pending and queued functions)");
|
|
||||||
} else {
|
|
||||||
beammp_error("internal command '" + cmd + "' is not known");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TConsole::TConsole() {
|
TConsole::TConsole() {
|
||||||
mCommandline.enable_history();
|
mCommandline.enable_history();
|
||||||
mCommandline.set_history_limit(20);
|
mCommandline.set_history_limit(20);
|
||||||
@@ -433,12 +381,12 @@ TConsole::TConsole() {
|
|||||||
if (mIsLuaConsole) {
|
if (mIsLuaConsole) {
|
||||||
if (!mLuaEngine) {
|
if (!mLuaEngine) {
|
||||||
beammp_info("Lua not started yet, please try again in a second");
|
beammp_info("Lua not started yet, please try again in a second");
|
||||||
} else if (!cmd.empty() && cmd.at(0) == ':') {
|
} else if (cmd == "exit()") {
|
||||||
HandleLuaInternalCommand(cmd.substr(1));
|
ChangeToRegularConsole();
|
||||||
} else {
|
} else {
|
||||||
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
||||||
while (!Future->Ready) {
|
while (!Future->Ready) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout
|
std::this_thread::yield(); // TODO: Add a timeout
|
||||||
}
|
}
|
||||||
if (Future->Error) {
|
if (Future->Error) {
|
||||||
beammp_lua_error(Future->ErrorMessage);
|
beammp_lua_error(Future->ErrorMessage);
|
||||||
|
|||||||
+56
-26
@@ -54,41 +54,71 @@ void THeartbeatThread::operator()() {
|
|||||||
|
|
||||||
auto Target = "/heartbeat";
|
auto Target = "/heartbeat";
|
||||||
unsigned int ResponseCode = 0;
|
unsigned int ResponseCode = 0;
|
||||||
T = Http::POST(Application::GetBackendHostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
|
||||||
|
|
||||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
json::Document Doc;
|
||||||
beammp_trace("got " + T + " from backend");
|
bool Ok = false;
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
for (const auto& Url : Application::GetBackendUrlsInOrder()) {
|
||||||
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
|
T = Http::POST(Url, 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode, { { "api-v", "2" } });
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
beammp_trace(T);
|
||||||
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
Doc.Parse(T.data(), T.size());
|
||||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
if (Doc.HasParseError() || !Doc.IsObject()) {
|
||||||
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
|
beammp_error("Backend response failed to parse as valid json");
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
beammp_debug("Response was: `" + T + "`");
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
Sentry.SetContext("JSON Response", { { "reponse", T } });
|
||||||
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
SentryReportError(Url + Target, ResponseCode);
|
||||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
} else if (ResponseCode != 200) {
|
||||||
beammp_warn("Backend system refused server! Server will not show in the public server list.");
|
SentryReportError(Url + Target, ResponseCode);
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
|
||||||
isAuth = false;
|
|
||||||
SentryReportError(Application::GetBackup2Hostname() + Target, ResponseCode);
|
|
||||||
} else {
|
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
// all ok
|
||||||
|
Ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
}
|
||||||
|
std::string Status {};
|
||||||
|
std::string Code {};
|
||||||
|
std::string Message {};
|
||||||
|
const auto StatusKey = "status";
|
||||||
|
const auto CodeKey = "code";
|
||||||
|
const auto MessageKey = "msg";
|
||||||
|
|
||||||
|
if (Ok) {
|
||||||
|
if (Doc.HasMember(StatusKey) && Doc[StatusKey].IsString()) {
|
||||||
|
Status = Doc[StatusKey].GetString();
|
||||||
|
} else {
|
||||||
|
Sentry.SetContext("JSON Response", { { StatusKey, "invalid string / missing" } });
|
||||||
|
Ok = false;
|
||||||
|
}
|
||||||
|
if (Doc.HasMember(CodeKey) && Doc[CodeKey].IsString()) {
|
||||||
|
Code = Doc[CodeKey].GetString();
|
||||||
|
} else {
|
||||||
|
Sentry.SetContext("JSON Response", { { CodeKey, "invalid string / missing" } });
|
||||||
|
Ok = false;
|
||||||
|
}
|
||||||
|
if (Doc.HasMember(MessageKey) && Doc[MessageKey].IsString()) {
|
||||||
|
Message = Doc[MessageKey].GetString();
|
||||||
|
} else {
|
||||||
|
Sentry.SetContext("JSON Response", { { MessageKey, "invalid string / missing" } });
|
||||||
|
Ok = false;
|
||||||
|
}
|
||||||
|
if (!Ok) {
|
||||||
|
beammp_error("Missing/invalid json members in backend response");
|
||||||
|
Sentry.LogError("Missing/invalid json members in backend response", __FILE__, std::to_string(__LINE__));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAuth) {
|
if (Ok && !isAuth) {
|
||||||
if (T == "2000") {
|
if (Status == "2000") {
|
||||||
beammp_info(("Authenticated!"));
|
beammp_info(("Authenticated!"));
|
||||||
isAuth = true;
|
isAuth = true;
|
||||||
} else if (T == "200") {
|
} else if (Status == "200") {
|
||||||
beammp_info(("Resumed authenticated session!"));
|
beammp_info(("Resumed authenticated session!"));
|
||||||
isAuth = true;
|
isAuth = true;
|
||||||
|
} else {
|
||||||
|
if (Message.empty()) {
|
||||||
|
Message = "Backend didn't provide a reason";
|
||||||
|
}
|
||||||
|
beammp_error("Backend REFUSED the auth key. " + Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-71
@@ -54,25 +54,17 @@ void TLuaEngine::operator()() {
|
|||||||
auto ResultCheckThread = std::thread([&] {
|
auto ResultCheckThread = std::thread([&] {
|
||||||
RegisterThread("ResultCheckThread");
|
RegisterThread("ResultCheckThread");
|
||||||
while (!mShutdown) {
|
while (!mShutdown) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
std::unique_lock Lock(mResultsToCheckMutex);
|
std::unique_lock Lock(mResultsToCheckMutex);
|
||||||
if (!mResultsToCheck.empty()) {
|
if (!mResultsToCheck.empty()) {
|
||||||
auto Res = mResultsToCheck.front();
|
auto Res = mResultsToCheck.front();
|
||||||
mResultsToCheck.pop();
|
mResultsToCheck.pop();
|
||||||
Lock.unlock();
|
Lock.unlock();
|
||||||
|
|
||||||
size_t Waited = 0;
|
if (!Res->Ready) {
|
||||||
while (!Res->Ready) {
|
Lock.lock();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
mResultsToCheck.push(Res);
|
||||||
Waited++;
|
Lock.unlock();
|
||||||
if (Waited > 250) {
|
|
||||||
// FIXME: This should *eventually* timeout.
|
|
||||||
// beammp_lua_error(Res->Function + " in " + Res->StateId + " took >1s to respond, not printing possible errors");
|
|
||||||
Lock.lock();
|
|
||||||
mResultsToCheck.push(Res);
|
|
||||||
Lock.unlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Res->Error) {
|
if (Res->Error) {
|
||||||
if (Res->ErrorMessage != BeamMPFnNotFoundError) {
|
if (Res->ErrorMessage != BeamMPFnNotFoundError) {
|
||||||
@@ -80,13 +72,14 @@ void TLuaEngine::operator()() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// event loop
|
// event loop
|
||||||
auto Before = std::chrono::high_resolution_clock::now();
|
auto Before = std::chrono::high_resolution_clock::now();
|
||||||
while (!mShutdown) {
|
while (!mShutdown) {
|
||||||
if (mLuaStates.size() == 0) {
|
if (mLuaStates.size() == 0) {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(500));
|
std::this_thread::sleep_for(std::chrono::seconds(100));
|
||||||
}
|
}
|
||||||
{ // Timed Events Scope
|
{ // Timed Events Scope
|
||||||
std::unique_lock Lock(mTimedEventsMutex);
|
std::unique_lock Lock(mTimedEventsMutex);
|
||||||
@@ -149,48 +142,9 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string /*event name */, std::vector<std::string> /* handlers */> TLuaEngine::Debug_GetEventsForState(TLuaStateId StateId) {
|
void TLuaEngine::AddResultToCheck(const std::shared_ptr<TLuaResult>& Result) {
|
||||||
std::unordered_map<std::string, std::vector<std::string>> Result;
|
|
||||||
std::unique_lock Lock(mLuaEventsMutex);
|
|
||||||
for (const auto& EventNameToEventMap : mLuaEvents) {
|
|
||||||
for (const auto& IdSetOfHandlersPair : EventNameToEventMap.second) {
|
|
||||||
if (IdSetOfHandlersPair.first == StateId) {
|
|
||||||
for (const auto& Handler : IdSetOfHandlersPair.second) {
|
|
||||||
Result[EventNameToEventMap.first].push_back(Handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> TLuaEngine::Debug_GetStateExecuteQueueForState(TLuaStateId StateId) {
|
|
||||||
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Result;
|
|
||||||
std::unique_lock Lock(mLuaStatesMutex);
|
|
||||||
Result = mLuaStates.at(StateId)->Debug_GetStateExecuteQueue();
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> TLuaEngine::Debug_GetStateFunctionQueueForState(TLuaStateId StateId) {
|
|
||||||
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Result;
|
|
||||||
std::unique_lock Lock(mLuaStatesMutex);
|
|
||||||
Result = mLuaStates.at(StateId)->Debug_GetStateFunctionQueue();
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TLuaResult> TLuaEngine::Debug_GetResultsToCheckForState(TLuaStateId StateId) {
|
|
||||||
std::unique_lock Lock(mResultsToCheckMutex);
|
std::unique_lock Lock(mResultsToCheckMutex);
|
||||||
auto ResultsToCheckCopy = mResultsToCheck;
|
mResultsToCheck.push(Result);
|
||||||
Lock.unlock();
|
|
||||||
std::vector<TLuaResult> Result;
|
|
||||||
while (!ResultsToCheckCopy.empty()) {
|
|
||||||
auto ResultToCheck = std::move(ResultsToCheckCopy.front());
|
|
||||||
ResultsToCheckCopy.pop();
|
|
||||||
if (ResultToCheck->StateId == StateId) {
|
|
||||||
Result.push_back(*ResultToCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
|
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
|
||||||
@@ -715,16 +669,6 @@ void TLuaEngine::StateThreadData::operator()() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> TLuaEngine::StateThreadData::Debug_GetStateExecuteQueue() {
|
|
||||||
std::unique_lock Lock(mStateExecuteQueueMutex);
|
|
||||||
return mStateExecuteQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> TLuaEngine::StateThreadData::Debug_GetStateFunctionQueue() {
|
|
||||||
std::unique_lock Lock(mStateFunctionQueueMutex);
|
|
||||||
return mStateFunctionQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS) {
|
void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS) {
|
||||||
std::unique_lock Lock(mTimedEventsMutex);
|
std::unique_lock Lock(mTimedEventsMutex);
|
||||||
TimedEvent Event {
|
TimedEvent Event {
|
||||||
@@ -759,6 +703,7 @@ void TLuaEngine::StateThreadData::AddPath(const fs::path& Path) {
|
|||||||
|
|
||||||
void TLuaResult::WaitUntilReady() {
|
void TLuaResult::WaitUntilReady() {
|
||||||
while (!Ready) {
|
while (!Ready) {
|
||||||
|
std::this_thread::yield();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -816,12 +761,7 @@ void TPluginMonitor::operator()() {
|
|||||||
auto StateID = mEngine.GetStateIDForPlugin(fs::path(Pair.first).parent_path());
|
auto StateID = mEngine.GetStateIDForPlugin(fs::path(Pair.first).parent_path());
|
||||||
auto Res = mEngine.EnqueueScript(StateID, Chunk);
|
auto Res = mEngine.EnqueueScript(StateID, Chunk);
|
||||||
// TODO: call onInit
|
// TODO: call onInit
|
||||||
while (!Res->Ready) {
|
mEngine.AddResultToCheck(Res);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
|
||||||
if (Res->Error) {
|
|
||||||
beammp_lua_error(Res->ErrorMessage);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: trigger onFileChanged event
|
// TODO: trigger onFileChanged event
|
||||||
beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet");
|
beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet");
|
||||||
|
|||||||
+2
-2
@@ -21,8 +21,8 @@ TPPSMonitor::TPPSMonitor(TServer& Server)
|
|||||||
void TPPSMonitor::operator()() {
|
void TPPSMonitor::operator()() {
|
||||||
RegisterThread("PPSMonitor");
|
RegisterThread("PPSMonitor");
|
||||||
while (!mNetwork) {
|
while (!mNetwork) {
|
||||||
// hard spi
|
// hard(-ish) spin
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
beammp_debug("PPSMonitor starting");
|
beammp_debug("PPSMonitor starting");
|
||||||
Application::SetSubsystemStatus("PPSMonitor", Application::Status::Good);
|
Application::SetSubsystemStatus("PPSMonitor", Application::Status::Good);
|
||||||
|
|||||||
+5
-5
@@ -77,11 +77,6 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
int BeamMPServerMain(MainArguments Arguments) {
|
int BeamMPServerMain(MainArguments Arguments) {
|
||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
Application::InitializeConsole();
|
|
||||||
Application::SetSubsystemStatus("Main", Application::Status::Starting);
|
|
||||||
|
|
||||||
SetupSignalHandlers();
|
|
||||||
|
|
||||||
ArgsParser Parser;
|
ArgsParser Parser;
|
||||||
Parser.RegisterArgument({ "help" }, ArgsParser::NONE);
|
Parser.RegisterArgument({ "help" }, ArgsParser::NONE);
|
||||||
Parser.RegisterArgument({ "version" }, ArgsParser::NONE);
|
Parser.RegisterArgument({ "version" }, ArgsParser::NONE);
|
||||||
@@ -121,6 +116,11 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Application::InitializeConsole();
|
||||||
|
Application::SetSubsystemStatus("Main", Application::Status::Starting);
|
||||||
|
|
||||||
|
SetupSignalHandlers();
|
||||||
|
|
||||||
bool Shutdown = false;
|
bool Shutdown = false;
|
||||||
Application::RegisterShutdownHandler([&Shutdown] {
|
Application::RegisterShutdownHandler([&Shutdown] {
|
||||||
|
|||||||
Reference in New Issue
Block a user