diff --git a/include/Common.h b/include/Common.h index 2c1c26c..94e3f15 100644 --- a/include/Common.h +++ b/include/Common.h @@ -56,7 +56,7 @@ private: static inline std::deque mShutdownHandlers {}; }; -/* +#ifndef DEBUG static inline void warn(const std::string& str) { Application::Console().Write(std::string("[WARN] ") + str); } @@ -72,9 +72,9 @@ static inline void debug(const std::string& str) { } } static inline void luaprint(const std::string& str) { - Application::Console().Write(std::string("[LUA] ") + str); + Application::Console().WriteRaw(str); } -*/ +#else // DEBUG #define warn(x) Application::Console().Write(std::string(__PRETTY_FUNCTION__) + ":" + std::to_string(__LINE__) + std::string(" [WARN] ") + (x)) #define info(x) Application::Console().Write(std::string(__PRETTY_FUNCTION__) + ":" + std::to_string(__LINE__) + std::string(" [INFO] ") + (x)) @@ -86,6 +86,7 @@ static inline void luaprint(const std::string& str) { Application::Console().Write(std::string(__PRETTY_FUNCTION__) + ":" + std::to_string(__LINE__) + std::string(" [DEBUG] ") + (x)); \ } \ } while (false) +#endif // DEBUG #define Biggest 30000 std::string Comp(std::string Data); diff --git a/include/TConsole.h b/include/TConsole.h index 741d313..86bf0db 100644 --- a/include/TConsole.h +++ b/include/TConsole.h @@ -1,5 +1,6 @@ #pragma once +#include "TLuaFile.h" #include "commandline/commandline.h" #include #include @@ -9,7 +10,10 @@ public: TConsole(); void Write(const std::string& str); + void WriteRaw(const std::string& str); + void InitializeLuaConsole(TLuaEngine& Engine); private: + std::unique_ptr mLuaConsole { nullptr }; Commandline mCommandline; }; diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 0c26d3a..40d8a7a 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -1,5 +1,4 @@ -#ifndef TLUAENGINE_H -#define TLUAENGINE_H +#pragma once #include "Common.h" #include "IThreaded.h" @@ -12,6 +11,7 @@ class TLuaEngine : public IThreaded { public: explicit TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPServer); + ~TLuaEngine(); using TSetOfLuaFile = std::set>; @@ -38,5 +38,3 @@ private: bool mShutdown { false }; TSetOfLuaFile mLuaFiles; }; - -#endif // TLUAENGINE_H diff --git a/include/TTCPServer.h b/include/TTCPServer.h index 3a6322b..a6e8b49 100644 --- a/include/TTCPServer.h +++ b/include/TTCPServer.h @@ -11,6 +11,7 @@ class TResourceManager; class TTCPServer : public IThreaded { public: explicit TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager); + ~TTCPServer(); void operator()() override; diff --git a/include/TUDPServer.h b/include/TUDPServer.h index 7269e7f..c79bb2b 100644 --- a/include/TUDPServer.h +++ b/include/TUDPServer.h @@ -10,6 +10,7 @@ class TUDPServer : public IThreaded { public: explicit TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCPServer); + ~TUDPServer(); void operator()() override; @@ -21,6 +22,7 @@ private: TPPSMonitor& mPPSMonitor; TTCPServer& mTCPServer; SOCKET mUDPSock {}; + bool mShutdown { false }; std::string UDPRcvFromClient(sockaddr_in& client) const; }; \ No newline at end of file diff --git a/include/commandline b/include/commandline index 01ec8e0..19184df 160000 --- a/include/commandline +++ b/include/commandline @@ -1 +1 @@ -Subproject commit 01ec8e0388ee4759813abf12c9619ac294721eab +Subproject commit 19184df67e80cecb02de957d922477f7218b7703 diff --git a/src/Common.cpp b/src/Common.cpp index 190b576..28ce8d0 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -16,6 +16,7 @@ void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) { } void Application::GracefullyShutdown() { + info("please wait while all subsystems are shutting down..."); std::unique_lock Lock(mShutdownHandlersMutex); for (auto& Handler : mShutdownHandlers) { Handler(); diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 57b2fef..b3742fd 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -43,6 +43,10 @@ TConsole::TConsole() { mCommandline.enable_history(); mCommandline.set_history_limit(20); mCommandline.set_prompt("> "); + bool success = mCommandline.enable_write_to_file("Server.log"); + if (!success) { + error("unable to open file for writing: \"Server.log\""); + } mCommandline.on_command = [this](Commandline& c) { auto cmd = c.get_command(); mCommandline.write("> " + cmd); @@ -52,7 +56,11 @@ TConsole::TConsole() { } else if (cmd == "clear" || cmd == "cls") { // TODO: clear screen } else { - // TODO: execute as lua + if (mLuaConsole) { + mLuaConsole->Execute(cmd); + } else { + error("Lua subsystem not yet initialized, please wait a few seconds and try again"); + } } }; } @@ -62,4 +70,9 @@ void TConsole::Write(const std::string& str) { mCommandline.write(ToWrite); // TODO write to logfile, too } - +void TConsole::InitializeLuaConsole(TLuaEngine& Engine) { + mLuaConsole = std::make_unique(Engine, true); +} +void TConsole::WriteRaw(const std::string& str) { + mCommandline.write(str); +} diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index 88c239a..1040a72 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -18,10 +18,12 @@ void THeartbeatThread::operator()() { 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(); - if (Last == Body && (Now - LastNormalUpdateTime) < std::chrono::seconds(30)) { - std::this_thread::sleep_for(std::chrono::seconds(5)); + if (((Now - LastNormalUpdateTime) < std::chrono::seconds(5)) + || (Last == Body && (Now - LastNormalUpdateTime) < std::chrono::seconds(30))) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue; } + Last = Body; LastNormalUpdateTime = Now; if (!Application::Settings.CustomIP.empty()) @@ -77,7 +79,14 @@ std::string THeartbeatThread::GenerateCall() { THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& Server) : mResourceManager(ResourceManager) , mServer(Server) { - Application::RegisterShutdownHandler([&] { mShutdown = true; }); + Application::RegisterShutdownHandler([&] { + if (mThread.joinable()) { + debug("shutting down Heartbeat"); + mShutdown = true; + mThread.join(); + debug("shut down Heartbeat"); + } + }); Start(); } std::string THeartbeatThread::GetPlayers() { @@ -91,7 +100,4 @@ std::string THeartbeatThread::GetPlayers() { return Return; } THeartbeatThread::~THeartbeatThread() { - if (mThread.joinable()) { - mThread.join(); - } } diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index d0929c9..7b30ec4 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -23,7 +23,12 @@ TLuaEngine::TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPSe } FolderList(Path, false); mPath = Path; - Application::RegisterShutdownHandler([&] { mShutdown = true; }); + Application::RegisterShutdownHandler([&] {if (mThread.joinable()) { + debug("shutting down LuaEngine"); + mShutdown = true; + mThread.join(); + debug("shut down LuaEngine"); + } }); Start(); } @@ -96,3 +101,6 @@ bool TLuaEngine::NewFile(const std::string& Path) { } return true; } + +TLuaEngine::~TLuaEngine() { +} diff --git a/src/TLuaFile.cpp b/src/TLuaFile.cpp index 4cba073..a0f6ef8 100644 --- a/src/TLuaFile.cpp +++ b/src/TLuaFile.cpp @@ -537,18 +537,44 @@ int lua_Set(lua_State* L) { extern "C" { int lua_Print(lua_State* L) { int Arg = lua_gettop(L); + std::string to_print; for (int i = 1; i <= Arg; i++) { - auto str = lua_tostring(L, i); - if (str != nullptr) { - luaprint(str + std::string(("\n"))); + if (lua_isstring(L, i)) { + to_print += lua_tostring(L, i); + } else if (lua_isinteger(L, i)) { + to_print += std::to_string(lua_tointeger(L, 1)); + } else if (lua_isnumber(L, i)) { + to_print += std::to_string(lua_tonumber(L, 1)); + } else if (lua_isboolean(L, i)) { + to_print += lua_toboolean(L, i) ? "true" : "false"; + } else if (lua_isfunction(L, i)) { + std::stringstream ss; + ss << std::hex << reinterpret_cast(lua_tocfunction(L, i)); + to_print += "function: " + ss.str(); + } else if (lua_istable(L, i)) { + std::stringstream ss; + ss << std::hex << reinterpret_cast(lua_topointer(L, i)); + to_print += "table: " + ss.str(); + } else if (lua_isnoneornil(L, i)) { + to_print += "nil"; + } else if (lua_isthread(L, i)) { + std::stringstream ss; + ss << std::hex << reinterpret_cast(lua_tothread(L, i)); + to_print += "thread: " + ss.str(); } else { - luaprint("nil\n"); + to_print += "(unknown)"; + } + if (i + 1 <= Arg) { + to_print += "\t"; } } + luaprint(to_print); return 0; } } +int lua_TempFix(lua_State* L); + TLuaFile::TLuaFile(TLuaEngine& Engine, const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote, bool Console) : mEngine(Engine) , mLuaState(luaL_newstate()) { @@ -564,13 +590,14 @@ TLuaFile::TLuaFile(TLuaEngine& Engine, const std::string& PluginName, const std: SetFileName(FileName); } SetLastWrite(LastWrote); - mConsole = Console; + Init(); } TLuaFile::TLuaFile(TLuaEngine& Engine, bool Console) : mEngine(Engine) , mLuaState(luaL_newstate()) { mConsole = Console; + Init(); } void TLuaFile::Execute(const std::string& Command) { @@ -614,23 +641,7 @@ void TLuaFile::SetPluginName(const std::string& Name) { void TLuaFile::SetFileName(const std::string& Name) { mFileName = Name; } -int lua_TempFix(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - auto MaybeClient = GetClient(Engine().Server(), ID); - if (!MaybeClient || MaybeClient.value().expired()) - return 0; - std::string Ret; - auto c = MaybeClient.value().lock(); - if (c->IsGuest()) { - Ret = "Guest-" + c->GetName(); - } else - Ret = c->GetName(); - lua_pushstring(L, Ret.c_str()); - } else - SendError(Engine(), L, "GetDID not enough arguments"); - return 1; -} + void TLuaFile::Init() { Assert(mLuaState); luaL_openlibs(mLuaState); @@ -722,6 +733,23 @@ void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg) { } warn(a + (" | Incorrect Call of ") + msg); } +int lua_TempFix(lua_State* L) { + if (lua_isnumber(L, 1)) { + int ID = int(lua_tonumber(L, 1)); + auto MaybeClient = GetClient(Engine().Server(), ID); + if (!MaybeClient || MaybeClient.value().expired()) + return 0; + std::string Ret; + auto c = MaybeClient.value().lock(); + if (c->IsGuest()) { + Ret = "Guest-" + c->GetName(); + } else + Ret = c->GetName(); + lua_pushstring(L, Ret.c_str()); + } else + SendError(Engine(), L, "GetDID not enough arguments"); + return 1; +} void TLuaArg::PushArgs(lua_State* State) { for (std::any arg : args) { diff --git a/src/TPPSMonitor.cpp b/src/TPPSMonitor.cpp index a840384..9e2711b 100644 --- a/src/TPPSMonitor.cpp +++ b/src/TPPSMonitor.cpp @@ -4,7 +4,14 @@ TPPSMonitor::TPPSMonitor(TServer& Server) : mServer(Server) { Application::SetPPS("-"); - Application::RegisterShutdownHandler([&] { mShutdown = true; }); + Application::RegisterShutdownHandler([&] { + if (mThread.joinable()) { + debug("shutting down PPSMonitor"); + mShutdown = true; + mThread.join(); + debug("shut down PPSMonitor"); + } + }); Start(); } void TPPSMonitor::operator()() { diff --git a/src/TTCPServer.cpp b/src/TTCPServer.cpp index c6020bb..53da9ce 100644 --- a/src/TTCPServer.cpp +++ b/src/TTCPServer.cpp @@ -19,7 +19,13 @@ TTCPServer::TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManage : mServer(Server) , mPPSMonitor(PPSMonitor) , mResourceManager(ResourceManager) { - Application::RegisterShutdownHandler([this] { mShutdown = true; }); + Application::RegisterShutdownHandler([&] {if (mThread.joinable()) { + debug("shutting down TCPServer"); + mShutdown = true; + // FIXME: Join once TCPServer can timeout on a read, accept, etc. + mThread.detach(); + debug("shut down TCPServer"); + } }); Start(); } @@ -282,6 +288,7 @@ void TTCPServer::TCPClient(std::weak_ptr c) { } void TTCPServer::UpdatePlayers() { + debug("Update Players!"); std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.MaxPlayers) + ":"; mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { if (!ClientPtr.expired()) { @@ -368,8 +375,8 @@ void TTCPServer::SyncResources(TClient& c) { } #ifndef DEBUG } catch (std::exception& e) { - except("Exception! : " + std::string(e.what())); - c->SetStatus(-1); + error("Exception! : " + std::string(e.what())); + c.SetStatus(-1); } #endif } @@ -651,3 +658,5 @@ void TTCPServer::operator()() { CloseSocketProper(client); #endif } +TTCPServer::~TTCPServer() { +} diff --git a/src/TUDPServer.cpp b/src/TUDPServer.cpp index de8f23d..83d5586 100644 --- a/src/TUDPServer.cpp +++ b/src/TUDPServer.cpp @@ -9,6 +9,13 @@ TUDPServer::TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCP : mServer(Server) , mPPSMonitor(PPSMonitor) , mTCPServer(TCPServer) { + Application::RegisterShutdownHandler([&] {if (mThread.joinable()) { + debug("shutting down UDPServer"); + mShutdown = true; + // FIXME: Once we use boost for UDP, set up a timeout so this doesn't block + mThread.detach(); + debug("shut down UDPServer"); + } }); Start(); } @@ -53,7 +60,7 @@ void TUDPServer::operator()() { info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ") + std::to_string(Application::Settings.MaxPlayers) + (" Clients")); - while (true) { + while (!mShutdown) { try { sockaddr_in client {}; std::string Data = UDPRcvFromClient(client); //Receives any data from Socket @@ -163,3 +170,6 @@ std::string TUDPServer::UDPRcvFromClient(sockaddr_in& client) const { } return std::string(Ret.begin(), Ret.begin() + Rcv); } + +TUDPServer::~TUDPServer() { +} diff --git a/src/main.cpp b/src/main.cpp index 589b0fa..01d8dd4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,9 @@ int main(int argc, char** argv) { info("registering handlers for SIGINT, SIGTERM, SIGPIPE"); signal(SIGPIPE, UnixSignalHandler); signal(SIGTERM, UnixSignalHandler); +#ifndef DEBUG signal(SIGINT, UnixSignalHandler); +#endif // DEBUG #endif // __unix bool Shutdown = false; @@ -53,6 +55,7 @@ int main(int argc, char** argv) { TUDPServer UDPServer(Server, PPSMonitor, TCPServer); TLuaEngine LuaEngine(Server, TCPServer, UDPServer); TCPServer.SetUDPServer(UDPServer); + Application::Console().InitializeLuaConsole(LuaEngine); // TODO: replace while (!Shutdown) {