diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..edc3926 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "commandline"] + path = commandline + url = https://github.com/lionkor/commandline +[submodule "include/commandline"] + path = include/commandline + url = https://github.com/lionkor/commandline diff --git a/CMakeLists.txt b/CMakeLists.txt index b77e4be..b4d50fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,16 +4,13 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +add_subdirectory("include/commandline") + if (UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -g") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -fno-builtin") elseif (WIN32) - # This might cause issues with old windows headers, but it's worth the trouble to keep the code - # completely cross platform. For fixes to common issues arising from /permissive- visit: - # https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance - - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /permissive-") message(STATUS "MSVC -> forcing use of statically-linked runtime.") STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) @@ -22,10 +19,13 @@ endif () find_package(Boost REQUIRED COMPONENTS system thread) -file(GLOB source_files "src/*.cpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "src/*/*.cpp") -add_executable(BeamMP-Server ${source_files}) +add_executable(BeamMP-Server + src/main.cpp + src/TConsole.cpp + src/Compat.cpp +) -target_include_directories(BeamMP-Server PUBLIC $) +target_include_directories(BeamMP-Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/commandline") find_package(Lua REQUIRED) target_include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${LUA_INCLUDE_DIR}) @@ -33,11 +33,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}) + target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} dl crypto ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} commandline) 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}) + target_link_libraries(BeamMP-Server PRIVATE ws2_32 ZLIB::ZLIB ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} commandline) endif () diff --git a/include/Client.hpp b/include/Client.hpp deleted file mode 100644 index c3f64f9..0000000 --- a/include/Client.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/8/2020 -/// - -#pragma once -#ifdef WIN32 -#include -#else -#include -#define SOCKET int -#endif -#include "CustomAssert.h" -#include -#include -#include -#include -#include - -struct VData { - int ID = -1; - std::string Data; -}; - -class Client { -private: - std::set> VehicleData; //ID and Data; - std::string Name = "Unknown Client"; - SOCKET SOCK[2] { SOCKET(-1) }; - sockaddr_in UDPADDR; - std::string Role; - std::string DID; - int Status = 0; - int ID = -1; - -public: - bool isConnected = false; - bool isSynced = false; - bool isGuest = false; - - void AddNewCar(int ident, const std::string& Data); - void SetCarData(int ident, const std::string& Data); - std::set>& GetAllCars(); - void SetName(const std::string& name) { Name = name; } - void SetRoles(const std::string& role) { Role = role; } - std::string GetCarData(int ident); - void SetUDPAddr(sockaddr_in Addr) { UDPADDR = Addr; } - void SetDownSock(SOCKET CSock) { SOCK[1] = CSock; } - void SetTCPSock(SOCKET CSock) { SOCK[0] = CSock; } - void SetStatus(int status) { Status = status; } - void DeleteCar(int ident); - sockaddr_in GetUDPAddr() { return UDPADDR; } - std::string GetRoles() { return Role; } - std::string GetName() { return Name; } - SOCKET GetDownSock() { return SOCK[1]; } - SOCKET GetTCPSock() { return SOCK[0]; } - void SetID(int ID) { this->ID = ID; } - int GetOpenCarID(); - int GetCarCount(); - void ClearCars(); - int GetStatus() { return Status; } - int GetID() { return ID; } -}; -struct ClientInterface { - std::set> Clients; - void RemoveClient(Client*& c) { - Assert(c); - c->ClearCars(); - auto Iter = std::find_if(Clients.begin(), Clients.end(), [&](auto& ptr) { - return c == ptr.get(); - }); - Assert(Iter != Clients.end()); - if (Iter == Clients.end()) { - return; - } - Clients.erase(Iter); - c = nullptr; - } - void AddClient(Client*&& c) { - Assert(c); - Clients.insert(std::unique_ptr(c)); - } - int Size() { - return int(Clients.size()); - } -}; - -extern std::unique_ptr CI; diff --git a/include/Compat.h b/include/Compat.h new file mode 100644 index 0000000..31fa8fa --- /dev/null +++ b/include/Compat.h @@ -0,0 +1,17 @@ +#pragma once + +// Unix - Win32 compatibility stuff +#ifdef WIN32 +#include +#include +#else // *nix +typedef unsigned long DWORD, *PDWORD, *LPDWORD; +#include +#include +#endif // WIN32 + +#ifndef WIN32 + +char _getch(void); + +#endif // !WIN32 diff --git a/include/Compressor.h b/include/Compressor.h deleted file mode 100644 index 3c2fe24..0000000 --- a/include/Compressor.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/24/2020 -/// -#pragma once -#include -std::string Comp(std::string Data); -std::string DeComp(std::string Compressed); diff --git a/include/Curl/Http.h b/include/Curl/Http.h deleted file mode 100644 index 714543d..0000000 --- a/include/Curl/Http.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/18/2020 -/// -#pragma once -#include -#include -std::string HttpRequest(const std::string& host, int port, const std::string& target); -std::string PostHTTP(const std::string& host, const std::string& target, const std::unordered_map& fields, const std::string& body, bool json); diff --git a/include/CustomAssert.h b/include/CustomAssert.h deleted file mode 100644 index 7144ddd..0000000 --- a/include/CustomAssert.h +++ /dev/null @@ -1,67 +0,0 @@ -// Author: lionkor - -/* - * Asserts are to be used anywhere where assumptions about state are made - * implicitly. AssertNotReachable is used where code should never go, like in - * default switch cases which shouldn't trigger. They make it explicit - * that a place cannot normally be reached and make it an error if they do. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include "Logger.h" - -static const char* const ANSI_RESET = "\u001b[0m"; - -static const char* const ANSI_BLACK = "\u001b[30m"; -static const char* const ANSI_RED = "\u001b[31m"; -static const char* const ANSI_GREEN = "\u001b[32m"; -static const char* const ANSI_YELLOW = "\u001b[33m"; -static const char* const ANSI_BLUE = "\u001b[34m"; -static const char* const ANSI_MAGENTA = "\u001b[35m"; -static const char* const ANSI_CYAN = "\u001b[36m"; -static const char* const ANSI_WHITE = "\u001b[37m"; - -static const char* const ANSI_BLACK_BOLD = "\u001b[30;1m"; -static const char* const ANSI_RED_BOLD = "\u001b[31;1m"; -static const char* const ANSI_GREEN_BOLD = "\u001b[32;1m"; -static const char* const ANSI_YELLOW_BOLD = "\u001b[33;1m"; -static const char* const ANSI_BLUE_BOLD = "\u001b[34;1m"; -static const char* const ANSI_MAGENTA_BOLD = "\u001b[35;1m"; -static const char* const ANSI_CYAN_BOLD = "\u001b[36;1m"; -static const char* const ANSI_WHITE_BOLD = "\u001b[37;1m"; - -static const char* const ANSI_BOLD = "\u001b[1m"; -static const char* const ANSI_UNDERLINE = "\u001b[4m"; - -#if DEBUG -inline void _assert([[maybe_unused]] const char* file, [[maybe_unused]] const char* function, [[maybe_unused]] unsigned line, - [[maybe_unused]] const char* condition_string, [[maybe_unused]] bool result) { - if (!result) { - std::cout << std::flush << "(debug build) TID " - << std::this_thread::get_id() << ": ASSERTION FAILED: at " - << file << ":" << line << " \n\t-> in " - << function << ", Line " << line << ": \n\t\t-> " - << "Failed Condition: " << condition_string << std::endl; - std::cout << "... terminating ..." << std::endl; - abort(); - } -} - -#define Assert(cond) _assert(__FILE__, __func__, __LINE__, #cond, (cond)) -#define AssertNotReachable() _assert(__FILE__, __func__, __LINE__, "reached unreachable code", false) -#else -// In release build, these macros turn into NOPs. The compiler will optimize these out. -#define Assert(x) \ - do { \ - } while (false) -#define AssertNotReachable() \ - do { \ - } while (false) -#endif // DEBUG diff --git a/include/IThreaded.h b/include/IThreaded.h new file mode 100644 index 0000000..27288eb --- /dev/null +++ b/include/IThreaded.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +// pure virtual class to be inherited from by classes which intend to be threaded +class IThreaded { +public: + IThreaded() + // invokes operator() on this object + : _Thread(std::thread([this] { (*this)(); })) { } + + virtual void operator()() = 0; + +protected: + std::thread _Thread; +}; diff --git a/include/Json.h b/include/Json.h deleted file mode 100644 index 839bba1..0000000 --- a/include/Json.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 11/27/2020 -/// -#pragma once -#include "rapidjson/document.h" -#include "rapidjson/stringbuffer.h" -#include "rapidjson/writer.h" -namespace json = rapidjson; \ No newline at end of file diff --git a/include/Logger.h b/include/Logger.h deleted file mode 100644 index 53beeec..0000000 --- a/include/Logger.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 4/2/2020. -/// -#pragma once - -#include -#include -#include -void InitLog(); -#define DebugPrintTID() DebugPrintTIDInternal(__func__, false) -void DebugPrintTIDInternal(const std::string& func, bool overwrite = true); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier -void ConsoleOut(const std::string& msg); -void except(const std::string& toPrint); -void debug(const std::string& toPrint); -void error(const std::string& toPrint); -void info(const std::string& toPrint); -void warn(const std::string& toPrint); diff --git a/include/Lua/LuaSystem.hpp b/include/Lua/LuaSystem.hpp deleted file mode 100644 index 0edfd9d..0000000 --- a/include/Lua/LuaSystem.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/20/2020 -/// - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; - -struct LuaArg { - std::vector args; - void PushArgs(lua_State* State) { - for (std::any arg : args) { - if (!arg.has_value()) - return; - std::string Type = arg.type().name(); - if (Type.find("bool") != std::string::npos) { - lua_pushboolean(State, std::any_cast(arg)); - } - if (Type.find("basic_string") != std::string::npos || Type.find("char") != std::string::npos) { - lua_pushstring(State, std::any_cast(arg).c_str()); - } - if (Type.find("int") != std::string::npos) { - lua_pushinteger(State, std::any_cast(arg)); - } - if (Type.find("float") != std::string::npos) { - lua_pushnumber(State, std::any_cast(arg)); - } - } - } -}; - -class Lua { -private: - std::set> _RegisteredEvents; - lua_State* luaState { nullptr }; - fs::file_time_type _LastWrote; - std::string _PluginName {}; - std::string _FileName {}; - bool _StopThread = false; - bool _Console = false; - -public: - void Init(); - void RegisterEvent(const std::string& Event, const std::string& FunctionName); - std::string GetRegistered(const std::string& Event) const; - void UnRegisterEvent(const std::string& Event); - void SetLastWrite(fs::file_time_type time); - bool IsRegistered(const std::string& Event); - void SetPluginName(const std::string& Name); - void Execute(const std::string& Command); - void SetFileName(const std::string& Name); - fs::file_time_type GetLastWrite(); - std::string GetPluginName() const; - std::string GetFileName() const; - lua_State* GetState(); - const lua_State* GetState() const; - std::string GetOrigin(); - std::mutex Lock; - void Reload(); - Lua(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote, bool Console = false); - Lua(bool Console = false); - ~Lua(); - void SetStopThread(bool StopThread) { _StopThread = StopThread; } - bool GetStopThread() const { return _StopThread; } -}; -std::any CallFunction(Lua* lua, const std::string& FuncName, std::shared_ptr args); -std::any TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::shared_ptr arg, bool Wait); -extern std::set> PluginEngine; diff --git a/include/Network.h b/include/Network.h deleted file mode 100644 index 15d6f4b..0000000 --- a/include/Network.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/31/2020 -/// -#pragma once -#include "Client.hpp" -#include -void TCPServerMain(); -void UpdatePlayers(); -void OnConnect(Client* c); -void TCPClient(Client* c); -std::string TCPRcv(Client* c); -void SyncResources(Client* c); -[[noreturn]] void UDPServerMain(); -void OnDisconnect(Client* c, bool kicked); -void UDPSend(Client* c, std::string Data); -void SendLarge(Client* c, std::string Data); -bool TCPSend(Client* c, const std::string& Data); -void GParser(Client* c, const std::string& Packet); -std::string StaticReason(bool Set, const std::string& R); -void Respond(Client* c, const std::string& MSG, bool Rel); -void SendToAll(Client* c, const std::string& Data, bool Self, bool Rel); diff --git a/include/RWMutex.h b/include/RWMutex.h deleted file mode 100644 index 5db780e..0000000 --- a/include/RWMutex.h +++ /dev/null @@ -1,19 +0,0 @@ -// Author: lionkor -#pragma once - -/* - * An RWMutex allows multiple simultaneous readlocks but only one writelock at a time, - * and write locks and read locks are mutually exclusive. - */ - -#include - -// Use ReadLock(m) and WriteLock(m) to lock it. -using RWMutex = std::shared_mutex; -// Construct with an RWMutex as a non-const reference. -// locks the mutex in lock_shared mode (for reading). Locking in a thread that already owns a lock -// i.e. locking multiple times successively is UB. Construction may be blocking. Destruction is guaranteed to release the lock. -using ReadLock = std::shared_lock; -// Construct with an RWMutex as a non-const reference. -// locks the mutex for writing. Construction may be blocking. Destruction is guaranteed to release the lock. -using WriteLock = std::unique_lock; diff --git a/include/Security/Enc.h b/include/Security/Enc.h deleted file mode 100644 index 66427fc..0000000 --- a/include/Security/Enc.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#pragma once -#ifdef __linux -#define EXCEPTION_POINTERS void -#else -#include -#endif -#include -int Handle(EXCEPTION_POINTERS* ep, char* Origin); diff --git a/include/Settings.h b/include/Settings.h deleted file mode 100644 index cc11aa0..0000000 --- a/include/Settings.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#pragma once -#include -#include -extern std::string ServerName; -extern std::string ServerDesc; -extern std::string StatReport; -extern std::string FileSizes; -extern std::string Resource; -extern std::string FileList; -extern std::string CustomIP; -extern std::string MapName; -extern uint64_t MaxModSize; -extern std::string Key; -std::string GetSVer(); -std::string GetCVer(); -extern int MaxPlayers; -extern int ModsLoaded; -extern bool Private; -extern int MaxCars; -extern bool Debug; -extern int Port; -extern int PPS; - -extern std::chrono::time_point StartTime; -inline std::chrono::seconds GetUptimeInSeconds() { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - StartTime); -} diff --git a/include/Startup.h b/include/Startup.h deleted file mode 100644 index 9c46e38..0000000 --- a/include/Startup.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#pragma once -void InitServer(int argc, char* argv[]); -void ConsoleInit(); -void InitConfig(); -void InitLua(); -void InitRes(); -void HBInit(); -void StatInit(); -void NetMain(); \ No newline at end of file diff --git a/include/TConsole.h b/include/TConsole.h new file mode 100644 index 0000000..133cb6b --- /dev/null +++ b/include/TConsole.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +class TConsole { +public: + TConsole(); + +private: + Commandline _Commandline; +}; diff --git a/include/UnixCompat.h b/include/UnixCompat.h deleted file mode 100644 index ffbc15e..0000000 --- a/include/UnixCompat.h +++ /dev/null @@ -1,38 +0,0 @@ -// Author: lionkor - -#pragma once - -// This header defines unix equivalents of common win32 functions. - -#ifndef WIN32 - -#include "CustomAssert.h" -#include -#include -#include - -// ZeroMemory is just a {0} or a memset(addr, 0, len), and it's a macro on MSVC -inline void ZeroMemory([[maybe_unused]] void* dst, [[maybe_unused]] size_t len) { - [[maybe_unused]] auto res = std::memset(dst, 0, len); - Assert(res != nullptr); -} -// provides unix equivalent of closesocket call in win32 -inline void CloseSocketProper(int socket) { - shutdown(socket, SHUT_RDWR); - close(socket); -} - -#ifndef __try -#define __try -#endif - -#ifndef __except -#define __except (x) /**/ -#endif - -#else // win32 -inline void CloseSocketProper(uint64_t socket) { - shutdown(socket, SD_BOTH); - closesocket(socket); -} -#endif // WIN32 diff --git a/include/commandline b/include/commandline new file mode 160000 index 0000000..01ec8e0 --- /dev/null +++ b/include/commandline @@ -0,0 +1 @@ +Subproject commit 01ec8e0388ee4759813abf12c9619ac294721eab diff --git a/src/Compat.cpp b/src/Compat.cpp new file mode 100644 index 0000000..a1765b7 --- /dev/null +++ b/src/Compat.cpp @@ -0,0 +1,35 @@ +#include "Compat.h" + +#ifndef WIN32 + +static struct termios old, current; + +void initTermios(int echo) { + tcgetattr(0, &old); /* grab old terminal i/o settings */ + current = old; /* make new settings same as old settings */ + current.c_lflag &= ~ICANON; /* disable buffered i/o */ + if (echo) { + current.c_lflag |= ECHO; /* set echo mode */ + } else { + current.c_lflag &= ~ECHO; /* set no echo mode */ + } + tcsetattr(0, TCSANOW, ¤t); /* use these new terminal i/o settings now */ +} + +void resetTermios(void) { + tcsetattr(0, TCSANOW, &old); +} + +char getch_(int echo) { + char ch; + initTermios(echo); + read(STDIN_FILENO, &ch, 1); + resetTermios(); + return ch; +} + +char _getch(void) { + return getch_(0); +} + +#endif // !WIN32 diff --git a/src/Compressor.cpp b/src/Compressor.cpp deleted file mode 100644 index 389599a..0000000 --- a/src/Compressor.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/15/2020 -/// - -#include -#include -#include -#include - -#define Biggest 30000 -std::string Comp(std::string Data) { - std::array C {}; - // obsolete - C.fill(0); - z_stream defstream; - defstream.zalloc = Z_NULL; - defstream.zfree = Z_NULL; - defstream.opaque = Z_NULL; - defstream.avail_in = (uInt)Data.length(); - defstream.next_in = (Bytef*)&Data[0]; - defstream.avail_out = Biggest; - defstream.next_out = reinterpret_cast(C.data()); - deflateInit(&defstream, Z_BEST_COMPRESSION); - deflate(&defstream, Z_SYNC_FLUSH); - deflate(&defstream, Z_FINISH); - deflateEnd(&defstream); - size_t TO = defstream.total_out; - std::string Ret(TO, 0); - std::copy_n(C.begin(), TO, Ret.begin()); - return Ret; -} -std::string DeComp(std::string Compressed) { - std::array C {}; - // not needed - C.fill(0); - z_stream infstream; - infstream.zalloc = Z_NULL; - infstream.zfree = Z_NULL; - infstream.opaque = Z_NULL; - infstream.avail_in = Biggest; - infstream.next_in = (Bytef*)(&Compressed[0]); - infstream.avail_out = Biggest; - infstream.next_out = (Bytef*)(C.data()); - inflateInit(&infstream); - inflate(&infstream, Z_SYNC_FLUSH); - inflate(&infstream, Z_FINISH); - inflateEnd(&infstream); - size_t TO = infstream.total_out; - std::string Ret(TO, 0); - std::copy_n(C.begin(), TO, Ret.begin()); - return Ret; -} diff --git a/src/Console.cpp b/src/Console.cpp deleted file mode 100644 index b217631..0000000 --- a/src/Console.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 10/29/2020 -/// - -#include "Lua/LuaSystem.hpp" -#ifdef WIN32 -#include -#include -#else // *nix -typedef unsigned long DWORD, *PDWORD, *LPDWORD; -#include -#include -#endif // WIN32 -#include "Logger.h" -#include -#include -#include -#include -#include -#include - -std::vector QConsoleOut; -std::string CInputBuff; -std::mutex MLock; -std::unique_ptr LuaConsole; -void HandleInput(const std::string& cmd) { - std::cout << std::endl; - if (cmd == ("exit")) { - _Exit(0); - } else if (cmd == ("clear") || cmd == ("cls")) { - // 2J is clearscreen, H is reset position to top-left - ConsoleOut(("\x1b[2J\x1b[H")); - } else { - LuaConsole->Execute(cmd); - } -} - -void ProcessOut() { - printf("%c[2K\r", 27); - for (const std::string& msg : QConsoleOut) - if (!msg.empty()) - std::cout << msg; - MLock.lock(); - QConsoleOut.clear(); - MLock.unlock(); - std::cout << "> " << CInputBuff << std::flush; -} - -void ConsoleOut(const std::string& msg) { - MLock.lock(); - QConsoleOut.emplace_back(msg); - MLock.unlock(); -} - -[[noreturn]] void OutputRefresh() { - DebugPrintTID(); - while (true) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - ProcessOut(); - } -} - -#ifndef WIN32 - -static struct termios old, current; - -void initTermios(int echo) { - tcgetattr(0, &old); /* grab old terminal i/o settings */ - current = old; /* make new settings same as old settings */ - current.c_lflag &= ~ICANON; /* disable buffered i/o */ - if (echo) { - current.c_lflag |= ECHO; /* set echo mode */ - } else { - current.c_lflag &= ~ECHO; /* set no echo mode */ - } - tcsetattr(0, TCSANOW, ¤t); /* use these new terminal i/o settings now */ -} - -void resetTermios(void) { - tcsetattr(0, TCSANOW, &old); -} - -char getch_(int echo) { - char ch; - initTermios(echo); - read(STDIN_FILENO, &ch, 1); - resetTermios(); - return ch; -} - -char _getch(void) { - return getch_(0); -} - -#endif // WIN32 - -void SetupConsole() { -#if defined(WIN32) - DWORD outMode = 0; - HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if (stdoutHandle == INVALID_HANDLE_VALUE) { - error("Invalid console handle! Inputs will not work properly"); - return; - } - if (!GetConsoleMode(stdoutHandle, &outMode)) { - error("Invalid console mode! Inputs will not work properly"); - return; - } - // Enable ANSI escape codes - outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(stdoutHandle, outMode)) { - error("failed to set console mode! Inputs will not work properly"); - return; - } -#else -#endif // WIN32 -} - -static std::vector ConsoleHistory {}; -// buffer used to revert back to what we were writing when we go all the way forward in history -static std::string LastInputBuffer {}; -static size_t ConsoleHistoryReadIndex { 0 }; - -static inline void ConsoleHistoryAdd(const std::string& cmd) { - LastInputBuffer.clear(); - ConsoleHistory.push_back(cmd); - ConsoleHistoryReadIndex = ConsoleHistory.size(); -} - -static inline void ConsoleHistoryEnsureBounds() { - if (ConsoleHistoryReadIndex >= ConsoleHistory.size()) { - ConsoleHistoryReadIndex = ConsoleHistory.size() - 1; - } -} - -static inline void ConsoleHistoryGoBack() { - if (ConsoleHistoryReadIndex > 0) { - --ConsoleHistoryReadIndex; - ConsoleHistoryEnsureBounds(); - } -} - -static inline void ConsoleHistoryGoForward() { - ++ConsoleHistoryReadIndex; - ConsoleHistoryEnsureBounds(); -} - -static std::string CompositeInput; -static bool CompositeInputExpected { false }; - -static void ProcessCompositeInput() { -#ifdef WIN32 - if (CompositeInput.size() == 1 && memcmp(CompositeInput.data(), std::array { 72 }.data(), 1) == 0) { -#else // unix - if (CompositeInput.size() == 2 && memcmp(CompositeInput.data(), std::array { 91, 65 }.data(), 2) == 0) { -#endif // WIN32 - - // UP ARROW - if (!ConsoleHistory.empty()) { - ConsoleHistoryGoBack(); - CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex); - } -#ifdef WIN32 - } else if (CompositeInput.size() == 1 && memcmp(CompositeInput.data(), std::array { 80 }.data(), 1) == 0) { -#else // unix - } else if (CompositeInput.size() == 2 && memcmp(CompositeInput.data(), std::array { 91, 66 }.data(), 2) == 0) { -#endif // WIN32 - - // DOWN ARROW - if (!ConsoleHistory.empty()) { - if (ConsoleHistoryReadIndex == ConsoleHistory.size() - 1) { - CInputBuff = LastInputBuffer; - } else { - ConsoleHistoryGoForward(); - CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex); - } - } - } else { - // not composite input, we made a mistake, so lets just add it to the buffer like usual - CInputBuff += CompositeInput; - } - // ensure history doesnt grow too far beyond a max - static constexpr size_t MaxHistory = 10; - if (ConsoleHistory.size() > 2 * MaxHistory) { - decltype(ConsoleHistory) NewHistory(ConsoleHistory.begin() + ConsoleHistory.size() - MaxHistory, ConsoleHistory.end()); - ConsoleHistory = std::move(NewHistory); - ConsoleHistoryReadIndex = ConsoleHistory.size(); - } -} - -void ReadCin() { - DebugPrintTID(); - size_t null_byte_counter = 0; - while (true) { - int In = _getch(); - //info(std::to_string(In)); - if (In == 0) { - ++null_byte_counter; - if (null_byte_counter > 50) { - info(("too many null bytes in input, this is now assumed to be a background thread - console input is now disabled")); - break; - } - } - if (CompositeInputExpected) { - CompositeInput += char(In); -#ifdef WIN32 - if (CompositeInput.size() == 1) { -#else // unix - if (CompositeInput.size() == 2) { -#endif // WIN32 - CompositeInputExpected = false; - ProcessCompositeInput(); - } - continue; - } - if (In == 13 || In == '\n') { - if (!CInputBuff.empty()) { - HandleInput(CInputBuff); - ConsoleHistoryAdd(CInputBuff); - CInputBuff.clear(); - } - } else if (In == 8 || In == 127) { - if (!CInputBuff.empty()) - CInputBuff.pop_back(); - } else if (In == 4) { - CInputBuff = "exit"; - HandleInput(CInputBuff); - CInputBuff.clear(); - } else if (In == 12) { - CInputBuff = "clear"; - HandleInput(CInputBuff); - CInputBuff.clear(); -#ifdef WIN32 - } else if (In == 224) { -#else // unix - } else if (In == 27) { -#endif // WIN32 - - // escape char, assume stuff follows - CompositeInputExpected = true; - CompositeInput.clear(); - } else if (!isprint(In)) { - // ignore - } else { - CInputBuff += char(In); - LastInputBuffer = CInputBuff; - } - } -} -void ConsoleInit() { - SetupConsole(); - LuaConsole = std::make_unique(true); - LuaConsole->Init(); - printf("> "); - std::thread In(ReadCin); - In.detach(); - std::thread Out(OutputRefresh); - Out.detach(); -} diff --git a/src/Enc.cpp b/src/Enc.cpp deleted file mode 100644 index 97be725..0000000 --- a/src/Enc.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#include "Security/Enc.h" -#include "CustomAssert.h" -#include "Logger.h" -#include - -#ifdef WIN32 -#include -int Handle(EXCEPTION_POINTERS* ep, char* Origin) { - Assert(false); - std::stringstream R; - R << ("Code : ") << std::hex - << ep->ExceptionRecord->ExceptionCode - << std::dec << (" Origin : ") << Origin; - except(R.str()); - return 1; -} -#else -// stub -int Handle(EXCEPTION_POINTERS*, char*) { return 1; } -#endif // WIN32 diff --git a/src/Init/Config.cpp b/src/Init/Config.cpp deleted file mode 100644 index 227055f..0000000 --- a/src/Init/Config.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#include "CustomAssert.h" -#include "Logger.h" -#include "Security/Enc.h" -#include -#include -#include -std::string ServerName; -std::string ServerDesc; -std::string Resource; -std::string MapName; -std::string Key; -int MaxPlayers; -bool Private; -int MaxCars; -bool Debug; -int Port; -std::chrono::time_point StartTime; - -void SetValues(const std::string& Line, int Index) { - int state = 0; - std::string Data; - bool Switch = false; - if (Index > 5) - Switch = true; - for (char c : Line) { - if (Switch) { - if (c == '\"') - state++; - if (state > 0 && state < 2) - Data += c; - } else { - if (c == ' ') - state++; - if (state > 1) - Data += c; - } - } - Data = Data.substr(1); - std::string::size_type sz; - bool FoundTrue = std::string(Data).find("true") != std::string::npos; //searches for "true" - switch (Index) { - case 1: - Debug = FoundTrue; //checks and sets the Debug Value - break; - case 2: - Private = FoundTrue; //checks and sets the Private Value - break; - case 3: - Port = std::stoi(Data, &sz); //sets the Port - break; - case 4: - MaxCars = std::stoi(Data, &sz); //sets the Max Car amount - break; - case 5: - MaxPlayers = std::stoi(Data, &sz); //sets the Max Amount of player - break; - case 6: - MapName = Data; //Map - break; - case 7: - ServerName = Data; //Name - break; - case 8: - ServerDesc = Data; //desc - break; - case 9: - Resource = Data; //File name - break; - case 10: - Key = Data; //File name - default: - break; - } -} -std::string RemoveComments(const std::string& Line) { - std::string Return; - for (char c : Line) { - if (c == '#') - break; - Return += c; - } - return Return; -} -void LoadConfig(std::ifstream& IFS) { - Assert(IFS.is_open()); - std::string line; - int index = 1; - while (getline(IFS, line)) { - index++; - } - if (index - 1 < 11) { - error(("Outdated/Incorrect config please remove it server will close in 5 secs")); - std::this_thread::sleep_for(std::chrono::seconds(3)); - _Exit(0); - } - IFS.close(); - IFS.open(("Server.cfg")); - info(("Config found updating values")); - index = 1; - while (getline(IFS, line)) { - if (line.rfind('#', 0) != 0 && line.rfind(' ', 0) != 0) { //Checks if it starts as Comment - std::string CleanLine = RemoveComments(line); //Cleans it from the Comments - SetValues(CleanLine, index); //sets the values - index++; - } - } -} -void GenerateConfig() { - std::ofstream FileStream; - FileStream.open(("Server.cfg")); - FileStream << ("# This is the BeamMP Server Configuration File v0.60\n" - "Debug = false # true or false to enable debug console output\n" - "Private = true # Private?\n" - "Port = 30814 # Port to run the server on UDP and TCP\n" - "Cars = 1 # Max cars for every player\n" - "MaxPlayers = 10 # Maximum Amount of Clients\n" - "Map = \"/levels/gridmap/info.json\" # Default Map\n" - "Name = \"BeamMP New Server\" # Server Name\n" - "Desc = \"BeamMP Default Description\" # Server Description\n" - "use = \"Resources\" # Resource file name\n" - "AuthKey = \"\" # Auth Key"); - FileStream.close(); -} -void Default() { - info(("Config not found generating default")); - GenerateConfig(); - error(("You are required to input the AuthKey")); - std::this_thread::sleep_for(std::chrono::seconds(3)); - _Exit(0); -} -void DebugData() { - debug(std::string("Debug : ") + (Debug ? "true" : "false")); - debug(std::string("Private : ") + (Private ? "true" : "false")); - debug("Port : " + std::to_string(Port)); - debug("Max Cars : " + std::to_string(MaxCars)); - debug("MaxPlayers : " + std::to_string(MaxPlayers)); - debug("MapName : " + MapName); - debug("ServerName : " + ServerName); - debug("ServerDesc : " + ServerDesc); - debug("File : " + Resource); - debug("Key length: " + std::to_string(Key.length())); -} -void InitConfig() { - ////TODO: Move to json after update 4 - - std::ifstream IFS; - IFS.open(("Server.cfg")); - if (IFS.good()) - LoadConfig(IFS); - else - Default(); - if (IFS.is_open()) - IFS.close(); - if (Key.empty()) { - error(("No AuthKey was found")); - std::this_thread::sleep_for(std::chrono::seconds(3)); - _Exit(0); - } - if (Debug) - DebugData(); -} diff --git a/src/Init/Heartbeat.cpp b/src/Init/Heartbeat.cpp deleted file mode 100644 index ebf0857..0000000 --- a/src/Init/Heartbeat.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#include "Client.hpp" -#include "Curl/Http.h" -#include "Logger.h" -#include "Settings.h" -#include -#include -#include -#include -#include - -void WebsocketInit(); -std::string GetPlayers() { - std::string Return; - for (auto& c : CI->Clients) { - if (c != nullptr) { - Return += c->GetName() + ";"; - } - } - return Return; -} -std::string GenerateCall() { - std::stringstream Ret; - Ret << "uuid=" << Key << "&players=" << CI->Size() - << "&maxplayers=" << MaxPlayers << "&port=" << Port - << "&map=" << MapName << "&private=" << (Private ? "true" : "false") - << "&version=" << GetSVer() << "&clientversion=" << GetCVer() - << "&name=" << ServerName << "&pps=" << StatReport - << "&modlist=" << FileList << "&modstotalsize=" << MaxModSize - << "&modstotal=" << ModsLoaded << "&playerslist=" << GetPlayers() - << "&desc=" << ServerDesc; - return Ret.str(); -} -std::string RunPromise(const std::string& host, const std::string& target, const std::unordered_map& R, const std::string& body) { - std::packaged_task task([&] { DebugPrintTIDInternal("Heartbeat_POST"); return PostHTTP(host, target, R, body, false); }); - std::future f1 = task.get_future(); - std::thread t(std::move(task)); - t.detach(); - auto status = f1.wait_for(std::chrono::seconds(15)); - if (status != std::future_status::timeout) - return f1.get(); - error("Backend system Timeout please try again later"); - return ""; -} - -[[noreturn]] void Heartbeat() { - DebugPrintTID(); - std::string R; - std::string T; - - // these are "hot-change" related variables - static std::string LastR = ""; - - static std::chrono::high_resolution_clock::time_point LastNormalUpdateTime = std::chrono::high_resolution_clock::now(); - bool isAuth = false; - while (true) { - R = 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 (LastR == R && (Now - LastNormalUpdateTime) < std::chrono::seconds(30)) { - std::this_thread::sleep_for(std::chrono::seconds(5)); - continue; - } - LastR = R; - LastNormalUpdateTime = Now; - if (!CustomIP.empty()) - R += "&ip=" + CustomIP; - T = RunPromise("backend.beammp.com", "/heartbeat", {}, R); - - if (T.substr(0, 2) != "20") { - //Backend system refused server startup! - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - T = RunPromise("backend.beammp.com", "/heartbeat", {}, R); - // TODO backup2 + HTTP flag (no TSL) - if (T.substr(0, 2) != "20") { - warn("Backend system refused server! Server might not show in the public list"); - } - } - //Server Authenticated - if (!isAuth) { - WebsocketInit(); - if (T.length() == 4) - info(("Authenticated!")); - else - info(("Resumed authenticated session!")); - isAuth = true; - } - } -} -void HBInit() { - std::thread HB(Heartbeat); - HB.detach(); -} diff --git a/src/Init/Resources.cpp b/src/Init/Resources.cpp deleted file mode 100644 index d754851..0000000 --- a/src/Init/Resources.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#include "Logger.h" -#include "Security/Enc.h" -#include "Settings.h" -#include -#include - -namespace fs = std::filesystem; - -uint64_t MaxModSize = 0; -std::string FileSizes; -std::string FileList; -int ModsLoaded = 0; - -void InitRes() { - std::string Path = Resource + "/Client"; - if (!fs::exists(Path)) - fs::create_directory(Path); - for (const auto& entry : fs::directory_iterator(Path)) { - auto pos = entry.path().string().find(".zip"); - if (pos != std::string::npos) { - if (entry.path().string().length() - pos == 4) { - FileList += entry.path().string() + ";"; - FileSizes += std::to_string(uint64_t(fs::file_size(entry.path()))) + ";"; - MaxModSize += uint64_t(fs::file_size(entry.path())); - ModsLoaded++; - } - } - } - std::replace(FileList.begin(), FileList.end(), '\\', '/'); - if (ModsLoaded) - info("Loaded " + std::to_string(ModsLoaded) + " Mods"); -} diff --git a/src/Init/Startup.cpp b/src/Init/Startup.cpp deleted file mode 100644 index c615156..0000000 --- a/src/Init/Startup.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/28/2020 -/// -#include "Client.hpp" -#include "Logger.h" -#include "Security/Enc.h" -#include -#include - -std::string CustomIP; -std::string GetSVer() { - return "1.20"; -} -std::string GetCVer() { - return "1.80"; -} -void Args(int argc, char* argv[]) { - info("BeamMP Server Running version " + GetSVer()); - if (argc > 1) { - CustomIP = argv[1]; - size_t n = std::count(CustomIP.begin(), CustomIP.end(), '.'); - auto p = CustomIP.find_first_not_of((".0123456789")); - if (p != std::string::npos || n != 3 || CustomIP.substr(0, 3) == ("127")) { - CustomIP.clear(); - warn("IP Specified is invalid! Ignoring"); - } else - info("Server started with custom IP"); - } -} -void InitServer(int argc, char* argv[]) { - InitLog(); - Args(argc, argv); - CI = std::make_unique(); -} diff --git a/src/Lua/LuaMain.cpp b/src/Lua/LuaMain.cpp deleted file mode 100644 index 890ec25..0000000 --- a/src/Lua/LuaMain.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/20/2020 -/// - -#include "Logger.h" -#include "Lua/LuaSystem.hpp" -#include "Security/Enc.h" -#include "Settings.h" -#include - -#ifdef __linux -// we need this for `struct stat` -#include -#endif // __linux - -std::set> PluginEngine; -bool NewFile(const std::string& Path) { - for (auto& Script : PluginEngine) { - if (Path == Script->GetFileName()) - return false; - } - return true; -} -void RegisterFiles(const std::string& Path, bool HotSwap) { - std::string Name = Path.substr(Path.find_last_of('\\') + 1); - if (!HotSwap) - info(("Loading plugin : ") + Name); - for (const auto& entry : fs::directory_iterator(Path)) { - auto pos = entry.path().string().find((".lua")); - if (pos != std::string::npos && entry.path().string().length() - pos == 4) { - if (!HotSwap || NewFile(entry.path().string())) { - auto FileName = entry.path().string(); - std::unique_ptr ScriptToInsert(new Lua(Name, FileName, fs::last_write_time(FileName))); - auto& Script = *ScriptToInsert; - PluginEngine.insert(std::move(ScriptToInsert)); - Script.Init(); - if (HotSwap) - info(("[HOTSWAP] Added : ") + Script.GetFileName().substr(Script.GetFileName().find('\\'))); - } - } - } -} -void FolderList(const std::string& Path, bool HotSwap) { - for (const auto& entry : fs::directory_iterator(Path)) { - auto pos = entry.path().filename().string().find('.'); - if (pos == std::string::npos) { - RegisterFiles(entry.path().string(), HotSwap); - } - } -} -[[noreturn]] void HotSwaps(const std::string& path) { - DebugPrintTID(); - while (true) { - if (!PluginEngine.empty()) { - for (auto& Script : PluginEngine) { - struct stat Info { }; - if (stat(Script->GetFileName().c_str(), &Info) != 0) { - Script->SetStopThread(true); - PluginEngine.erase(Script); - info(("[HOTSWAP] Removed removed script due to delete")); - break; - } - if (Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())) { - Script->SetStopThread(true); - info(("[HOTSWAP] Updated Scripts due to edit")); - Script->SetLastWrite(fs::last_write_time(Script->GetFileName())); - Script->Reload(); - } - } - } - FolderList(path, true); - std::this_thread::sleep_for(std::chrono::seconds(2)); - } -} - -void InitLua() { - if (!fs::exists(Resource)) { - fs::create_directory(Resource); - } - std::string Path = Resource + ("/Server"); - if (!fs::exists(Path)) { - fs::create_directory(Path); - } - FolderList(Path, false); - std::thread t1(HotSwaps, Path); - t1.detach(); - info(("Lua system online")); -} diff --git a/src/Lua/LuaSystem.cpp b/src/Lua/LuaSystem.cpp deleted file mode 100644 index 8dcbc08..0000000 --- a/src/Lua/LuaSystem.cpp +++ /dev/null @@ -1,705 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/19/2020 -/// - -#include "Lua/LuaSystem.hpp" -#include "Client.hpp" -#include "Logger.h" -#include "Network.h" -#include "Security/Enc.h" -#include "Settings.h" -#include "UnixCompat.h" -#include -#include -#include -#include - -std::shared_ptr CreateArg(lua_State* L, int T, int S) { - if (S > T) - return nullptr; - std::shared_ptr temp(new LuaArg); - for (int C = S; C <= T; C++) { - if (lua_isstring(L, C)) { - temp->args.emplace_back(std::string(lua_tostring(L, C))); - } else if (lua_isinteger(L, C)) { - temp->args.emplace_back(int(lua_tointeger(L, C))); - } else if (lua_isboolean(L, C)) { - temp->args.emplace_back(bool(lua_toboolean(L, C))); - } else if (lua_isnumber(L, C)) { - temp->args.emplace_back(float(lua_tonumber(L, C))); - } - } - return temp; -} -void ClearStack(lua_State* L) { - lua_settop(L, 0); -} -std::optional> GetScript(lua_State* L) { - for (auto& Script : PluginEngine) { - if (Script->GetState() == L) - return *Script; - } - return std::nullopt; -} -void SendError(lua_State* L, const std::string& msg) { - Assert(L); - auto MaybeS = GetScript(L); - std::string a; - if (!MaybeS.has_value()) { - a = ("_Console"); - } else { - Lua& S = MaybeS.value(); - a = fs::path(S.GetFileName()).filename().string(); - } - warn(a + (" | Incorrect Call of ") + msg); -} -std::any Trigger(Lua* lua, const std::string& R, std::shared_ptr arg) { - std::lock_guard lockGuard(lua->Lock); - std::packaged_task)> task([lua, R](std::shared_ptr arg) { return CallFunction(lua, R, arg); }); - std::future f1 = task.get_future(); - std::thread t(std::move(task), arg); - t.detach(); - auto status = f1.wait_for(std::chrono::seconds(5)); - if (status != std::future_status::timeout) - return f1.get(); - SendError(lua->GetState(), R + " took too long to respond"); - return 0; -} -std::any FutureWait(Lua* lua, const std::string& R, std::shared_ptr arg, bool Wait) { - Assert(lua); - std::packaged_task)> task([lua, R](std::shared_ptr arg) { return Trigger(lua, R, arg); }); - std::future f1 = task.get_future(); - std::thread t(std::move(task), arg); - t.detach(); - int T = 0; - if (Wait) - T = 6; - auto status = f1.wait_for(std::chrono::seconds(T)); - if (status != std::future_status::timeout) - return f1.get(); - return 0; -} -std::any TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::shared_ptr arg, bool Wait) { - std::any R; - std::string Type; - int Ret = 0; - for (auto& Script : PluginEngine) { - if (Script->IsRegistered(Event)) { - if (local) { - if (Script->GetPluginName() == Caller->GetPluginName()) { - R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait); - Type = R.type().name(); - if (Type.find("int") != std::string::npos) { - if (std::any_cast(R)) - Ret++; - } else if (Event == "onPlayerAuth") - return R; - } - } else { - R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait); - Type = R.type().name(); - if (Type.find("int") != std::string::npos) { - if (std::any_cast(R)) - Ret++; - } else if (Event == "onPlayerAuth") - return R; - } - } - } - return Ret; -} -bool ConsoleCheck(lua_State* L, int r) { - if (r != LUA_OK) { - std::string msg = lua_tostring(L, -1); - warn(("_Console | ") + msg); - return false; - } - return true; -} -bool CheckLua(lua_State* L, int r) { - if (r != LUA_OK) { - std::string msg = lua_tostring(L, -1); - auto MaybeS = GetScript(L); - if (MaybeS.has_value()) { - Lua& S = MaybeS.value(); - std::string a = fs::path(S.GetFileName()).filename().string(); - warn(a + " | " + msg); - return false; - } - // What the fuck, what do we do?! - AssertNotReachable(); - } - return true; -} - -int lua_RegisterEvent(lua_State* L) { - int Args = lua_gettop(L); - auto MaybeScript = GetScript(L); - Assert(MaybeScript.has_value()); - Lua& Script = MaybeScript.value(); - if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) { - Script.RegisterEvent(lua_tostring(L, 1), lua_tostring(L, 2)); - } else - SendError(L, ("RegisterEvent invalid argument count expected 2 got ") + std::to_string(Args)); - return 0; -} -int lua_TriggerEventL(lua_State* L) { - int Args = lua_gettop(L); - auto MaybeScript = GetScript(L); - Assert(MaybeScript.has_value()); - Lua& Script = MaybeScript.value(); - if (Args > 0) { - if (lua_isstring(L, 1)) { - TriggerLuaEvent(lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false); - } else - SendError(L, ("TriggerLocalEvent wrong argument [1] need string")); - } else { - SendError(L, ("TriggerLocalEvent not enough arguments expected 1 got 0")); - } - return 0; -} - -int lua_TriggerEventG(lua_State* L) { - int Args = lua_gettop(L); - auto MaybeScript = GetScript(L); - Assert(MaybeScript.has_value()); - Lua& Script = MaybeScript.value(); - if (Args > 0) { - if (lua_isstring(L, 1)) { - TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false); - } else - SendError(L, ("TriggerGlobalEvent wrong argument [1] need string")); - } else - SendError(L, ("TriggerGlobalEvent not enough arguments")); - return 0; -} - -char* ThreadOrigin(Lua* lua) { - std::string T = "Thread in " + fs::path(lua->GetFileName()).filename().string(); - char* Data = new char[T.size() + 1]; - ZeroMemory(Data, T.size() + 1); - memcpy(Data, T.c_str(), T.size()); - return Data; -} -void SafeExecution(Lua* lua, const std::string& FuncName) { - lua_State* luaState = lua->GetState(); - lua_getglobal(luaState, FuncName.c_str()); - if (lua_isfunction(luaState, -1)) { - char* Origin = ThreadOrigin(lua); -#ifdef WIN32 - __try { - int R = lua_pcall(luaState, 0, 0, 0); - CheckLua(luaState, R); - } __except (Handle(GetExceptionInformation(), Origin)) { - } -#else // unix - int R = lua_pcall(luaState, 0, 0, 0); - CheckLua(luaState, R); -#endif // WIN32 - delete[] Origin; - } - ClearStack(luaState); -} - -void ExecuteAsync(Lua* lua, const std::string& FuncName) { - std::lock_guard lockGuard(lua->Lock); - SafeExecution(lua, FuncName); -} -void CallAsync(Lua* lua, const std::string& Func, int U) { - DebugPrintTID(); - lua->SetStopThread(false); - int D = 1000 / U; - while (!lua->GetStopThread()) { - ExecuteAsync(lua, Func); - std::this_thread::sleep_for(std::chrono::milliseconds(D)); - } -} -int lua_StopThread(lua_State* L) { - auto MaybeScript = GetScript(L); - Assert(MaybeScript.has_value()); - // ugly, but whatever, this is safe as fuck - MaybeScript.value().get().SetStopThread(true); - return 0; -} -int lua_CreateThread(lua_State* L) { - int Args = lua_gettop(L); - if (Args > 1) { - if (lua_isstring(L, 1)) { - std::string STR = lua_tostring(L, 1); - if (lua_isinteger(L, 2) || lua_isnumber(L, 2)) { - int U = int(lua_tointeger(L, 2)); - if (U > 0 && U < 501) { - auto MaybeScript = GetScript(L); - Assert(MaybeScript.has_value()); - Lua& Script = MaybeScript.value(); - std::thread t1(CallAsync, &Script, STR, U); - t1.detach(); - } else - SendError(L, ("CreateThread wrong argument [2] number must be between 1 and 500")); - } else - SendError(L, ("CreateThread wrong argument [2] need number")); - } else - SendError(L, ("CreateThread wrong argument [1] need string")); - } else - SendError(L, ("CreateThread not enough arguments")); - return 0; -} -int lua_Sleep(lua_State* L) { - if (lua_isnumber(L, 1)) { - int t = int(lua_tonumber(L, 1)); - std::this_thread::sleep_for(std::chrono::milliseconds(t)); - } else { - SendError(L, ("Sleep not enough arguments")); - return 0; - } - return 1; -} -Client* GetClient(int ID) { - for (auto& c : CI->Clients) { - if (c != nullptr && c->GetID() == ID) { - return c.get(); - } - } - return nullptr; -} -int lua_isConnected(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c != nullptr) - lua_pushboolean(L, c->isConnected); - else - return 0; - } else { - SendError(L, ("isConnected not enough arguments")); - return 0; - } - return 1; -} -int lua_GetPlayerName(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c != nullptr) - lua_pushstring(L, c->GetName().c_str()); - else - return 0; - } else { - SendError(L, ("GetPlayerName not enough arguments")); - return 0; - } - return 1; -} -int lua_GetPlayerCount(lua_State* L) { - lua_pushinteger(L, CI->Size()); - return 1; -} -int lua_GetGuest(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c != nullptr) - lua_pushboolean(L, c->isGuest); - else - return 0; - } else { - SendError(L, "GetGuest not enough arguments"); - return 0; - } - return 1; -} -int lua_GetAllPlayers(lua_State* L) { - lua_newtable(L); - int i = 1; - for (auto& c : CI->Clients) { - if (c == nullptr) - continue; - lua_pushinteger(L, c->GetID()); - lua_pushstring(L, c->GetName().c_str()); - lua_settable(L, -3); - i++; - } - if (CI->Clients.empty()) - return 0; - return 1; -} -int lua_GetCars(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c != nullptr) { - int i = 1; - for (auto& v : c->GetAllCars()) { - if (v != nullptr) { - lua_pushinteger(L, v->ID); - lua_pushstring(L, v->Data.substr(3).c_str()); - lua_settable(L, -3); - i++; - } - } - if (c->GetAllCars().empty()) - return 0; - } else - return 0; - } else { - SendError(L, ("GetPlayerVehicles not enough arguments")); - return 0; - } - return 1; -} -int lua_dropPlayer(lua_State* L) { - int Args = lua_gettop(L); - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c == nullptr) - return 0; - std::string Reason; - if (Args > 1 && lua_isstring(L, 2)) { - Reason = std::string((" Reason : ")) + lua_tostring(L, 2); - } - 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()); - } else - SendError(L, ("DropPlayer not enough arguments")); - return 0; -} -int lua_sendChat(lua_State* L) { - if (lua_isinteger(L, 1) || lua_isnumber(L, 1)) { - if (lua_isstring(L, 2)) { - 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); - } else { - Client* c = GetClient(ID); - if (c != nullptr) { - if (!c->isSynced) - return 0; - std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2)); - Respond(c, Packet, true); - } else - SendError(L, ("SendChatMessage invalid argument [1] invalid ID")); - } - } else - SendError(L, ("SendChatMessage invalid argument [2] expected string")); - } else - SendError(L, ("SendChatMessage invalid argument [1] expected number")); - return 0; -} -int lua_RemoveVehicle(lua_State* L) { - int Args = lua_gettop(L); - if (Args != 2) { - SendError(L, ("RemoveVehicle invalid argument count expected 2 got ") + std::to_string(Args)); - return 0; - } - if ((lua_isinteger(L, 1) || lua_isnumber(L, 1)) && (lua_isinteger(L, 2) || lua_isnumber(L, 2))) { - int PID = int(lua_tointeger(L, 1)); - int VID = int(lua_tointeger(L, 2)); - Client* c = GetClient(PID); - if (c == nullptr) { - SendError(L, ("RemoveVehicle invalid Player ID")); - return 0; - } - if (!c->GetCarData(VID).empty()) { - std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID); - SendToAll(nullptr, Destroy, true, true); - c->DeleteCar(VID); - } - } else - SendError(L, ("RemoveVehicle invalid argument expected number")); - return 0; -} -int lua_HWID(lua_State* L) { - lua_pushinteger(L, -1); - return 1; -} -int lua_RemoteEvent(lua_State* L) { - int Args = lua_gettop(L); - if (Args != 3) { - SendError(L, ("TriggerClientEvent invalid argument count expected 3 got ") + std::to_string(Args)); - return 0; - } - if (!lua_isnumber(L, 1)) { - SendError(L, ("TriggerClientEvent invalid argument [1] expected number")); - return 0; - } - if (!lua_isstring(L, 2)) { - SendError(L, ("TriggerClientEvent invalid argument [2] expected string")); - return 0; - } - if (!lua_isstring(L, 3)) { - SendError(L, ("TriggerClientEvent invalid argument [3] expected string")); - return 0; - } - 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); - else { - Client* c = GetClient(ID); - if (c == nullptr) { - SendError(L, ("TriggerClientEvent invalid Player ID")); - return 0; - } - Respond(c, Packet, true); - } - return 0; -} -int lua_ServerExit(lua_State* L) { - if (lua_gettop(L) > 0) { - if (lua_isnumber(L, 1)) { - _Exit(int(lua_tointeger(L, 1))); - } - } - _Exit(0); -} -int lua_Set(lua_State* L) { - int Args = lua_gettop(L); - if (Args != 2) { - SendError(L, ("set invalid argument count expected 2 got ") + std::to_string(Args)); - return 0; - } - if (!lua_isnumber(L, 1)) { - SendError(L, ("set invalid argument [1] expected number")); - return 0; - } - auto MaybeSrc = GetScript(L); - std::string Name; - if (!MaybeSrc.has_value()) { - Name = ("_Console"); - } else { - Name = MaybeSrc.value().get().GetPluginName(); - } - int C = int(lua_tointeger(L, 1)); - switch (C) { - case 0: //debug - if (lua_isboolean(L, 2)) { - Debug = lua_toboolean(L, 2); - info(Name + (" | Debug -> ") + (Debug ? "true" : "false")); - } else - SendError(L, ("set invalid argument [2] expected boolean for ID : 0")); - break; - case 1: //private - if (lua_isboolean(L, 2)) { - Private = lua_toboolean(L, 2); - info(Name + (" | Private -> ") + (Private ? "true" : "false")); - } else - SendError(L, ("set invalid argument [2] expected boolean for ID : 1")); - break; - case 2: //max cars - if (lua_isnumber(L, 2)) { - MaxCars = int(lua_tointeger(L, 2)); - info(Name + (" | MaxCars -> ") + std::to_string(MaxCars)); - } else - SendError(L, ("set invalid argument [2] expected number for ID : 2")); - break; - case 3: //max players - if (lua_isnumber(L, 2)) { - MaxPlayers = int(lua_tointeger(L, 2)); - info(Name + (" | MaxPlayers -> ") + std::to_string(MaxPlayers)); - } else - SendError(L, ("set invalid argument [2] expected number for ID : 3")); - break; - case 4: //Map - if (lua_isstring(L, 2)) { - MapName = lua_tostring(L, 2); - info(Name + (" | MapName -> ") + MapName); - } else - SendError(L, ("set invalid argument [2] expected string for ID : 4")); - break; - case 5: //Name - if (lua_isstring(L, 2)) { - ServerName = lua_tostring(L, 2); - info(Name + (" | ServerName -> ") + ServerName); - } else - SendError(L, ("set invalid argument [2] expected string for ID : 5")); - break; - case 6: //Desc - if (lua_isstring(L, 2)) { - ServerDesc = lua_tostring(L, 2); - info(Name + (" | ServerDesc -> ") + ServerDesc); - } else - SendError(L, ("set invalid argument [2] expected string for ID : 6")); - break; - default: - warn(("Invalid config ID : ") + std::to_string(C)); - break; - } - - return 0; -} -extern "C" { -int lua_Print(lua_State* L) { - int Arg = lua_gettop(L); - for (int i = 1; i <= Arg; i++) { - auto str = lua_tostring(L, i); - if (str != nullptr) { - ConsoleOut(str + std::string(("\n"))); - } else { - ConsoleOut(("nil\n")); - } - } - return 0; -} -} - -Lua::Lua(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote, bool Console) - : luaState(luaL_newstate()) { - Assert(luaState); - if (!PluginName.empty()) { - SetPluginName(PluginName); - } - if (!FileName.empty()) { - SetFileName(FileName); - } - SetLastWrite(LastWrote); - _Console = Console; -} - -Lua::Lua(bool Console) - : luaState(luaL_newstate()) { - _Console = Console; -} - -void Lua::Execute(const std::string& Command) { - if (ConsoleCheck(luaState, luaL_dostring(luaState, Command.c_str()))) { - lua_settop(luaState, 0); - } -} -void Lua::Reload() { - if (CheckLua(luaState, luaL_dofile(luaState, _FileName.c_str()))) { - CallFunction(this, ("onInit"), nullptr); - } -} -std::string Lua::GetOrigin() { - return fs::path(GetFileName()).filename().string(); -} - -std::any CallFunction(Lua* lua, const std::string& FuncName, std::shared_ptr Arg) { - lua_State* luaState = lua->GetState(); - lua_getglobal(luaState, FuncName.c_str()); - if (lua_isfunction(luaState, -1)) { - int Size = 0; - if (Arg != nullptr) { - Size = int(Arg->args.size()); - Arg->PushArgs(luaState); - } - int R = lua_pcall(luaState, Size, 1, 0); - if (CheckLua(luaState, R)) { - if (lua_isnumber(luaState, -1)) { - return int(lua_tointeger(luaState, -1)); - } else if (lua_isstring(luaState, -1)) { - return std::string(lua_tostring(luaState, -1)); - } - } - } - ClearStack(luaState); - return 0; -} -void Lua::SetPluginName(const std::string& Name) { - _PluginName = Name; -} -void Lua::SetFileName(const std::string& Name) { - _FileName = Name; -} -int lua_TempFix(lua_State* L) { - if (lua_isnumber(L, 1)) { - int ID = int(lua_tonumber(L, 1)); - Client* c = GetClient(ID); - if (c == nullptr) - return 0; - std::string Ret; - if (c->isGuest) { - Ret = "Guest-" + c->GetName(); - } else - Ret = c->GetName(); - lua_pushstring(L, Ret.c_str()); - } else - SendError(L, "GetDID not enough arguments"); - return 1; -} -void Lua::Init() { - Assert(luaState); - luaL_openlibs(luaState); - lua_register(luaState, "TriggerGlobalEvent", lua_TriggerEventG); - lua_register(luaState, "TriggerLocalEvent", lua_TriggerEventL); - lua_register(luaState, "TriggerClientEvent", lua_RemoteEvent); - lua_register(luaState, "GetPlayerCount", lua_GetPlayerCount); - lua_register(luaState, "isPlayerConnected", lua_isConnected); - lua_register(luaState, "RegisterEvent", lua_RegisterEvent); - lua_register(luaState, "GetPlayerName", lua_GetPlayerName); - lua_register(luaState, "RemoveVehicle", lua_RemoveVehicle); - lua_register(luaState, "GetPlayerDiscordID", lua_TempFix); - lua_register(luaState, "CreateThread", lua_CreateThread); - lua_register(luaState, "GetPlayerVehicles", lua_GetCars); - lua_register(luaState, "SendChatMessage", lua_sendChat); - lua_register(luaState, "GetPlayers", lua_GetAllPlayers); - lua_register(luaState, "GetPlayerGuest", lua_GetGuest); - lua_register(luaState, "StopThread", lua_StopThread); - lua_register(luaState, "DropPlayer", lua_dropPlayer); - lua_register(luaState, "GetPlayerHWID", lua_HWID); - lua_register(luaState, "exit", lua_ServerExit); - lua_register(luaState, "Sleep", lua_Sleep); - lua_register(luaState, "print", lua_Print); - lua_register(luaState, "Set", lua_Set); - if (!_Console) - Reload(); -} - -void Lua::RegisterEvent(const std::string& Event, const std::string& FunctionName) { - _RegisteredEvents.insert(std::make_pair(Event, FunctionName)); -} -void Lua::UnRegisterEvent(const std::string& Event) { - for (const std::pair& a : _RegisteredEvents) { - if (a.first == Event) { - _RegisteredEvents.erase(a); - break; - } - } -} -bool Lua::IsRegistered(const std::string& Event) { - for (const std::pair& a : _RegisteredEvents) { - if (a.first == Event) - return true; - } - return false; -} -std::string Lua::GetRegistered(const std::string& Event) const { - for (const std::pair& a : _RegisteredEvents) { - if (a.first == Event) - return a.second; - } - return ""; -} -std::string Lua::GetFileName() const { - return _FileName; -} -std::string Lua::GetPluginName() const { - return _PluginName; -} -lua_State* Lua::GetState() { - return luaState; -} - -const lua_State* Lua::GetState() const { - return luaState; -} - -void Lua::SetLastWrite(fs::file_time_type time) { - _LastWrote = time; -} -fs::file_time_type Lua::GetLastWrite() { - return _LastWrote; -} - -Lua::~Lua() { - info("closing lua state"); - lua_close(luaState); -} diff --git a/src/Network/Auth.cpp b/src/Network/Auth.cpp deleted file mode 100644 index 570e774..0000000 --- a/src/Network/Auth.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/31/2020 -/// - -#include "Curl/Http.h" -#include "Json.h" -#include "Logger.h" -#include "Network.h" -#include "Security/Enc.h" -#include "Settings.h" -#include "UnixCompat.h" -#include -#include -#include -#include - -std::string GetClientInfo(const std::string& PK) { - if (!PK.empty()) { - return PostHTTP("auth.beammp.com", "/pkToUser", {}, R"({"key":")" + PK + "\"}", true); - } - return ""; -} - -Client* CreateClient(SOCKET TCPSock) { - auto* c = new Client; - c->SetTCPSock(TCPSock); - return c; -} - -void ClientKick(Client* c, const std::string& R) { - info("Client kicked: " + R); - TCPSend(c, "E" + R); - CloseSocketProper(c->GetTCPSock()); -} - -void Authentication(SOCKET TCPSock) { - DebugPrintTID(); - auto* c = CreateClient(TCPSock); - - info("Identifying new client..."); - std::string Rc = TCPRcv(c); - - if (Rc.size() > 3 && Rc.substr(0, 2) == "VC") { - Rc = Rc.substr(2); - if (Rc.length() > 4 || Rc != GetCVer()) { - ClientKick(c, "Outdated Version!"); - return; - } - } else { - ClientKick(c, "Invalid version header!"); - return; - } - TCPSend(c, "S"); - - Rc = TCPRcv(c); - - if (Rc.size() > 50) { - ClientKick(c, "Invalid Key!"); - return; - } - - Rc = GetClientInfo(Rc); - json::Document d; - d.Parse(Rc.c_str()); - if (Rc == "-1" || d.HasParseError()) { - ClientKick(c, "Invalid key! Please restart your game."); - return; - } - - if (d["username"].IsString() && d["roles"].IsString() && d["guest"].IsBool()) { - c->SetName(d["username"].GetString()); - c->SetRoles(d["roles"].GetString()); - c->isGuest = d["guest"].GetBool(); - } else { - ClientKick(c, "Invalid authentication data!"); - return; - } - - debug("Name -> " + c->GetName() + ", Guest -> " + std::to_string(c->isGuest) + ", Roles -> " + c->GetRoles()); - for (auto& Cl : CI->Clients) { - if (Cl != nullptr) { - if (Cl->GetName() == c->GetName() && Cl->isGuest == c->isGuest) { - info("Old client (" + Cl->GetName() + ") kicked: Reconnecting"); - CloseSocketProper(Cl->GetTCPSock()); - Cl->SetStatus(-2); - break; - } - } - } - - auto arg = std::make_unique(LuaArg { { c->GetName(), c->GetRoles(), c->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(c, "you are not allowed on the server!"); - return; - } else if (Type.find("string") != std::string::npos) { - ClientKick(c, std::any_cast(Res)); - return; - } - if (CI->Size() < MaxPlayers) { - info("Identification success"); - Client& Client = *c; - CI->AddClient(std::move(c)); - TCPClient(&Client); - } else - ClientKick(c, "Server full!"); -} - -void HandleDownload(SOCKET TCPSock) { - char D; - if (recv(TCPSock, &D, 1, 0) != 1) { - CloseSocketProper(TCPSock); - return; - } - auto ID = uint8_t(D); - for (auto& c : CI->Clients) { - if (c->GetID() == ID) { - c->SetDownSock(TCPSock); - } - } -} - -void 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 TCPServerMain() { - DebugPrintTID(); -#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(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(Identify, 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, 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(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(Identify, client); - ID.detach(); - } catch (const std::exception& e) { - error(("fatal: ") + std::string(e.what())); - } - } while (client); - - debug("all ok, arrived at " + std::string(__func__) + ":" + std::to_string(__LINE__)); - CloseSocketProper(client); -#endif // WIN32 -} diff --git a/src/Network/Client.cpp b/src/Network/Client.cpp deleted file mode 100644 index 1b4ab5a..0000000 --- a/src/Network/Client.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/8/2020 -/// -#include "Client.hpp" - -#include - -void Client::DeleteCar(int ident) { - for (auto& v : VehicleData) { - if (v != nullptr && v->ID == ident) { - VehicleData.erase(v); - break; - } - } -} -void Client::ClearCars() { - VehicleData.clear(); -} -int Client::GetOpenCarID() { - int OpenID = 0; - bool found; - do { - found = true; - for (auto& v : VehicleData) { - if (v != nullptr && v->ID == OpenID) { - OpenID++; - found = false; - } - } - } while (!found); - return OpenID; -} -void Client::AddNewCar(int ident, const std::string& Data) { - VehicleData.insert(std::make_unique(VData { ident, Data })); -} - -std::set>& Client::GetAllCars() { - return VehicleData; -} - -std::string Client::GetCarData(int ident) { - for (auto& v : VehicleData) { - if (v != nullptr && v->ID == ident) { - return v->Data; - } - } - DeleteCar(ident); - return ""; -} - -void Client::SetCarData(int ident, const std::string& Data) { - for (auto& v : VehicleData) { - if (v != nullptr && v->ID == ident) { - v->Data = Data; - return; - } - } - DeleteCar(ident); -} -int Client::GetCarCount() { - return int(VehicleData.size()); -} diff --git a/src/Network/GParser.cpp b/src/Network/GParser.cpp deleted file mode 100644 index cca1edd..0000000 --- a/src/Network/GParser.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 8/1/2020 -/// - -#include "Client.hpp" -#include "Logger.h" -#include "Lua/LuaSystem.hpp" -#include "Network.h" -#include "Security/Enc.h" -#include "Settings.h" -#include "UnixCompat.h" -#undef GetObject //to fix microsoft bs -#include "Json.h" - -void Apply(Client* c, int VID, const std::string& pckt) { - Assert(c); - 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()); -} - -void VehicleParser(Client* c, const std::string& Pckt) { - Assert(c); - if (c == nullptr || 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(LuaArg { { c->GetID(), CarID, Packet.substr(3) } }), true); - if (c->GetCarCount() >= MaxCars || std::any_cast(Res)) { - Respond(c, Packet, true); - std::string Destroy = "Od:" + std::to_string(c->GetID()) + "-" + std::to_string(CarID); - Respond(c, Destroy, true); - debug(c->GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID)); - } else { - c->AddNewCar(CarID, Packet); - 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(LuaArg { { c->GetID(), VID, Packet.substr(3) } }), - true); - if (!std::any_cast(Res)) { - SendToAll(c, Packet, false, true); - Apply(c, VID, Packet); - } else { - std::string Destroy = "Od:" + std::to_string(c->GetID()) + "-" + std::to_string(VID); - 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()) { - SendToAll(nullptr, Packet, true, true); - TriggerLuaEvent(("onVehicleDeleted"), false, nullptr, - std::make_unique(LuaArg { { 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 - SendToAll(c, Packet, false, true); - return; - case 't': -#ifdef DEBUG - debug(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); -#endif - 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 SyncClient(Client* c) { - Assert(c); - if (c->isSynced) - return; - c->isSynced = true; - std::this_thread::sleep_for(std::chrono::seconds(1)); - Respond(c, ("Sn") + c->GetName(), true); - SendToAll(c, ("JWelcome ") + c->GetName() + "!", false, true); - TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique(LuaArg { { c->GetID() } }), false); - for (auto& client : CI->Clients) { - if (client != nullptr) { - if (client.get() != c) { - for (auto& v : client->GetAllCars()) { - if (v != nullptr) { - if (c->GetStatus() < 0) - return; - Respond(c, v->Data, true); - std::this_thread::sleep_for(std::chrono::seconds(2)); - } - } - } - } - } - info(c->GetName() + (" is now synced!")); -} -void ParseVeh(Client* c, const std::string& Packet) { - Assert(c); -#ifdef WIN32 - __try { - VehicleParser(c, Packet); - } __except (Handle(GetExceptionInformation(), ("Vehicle Handler"))) { } -#else // unix - VehicleParser(c, Packet); -#endif // WIN32 -} - -void HandleEvent(Client* c, const std::string& Data) { - Assert(c); - 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(LuaArg { { c->GetID(), t } }), false); - break; - default: - break; - } - if (a == 2) - break; - a++; - } -} - -void GlobalParser(Client* c, const std::string& Packet) { - Assert(c); - if (Packet.empty() || c == nullptr) - return; - std::any Res; - char Code = Packet.at(0); - - //V to Z - if (Code <= 90 && Code >= 86) { - PPS++; - SendToAll(c, 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(c); - return; - case 'p': - Respond(c, ("p"), false); - UpdatePlayers(); - return; - case 'O': - if (Packet.length() > 1000) { - debug(("Received data from: ") + c->GetName() + (" Size: ") + std::to_string(Packet.length())); - } - ParseVeh(c, Packet); - return; - case 'J': -#ifdef DEBUG - debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); -#endif - SendToAll(c, 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 { { c->GetID(), c->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(c, Packet); - return; - default: - return; - } -} - -void GParser(Client* c, const std::string& Packet) { - Assert(c); - if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) { - abort(); - } -#ifdef WIN32 - __try { - GlobalParser(c, Packet); - } __except (Handle(GetExceptionInformation(), ("Global Handler"))) { } -#else - GlobalParser(c, Packet); -#endif // WIN32 -} diff --git a/src/Network/Http.cpp b/src/Network/Http.cpp deleted file mode 100644 index ff82c70..0000000 --- a/src/Network/Http.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 4/9/2020 -/// - -#include "CustomAssert.h" -#include -#include -#include -#include -#include - -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -namespace ssl = net::ssl; // from -using tcp = net::ip::tcp; // from - -// UNUSED?! -std::string HttpRequest(const std::string& host, int port, const std::string& target) { - // FIXME: this is likely not very well written. - // if it causes issues, yell at me and I'll fix it asap. - Lion - try { - net::io_context io; - tcp::resolver resolver(io); - beast::tcp_stream stream(io); - auto const results = resolver.resolve(host, std::to_string(port)); - stream.connect(results); - - http::request req { http::verb::get, target, 11 /* http 1.1 */ }; - - req.set(http::field::host, host); - // tell the server what we are (boost beast) - req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); - - http::write(stream, req); - - // used for reading - beast::flat_buffer buffer; - http::response response; - - http::read(stream, buffer, response); - - std::string result(response.body()); - - beast::error_code ec; - stream.socket().shutdown(tcp::socket::shutdown_both, ec); - if (ec && ec != beast::errc::not_connected) { - throw beast::system_error { ec }; // goes down to `return "-1"` anyways - } - - return result; - - } catch (const std::exception& e) { - error(e.what()); - return "-1"; - } -} - -std::string PostHTTP(const std::string& host, const std::string& target, const std::unordered_map& fields, const std::string& body, bool json) { - try { - net::io_context io; - - // The SSL context is required, and holds certificates - ssl::context ctx(ssl::context::tlsv13); - - ctx.set_verify_mode(ssl::verify_none); - - tcp::resolver resolver(io); - beast::ssl_stream stream(io, ctx); - decltype(resolver)::results_type results; - auto try_connect_with_protocol = [&](tcp protocol) { - try { - results = resolver.resolve(protocol, host, std::to_string(443)); - if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) { - boost::system::error_code ec { static_cast(::ERR_get_error()), boost::asio::error::get_ssl_category() }; - // FIXME: we could throw and crash, if we like - // throw boost::system::system_error { ec }; - debug("POST " + host + target + " failed."); - return false; - } - beast::get_lowest_layer(stream).connect(results); - } catch (const boost::system::system_error&) { - return false; - } - return true; - }; - //bool ok = try_connect_with_protocol(tcp::v6()); - //if (!ok) { - //debug("IPv6 connect failed, trying IPv4"); - bool ok = try_connect_with_protocol(tcp::v4()); - if (!ok) { - error("failed to resolve or connect in POST " + host + target); - return "-1"; - } - //} - stream.handshake(ssl::stream_base::client); - http::request req { http::verb::post, target, 11 /* http 1.1 */ }; - - req.set(http::field::host, host); - if (!body.empty()) { - if (json) { - // FIXME: json is untested. - req.set(http::field::content_type, "application/json"); - } else { - req.set(http::field::content_type, "application/x-www-form-urlencoded"); - } - req.set(http::field::content_length, std::to_string(body.size())); - req.body() = body; - // info("body is " + body + " (" + req.body() + ")"); - // info("content size is " + std::to_string(body.size()) + " (" + boost::lexical_cast(body.size()) + ")"); - } - for (const auto& pair : fields) { - // info("setting " + pair.first + " to " + pair.second); - req.set(pair.first, pair.second); - } - - std::stringstream oss; - oss << req; - - beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(5)); - - http::write(stream, req); - - // used for reading - beast::flat_buffer buffer; - http::response response; - - http::read(stream, buffer, response); - - std::stringstream result; - result << response; - - beast::error_code ec; - stream.shutdown(ec); - // IGNORING ec - - // info(result.str()); - std::string debug_response_str; - std::getline(result, debug_response_str); - debug("POST " + host + target + ": " + debug_response_str); - return std::string(response.body()); - - } catch (const std::exception& e) { - error(e.what()); - return "-1"; - } -} diff --git a/src/Network/InitClient.cpp b/src/Network/InitClient.cpp deleted file mode 100644 index 1234cd4..0000000 --- a/src/Network/InitClient.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 8/1/2020 -/// -#include "Client.hpp" -#include "Logger.h" -#include "Lua/LuaSystem.hpp" -#include "Network.h" -#include "Settings.h" -#include "UnixCompat.h" -#include - -int OpenID() { - int ID = 0; - bool found; - do { - found = true; - for (auto& c : CI->Clients) { - if (c != nullptr) { - if (c->GetID() == ID) { - found = false; - ID++; - } - } - } - } while (!found); - return ID; -} -void Respond(Client* c, const std::string& MSG, bool Rel) { - Assert(c); - 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 { - UDPSend(c, MSG); - } -} -void SendToAll(Client* c, const std::string& Data, bool Self, bool Rel) { - if (!Self) - Assert(c); - char C = Data.at(0); - for (auto& client : CI->Clients) { - if (client != nullptr) { - if (Self || client.get() != c) { - if (client->isSynced) { - if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { - if (C == 'O' || C == 'T' || Data.length() > 1000) - SendLarge(client.get(), Data); - else - TCPSend(client.get(), Data); - } else - UDPSend(client.get(), Data); - } - } - } - } -} -void UpdatePlayers() { - std::string Packet = ("Ss") + std::to_string(CI->Size()) + "/" + std::to_string(MaxPlayers) + ":"; - for (auto& c : CI->Clients) { - if (c != nullptr) - Packet += c->GetName() + ","; - } - Packet = Packet.substr(0, Packet.length() - 1); - SendToAll(nullptr, Packet, true, true); -} -void OnDisconnect(Client* c, bool kicked) { - Assert(c); - 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); - SendToAll(c, Packet, false, true); - } - } - if (kicked) - Packet = ("L") + c->GetName() + (" was kicked!"); - else - Packet = ("L") + c->GetName() + (" left the server!"); - SendToAll(c, Packet, false, true); - Packet.clear(); - TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique(LuaArg { { c->GetID() } }), false); - if (c->GetTCPSock()) - CloseSocketProper(c->GetTCPSock()); - if (c->GetDownSock()) - CloseSocketProper(c->GetDownSock()); - CI->RemoveClient(c); -} -void OnConnect(Client* c) { - Assert(c); - info("Client connected"); - c->SetID(OpenID()); - info("Assigned ID " + std::to_string(c->GetID()) + " to " + c->GetName()); - TriggerLuaEvent("onPlayerConnecting", false, nullptr, std::make_unique(LuaArg { { c->GetID() } }), false); - SyncResources(c); - if (c->GetStatus() < 0) - return; - Respond(c, "M" + MapName, true); //Send the Map on connect - info(c->GetName() + " : Connected"); - TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique(LuaArg { { c->GetID() } }), false); -} diff --git a/src/Network/NetMain.cpp b/src/Network/NetMain.cpp deleted file mode 100644 index d1c94fa..0000000 --- a/src/Network/NetMain.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "Network.h" -#include -#include -std::unique_ptr CI; -void NetMain() { - std::thread TCP(TCPServerMain); - TCP.detach(); - UDPServerMain(); -} diff --git a/src/Network/StatMonitor.cpp b/src/Network/StatMonitor.cpp deleted file mode 100644 index 6d810f6..0000000 --- a/src/Network/StatMonitor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 6/18/2020 -/// -#include "Client.hpp" -#include "Security/Enc.h" -#include -#include -#include -std::string StatReport; -int PPS = 0; -void Monitor() { - int C = 0, V = 0; - if (CI->Clients.empty()) { - StatReport = "-"; - return; - } - for (auto& c : CI->Clients) { - if (c != nullptr && c->GetCarCount() > 0) { - C++; - V += c->GetCarCount(); - } - } - if (C == 0 || PPS == 0) { - StatReport = "-"; - } else { - int R = (PPS / C) / V; - StatReport = std::to_string(R); - } - PPS = 0; -} - -[[noreturn]] void Stat() { - DebugPrintTID(); - while (true) { - Monitor(); - std::this_thread::sleep_for(std::chrono::seconds(1)); - } -} - -void StatInit() { - StatReport = "-"; - std::thread Init(Stat); - Init.detach(); -} diff --git a/src/Network/Sync.cpp b/src/Network/Sync.cpp deleted file mode 100644 index 9b4a231..0000000 --- a/src/Network/Sync.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 8/1/2020 -/// - -#include "Client.hpp" -#include "Logger.h" -#include "Network.h" -#include "Security/Enc.h" -#include "Settings.h" -#include "UnixCompat.h" -#include -#include - -bool 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 SplitLoad(Client* 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(); -} - -void SendFile(Client* c, const std::string& Name) { - Assert(c); - 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 Dt(SplitLoad, c, 0, MSize, false, Name); - Dt.detach(); - - SplitLoad(c, MSize, Size, true, Name); - - if (Dt.joinable()) - Dt.join(); -} - -void Parse(Client* c, const std::string& Packet) { - Assert(c); - if (c == nullptr || 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 = FileList + FileSizes; - if (ToSend.empty()) - ToSend = "-"; - TCPSend(c, ToSend); - } - return; - default: - return; - } -} - -void SyncResources(Client* c) { - Assert(c); - if (c == nullptr) - return; -#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 -} diff --git a/src/Network/TCPHandler.cpp b/src/Network/TCPHandler.cpp deleted file mode 100644 index 866dd7e..0000000 --- a/src/Network/TCPHandler.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 8/1/2020 -/// -#include "Compressor.h" -#include "Logger.h" -#include "Network.h" -#include "Security/Enc.h" -#include "UnixCompat.h" -#include - -bool TCPSend(Client* c, const std::string& Data) { - Assert(c); - if (c == nullptr) - return false; - - 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 CheckBytes(Client* c, int32_t BytesRcv) { - Assert(c); - 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 TCPRcv(Client* c) { - Assert(c); - int32_t Header, BytesRcv = 0, Temp; - if (c == nullptr || 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 TCPClient(Client* c) { - DebugPrintTIDInternal("Client(" + c->GetName() + ")", true); - Assert(c); - if (c->GetTCPSock() == -1) { - CI->RemoveClient(c); - return; - } - OnConnect(c); - while (c->GetStatus() > -1) { - GParser(c, TCPRcv(c)); - } - OnDisconnect(c, c->GetStatus() == -2); -} diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp deleted file mode 100644 index 1834d9b..0000000 --- a/src/Network/VehicleData.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 5/8/2020 -/// - -#include "Client.hpp" -#include "Compressor.h" -#include "Logger.h" -#include "Network.h" -#include "Security/Enc.h" -#include "Settings.h" -#include "UnixCompat.h" -#include -#include -#include -#include -#include -#include - -SOCKET UDPSock; -void UDPSend(Client* c, std::string Data) { - Assert(c); - if (c == nullptr || !c->isConnected || c->GetStatus() < 0) - return; - sockaddr_in Addr = c->GetUDPAddr(); - socklen_t AddrSize = sizeof(c->GetUDPAddr()); - if (Data.length() > 400) { - std::string CMP(Comp(Data)); - Data = "ABG:" + CMP; - } -#ifdef WIN32 - int sendOk; - int len = static_cast(Data.size()); -#else - int64_t sendOk; - size_t len = Data.size(); -#endif // WIN32 - - sendOk = sendto(UDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, AddrSize); -#ifdef WIN32 - if (sendOk == -1) { - debug(("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError())); - if (c->GetStatus() > -1) - c->SetStatus(-1); - } else if (sendOk == 0) { - debug(("(UDP) sendto returned 0")); - if (c->GetStatus() > -1) - c->SetStatus(-1); - } -#else // unix - if (sendOk == -1) { - debug(("(UDP) Send Failed Code : ") + std::string(strerror(errno))); - if (c->GetStatus() > -1) - c->SetStatus(-1); - } else if (sendOk == 0) { - debug(("(UDP) sendto returned 0")); - if (c->GetStatus() > -1) - c->SetStatus(-1); - } -#endif // WIN32 -} - -void SendLarge(Client* c, std::string Data) { - Assert(c); - if (Data.length() > 400) { - std::string CMP(Comp(Data)); - Data = "ABG:" + CMP; - } - TCPSend(c, Data); -} - -std::string UDPRcvFromClient(sockaddr_in& client) { - size_t clientLength = sizeof(client); - std::array Ret{}; - int64_t Rcv = recvfrom(UDPSock, Ret.data(), Ret.size(), 0, (sockaddr*)&client, (socklen_t*)&clientLength); - if (Rcv == -1) { -#ifdef WIN32 - error(("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError())); -#else // unix - error(("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno))); -#endif // WIN32 - return ""; - } - return std::string(Ret.begin(), Ret.begin() + Rcv); -} - -void UDPParser(Client* c, std::string Packet) { - if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) { - abort(); - } - Assert(c); - if (Packet.substr(0, 4) == "ABG:") { - Packet = DeComp(Packet.substr(4)); - } - GParser(c, Packet); -} - -[[noreturn]] void UDPServerMain() { -#ifdef WIN32 - WSADATA data; - if (WSAStartup(514, &data)) { - error(("Can't start Winsock!")); - //return; - } - - UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - // Create a server hint structure for the server - sockaddr_in serverAddr {}; - serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local - serverAddr.sin_family = AF_INET; // Address format is IPv4 - serverAddr.sin_port = htons(Port); // Convert from little to big endian - - // Try and bind the socket to the IP and port - if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { - error(("Can't bind socket!") + std::to_string(WSAGetLastError())); - std::this_thread::sleep_for(std::chrono::seconds(5)); - _Exit(-1); - //return; - } - - info(("Vehicle data network online on port ") + std::to_string(Port) + (" with a Max of ") + std::to_string(MaxPlayers) + (" Clients")); - while (true) { - try { - sockaddr_in client {}; - std::string Data = UDPRcvFromClient(client); //Receives any data from Socket - auto Pos = Data.find(':'); - if (Data.empty() || Pos == std::string::npos || Pos > 2) - continue; - /*char clientIp[256]; - ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet - inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ - uint8_t ID = Data.at(0) - 1; - for (auto& c : CI->Clients) { - if (c != nullptr && c->GetID() == ID) { - c->SetUDPAddr(client); - c->isConnected = true; - UDPParser(c.get(), Data.substr(2)); - } - } - } catch (const std::exception& e) { - error(("fatal: ") + std::string(e.what())); - } - } - /*CloseSocketProper(UDPSock); - WSACleanup(); - return;*/ -#else // unix - UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - // Create a server hint structure for the server - sockaddr_in serverAddr {}; - serverAddr.sin_addr.s_addr = INADDR_ANY; //Any Local - serverAddr.sin_family = AF_INET; // Address format is IPv4 - serverAddr.sin_port = htons(uint16_t(Port)); // Convert from little to big endian - - // Try and bind the socket to the IP and port - if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) { - error(("Can't bind socket!") + std::string(strerror(errno))); - std::this_thread::sleep_for(std::chrono::seconds(5)); - _Exit(-1); - //return; - } - - info(("Vehicle data network online on port ") + std::to_string(Port) + (" with a Max of ") + std::to_string(MaxPlayers) + (" Clients")); - while (true) { - try { - sockaddr_in client {}; - std::string Data = UDPRcvFromClient(client); //Receives any data from Socket - size_t Pos = Data.find(':'); - if (Data.empty() || Pos > 2) - continue; - /*char clientIp[256]; - ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet - inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ - uint8_t ID = uint8_t(Data.at(0)) - 1; - for (auto& c : CI->Clients) { - if (c != nullptr && c->GetID() == ID) { - c->SetUDPAddr(client); - c->isConnected = true; - UDPParser(c.get(), Data.substr(2)); - } - } - } catch (const std::exception& e) { - error(("fatal: ") + std::string(e.what())); - } - } - /*CloseSocketProper(UDPSock); // TODO: Why not this? We did this in TCPServerMain? - return; - */ -#endif // WIN32 -} diff --git a/src/Network/Websocket.cpp b/src/Network/Websocket.cpp deleted file mode 100644 index a7789bc..0000000 --- a/src/Network/Websocket.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 11/6/2020 -/// -/*#include -#include "Logger.h" -#include "Security/Enc.h" -#include -#include -#include -#include -#include -#include */ - -/*namespace beast = boost::beast; -namespace http = beast::http; -namespace websocket = beast::websocket; -namespace net = boost::asio; -using tcp = boost::asio::ip::tcp; - -std::string GetRes(const beast::flat_buffer& buff) { - return (char*)buff.data().data(); -}*/ - -void SyncData() { - /*DebugPrintTID(); - try { - std::string const host = ("95.216.35.232"); - - net::io_context ioc; - tcp::resolver r(ioc); - - websocket::stream ws(ioc); - auto const results = r.resolve(host, ("3600")); - net::connect(ws.next_layer(), results.begin(), results.end()); - - - ws.handshake(host, "/"); - beast::flat_buffer buffer; - ws.write(boost::asio::buffer("Hello, world!")); - ws.read(buffer); - - std::cout << GetRes(buffer) << std::endl; - - ws.close(websocket::close_code::normal); - - }catch(std::exception const& e){ - error(e.what()); - std::this_thread::sleep_for(std::chrono::seconds(3)); - _Exit(0); - }*/ -} - -void WebsocketInit() { - /*std::thread t1(SyncData); - t1.detach();*/ -} diff --git a/src/TConsole.cpp b/src/TConsole.cpp new file mode 100644 index 0000000..18270de --- /dev/null +++ b/src/TConsole.cpp @@ -0,0 +1,17 @@ +#include "TConsole.h" +#include "Compat.h" + +TConsole::TConsole() { + _Commandline.enable_history(); + _Commandline.set_history_limit(20); + _Commandline.on_command = [](Commandline& c) { + auto cmd = c.get_command(); + if (cmd == "exit") { + _Exit(0); + } else if (cmd == "clear" || cmd == "cls") { + // TODO: clear screen + } else { + // TODO: execute as lua + } + }; +} diff --git a/src/logger.cpp b/src/logger.cpp deleted file mode 100644 index 2260b6e..0000000 --- a/src/logger.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2019-present Anonymous275. -// BeamMP Server code is not in the public domain and is not free software. -// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries. -// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. -/// -/// Created by Anonymous275 on 7/17/2020 -/// -#include "Logger.h" -#include "RWMutex.h" -#include "Security/Enc.h" -#include "Settings.h" -#include -#include -#include -#include -#include -#include - -static RWMutex ThreadNameMapMutex; -static std::unordered_map ThreadNameMap; - -std::string ThreadName() { - ReadLock lock(ThreadNameMapMutex); - std::string Name; - if (ThreadNameMap.find(std::this_thread::get_id()) != ThreadNameMap.end()) { - Name = ThreadNameMap.at(std::this_thread::get_id()); - } else { - std::stringstream ss; - ss << std::this_thread::get_id(); - Name = ss.str(); - } - return Name; -} - -void SetThreadName(const std::string& Name, bool overwrite) { - WriteLock lock(ThreadNameMapMutex); - if (overwrite || ThreadNameMap.find(std::this_thread::get_id()) == ThreadNameMap.end()) { - ThreadNameMap[std::this_thread::get_id()] = Name; - } -} - -std::string getDate() { - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - time_t tt = std::chrono::system_clock::to_time_t(now); - tm local_tm {}; -#ifdef WIN32 - localtime_s(&local_tm, &tt); -#else // unix - localtime_r(&tt, &local_tm); -#endif // WIN32 - std::stringstream date; - int S = local_tm.tm_sec; - int M = local_tm.tm_min; - int H = local_tm.tm_hour; - std::string Secs = (S > 9 ? std::to_string(S) : "0" + std::to_string(S)); - std::string Min = (M > 9 ? std::to_string(M) : "0" + std::to_string(M)); - std::string Hour = (H > 9 ? std::to_string(H) : "0" + std::to_string(H)); - date - << "[" - << local_tm.tm_mday << "/" - << local_tm.tm_mon + 1 << "/" - << local_tm.tm_year + 1900 << " " - << Hour << ":" - << Min << ":" - << Secs - << "] "; - if (Debug) { - date << ThreadName() - << " "; - } - return date.str(); -} - -void InitLog() { - std::ofstream LFS; - LFS.open(("Server.log")); - if (!LFS.is_open()) { - error(("logger file init failed!")); - } else - LFS.close(); -} -std::mutex LogLock; - -void DebugPrintTIDInternal(const std::string& func, bool overwrite) { - // we need to print to cout here as we might crash before all console output is handled, - // due to segfaults or asserts. - SetThreadName(func, overwrite); -#ifdef DEBUG - std::scoped_lock Guard(LogLock); - std::stringstream Print; - Print << "(debug build) Thread '" << std::this_thread::get_id() << "' is " << func << "\n"; - ConsoleOut(Print.str()); -#endif // DEBUG -} - -void addToLog(const std::string& Line) { - std::ofstream LFS("Server.log", std::ios_base::app); - LFS << Line.c_str(); -} -void info(const std::string& toPrint) { - std::scoped_lock Guard(LogLock); - std::string Print = getDate() + ("[INFO] ") + toPrint + "\n"; - ConsoleOut(Print); - addToLog(Print); -} -void debug(const std::string& toPrint) { - if (!Debug) - return; - std::scoped_lock Guard(LogLock); - std::string Print = getDate() + ("[DEBUG] ") + toPrint + "\n"; - ConsoleOut(Print); - addToLog(Print); -} -void warn(const std::string& toPrint) { - std::scoped_lock Guard(LogLock); - std::string Print = getDate() + ("[WARN] ") + toPrint + "\n"; - ConsoleOut(Print); - addToLog(Print); -} -void error(const std::string& toPrint) { - std::scoped_lock Guard(LogLock); - std::string Print = getDate() + ("[ERROR] ") + toPrint + "\n"; - ConsoleOut(Print); - addToLog(Print); -} -void except(const std::string& toPrint) { - std::scoped_lock Guard(LogLock); - std::string Print = getDate() + ("[EXCEP] ") + toPrint + "\n"; - ConsoleOut(Print); - addToLog(Print); -} diff --git a/src/main.cpp b/src/main.cpp index f39f1f7..2f06ab7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,50 +1,12 @@ -#include "CustomAssert.h" - -#include "Settings.h" -#include "Startup.h" +#include +#include #include #include -#ifndef WIN32 -#include -void UnixSignalHandler(int sig) { - switch (sig) { - case SIGPIPE: - warn(("ignored signal SIGPIPE: Pipe broken")); - break; - default: - error(("Signal arrived in handler but was not handled: ") + std::to_string(sig)); - break; - } -} -#endif // WIN32 -[[noreturn]] void loop() { - DebugPrintTID(); +#include "TConsole.h" + +int main(int argc, char** argv) { + TConsole Console; while (true) { - std::cout.flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(600)); } } - -int main(int argc, char* argv[]) { -#ifndef WIN32 - // ignore SIGPIPE, the signal that is sent for example when a client - // disconnects while data is being sent to him ("broken pipe"). - signal(SIGPIPE, UnixSignalHandler); -#endif // WIN32 - DebugPrintTID(); -#ifdef DEBUG - std::thread t1(loop); - t1.detach(); -#endif - StartTime = std::chrono::high_resolution_clock::now(); - ConsoleInit(); - InitServer(argc, argv); - InitConfig(); - InitLua(); - InitRes(); - HBInit(); - StatInit(); - NetMain(); - return 0; -}