From d360403c56337303fa8df62c2387e4cc35285d90 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Wed, 17 Feb 2021 00:46:18 +0100 Subject: [PATCH] finish rewrite, builds fully --- CMakeLists.txt | 8 +- include/Client.h | 3 + include/Common.h | 4 +- include/TLuaEngine.h | 7 +- include/TLuaFile.h | 2 + include/TPPSMonitor.h | 3 +- include/TServer.h | 13 +- include/TTCPServer.h | 39 ++- include/TUDPServer.h | 8 +- src/Common.cpp | 2 +- src/TLuaEngine.cpp | 6 +- src/TLuaFile.cpp | 22 +- src/TServer.cpp | 222 +++++++++++++++ src/TTCPServer.cpp | 643 +++++++++++++++++++++++++++++++++++++++++- src/TUDPServer.cpp | 78 +---- src/main.cpp | 22 +- 16 files changed, 971 insertions(+), 111 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7115ef9..553c3db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,9 @@ add_executable(BeamMP-Server include/THeartbeatThread.h src/THeartbeatThread.cpp include/Http.h src/Http.cpp include/SocketIO.h src/SocketIO.cpp - include/TPPSMonitor.h src/TPPSMonitor.cpp include/TUDPServer.h src/TUDPServer.cpp include/TTCPServer.h src/TTCPServer.cpp) + include/TPPSMonitor.h src/TPPSMonitor.cpp + include/TUDPServer.h src/TUDPServer.cpp + include/TTCPServer.h src/TTCPServer.cpp) target_include_directories(BeamMP-Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/commandline") @@ -54,11 +56,11 @@ target_include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${LUA_INCL find_package(OpenSSL REQUIRED) if (UNIX) - target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} dl crypto ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} commandline) + target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} dl crypto ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} commandline sioclient) elseif (WIN32) include(FindLua) find_package(ZLIB REQUIRED) find_package(RapidJSON CONFIG REQUIRED) target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) - target_link_libraries(BeamMP-Server PRIVATE ws2_32 ZLIB::ZLIB ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} commandline) + target_link_libraries(BeamMP-Server PRIVATE ws2_32 ZLIB::ZLIB ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} commandline sioclient) endif () diff --git a/include/Client.h b/include/Client.h index 23332ec..d4bf8cb 100644 --- a/include/Client.h +++ b/include/Client.h @@ -41,6 +41,9 @@ public: bool IsConnected() const { return mIsConnected; } bool IsSynced() const { return mIsSynced; } bool IsGuest() const { return mIsGuest; } + void SetIsGuest(bool NewIsGuest) { mIsGuest = NewIsGuest; } + void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; } + void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; } TServer& Server() const; private: diff --git a/include/Common.h b/include/Common.h index 1e9f5a9..6ed9eae 100644 --- a/include/Common.h +++ b/include/Common.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "TConsole.h" @@ -56,7 +56,7 @@ private: static inline std::string mPPS; static std::unique_ptr mConsole; static inline std::mutex mShutdownHandlersMutex {}; - static inline std::vector mShutdownHandlers {}; + static inline std::deque mShutdownHandlers {}; }; static inline void warn(const std::string& str) { diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index da7b8d2..ee51eb1 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -11,7 +11,7 @@ class TLuaEngine : public IThreaded { public: - explicit TLuaEngine(TServer& Server); + explicit TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPServer); using TSetOfLuaFile = std::set>; @@ -23,11 +23,16 @@ public: std::optional> GetScript(lua_State* L); + TTCPServer& TCPServer() { return mTCPServer; } + TUDPServer& UDPServer() { return mUDPServer; } + private: void FolderList(const std::string& Path, bool HotSwap); void RegisterFiles(const std::string& Path, bool HotSwap); bool NewFile(const std::string& Path); + TTCPServer& mTCPServer; + TUDPServer& mUDPServer; TServer& mServer; TSetOfLuaFile mLuaFiles; }; diff --git a/include/TLuaFile.h b/include/TLuaFile.h index f7c09c8..0541da1 100644 --- a/include/TLuaFile.h +++ b/include/TLuaFile.h @@ -56,4 +56,6 @@ private: bool mConsole = false; }; +std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr arg, bool Wait); + #endif // TLUAFILE_H diff --git a/include/TPPSMonitor.h b/include/TPPSMonitor.h index 5ce0406..e2539b2 100644 --- a/include/TPPSMonitor.h +++ b/include/TPPSMonitor.h @@ -1,12 +1,11 @@ #pragma once #include "Common.h" -#include "IThreaded.h" #include "TServer.h" class TPPSMonitor : public IThreaded { public: - TPPSMonitor(TServer& Server); + explicit TPPSMonitor(TServer& Server); void operator()() override; diff --git a/include/TServer.h b/include/TServer.h index 367c589..f057012 100644 --- a/include/TServer.h +++ b/include/TServer.h @@ -1,13 +1,16 @@ #pragma once +#include "IThreaded.h" +#include "RWMutex.h" #include #include #include #include -#include "RWMutex.h" - class TClient; +class TUDPServer; +class TTCPServer; +class TPPSMonitor; class TServer final { public: @@ -17,10 +20,16 @@ public: std::weak_ptr InsertNewClient(); void RemoveClient(std::weak_ptr); + // in Fn, return true to continue, return false to break void ForEachClient(const std::function)>& Fn); size_t ClientCount() const; + static void GlobalParser(std::weak_ptr Client, std::string Packet, TPPSMonitor& PPSMonitor, TUDPServer& UDPServer, TTCPServer& TCPServer); + static void HandleEvent(TClient& c, const std::string& Data); + private: TClientSet mClients; mutable RWMutex mClientsMutex; + static void ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPServer, TUDPServer& UDPServer); + static void Apply(TClient& c, int VID, const std::string& pckt); }; diff --git a/include/TTCPServer.h b/include/TTCPServer.h index 946741e..4c0a960 100644 --- a/include/TTCPServer.h +++ b/include/TTCPServer.h @@ -1,14 +1,51 @@ #pragma once +#include "Client.h" #include "Common.h" #include "Compat.h" #include "IThreaded.h" #include "TServer.h" +class TResourceManager; + class TTCPServer : public IThreaded { public: - explicit TTCPServer(TServer& Server); + explicit TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager); + void operator()() override; + + bool TCPSend(TClient& c, const std::string& Data); + void SendLarge(TClient& c, std::string Data); + void Respond(TClient& c, const std::string& MSG, bool Rel); + std::weak_ptr CreateClient(SOCKET TCPSock); + std::string TCPRcv(TClient& c); + void ClientKick(TClient& c, const std::string& R); + + void SetUDPServer(TUDPServer& UDPServer); + + TUDPServer& UDPServer() { return mUDPServer->get(); } + + void SyncClient(std::weak_ptr c); + void Identify(SOCKET TCPSock); + void Authentication(SOCKET TCPSock); + bool CheckBytes(TClient& c, int32_t BytesRcv); + void SyncResources(TClient& c); + + void UpdatePlayers(); private: + std::optional> mUDPServer { std::nullopt }; TServer& mServer; + TPPSMonitor& mPPSMonitor; + TResourceManager& mResourceManager; + bool mShutdown { false }; + + void HandleDownload(SOCKET TCPSock); + void OnConnect(std::weak_ptr c); + void TCPClient(std::weak_ptr c); + int OpenID(); + void OnDisconnect(std::weak_ptr ClientPtr, bool kicked); + void Parse(TClient& c, const std::string& Packet); + void SendFile(TClient& c, const std::string& Name); + static bool TCPSendRaw(SOCKET C, char* Data, int32_t Size); + static void SplitLoad(TClient& c, int64_t Sent, int64_t Size, bool D, const std::string& Name); }; \ No newline at end of file diff --git a/include/TUDPServer.h b/include/TUDPServer.h index 481b553..7269e7f 100644 --- a/include/TUDPServer.h +++ b/include/TUDPServer.h @@ -9,7 +9,7 @@ class TUDPServer : public IThreaded { public: - explicit TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor); + explicit TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCPServer); void operator()() override; @@ -17,10 +17,10 @@ public: void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel); private: - void UDPParser(TClient& Client, std::string Packet); - TServer& mServer; TPPSMonitor& mPPSMonitor; - SOCKET mUDPSock; + TTCPServer& mTCPServer; + SOCKET mUDPSock {}; + std::string UDPRcvFromClient(sockaddr_in& client) const; }; \ No newline at end of file diff --git a/src/Common.cpp b/src/Common.cpp index 81bf7b8..190b576 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -11,7 +11,7 @@ std::unique_ptr Application::mConsole = std::make_unique(); void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) { std::unique_lock Lock(mShutdownHandlersMutex); if (Handler) { - mShutdownHandlers.push_back(Handler); + mShutdownHandlers.push_front(Handler); } } diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index e657cd5..a2f4dfc 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -5,8 +5,10 @@ namespace fs = std::filesystem; -TLuaEngine::TLuaEngine(TServer& Server) - : mServer(Server) { +TLuaEngine::TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPServer) + : mTCPServer(TCPServer) + , mUDPServer(UDPServer) + , mServer(Server) { if (!fs::exists(Application::Settings.ResourceFolder)) { fs::create_directory(Application::Settings.ResourceFolder); } diff --git a/src/TLuaFile.cpp b/src/TLuaFile.cpp index 39328c4..8b6ef32 100644 --- a/src/TLuaFile.cpp +++ b/src/TLuaFile.cpp @@ -4,6 +4,8 @@ #include "CustomAssert.h" #include "TLuaEngine.h" #include "TServer.h" +#include "TTCPServer.h" +#include "TUDPServer.h" #include #include @@ -68,11 +70,11 @@ std::any FutureWait(TLuaFile* lua, const std::string& R, std::shared_ptr arg, bool Wait) { +std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr arg, bool Wait) { std::any R; std::string Type; int Ret = 0; - for (auto& Script : Engine.LuaFiles()) { + for (auto& Script : Engine().LuaFiles()) { if (Script->IsRegistered(Event)) { if (local) { if (Script->GetPluginName() == Caller->GetPluginName()) { @@ -139,7 +141,7 @@ int lua_TriggerEventL(lua_State* L) { TLuaFile& Script = MaybeScript.value(); if (Args > 0) { if (lua_isstring(L, 1)) { - TriggerLuaEvent(Engine(), lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false); + TriggerLuaEvent(lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false); } else SendError(Engine(), L, ("TriggerLocalEvent wrong argument [1] need string")); } else { @@ -155,7 +157,7 @@ int lua_TriggerEventG(lua_State* L) { TLuaFile& Script = MaybeScript.value(); if (Args > 0) { if (lua_isstring(L, 1)) { - TriggerLuaEvent(Engine(), lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false); + TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false); } else SendError(Engine(), L, ("TriggerGlobalEvent wrong argument [1] need string")); } else @@ -356,7 +358,7 @@ int lua_dropPlayer(lua_State* L) { Reason = std::string((" Reason : ")) + lua_tostring(L, 2); } auto c = MaybeClient.value().lock(); - Respond(c, "C:Server:You have been Kicked from the server! " + Reason, true); + Engine().TCPServer().Respond(*c, "C:Server:You have been Kicked from the server! " + Reason, true); c->SetStatus(-2); info(("Closing socket due to kick")); CloseSocketProper(c->GetTCPSock()); @@ -370,7 +372,7 @@ int lua_sendChat(lua_State* L) { int ID = int(lua_tointeger(L, 1)); if (ID == -1) { std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2)); - SendToAll(nullptr, Packet, true, true); + Engine().UDPServer().SendToAll(nullptr, Packet, true, true); } else { auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) { @@ -378,7 +380,7 @@ int lua_sendChat(lua_State* L) { if (!c->IsSynced()) return 0; std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2)); - Respond(c, Packet, true); + Engine().TCPServer().Respond(*c, Packet, true); } else SendError(Engine(), L, ("SendChatMessage invalid argument [1] invalid ID")); } @@ -405,7 +407,7 @@ int lua_RemoveVehicle(lua_State* L) { auto c = MaybeClient.value().lock(); if (!c->GetCarData(VID).empty()) { std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID); - SendToAll(nullptr, Destroy, true, true); + Engine().UDPServer().SendToAll(nullptr, Destroy, true, true); c->DeleteCar(VID); } } else @@ -437,7 +439,7 @@ int lua_RemoteEvent(lua_State* L) { int ID = int(lua_tointeger(L, 1)); std::string Packet = "E:" + std::string(lua_tostring(L, 2)) + ":" + std::string(lua_tostring(L, 3)); if (ID == -1) - SendToAll(nullptr, Packet, true, true); + Engine().UDPServer().SendToAll(nullptr, Packet, true, true); else { auto MaybeClient = GetClient(Engine().Server(), ID); if (!MaybeClient || MaybeClient.value().expired()) { @@ -445,7 +447,7 @@ int lua_RemoteEvent(lua_State* L) { return 0; } auto c = MaybeClient.value().lock(); - Respond(c, Packet, true); + Engine().TCPServer().Respond(*c, Packet, true); } return 0; } diff --git a/src/TServer.cpp b/src/TServer.cpp index e6ba42c..b1dec53 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -1,6 +1,17 @@ #include "TServer.h" #include "Client.h" #include "Common.h" +#include "TPPSMonitor.h" +#include "TTCPServer.h" +#include "TUDPServer.h" +#include +#include +#include + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" +namespace json = rapidjson; TServer::TServer(int argc, char** argv) { info("BeamMP Server running version " + Application::ServerVersion()); @@ -47,3 +58,214 @@ size_t TServer::ClientCount() const { ReadLock Lock(mClientsMutex); return mClients.size(); } + +void TServer::GlobalParser(std::weak_ptr Client, std::string Packet, TPPSMonitor& PPSMonitor, TUDPServer& UDPServer, TTCPServer& TCPServer) { + if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) { + abort(); + } + if (Packet.substr(0, 4) == "ABG:") { + Packet = DeComp(Packet.substr(4)); + } + if (Packet.empty()) { + return; + } + + if (Client.expired()) { + return; + } + auto LockedClient = Client.lock(); + + std::any Res; + char Code = Packet.at(0); + + //V to Z + if (Code <= 90 && Code >= 86) { + PPSMonitor.IncrementInternalPPS(); + UDPServer.SendToAll(LockedClient.get(), Packet, false, false); + return; + } + switch (Code) { + case 'H': // initial connection +#ifdef DEBUG + debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")"); +#endif + TCPServer.SyncClient(Client); + return; + case 'p': + TCPServer.Respond(*LockedClient, ("p"), false); + TCPServer.UpdatePlayers(); + return; + case 'O': + if (Packet.length() > 1000) { + debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.length())); + } + ParseVehicle(*LockedClient, Packet, TCPServer, UDPServer); + return; + case 'J': +#ifdef DEBUG + debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + UDPServer.SendToAll(LockedClient.get(), Packet, false, true); + return; + case 'C': +#ifdef DEBUG + debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos) + break; + Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique(TLuaArg { { LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true); + if (std::any_cast(Res)) + break; + UDPServer.SendToAll(nullptr, Packet, true, true); + return; + case 'E': +#ifdef DEBUG + debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + HandleEvent(*LockedClient, Packet); + return; + default: + return; + } +} + +void TServer::HandleEvent(TClient& c, const std::string& Data) { + std::stringstream ss(Data); + std::string t, Name; + int a = 0; + while (std::getline(ss, t, ':')) { + switch (a) { + case 1: + Name = t; + break; + case 2: + TriggerLuaEvent(Name, false, nullptr, std::make_unique(TLuaArg { { c.GetID(), t } }), false); + break; + default: + break; + } + if (a == 2) + break; + a++; + } +} + +void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPServer, TUDPServer& UDPServer) { + if (Pckt.length() < 4) + return; + std::string Packet = Pckt; + char Code = Packet.at(1); + int PID = -1; + int VID = -1; + std::string Data = Packet.substr(3), pid, vid; + switch (Code) { //Spawned Destroyed Switched/Moved NotFound Reset + case 's': +#ifdef DEBUG + debug(std::string(("got 'Os' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + if (Data.at(0) == '0') { + int CarID = c.GetOpenCarID(); + debug(c.GetName() + (" created a car with ID ") + std::to_string(CarID)); + Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + Packet.substr(4); + auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true); + if (c.GetCarCount() >= Application::Settings.MaxCars || std::any_cast(Res)) { + TCPServer.Respond(c, Packet, true); + std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(CarID); + TCPServer.Respond(c, Destroy, true); + debug(c.GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID)); + } else { + c.AddNewCar(CarID, Packet); + UDPServer.SendToAll(nullptr, Packet, true, true); + } + } + return; + case 'c': +#ifdef DEBUG + debug(std::string(("got 'Oc' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + pid = Data.substr(0, Data.find('-')); + vid = Data.substr(Data.find('-') + 1, Data.find(':', 1) - Data.find('-') - 1); + if (pid.find_first_not_of("0123456789") == std::string::npos && vid.find_first_not_of("0123456789") == std::string::npos) { + PID = stoi(pid); + VID = stoi(vid); + } + if (PID != -1 && VID != -1 && PID == c.GetID()) { + auto Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr, + std::make_unique(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }), + true); + if (!std::any_cast(Res)) { + UDPServer.SendToAll(&c, Packet, false, true); + Apply(c, VID, Packet); + } else { + std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID); + TCPServer.Respond(c, Destroy, true); + c.DeleteCar(VID); + } + } + return; + case 'd': +#ifdef DEBUG + debug(std::string(("got 'Od' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + pid = Data.substr(0, Data.find('-')); + vid = Data.substr(Data.find('-') + 1); + if (pid.find_first_not_of("0123456789") == std::string::npos && vid.find_first_not_of("0123456789") == std::string::npos) { + PID = stoi(pid); + VID = stoi(vid); + } + if (PID != -1 && VID != -1 && PID == c.GetID()) { + UDPServer.SendToAll(nullptr, Packet, true, true); + TriggerLuaEvent(("onVehicleDeleted"), false, nullptr, + std::make_unique(TLuaArg { { c.GetID(), VID } }), false); + c.DeleteCar(VID); + debug(c.GetName() + (" deleted car with ID ") + std::to_string(VID)); + } + return; + case 'r': +#ifdef DEBUG + debug(std::string(("got 'Or' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + UDPServer.SendToAll(&c, Packet, false, true); + return; + case 't': +#ifdef DEBUG + debug(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); +#endif + UDPServer.SendToAll(&c, Packet, false, true); + return; + default: +#ifdef DEBUG + warn(std::string(("possibly not implemented: '") + Packet + ("' (") + std::to_string(Packet.size()) + (")"))); +#endif // DEBUG + return; + } +} + +void TServer::Apply(TClient& c, int VID, const std::string& pckt) { + std::string Packet = pckt.substr(pckt.find('{')), VD = c.GetCarData(VID); + std::string Header = VD.substr(0, VD.find('{')); + VD = VD.substr(VD.find('{')); + rapidjson::Document Veh, Pack; + Veh.Parse(VD.c_str()); + if (Veh.HasParseError()) { + error("Could not get vehicle config!"); + return; + } + Pack.Parse(Packet.c_str()); + if (Pack.HasParseError() || Pack.IsNull()) { + error("Could not get active vehicle config!"); + return; + } + + for (auto& M : Pack.GetObject()) { + if (Veh[M.name].IsNull()) { + Veh.AddMember(M.name, M.value, Veh.GetAllocator()); + } else { + Veh[M.name] = Pack[M.name]; + } + } + rapidjson::StringBuffer Buffer; + rapidjson::Writer writer(Buffer); + Veh.Accept(writer); + c.SetCarData(VID, Header + Buffer.GetString()); +} diff --git a/src/TTCPServer.cpp b/src/TTCPServer.cpp index de3b281..5edf3ab 100644 --- a/src/TTCPServer.cpp +++ b/src/TTCPServer.cpp @@ -1,5 +1,644 @@ #include "TTCPServer.h" +#include "TLuaEngine.h" +#include "TLuaFile.h" +#include "TResourceManager.h" +#include "TUDPServer.h" +#include +#include +#include -TTCPServer::TTCPServer(TServer& Server) - : mServer(Server) { +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" +namespace json = rapidjson; + +bool TCPSend(std::weak_ptr c, const std::string& Data); +bool TCPSend(TClient& c, const std::string& Data); + +TTCPServer::TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager) + : mServer(Server) + , mPPSMonitor(PPSMonitor) + , mResourceManager(ResourceManager) { + Application::RegisterShutdownHandler([this] { mShutdown = true; }); +} + +void TTCPServer::Identify(SOCKET TCPSock) { + char Code; + if (recv(TCPSock, &Code, 1, 0) != 1) { + CloseSocketProper(TCPSock); + return; + } + if (Code == 'C') { + Authentication(TCPSock); + } else if (Code == 'D') { + HandleDownload(TCPSock); + } else { + CloseSocketProper(TCPSock); + } +} + +void TTCPServer::HandleDownload(SOCKET TCPSock) { + char D; + if (recv(TCPSock, &D, 1, 0) != 1) { + CloseSocketProper(TCPSock); + return; + } + auto ID = uint8_t(D); + mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { + if (!ClientPtr.expired()) { + auto c = ClientPtr.lock(); + if (c->GetID() == ID) { + c->SetDownSock(TCPSock); + } + } + return true; + }); +} + +void TTCPServer::Authentication(SOCKET TCPSock) { + auto c = CreateClient(TCPSock); + + std::string Rc; + info("Identifying new client..."); + + Assert(!c.expired()); + + auto LockedClient = c.lock(); + Rc = TCPRcv(*LockedClient); + + if (Rc.size() > 3 && Rc.substr(0, 2) == "VC") { + Rc = Rc.substr(2); + if (Rc.length() > 4 || Rc != Application::ClientVersion()) { + ClientKick(*LockedClient, "Outdated Version!"); + return; + } + } else { + ClientKick(*LockedClient, "Invalid version header!"); + return; + } + TCPSend(*LockedClient, "S"); + + Rc = TCPRcv(*LockedClient); + + if (Rc.size() > 50) { + ClientKick(*LockedClient, "Invalid Key!"); + return; + } + + if (!Rc.empty()) { + Rc = Http::POST("auth.beammp.com", "/pkToUser", {}, R"({"key":")" + Rc + "\"}", true); + } + + json::Document AuthResponse; + AuthResponse.Parse(Rc.c_str()); + if (Rc == "-1" || AuthResponse.HasParseError()) { + ClientKick(*LockedClient, "Invalid key! Please restart your game."); + return; + } + + if (AuthResponse["username"].IsString() && AuthResponse["roles"].IsString() && AuthResponse["guest"].IsBool()) { + LockedClient->SetName(AuthResponse["username"].GetString()); + LockedClient->SetRoles(AuthResponse["roles"].GetString()); + LockedClient->SetIsGuest(AuthResponse["guest"].GetBool()); + } else { + ClientKick(*LockedClient, "Invalid authentication data!"); + return; + } + + debug("Name -> " + LockedClient->GetName() + ", Guest -> " + std::to_string(LockedClient->IsGuest()) + ", Roles -> " + LockedClient->GetRoles()); + mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { + if (!ClientPtr.expired()) { + auto Cl = ClientPtr.lock(); + if (Cl->GetName() == LockedClient->GetName() && Cl->IsGuest() == LockedClient->IsGuest()) { + info("Old client (" + Cl->GetName() + ") kicked: Reconnecting"); + CloseSocketProper(Cl->GetTCPSock()); + Cl->SetStatus(-2); + return false; + } + return true; + } + }); + + auto arg = std::make_unique(TLuaArg { { LockedClient->GetName(), LockedClient->GetRoles(), LockedClient->IsGuest() } }); + std::any Res = TriggerLuaEvent("onPlayerAuth", false, nullptr, std::move(arg), true); + std::string Type = Res.type().name(); + if (Type.find("int") != std::string::npos && std::any_cast(Res)) { + ClientKick(*LockedClient, "you are not allowed on the server!"); + return; + } else if (Type.find("string") != std::string::npos) { + ClientKick(*LockedClient, std::any_cast(Res)); + return; + } + + if (mServer.ClientCount() < size_t(Application::Settings.MaxPlayers)) { + info("Identification success"); + TCPClient(c); + } else + ClientKick(*LockedClient, "Server full!"); +} + +std::weak_ptr TTCPServer::CreateClient(SOCKET TCPSock) { + auto c = mServer.InsertNewClient(); + c.lock()->SetTCPSock(TCPSock); + return c; +} + +bool TTCPServer::TCPSend(TClient& c, const std::string& Data) { + int32_t Size, Sent; + std::string Send(4, 0); + Size = int32_t(Data.size()); + memcpy(&Send[0], &Size, sizeof(Size)); + Send += Data; + Sent = 0; + Size += 4; + do { + int32_t Temp = send(c.GetTCPSock(), &Send[Sent], Size - Sent, 0); + if (Temp == 0) { + if (c.GetStatus() > -1) + c.SetStatus(-1); + return false; + } else if (Temp < 0) { + if (c.GetStatus() > -1) + c.SetStatus(-1); + CloseSocketProper(c.GetTCPSock()); + return false; + } + Sent += Temp; + } while (Sent < Size); + return true; +} + +bool TTCPServer::CheckBytes(TClient& c, int32_t BytesRcv) { + if (BytesRcv == 0) { + debug("(TCP) Connection closing..."); + if (c.GetStatus() > -1) + c.SetStatus(-1); + return false; + } else if (BytesRcv < 0) { +#ifdef WIN32 + debug(("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError())); +#else // unix + debug(("(TCP) recv failed with error: ") + std::string(strerror(errno))); +#endif // WIN32 + if (c.GetStatus() > -1) + c.SetStatus(-1); + info(("Closing socket in CheckBytes, BytesRcv < 0")); + CloseSocketProper(c.GetTCPSock()); + return false; + } + return true; +} + +std::string TTCPServer::TCPRcv(TClient& c) { + int32_t Header, BytesRcv = 0, Temp; + if (c.GetStatus() < 0) + return ""; + + std::vector Data(sizeof(Header)); + do { + Temp = recv(c.GetTCPSock(), &Data[BytesRcv], 4 - BytesRcv, 0); + if (!CheckBytes(c, Temp)) { +#ifdef DEBUG + error(std::string(__func__) + (": failed on CheckBytes in while(BytesRcv < 4)")); +#endif // DEBUG + return ""; + } + BytesRcv += Temp; + } while (size_t(BytesRcv) < sizeof(Header)); + memcpy(&Header, &Data[0], sizeof(Header)); + +#ifdef DEBUG + //debug(std::string(__func__) + (": expecting ") + std::to_string(Header) + (" bytes.")); +#endif // DEBUG + if (!CheckBytes(c, BytesRcv)) { +#ifdef DEBUG + error(std::string(__func__) + (": failed on CheckBytes")); +#endif // DEBUG + return ""; + } + Data.resize(Header); + BytesRcv = 0; + do { + Temp = recv(c.GetTCPSock(), &Data[BytesRcv], Header - BytesRcv, 0); + if (!CheckBytes(c, Temp)) { +#ifdef DEBUG + error(std::string(__func__) + (": failed on CheckBytes in while(BytesRcv < Header)")); +#endif // DEBUG + + return ""; + } +#ifdef DEBUG + //debug(std::string(__func__) + (": Temp: ") + std::to_string(Temp) + (", BytesRcv: ") + std::to_string(BytesRcv)); +#endif // DEBUG + BytesRcv += Temp; + } while (BytesRcv < Header); +#ifdef DEBUG + //debug(std::string(__func__) + (": finished recv with Temp: ") + std::to_string(Temp) + (", BytesRcv: ") + std::to_string(BytesRcv)); +#endif // DEBUG + std::string Ret(Data.data(), Header); + + if (Ret.substr(0, 4) == "ABG:") { + Ret = DeComp(Ret.substr(4)); + } +#ifdef DEBUG + //debug("Parsing from " + c->GetName() + " -> " +std::to_string(Ret.size())); +#endif + + return Ret; +} + +void TTCPServer::ClientKick(TClient& c, const std::string& R) { + info("Client kicked: " + R); + TCPSend(c, "E" + R); + CloseSocketProper(c.GetTCPSock()); +} + +void TTCPServer::TCPClient(std::weak_ptr c) { + // TODO: the c.expired() might cause issues here, remove if you end up here with your debugger + if (c.expired() || c.lock()->GetTCPSock() == -1) { + mServer.RemoveClient(c); + return; + } + OnConnect(c); + while (true) { + if (c.expired()) + break; + auto Client = c.lock(); + if (Client->GetStatus() <= -1) { + break; + } + TServer::GlobalParser(c, TCPRcv(*Client), mPPSMonitor, UDPServer(), *this); + } + if (!c.expired()) { + auto Client = c.lock(); + OnDisconnect(c, Client->GetStatus() == -2); + } else { + warn("client expired in TCPClient, should never happen"); + } +} + +void TTCPServer::UpdatePlayers() { + 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()) { + auto c = ClientPtr.lock(); + Packet += c->GetName() + ","; + } + }); + Packet = Packet.substr(0, Packet.length() - 1); + UDPServer().SendToAll(nullptr, Packet, true, true); +} + +void TTCPServer::OnDisconnect(std::weak_ptr ClientPtr, bool kicked) { + Assert(!ClientPtr.expired()); + auto LockedClientPtr = ClientPtr.lock(); + TClient& c = *LockedClientPtr; + info(c.GetName() + (" Connection Terminated")); + std::string Packet; + for (auto& v : c.GetAllCars()) { + if (v != nullptr) { + Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v->ID()); + UDPServer().SendToAll(&c, Packet, false, true); + } + } + if (kicked) + Packet = ("L") + c.GetName() + (" was kicked!"); + else + Packet = ("L") + c.GetName() + (" left the server!"); + UDPServer().SendToAll(&c, Packet, false, true); + Packet.clear(); + TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique(TLuaArg { { c.GetID() } }), false); + if (c.GetTCPSock()) + CloseSocketProper(c.GetTCPSock()); + if (c.GetDownSock()) + CloseSocketProper(c.GetDownSock()); + mServer.RemoveClient(ClientPtr); +} + +int TTCPServer::OpenID() { + int ID = 0; + bool found; + do { + found = true; + mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { + if (!ClientPtr.expired()) { + auto c = ClientPtr.lock(); + if (c->GetID() == ID) { + found = false; + ID++; + } + return true; + } + }); + } while (!found); + return ID; +} + +void TTCPServer::OnConnect(std::weak_ptr c) { + Assert(!c.expired()); + info("Client connected"); + auto LockedClient = c.lock(); + LockedClient->SetID(OpenID()); + info("Assigned ID " + std::to_string(LockedClient->GetID()) + " to " + LockedClient->GetName()); + TriggerLuaEvent("onPlayerConnecting", false, nullptr, std::make_unique(TLuaArg { { LockedClient->GetID() } }), false); + SyncResources(*LockedClient); + if (LockedClient->GetStatus() < 0) + return; + Respond(*LockedClient, "M" + Application::Settings.MapName, true); //Send the Map on connect + info(LockedClient->GetName() + " : Connected"); + TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique(TLuaArg { { LockedClient->GetID() } }), false); +} + +void TTCPServer::SyncResources(TClient& c) { +#ifndef DEBUG + try { +#endif + TCPSend(c, "P" + std::to_string(c.GetID())); + std::string Data; + while (c.GetStatus() > -1) { + Data = TCPRcv(c); + if (Data == "Done") + break; + Parse(c, Data); + } +#ifndef DEBUG + } catch (std::exception& e) { + except("Exception! : " + std::string(e.what())); + c->SetStatus(-1); + } +#endif +} + +void TTCPServer::Parse(TClient& c, const std::string& Packet) { + if (Packet.empty()) + return; + char Code = Packet.at(0), SubCode = 0; + if (Packet.length() > 1) + SubCode = Packet.at(1); + switch (Code) { + case 'f': + SendFile(c, Packet.substr(1)); + return; + case 'S': + if (SubCode == 'R') { + debug("Sending Mod Info"); + std::string ToSend = mResourceManager.FileList() + mResourceManager.FileSizes(); + if (ToSend.empty()) + ToSend = "-"; + TCPSend(c, ToSend); + } + return; + default: + return; + } +} + +void TTCPServer::SendFile(TClient& c, const std::string& Name) { + info(c.GetName() + " requesting : " + Name.substr(Name.find_last_of('/'))); + + if (!std::filesystem::exists(Name)) { + TCPSend(c, "CO"); + warn("File " + Name + " could not be accessed!"); + return; + } else + TCPSend(c, "AG"); + + ///Wait for connections + int T = 0; + while (c.GetDownSock() < 1 && T < 50) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + T++; + } + + if (c.GetDownSock() < 1) { + error("Client doesn't have a download socket!"); + if (c.GetStatus() > -1) + c.SetStatus(-1); + return; + } + + int64_t Size = std::filesystem::file_size(Name), MSize = Size / 2; + + std::thread SplitThreads[2] { + std::thread([&] { + SplitLoad(c, 0, MSize, false, Name); + }), + std::thread([&] { + SplitLoad(c, MSize, Size, true, Name); + }) + }; + + for (auto& SplitThread : SplitThreads) { + if (SplitThread.joinable()) { + SplitThread.join(); + } + } +} + +void TTCPServer::SplitLoad(TClient& c, int64_t Sent, int64_t Size, bool D, const std::string& Name) { + std::ifstream f(Name.c_str(), std::ios::binary); + int32_t Split = 0x7735940; //125MB + char* Data; + if (Size > Split) + Data = new char[Split]; + else + Data = new char[Size]; + SOCKET TCPSock; + if (D) + TCPSock = c.GetDownSock(); + else + TCPSock = c.GetTCPSock(); + info("Split load Socket " + std::to_string(TCPSock)); + while (c.GetStatus() > -1 && Sent < Size) { + int64_t Diff = Size - Sent; + if (Diff > Split) { + f.seekg(Sent, std::ios_base::beg); + f.read(Data, Split); + if (!TCPSendRaw(TCPSock, Data, Split)) { + if (c.GetStatus() > -1) + c.SetStatus(-1); + break; + } + Sent += Split; + } else { + f.seekg(Sent, std::ios_base::beg); + f.read(Data, Diff); + if (!TCPSendRaw(TCPSock, Data, int32_t(Diff))) { + if (c.GetStatus() > -1) + c.SetStatus(-1); + break; + } + Sent += Diff; + } + } + delete[] Data; + f.close(); +} + +bool TTCPServer::TCPSendRaw(SOCKET C, char* Data, int32_t Size) { + int64_t Sent = 0; + do { + int64_t Temp = send(C, &Data[Sent], int(Size - Sent), 0); + if (Temp < 1) { + info("Socket Closed! " + std::to_string(C)); + CloseSocketProper(C); + return false; + } + Sent += Temp; + } while (Sent < Size); + return true; +} + +void TTCPServer::SendLarge(TClient& c, std::string Data) { + if (Data.length() > 400) { + std::string CMP(Comp(Data)); + Data = "ABG:" + CMP; + } + TCPSend(c, Data); +} + +void TTCPServer::Respond(TClient& c, const std::string& MSG, bool Rel) { + char C = MSG.at(0); + if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { + if (C == 'O' || C == 'T' || MSG.length() > 1000) { + SendLarge(c, MSG); + } else { + TCPSend(c, MSG); + } + } else { + UDPServer().UDPSend(c, MSG); + } +} + +void TTCPServer::SyncClient(std::weak_ptr c) { + if (c.expired()) { + return; + } + auto LockedClient = c.lock(); + if (LockedClient->IsSynced()) + return; + LockedClient->SetIsSynced(true); + std::this_thread::sleep_for(std::chrono::seconds(1)); + Respond(*LockedClient, ("Sn") + LockedClient->GetName(), true); + UDPServer().SendToAll(LockedClient.get(), ("JWelcome ") + LockedClient->GetName() + "!", false, true); + TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique(TLuaArg { { LockedClient->GetID() } }), false); + bool Return = false; + mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { + if (!ClientPtr.expired()) { + auto client = ClientPtr.lock(); + if (client != LockedClient) { + for (auto& v : LockedClient->GetAllCars()) { + if (v != nullptr) { + if (LockedClient->GetStatus() < 0) { + Return = true; + return false; + } + Respond(*LockedClient, v->Data(), true); + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + } + } + } + return true; + }); + if (Return) { + return; + } + info(LockedClient->GetName() + (" is now synced!")); +} + +void TTCPServer::SetUDPServer(TUDPServer& UDPServer) { + mUDPServer = std::ref(UDPServer); +} + +void TTCPServer::operator()() { + while (!mUDPServer.has_value()) { + // hard spin + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +#ifdef WIN32 + WSADATA wsaData; + if (WSAStartup(514, &wsaData)) { + error("Can't start Winsock!"); + return; + } + SOCKET client, Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + sockaddr_in addr {}; + addr.sin_addr.S_un.S_addr = ADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = htons(Application::Settings.Port); + if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { + error("Can't bind socket! " + std::to_string(WSAGetLastError())); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(-1); + } + if (Listener == -1) { + error("Invalid listening socket"); + return; + } + if (listen(Listener, SOMAXCONN)) { + error("listener failed " + std::to_string(GetLastError())); + return; + } + info("Vehicle event network online"); + do { + try { + client = accept(Listener, nullptr, nullptr); + if (client == -1) { + warn("Got an invalid client socket on connect! Skipping..."); + continue; + } + std::thread ID(&TTCPServer::Identify, this, client); + ID.detach(); + } catch (const std::exception& e) { + error("fatal: " + std::string(e.what())); + } + } while (client); + + CloseSocketProper(client); + WSACleanup(); +#else // unix + // wondering why we need slightly different implementations of this? + // ask ms. + SOCKET client = -1; + SOCKET Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + int optval = 1; + setsockopt(Listener, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); + // TODO: check optval or return value idk + sockaddr_in addr {}; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = htons(uint16_t(Application::Settings.Port)); + if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) { + error(("Can't bind socket! ") + std::string(strerror(errno))); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(-1); + } + if (Listener == -1) { + error(("Invalid listening socket")); + return; + } + if (listen(Listener, SOMAXCONN)) { + error(("listener failed ") + std::string(strerror(errno))); + return; + } + info(("Vehicle event network online")); + do { + try { + client = accept(Listener, nullptr, nullptr); + if (client == -1) { + warn(("Got an invalid client socket on connect! Skipping...")); + continue; + } + std::thread ID(&TTCPServer::Identify, this, client); + ID.detach(); + } catch (const std::exception& e) { + error(("fatal: ") + std::string(e.what())); + } + } while (client && !mShutdown); + + debug("all ok, arrived at " + std::string(__func__) + ":" + std::to_string(__LINE__)); + + CloseSocketProper(client); +#endif } diff --git a/src/TUDPServer.cpp b/src/TUDPServer.cpp index a99bdc3..59b7195 100644 --- a/src/TUDPServer.cpp +++ b/src/TUDPServer.cpp @@ -1,11 +1,14 @@ #include "TUDPServer.h" #include "CustomAssert.h" +#include "TTCPServer.h" #include #include +#include -TUDPServer::TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor) +TUDPServer::TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCPServer) : mServer(Server) - , mPPSMonitor(PPSMonitor) { + , mPPSMonitor(PPSMonitor) + , mTCPServer(TCPServer) { } void TUDPServer::operator()() { @@ -65,8 +68,8 @@ void TUDPServer::operator()() { auto Client = ClientPtr.lock(); if (Client->GetID() == ID) { Client->SetUDPAddr(client); - Client->SetConnected(true); - UDPParser(*Client, Data.substr(2)); + Client->SetIsConnected(true); + TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this, mTCPServer); } } return true; @@ -76,69 +79,6 @@ void TUDPServer::operator()() { } } } -void TUDPServer::UDPParser(TClient& Client, std::string Packet) { - if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) { - abort(); - } - if (Packet.substr(0, 4) == "ABG:") { - Packet = DeComp(Packet.substr(4)); - } - if (Packet.empty()) { - return; - } - std::any Res; - char Code = Packet.at(0); - - //V to Z - if (Code <= 90 && Code >= 86) { - mPPSMonitor.IncrementInternalPPS(); - SendToAll(&Client, Packet, false, false); - return; - } - switch (Code) { - case 'H': // initial connection -#ifdef DEBUG - debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")"); -#endif - SyncClient(Client); - return; - case 'p': - Respond(Client, ("p"), false); - UpdatePlayers(); - return; - case 'O': - if (Packet.length() > 1000) { - debug(("Received data from: ") + Client->GetName() + (" Size: ") + std::to_string(Packet.length())); - } - ParseVeh(Client, Packet); - return; - case 'J': -#ifdef DEBUG - debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); -#endif - SendToAll(Client, Packet, false, true); - return; - case 'C': -#ifdef DEBUG - debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); -#endif - if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos) - break; - Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique(LuaArg { { Client->GetID(), Client->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true); - if (std::any_cast(Res)) - break; - SendToAll(nullptr, Packet, true, true); - return; - case 'E': -#ifdef DEBUG - debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); -#endif - HandleEvent(Client, Packet); - return; - default: - return; - } -} void TUDPServer::SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel) { if (!Self) @@ -151,9 +91,9 @@ void TUDPServer::SendToAll(TClient* c, const std::string& Data, bool Self, bool if (Client->IsSynced()) { if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { if (C == 'O' || C == 'T' || Data.length() > 1000) - SendLarge(*Client, Data); + mTCPServer.SendLarge(*Client, Data); else - TCPSend(*Client, Data); + mTCPServer.TCPSend(*Client, Data); } else UDPSend(*Client, Data); } diff --git a/src/main.cpp b/src/main.cpp index e64b4a1..daa9357 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,16 @@ -#include "Client.h" #include "Common.h" -#include "IThreaded.h" #include "TConfig.h" -#include "TConsole.h" #include "THeartbeatThread.h" #include "TLuaEngine.h" +#include "TPPSMonitor.h" #include "TResourceManager.h" #include "TServer.h" -#include "TPPSMonitor.h" #include "TUDPServer.h" -#include -#include #include #include #ifdef __unix +#include #include void UnixSignalHandler(int sig) { @@ -45,18 +41,20 @@ int main(int argc, char** argv) { signal(SIGINT, UnixSignalHandler); #endif // __unix + bool Shutdown = false; + Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; }); + TServer Server(argc, argv); [[maybe_unused]] TConfig Config("Server.cfg"); TResourceManager ResourceManager; - [[maybe_unused]] TPPSMonitor PPSMonitor(Server); + TPPSMonitor PPSMonitor(Server); THeartbeatThread Heartbeat(ResourceManager, Server); - TTCPServer TCPServer(Server); - TUDPServer UDPServer(Server, PPSMonitor); - TLuaEngine LuaEngine(Server); + TTCPServer TCPServer(Server, PPSMonitor, ResourceManager); + TUDPServer UDPServer(Server, PPSMonitor, TCPServer); + TCPServer.SetUDPServer(UDPServer); + TLuaEngine LuaEngine(Server, TCPServer, UDPServer); // TODO: replace - bool Shutdown = false; - Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; }); while (!Shutdown) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }