mirror of
https://github.com/SantaSpeen/BeamMP-Server.git
synced 2025-07-03 09:15:24 +00:00
Fix various issues and crashes
This commit is contained in:
parent
279c93179c
commit
0f74eca2ee
@ -82,9 +82,32 @@ public:
|
|||||||
static std::array<uint8_t, 3> VersionStrToInts(const std::string& str);
|
static std::array<uint8_t, 3> VersionStrToInts(const std::string& str);
|
||||||
static bool IsOutdated(const Version& Current, const Version& Newest);
|
static bool IsOutdated(const Version& Current, const Version& Newest);
|
||||||
|
|
||||||
|
static void InitializeConsole() {
|
||||||
|
if (!mConsole) {
|
||||||
|
mConsole = std::make_unique<TConsole>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
Starting,
|
||||||
|
Good,
|
||||||
|
Bad,
|
||||||
|
};
|
||||||
|
|
||||||
|
using SystemStatusMap = std::unordered_map<std::string /* system name */, Status /* status */>;
|
||||||
|
|
||||||
|
static const SystemStatusMap& GetSubsystemStatuses() {
|
||||||
|
return mSystemStatusMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetSubsystemStatus(const std::string& Subsystem, Status status) {
|
||||||
|
mSystemStatusMap[Subsystem] = status;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static inline SystemStatusMap mSystemStatusMap {};
|
||||||
static inline std::string mPPS;
|
static inline std::string mPPS;
|
||||||
static std::unique_ptr<TConsole> mConsole;
|
static inline std::unique_ptr<TConsole> mConsole;
|
||||||
static inline std::mutex mShutdownHandlersMutex {};
|
static inline std::mutex mShutdownHandlersMutex {};
|
||||||
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
||||||
|
|
||||||
|
@ -91,14 +91,14 @@ static auto w_printf_s = [](const char* fmt, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
static auto w_sprintf_s = [](char* buf, size_t, const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsprintf(buf, fmt, args);
|
vsprintf(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
static auto w_sprintf_s_ret = [](char* buf, size_t, const char* fmt, ...) {
|
||||||
int ret;
|
int ret;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
@ -3,12 +3,16 @@
|
|||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include <IThreaded.h>
|
#include <IThreaded.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <httplib.h>
|
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||||
|
#include <httplib.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
@ -36,12 +40,6 @@ namespace Server {
|
|||||||
void operator()();
|
void operator()();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* the shared pointer is necessary because httplib is a blocking library and due lacking thread-safety
|
|
||||||
* will "forget" about its environment, when configured across multiple threads.
|
|
||||||
* So we need to able to start the server (make it "listen()") in a single Thread.
|
|
||||||
*/
|
|
||||||
std::shared_ptr<httplib::SSLServer> mHttpLibServerInstancePtr;
|
|
||||||
std::thread mThread;
|
std::thread mThread;
|
||||||
};
|
};
|
||||||
// todo: all of these functions are likely unsafe,
|
// todo: all of these functions are likely unsafe,
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
|
|
||||||
Application::TSettings Application::Settings = {};
|
Application::TSettings Application::Settings = {};
|
||||||
std::unique_ptr<TConsole> Application::mConsole = std::make_unique<TConsole>();
|
|
||||||
|
|
||||||
void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) {
|
void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) {
|
||||||
std::unique_lock Lock(mShutdownHandlersMutex);
|
std::unique_lock Lock(mShutdownHandlersMutex);
|
||||||
|
@ -270,14 +270,14 @@ Http::Server::THttpServerInstance::THttpServerInstance() {
|
|||||||
|
|
||||||
void Http::Server::THttpServerInstance::operator()() {
|
void Http::Server::THttpServerInstance::operator()() {
|
||||||
beammp_info("HTTPS Server started on port " + std::to_string(Application::Settings.HTTPServerPort));
|
beammp_info("HTTPS Server started on port " + std::to_string(Application::Settings.HTTPServerPort));
|
||||||
|
httplib::SSLServer HttpLibServerInstance { Application::Settings.SSLCertPath.c_str(), Application::Settings.SSLKeyPath.c_str() };
|
||||||
// todo: make this IP agnostic so people can set their own IP
|
// todo: make this IP agnostic so people can set their own IP
|
||||||
mHttpLibServerInstancePtr = std::make_shared<httplib::SSLServer>(Application::Settings.SSLCertPath.c_str(), Application::Settings.SSLKeyPath.c_str());
|
HttpLibServerInstance.Get("/", [](const httplib::Request&, httplib::Response& res) {
|
||||||
mHttpLibServerInstancePtr->Get("/", [](const httplib::Request&, httplib::Response& res) {
|
|
||||||
res.set_content("<!DOCTYPE html><article><h1>Hello World!</h1><section><p>BeamMP Server can now serve HTTP requests!</p></section></article></html>", "text/html");
|
res.set_content("<!DOCTYPE html><article><h1>Hello World!</h1><section><p>BeamMP Server can now serve HTTP requests!</p></section></article></html>", "text/html");
|
||||||
});
|
});
|
||||||
mHttpLibServerInstancePtr->Get("/health", [](const httplib::Request&, httplib::Response& res) {
|
HttpLibServerInstance.Get("/health", [](const httplib::Request&, httplib::Response& res) {
|
||||||
res.set_content("0", "text/plain");
|
res.set_content("0", "text/plain");
|
||||||
res.status = 200;
|
res.status = 200;
|
||||||
});
|
});
|
||||||
mHttpLibServerInstancePtr->listen("0.0.0.0", Application::Settings.HTTPServerPort);
|
HttpLibServerInstance.listen("0.0.0.0", Application::Settings.HTTPServerPort);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ TConfig::TConfig(const std::string& ConfigFileName)
|
|||||||
ParseFromFile(mConfigFileName);
|
ParseFromFile(mConfigFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes out the loaded application state into ServerConfig.toml
|
* @brief Writes out the loaded application state into ServerConfig.toml
|
||||||
*
|
*
|
||||||
|
@ -38,7 +38,7 @@ std::string GetDate() {
|
|||||||
auto fraction = now - seconds;
|
auto fraction = now - seconds;
|
||||||
size_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(fraction).count();
|
size_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(fraction).count();
|
||||||
char fracstr[5];
|
char fracstr[5];
|
||||||
std::sprintf(fracstr, "%0.3lu", ms);
|
std::sprintf(fracstr, "%03lu", ms);
|
||||||
date += fracstr;
|
date += fracstr;
|
||||||
date += "] ";
|
date += "] ";
|
||||||
} else {
|
} else {
|
||||||
@ -99,6 +99,11 @@ void TConsole::BackupOldLog() {
|
|||||||
|
|
||||||
void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) {
|
void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) {
|
||||||
if (!mIsLuaConsole) {
|
if (!mIsLuaConsole) {
|
||||||
|
if (!mLuaEngine) {
|
||||||
|
beammp_error("Lua engine not initialized yet, please wait and try again");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLuaEngine->EnsureStateExists(mDefaultStateId, "Console");
|
||||||
mStateId = LuaStateId;
|
mStateId = LuaStateId;
|
||||||
mIsLuaConsole = true;
|
mIsLuaConsole = true;
|
||||||
if (mStateId != mDefaultStateId) {
|
if (mStateId != mDefaultStateId) {
|
||||||
@ -106,8 +111,8 @@ void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) {
|
|||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Entered Lua console. To exit, type `exit()`");
|
Application::Console().WriteRaw("Entered Lua console. To exit, type `exit()`");
|
||||||
}
|
}
|
||||||
//mCachedRegularHistory = mCommandline.history();
|
// mCachedRegularHistory = mCommandline.history();
|
||||||
//mCommandline.set_history(mCachedLuaHistory);
|
// mCommandline.set_history(mCachedLuaHistory);
|
||||||
mCommandline.set_prompt("lua> ");
|
mCommandline.set_prompt("lua> ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,8 +125,8 @@ void TConsole::ChangeToRegularConsole() {
|
|||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Left Lua console.");
|
Application::Console().WriteRaw("Left Lua console.");
|
||||||
}
|
}
|
||||||
//mCachedLuaHistory = mCommandline.history();
|
// mCachedLuaHistory = mCommandline.history();
|
||||||
//mCommandline.set_history(mCachedRegularHistory);
|
// mCommandline.set_history(mCachedRegularHistory);
|
||||||
mCommandline.set_prompt("> ");
|
mCommandline.set_prompt("> ");
|
||||||
mStateId = mDefaultStateId;
|
mStateId = mDefaultStateId;
|
||||||
}
|
}
|
||||||
@ -322,45 +327,45 @@ TConsole::TConsole() {
|
|||||||
auto cmd = c.get_command();
|
auto cmd = c.get_command();
|
||||||
cmd = TrimString(cmd);
|
cmd = TrimString(cmd);
|
||||||
mCommandline.write(mCommandline.prompt() + cmd);
|
mCommandline.write(mCommandline.prompt() + cmd);
|
||||||
if (!mLuaEngine) {
|
if (mIsLuaConsole) {
|
||||||
beammp_info("Lua not started yet, please try again in a second");
|
if (!mLuaEngine) {
|
||||||
} else {
|
beammp_info("Lua not started yet, please try again in a second");
|
||||||
if (mIsLuaConsole) {
|
} else if (cmd == "exit()") {
|
||||||
if (cmd == "exit()") {
|
ChangeToRegularConsole();
|
||||||
ChangeToRegularConsole();
|
|
||||||
} else {
|
|
||||||
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
|
||||||
while (!Future->Ready) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout
|
|
||||||
}
|
|
||||||
if (Future->Error) {
|
|
||||||
beammp_lua_error(Future->ErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (cmd == "exit") {
|
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
||||||
beammp_info("gracefully shutting down");
|
while (!Future->Ready) {
|
||||||
Application::GracefullyShutdown();
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout
|
||||||
} else if (StringStartsWith(cmd, "lua")) {
|
|
||||||
Command_Lua(cmd);
|
|
||||||
} else if (StringStartsWith(cmd, "help")) {
|
|
||||||
RunAsCommand(cmd, true);
|
|
||||||
Command_Help(cmd);
|
|
||||||
} else if (StringStartsWith(cmd, "kick")) {
|
|
||||||
RunAsCommand(cmd, true);
|
|
||||||
Command_Kick(cmd);
|
|
||||||
} else if (StringStartsWith(cmd, "say")) {
|
|
||||||
RunAsCommand(cmd, true);
|
|
||||||
Command_Say(cmd);
|
|
||||||
} else if (StringStartsWith(cmd, "list")) {
|
|
||||||
RunAsCommand(cmd, true);
|
|
||||||
Command_List(cmd);
|
|
||||||
} else if (StringStartsWith(cmd, "status")) {
|
|
||||||
RunAsCommand(cmd, true);
|
|
||||||
Command_Status(cmd);
|
|
||||||
} else if (!cmd.empty()) {
|
|
||||||
RunAsCommand(cmd);
|
|
||||||
}
|
}
|
||||||
|
if (Future->Error) {
|
||||||
|
beammp_lua_error(Future->ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mLuaEngine) {
|
||||||
|
beammp_error("Attempted to run a command before Lua engine started. Please wait and try again.");
|
||||||
|
} else if (cmd == "exit") {
|
||||||
|
beammp_info("gracefully shutting down");
|
||||||
|
Application::GracefullyShutdown();
|
||||||
|
} else if (StringStartsWith(cmd, "lua")) {
|
||||||
|
Command_Lua(cmd);
|
||||||
|
} else if (StringStartsWith(cmd, "help")) {
|
||||||
|
RunAsCommand(cmd, true);
|
||||||
|
Command_Help(cmd);
|
||||||
|
} else if (StringStartsWith(cmd, "kick")) {
|
||||||
|
RunAsCommand(cmd, true);
|
||||||
|
Command_Kick(cmd);
|
||||||
|
} else if (StringStartsWith(cmd, "say")) {
|
||||||
|
RunAsCommand(cmd, true);
|
||||||
|
Command_Say(cmd);
|
||||||
|
} else if (StringStartsWith(cmd, "list")) {
|
||||||
|
RunAsCommand(cmd, true);
|
||||||
|
Command_List(cmd);
|
||||||
|
} else if (StringStartsWith(cmd, "status")) {
|
||||||
|
RunAsCommand(cmd, true);
|
||||||
|
Command_Status(cmd);
|
||||||
|
} else if (!cmd.empty()) {
|
||||||
|
RunAsCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
@ -380,5 +385,4 @@ void TConsole::WriteRaw(const std::string& str) {
|
|||||||
|
|
||||||
void TConsole::InitializeLuaConsole(TLuaEngine& Engine) {
|
void TConsole::InitializeLuaConsole(TLuaEngine& Engine) {
|
||||||
mLuaEngine = &Engine;
|
mLuaEngine = &Engine;
|
||||||
Engine.EnsureStateExists(mDefaultStateId, "Console");
|
|
||||||
}
|
}
|
||||||
|
13
src/main.cpp
13
src/main.cpp
@ -77,6 +77,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
int BeamMPServerMain(MainArguments Arguments) {
|
int BeamMPServerMain(MainArguments Arguments) {
|
||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
|
Application::InitializeConsole();
|
||||||
|
|
||||||
SetupSignalHandlers();
|
SetupSignalHandlers();
|
||||||
|
|
||||||
@ -131,6 +132,7 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
TConfig Config(ConfigPath);
|
TConfig Config(ConfigPath);
|
||||||
TLuaEngine LuaEngine;
|
TLuaEngine LuaEngine;
|
||||||
LuaEngine.SetServer(&Server);
|
LuaEngine.SetServer(&Server);
|
||||||
|
Application::Console().InitializeLuaConsole(LuaEngine);
|
||||||
|
|
||||||
if (Config.Failed()) {
|
if (Config.Failed()) {
|
||||||
beammp_info("Closing in 10 seconds");
|
beammp_info("Closing in 10 seconds");
|
||||||
@ -152,7 +154,6 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||||
LuaEngine.SetNetwork(&Network);
|
LuaEngine.SetNetwork(&Network);
|
||||||
PPSMonitor.SetNetwork(Network);
|
PPSMonitor.SetNetwork(Network);
|
||||||
Application::Console().InitializeLuaConsole(LuaEngine);
|
|
||||||
Application::CheckForUpdates();
|
Application::CheckForUpdates();
|
||||||
|
|
||||||
if (Application::Settings.HTTPServerEnabled) {
|
if (Application::Settings.HTTPServerEnabled) {
|
||||||
@ -160,11 +161,15 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
Http::Server::THttpServerInstance HttpServerInstance {};
|
Http::Server::THttpServerInstance HttpServerInstance {};
|
||||||
}
|
}
|
||||||
|
|
||||||
beammp_debug("cert.pem is " + std::to_string(fs::file_size("cert.pem")) + " bytes");
|
|
||||||
beammp_debug("key.pem is " + std::to_string(fs::file_size("key.pem")) + " bytes");
|
|
||||||
|
|
||||||
RegisterThread("Main(Waiting)");
|
RegisterThread("Main(Waiting)");
|
||||||
|
|
||||||
|
auto Statuses = Application::GetSubsystemStatuses();
|
||||||
|
for (const auto& NameStatusPair : Statuses) {
|
||||||
|
if (NameStatusPair.second != Application::Status::Good) {
|
||||||
|
beammp_info("not good: " + NameStatusPair.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!Shutdown) {
|
while (!Shutdown) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user