Compare commits

...

19 Commits

Author SHA1 Message Date
Lion Kortlepel 5c44a307bc update changelog 2022-02-03 19:03:21 +01:00
Lion Kortlepel 754053e73f Use yield() where possible
Replaced calls of this_thread::sleep_* with this_thread::yield(), which
yields the thread to the OS' scheduler.
2022-02-03 18:57:52 +01:00
Lion Kortlepel 29f8d29e33 Move commandline initialization after cwd setting
This fixes an issue where the log file is written to the original
directory, even if --working-directory=path was used. This can obviously
be pretty bad.
2022-02-03 18:31:18 +01:00
Lion Kortlepel e043361abb update libraries 2022-02-03 18:30:00 +01:00
Lion Kortlepel fca5bbcec9 UpdateCheck: Try all URLs 2022-01-21 14:26:42 +01:00
Lion Kortlepel 2a588954be advance to 3.0.1 2022-01-20 21:31:00 +01:00
Lion Kortlepel cd4129e05d add api-v header to heartbeat post 2022-01-20 16:09:08 +01:00
Lion Kortlepel c42c748b37 start fixing backend heartbeat 2022-01-20 15:46:13 +01:00
Lion 179b33a7ab Merge pull request #76 from BeamMP/patch-http-server-default
HTTP Server disabled by default
2021-12-23 14:28:33 +01:00
Lion Kortlepel 1b14206a3c HTTP Server disabled by default 2021-12-23 14:24:00 +01:00
Lion 0cf81cf3f4 Merge pull request #73 from BeamMP/lionkor-readme-patch
Patch README Dependency List, fix Changelog
2021-12-16 23:54:33 +01:00
Lion 801780bcb1 Update Changelog.md 2021-12-16 16:02:31 +01:00
Lion 84d52578e0 Merge pull request #75 from BeamMP/release-3-0-0-patch
Release v3.0.0 final patch
2021-12-15 18:26:08 +01:00
Lion Kortlepel 3555cec5fe Simplify fix for event argument bug 2021-12-13 13:48:18 +01:00
Lion Kortlepel 71efe30345 Bump to 3.0.0, possible fix for event argument bug 2021-12-13 13:22:58 +01:00
Lion 5df8aedf08 Update Changelog.md 2021-12-11 10:35:11 +01:00
Lion c3ab4b729a Update README.md 2021-12-09 14:15:50 +01:00
Lion 464aa3b59f Update README.md 2021-12-09 14:13:05 +01:00
Lion cfe63198c7 Merge pull request #50 from BeamMP/rewrite-lua
Rewrite Lua + New Lua Features + New Console + Commandline Args
2021-12-09 13:04:48 +01:00
15 changed files with 173 additions and 112 deletions
+2
View File
@@ -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")
+9 -3
View File
@@ -1,7 +1,13 @@
# v2.4.0 # 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
- CHANGED entire plugin Lua implementation (rewrite) - CHANGED entire plugin Lua implementation (rewrite)
- CHANGED moved *almost all* functions into MP.\* - CHANGED moved *almost all* Lua functions into MP.\*
- CHANGED console to use a custom language (type `help`, `list`, or `status`!) - CHANGED console to use a custom language (type `help`, `list`, or `status`!)
- CHANGED all files of a Lua plugin to share a Lua state (no more state-per-file) - CHANGED all files of a Lua plugin to share a Lua state (no more state-per-file)
- ADDED many new Lua API functions, which can be found at <https://wiki.beammp.com/en/Scripting/functions> - ADDED many new Lua API functions, which can be found at <https://wiki.beammp.com/en/Scripting/functions>
@@ -14,7 +20,7 @@
- ADDED dumping tables with `print()` (try it with `print(MP)`) - ADDED dumping tables with `print()` (try it with `print(MP)`)
- ADDED `MP.GetOSName()`, `MP.CreateTimer()`, `MP.GetLuaMemoryUsage()` and many more (see <https://wiki.beammp.com/en/Scripting/functions>) - ADDED `MP.GetOSName()`, `MP.CreateTimer()`, `MP.GetLuaMemoryUsage()` and many more (see <https://wiki.beammp.com/en/Scripting/functions>)
- ADDED `MP.Settings` table to make usage of `MP.Set()` easier - ADDED `MP.Settings` table to make usage of `MP.Set()` easier
- ADDED `FS.*` table with common filesystem operations - ADDED `FS.*` table with common filesystem operations (do `print(FS)` to see them!)
- FIXED i/o thread spin when stdout is /dev/null on linux - FIXED i/o thread spin when stdout is /dev/null on linux
- FIXED removed extra whitespace infront of onChatMessage message - FIXED removed extra whitespace infront of onChatMessage message
+38 -27
View File
@@ -6,6 +6,8 @@
This is the server for the multiplayer mod **[BeamMP](https://beammp.com/)** for the game [BeamNG.drive](https://www.beamng.com/). This is the server for the multiplayer mod **[BeamMP](https://beammp.com/)** for the game [BeamNG.drive](https://www.beamng.com/).
The server is the point throug which all clients communicate. You can write lua mods for the server, detailed instructions on the [BeamMP Wiki](https://wiki.beammp.com). The server is the point throug which all clients communicate. You can write lua mods for the server, detailed instructions on the [BeamMP Wiki](https://wiki.beammp.com).
**For Linux, you __need__ the runtime dependencies, listed below under "prerequisites".**
## Support + Contact ## Support + Contact
Feel free to ask any questions via the following channels: Feel free to ask any questions via the following channels:
@@ -48,7 +50,7 @@ You can find precompiled binaries under [Releases](https://github.com/BeamMP/Bea
## Build Instructions ## Build Instructions
**__Do not compile from `master`. Always build from a release tag, i.e. `tags/v2.0`!__** **__Do not compile from `master`. Always build from a release tag, i.e. `tags/v2.3.3`!__**
Currently only linux and windows are supported (generally). See [Releases](https://github.com/BeamMP/BeamMP-Server/releases/) for official binary releases. On systems to which we do not provide binaries (so anything but windows), you are allowed to compile the program and use it. Other restrictions, such as not being allowed to distribute those binaries, still apply (see [copyright notice](#copyright)). Currently only linux and windows are supported (generally). See [Releases](https://github.com/BeamMP/BeamMP-Server/releases/) for official binary releases. On systems to which we do not provide binaries (so anything but windows), you are allowed to compile the program and use it. Other restrictions, such as not being allowed to distribute those binaries, still apply (see [copyright notice](#copyright)).
@@ -58,38 +60,47 @@ Currently only linux and windows are supported (generally). See [Releases](https
Please use the prepackaged binaries in [Releases](https://github.com/BeamMP/BeamMP-Server/releases/). Please use the prepackaged binaries in [Releases](https://github.com/BeamMP/BeamMP-Server/releases/).
Dependencies for windows can be installed with `vcpkg`, in which case the current dependencies are the `x64-windows-static` versions of `lua`, `zlib`, `rapidjson`, and `openssl`. Dependencies for **windows** can be installed with `vcpkg`.
These are:
```
lua
zlib
rapidjson
openssl
websocketpp
curl
```
#### Linux / \*nix #### Linux
These package names are in the debian / ubuntu style. Feel free to PR your own guide for a different distro. These package names are in the debian / ubuntu style. Feel free to PR your own guide for a different distro.
- `git` Runtime dependencies for **linux** are (debian/ubuntu):
- `make` ```
- `cmake` libz-dev
- `g++` rapidjson-dev
- `libcurl4-openssl-dev` or similar (search for `libcurl` and look for one with `-dev`) liblua5.3
libssl-dev
Must support ISO C++17. If your distro's `g++` doesn't support C++17, chances are that it has a `g++-8` or `g++-10` package that does. If this is the case. you just need to run CMake with `-DCMAKE_CXX_COMPILER=g++-10` (replace `g++-10` with your compiler's name). libwebsocketpp-dev
- `liblua5.3-dev` libcurl4-openssl-dev
Any 5.x version should work, but 5.3 is what we officially use. Any other version might break in the future.
You can also use any version of `libluajit`, but the same applies regarding the version.
- `libz-dev`
- `rapidjson-dev`
- `libopenssl-dev` or `libssl-dev`
In the end you should end up with a command something like this:
```sh
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev
``` ```
In the end you should end up with a command something like this: Build-time dependencies for **linux** are:
```sh
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev
``` ```
git
make
cmake
g++
```
For other distributions (e.g. Arch) you want to find packages for:
- libz
- rapidjson
- lua5.3
- ssl / openssl
- websocketpp
- curl (with ssl support)
- \+ the build time dependencies from above
### How to build ### How to build
@@ -98,7 +109,7 @@ On windows, use git-bash for these commands. On Linux, these should work in your
1. Make sure you have all [prerequisites](#prerequisites) installed 1. Make sure you have all [prerequisites](#prerequisites) installed
2. Clone the repository in a location of your choice with `git clone --recurse-submodules https://github.com/BeamMP/BeamMP-Server`. 2. Clone the repository in a location of your choice with `git clone --recurse-submodules https://github.com/BeamMP/BeamMP-Server`.
3. Ensure that all submodules are initialized by running `git submodule update --init --recursive`. Then change into the cloned directory by running `cd BeamMP-Server`. 3. Ensure that all submodules are initialized by running `git submodule update --init --recursive`. Then change into the cloned directory by running `cd BeamMP-Server`.
4. Checkout the branch of the release you want to compile (`master` is often unstable), for example `git checkout tags/v1.20` for version 1.20. You can find the latest version [here](https://github.com/BeamMP/BeamMP-Server/tags). 4. Checkout the branch of the release you want to compile (`master` is often unstable), for example `git checkout tags/v2.3.3` for version 2.3.3. You can find the latest version [here](https://github.com/BeamMP/BeamMP-Server/tags).
5. Run `cmake . -DCMAKE_BUILD_TYPE=Release` (with `.`) 5. Run `cmake . -DCMAKE_BUILD_TYPE=Release` (with `.`)
6. Run `make` 6. Run `make`
7. You will now have a `BeamMP-Server` file in your directory, which is executable with `./BeamMP-Server` (`.\BeamMP-Server.exe` for windows). Follow the (windows or linux, doesnt matter) instructions on the [wiki](https://wiki.beammp.com/en/home/Server_Mod) for further setup after installation (which we just did), such as port-forwarding and getting a key to actually run the server. 7. You will now have a `BeamMP-Server` file in your directory, which is executable with `./BeamMP-Server` (`.\BeamMP-Server.exe` for windows). Follow the (windows or linux, doesnt matter) instructions on the [wiki](https://wiki.beammp.com/en/home/Server_Mod) for further setup after installation (which we just did), such as port-forwarding and getting a key to actually run the server.
+10 -5
View File
@@ -42,7 +42,7 @@ public:
std::string Key {}; std::string Key {};
std::string SSLKeyPath { "./.ssl/HttpServer/key.pem" }; std::string SSLKeyPath { "./.ssl/HttpServer/key.pem" };
std::string SSLCertPath { "./.ssl/HttpServer/cert.pem" }; std::string SSLCertPath { "./.ssl/HttpServer/cert.pem" };
bool HTTPServerEnabled { true }; bool HTTPServerEnabled { false };
int MaxPlayers { 10 }; int MaxPlayers { 10 };
bool Private { true }; bool Private { true };
int MaxCars { 1 }; int MaxCars { 1 };
@@ -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 { 2, 4, 0 }; static inline Version mVersion { 3, 0, 1 };
}; };
std::string ThreadName(bool DebugModeOverride = false); std::string ThreadName(bool DebugModeOverride = false);
+1 -1
View File
@@ -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);
} }
+4 -1
View File
@@ -133,10 +133,12 @@ public:
} }
std::vector<std::shared_ptr<TLuaResult>> Results; std::vector<std::shared_ptr<TLuaResult>> Results;
std::vector<TLuaArgTypes> Arguments { TLuaArgTypes { std::forward<ArgsT>(Args) }... };
for (const auto& Event : mLuaEvents.at(EventName)) { for (const auto& Event : mLuaEvents.at(EventName)) {
for (const auto& Function : Event.second) { for (const auto& Function : Event.second) {
if (Event.first != IgnoreId) { if (Event.first != IgnoreId) {
Results.push_back(EnqueueFunctionCall(Event.first, Function, { TLuaArgTypes { std::forward<ArgsT>(Args) }... })); Results.push_back(EnqueueFunctionCall(Event.first, Function, Arguments));
} }
} }
} }
@@ -147,6 +149,7 @@ 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";
+23 -17
View File
@@ -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
View File
@@ -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;
} }
} }
+1 -1
View File
@@ -386,7 +386,7 @@ TConsole::TConsole() {
} 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
View File
@@ -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);
} }
} }
} }
+14 -20
View File
@@ -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,6 +142,11 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
return ""; return "";
} }
void TLuaEngine::AddResultToCheck(const std::shared_ptr<TLuaResult>& Result) {
std::unique_lock Lock(mResultsToCheckMutex);
mResultsToCheck.push(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) {
for (const auto& Result : Results) { for (const auto& Result : Results) {
bool Cancelled = false; bool Cancelled = false;
@@ -705,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));
} }
} }
@@ -762,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
View File
@@ -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
View File
@@ -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] {