mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 18:24:16 +00:00
Compare commits
2 Commits
v3.9.2
..
update-lua
| Author | SHA1 | Date | |
|---|---|---|---|
| 43e86a1e22 | |||
| 70fc8436ed |
@@ -3,8 +3,8 @@ name: Linux
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "develop"
|
- 'develop'
|
||||||
- "minor"
|
- 'minor'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -21,8 +21,6 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: debian
|
|
||||||
version: 13
|
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
version: 22.04
|
version: 22.04
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -47,7 +45,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: 'recursive'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
@@ -93,8 +91,6 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: debian
|
|
||||||
version: 13
|
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
version: 22.04
|
version: 22.04
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -119,7 +115,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: 'recursive'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
@@ -155,3 +151,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: ./bin/BeamMP-Server-tests
|
run: ./bin/BeamMP-Server-tests
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
# Sequence of patterns matched against refs/tags
|
# Sequence of patterns matched against refs/tags
|
||||||
tags:
|
tags:
|
||||||
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
@@ -40,8 +40,6 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: debian
|
|
||||||
version: 13
|
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
version: 22.04
|
version: 22.04
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -66,7 +64,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: 'recursive'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
@@ -112,8 +110,6 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: debian
|
|
||||||
version: 13
|
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
version: 22.04
|
version: 22.04
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -141,7 +137,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: 'recursive'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
@@ -195,7 +191,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: 'recursive'
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
|
|||||||
+6
-3
@@ -80,14 +80,15 @@ set(PRJ_SOURCES
|
|||||||
src/ChronoWrapper.cpp
|
src/ChronoWrapper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Lua REQUIRED)
|
# fix for sol2
|
||||||
|
find_path(LUAJIT_INCLUDE_DIR lua.hpp PATH_SUFFIXES luajit)
|
||||||
|
|
||||||
# set the source file containing main()
|
# set the source file containing main()
|
||||||
set(PRJ_MAIN src/main.cpp)
|
set(PRJ_MAIN src/main.cpp)
|
||||||
# set the source file containing the test's main
|
# set the source file containing the test's main
|
||||||
set(PRJ_TEST_MAIN test/test_main.cpp)
|
set(PRJ_TEST_MAIN test/test_main.cpp)
|
||||||
# set include paths not part of libraries
|
# set include paths not part of libraries
|
||||||
set(PRJ_INCLUDE_DIRS ${LUA_INCLUDE_DIR})
|
set(PRJ_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIR})
|
||||||
# set compile features (e.g. standard version)
|
# set compile features (e.g. standard version)
|
||||||
set(PRJ_COMPILE_FEATURES cxx_std_20)
|
set(PRJ_COMPILE_FEATURES cxx_std_20)
|
||||||
# set #defines (test enable/disable not included here)
|
# set #defines (test enable/disable not included here)
|
||||||
@@ -105,9 +106,11 @@ set(PRJ_LIBRARIES
|
|||||||
libzip::zip
|
libzip::zip
|
||||||
OpenSSL::SSL OpenSSL::Crypto
|
OpenSSL::SSL OpenSSL::Crypto
|
||||||
CURL::libcurl
|
CURL::libcurl
|
||||||
${LUA_LIBRARIES}
|
lua51
|
||||||
)
|
)
|
||||||
|
|
||||||
|
link_directories(${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib)
|
||||||
|
|
||||||
# add dependency find_package calls and similar here
|
# add dependency find_package calls and similar here
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|||||||
+1
-1
@@ -129,7 +129,7 @@ private:
|
|||||||
static inline std::mutex mShutdownHandlersMutex {};
|
static inline std::mutex mShutdownHandlersMutex {};
|
||||||
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
||||||
|
|
||||||
static inline Version mVersion { 3, 9, 2 };
|
static inline Version mVersion { 3, 9, 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
void SplitString(std::string const& str, const char delim, std::vector<std::string>& out);
|
void SplitString(std::string const& str, const char delim, std::vector<std::string>& out);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ enum class Key {
|
|||||||
// provider settings
|
// provider settings
|
||||||
PROVIDER_UPDATE_MESSAGE,
|
PROVIDER_UPDATE_MESSAGE,
|
||||||
PROVIDER_DISABLE_CONFIG,
|
PROVIDER_DISABLE_CONFIG,
|
||||||
PROVIDER_DISABLE_MP_SET,
|
|
||||||
PROVIDER_PORT_ENV,
|
PROVIDER_PORT_ENV,
|
||||||
PROVIDER_IP_ENV
|
PROVIDER_IP_ENV
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ namespace MP {
|
|||||||
std::pair<bool, std::string> TriggerClientEventJson(int PlayerID, const std::string& EventName, const sol::table& Data);
|
std::pair<bool, std::string> TriggerClientEventJson(int PlayerID, const std::string& EventName, const sol::table& Data);
|
||||||
inline size_t GetPlayerCount() { return Engine->Server().ClientCount(); }
|
inline size_t GetPlayerCount() { return Engine->Server().ClientCount(); }
|
||||||
std::pair<bool, std::string> DropPlayer(int ID, std::optional<std::string> MaybeReason);
|
std::pair<bool, std::string> DropPlayer(int ID, std::optional<std::string> MaybeReason);
|
||||||
std::pair<bool, std::string> SendChatMessage(int ID, const std::string& Message, const bool& LogChat = true);
|
std::pair<bool, std::string> SendChatMessage(int ID, const std::string& Message);
|
||||||
std::pair<bool, std::string> SendNotification(int ID, const std::string& Message, const std::string& Icon, const std::string& Category);
|
std::pair<bool, std::string> SendNotification(int ID, const std::string& Message, const std::string& Icon, const std::string& Category);
|
||||||
std::pair<bool, std::string> ConfirmationDialog(int ID, const std::string& Title, const std::string& Body, const sol::table& buttons, const std::string& InteractionID, const bool& warning = false, const bool& reportToServer = true, const bool& reportToExtensions = true);
|
std::pair<bool, std::string> ConfirmationDialog(int ID, const std::string& Title, const std::string& Body, const sol::table& buttons, const std::string& InteractionID, const bool& warning = false, const bool& reportToServer = true, const bool& reportToExtensions = true);
|
||||||
std::pair<bool, std::string> RemoveVehicle(int PlayerID, int VehicleID);
|
std::pair<bool, std::string> RemoveVehicle(int PlayerID, int VehicleID);
|
||||||
|
|||||||
+6
-11
@@ -34,11 +34,9 @@ public:
|
|||||||
[[nodiscard]] bool TCPSend(TClient& c, const std::vector<uint8_t>& Data, bool IsSync = false);
|
[[nodiscard]] bool TCPSend(TClient& c, const std::vector<uint8_t>& Data, bool IsSync = false);
|
||||||
[[nodiscard]] bool SendLarge(TClient& c, std::vector<uint8_t> Data, bool isSync = false);
|
[[nodiscard]] bool SendLarge(TClient& c, std::vector<uint8_t> Data, bool isSync = false);
|
||||||
[[nodiscard]] bool Respond(TClient& c, const std::vector<uint8_t>& MSG, bool Rel, bool isSync = false);
|
[[nodiscard]] bool Respond(TClient& c, const std::vector<uint8_t>& MSG, bool Rel, bool isSync = false);
|
||||||
std::shared_ptr<TClient> CreateClient(boost::asio::ip::tcp::socket&& TCPSock);
|
std::shared_ptr<TClient> CreateClient(ip::tcp::socket&& TCPSock);
|
||||||
std::vector<uint8_t> TCPRcv(TClient& c);
|
std::vector<uint8_t> TCPRcv(TClient& c);
|
||||||
void ClientKick(TClient& c, const std::string& R);
|
void ClientKick(TClient& c, const std::string& R);
|
||||||
void DisconnectClient(const std::weak_ptr<TClient>& c, const std::string& R);
|
|
||||||
void DisconnectClient(TClient& c, const std::string& R);
|
|
||||||
[[nodiscard]] bool SyncClient(const std::weak_ptr<TClient>& c);
|
[[nodiscard]] bool SyncClient(const std::weak_ptr<TClient>& c);
|
||||||
void Identify(TConnection&& client);
|
void Identify(TConnection&& client);
|
||||||
std::shared_ptr<TClient> Authentication(TConnection&& ClientConnection);
|
std::shared_ptr<TClient> Authentication(TConnection&& ClientConnection);
|
||||||
@@ -46,7 +44,6 @@ public:
|
|||||||
[[nodiscard]] bool UDPSend(TClient& Client, std::vector<uint8_t> Data);
|
[[nodiscard]] bool UDPSend(TClient& Client, std::vector<uint8_t> Data);
|
||||||
void SendToAll(TClient* c, const std::vector<uint8_t>& Data, bool Self, bool Rel);
|
void SendToAll(TClient* c, const std::vector<uint8_t>& Data, bool Self, bool Rel);
|
||||||
void UpdatePlayer(TClient& Client);
|
void UpdatePlayer(TClient& Client);
|
||||||
boost::system::error_code ReadWithTimeout(TConnection& Connection, void* Buf, size_t Len, std::chrono::steady_clock::duration Timeout);
|
|
||||||
|
|
||||||
TResourceManager& ResourceManager() const { return mResourceManager; }
|
TResourceManager& ResourceManager() const { return mResourceManager; }
|
||||||
|
|
||||||
@@ -56,15 +53,13 @@ private:
|
|||||||
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
TPPSMonitor& mPPSMonitor;
|
TPPSMonitor& mPPSMonitor;
|
||||||
boost::asio::ip::udp::socket mUDPSock;
|
ip::udp::socket mUDPSock;
|
||||||
TResourceManager& mResourceManager;
|
TResourceManager& mResourceManager;
|
||||||
std::thread mUDPThread;
|
std::thread mUDPThread;
|
||||||
std::thread mTCPThread;
|
std::thread mTCPThread;
|
||||||
std::mutex mOpenIDMutex;
|
std::mutex mOpenIDMutex;
|
||||||
std::map<std::string, uint16_t> mClientMap;
|
|
||||||
std::mutex mClientMapMutex;
|
|
||||||
|
|
||||||
std::vector<uint8_t> UDPRcvFromClient(boost::asio::ip::udp::endpoint& ClientEndpoint);
|
std::vector<uint8_t> UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint);
|
||||||
void OnConnect(const std::weak_ptr<TClient>& c);
|
void OnConnect(const std::weak_ptr<TClient>& c);
|
||||||
void TCPClient(const std::weak_ptr<TClient>& c);
|
void TCPClient(const std::weak_ptr<TClient>& c);
|
||||||
void Looper(const std::weak_ptr<TClient>& c);
|
void Looper(const std::weak_ptr<TClient>& c);
|
||||||
@@ -72,9 +67,9 @@ private:
|
|||||||
void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr);
|
void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr);
|
||||||
void Parse(TClient& c, const std::vector<uint8_t>& Packet);
|
void Parse(TClient& c, const std::vector<uint8_t>& Packet);
|
||||||
void SendFile(TClient& c, const std::string& Name);
|
void SendFile(TClient& c, const std::string& Name);
|
||||||
static bool TCPSendRaw(TClient& C, boost::asio::ip::tcp::socket& socket, const uint8_t* Data, size_t Size);
|
static bool TCPSendRaw(TClient& C, ip::tcp::socket& socket, const uint8_t* Data, size_t Size);
|
||||||
void SendFileToClient(TClient& c, size_t Size, const std::string& Name);
|
static void SendFileToClient(TClient& c, size_t Size, const std::string& Name);
|
||||||
static const uint8_t* SendSplit(TClient& c, boost::asio::ip::tcp::socket& Socket, const uint8_t* DataPtr, size_t Size);
|
static const uint8_t* SendSplit(TClient& c, ip::tcp::socket& Socket, const uint8_t* DataPtr, size_t Size);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string HashPassword(const std::string& str);
|
std::string HashPassword(const std::string& str);
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ set -ex
|
|||||||
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
./vcpkg/bootstrap-vcpkg.sh
|
||||||
|
|
||||||
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--export-dynamic" -DBeamMP-Server_ENABLE_LTO=ON
|
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ set -ex
|
|||||||
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
./vcpkg/bootstrap-vcpkg.sh
|
||||||
|
|
||||||
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--export-dynamic" -DBeamMP-Server_ENABLE_LTO=ON
|
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
apt-get update -y
|
|
||||||
|
|
||||||
apt-get install -y liblua5.3-0 liblua5.3-dev curl zip unzip tar cmake make git g++ ninja-build
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
git config --global --add safe.directory $(pwd)
|
|
||||||
git config --global --add safe.directory $(pwd)/vcpkg
|
|
||||||
git config --global --add safe.directory $(pwd)/deps/commandline
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
|
||||||
|
|
||||||
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--export-dynamic" -DBeamMP-Server_ENABLE_LTO=ON
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
cmake --build bin --parallel -t BeamMP-Server-tests
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
cmake --build bin --parallel -t BeamMP-Server
|
|
||||||
|
|
||||||
objcopy --only-keep-debug bin/BeamMP-Server bin/BeamMP-Server.debug
|
|
||||||
objcopy --add-gnu-debuglink bin/BeamMP-Server bin/BeamMP-Server.debug
|
|
||||||
|
|
||||||
strip -s bin/BeamMP-Server
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
apt-get update -y
|
|
||||||
|
|
||||||
apt-get install -y liblua5.3-0 curl
|
|
||||||
|
|
||||||
@@ -4,4 +4,4 @@ set -ex
|
|||||||
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
./vcpkg/bootstrap-vcpkg.sh
|
||||||
|
|
||||||
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--export-dynamic" -DBeamMP-Server_ENABLE_LTO=ON
|
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ set -ex
|
|||||||
|
|
||||||
./vcpkg/bootstrap-vcpkg.sh
|
./vcpkg/bootstrap-vcpkg.sh
|
||||||
|
|
||||||
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--export-dynamic" -DBeamMP-Server_ENABLE_LTO=ON
|
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -g -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ std::string_view Env::ToString(Env::Key key) {
|
|||||||
case Key::PROVIDER_DISABLE_CONFIG:
|
case Key::PROVIDER_DISABLE_CONFIG:
|
||||||
return "BEAMMP_PROVIDER_DISABLE_CONFIG";
|
return "BEAMMP_PROVIDER_DISABLE_CONFIG";
|
||||||
break;
|
break;
|
||||||
case Key::PROVIDER_DISABLE_MP_SET:
|
|
||||||
return "BEAMMP_PROVIDER_DISABLE_MP_SET";
|
|
||||||
break;
|
|
||||||
case Key::PROVIDER_PORT_ENV:
|
case Key::PROVIDER_PORT_ENV:
|
||||||
return "BEAMMP_PROVIDER_PORT_ENV";
|
return "BEAMMP_PROVIDER_PORT_ENV";
|
||||||
break;
|
break;
|
||||||
|
|||||||
+3
-7
@@ -178,13 +178,11 @@ std::pair<bool, std::string> LuaAPI::MP::DropPlayer(int ID, std::optional<std::s
|
|||||||
return { true, "" };
|
return { true, "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::string& Message, const bool& LogChat) {
|
std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::string& Message) {
|
||||||
std::pair<bool, std::string> Result;
|
std::pair<bool, std::string> Result;
|
||||||
std::string Packet = "C:Server: " + Message;
|
std::string Packet = "C:Server: " + Message;
|
||||||
if (ID == -1) {
|
if (ID == -1) {
|
||||||
if (LogChat) {
|
LogChatMessage("<Server> (to everyone) ", -1, Message);
|
||||||
LogChatMessage("<Server> (to everyone) ", -1, Message);
|
|
||||||
}
|
|
||||||
Engine->Network().SendToAll(nullptr, StringToVector(Packet), true, true);
|
Engine->Network().SendToAll(nullptr, StringToVector(Packet), true, true);
|
||||||
Result.first = true;
|
Result.first = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -196,9 +194,7 @@ std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::stri
|
|||||||
Result.second = "Player still syncing data";
|
Result.second = "Player still syncing data";
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
if (LogChat) {
|
LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message);
|
||||||
LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message);
|
|
||||||
}
|
|
||||||
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
beammp_errorf("Failed to send chat message back to sender (id {}) - did the sender disconnect?", ID);
|
beammp_errorf("Failed to send chat message back to sender (id {}) - did the sender disconnect?", ID);
|
||||||
// TODO: should we return an error here?
|
// TODO: should we return an error here?
|
||||||
|
|||||||
+1
-2
@@ -260,8 +260,7 @@ void TConsole::Command_Version(const std::string& cmd, const std::vector<std::st
|
|||||||
|
|
||||||
Application::Console().WriteRaw("Platform: " + platform);
|
Application::Console().WriteRaw("Platform: " + platform);
|
||||||
Application::Console().WriteRaw("Server: v" + Application::ServerVersionString());
|
Application::Console().WriteRaw("Server: v" + Application::ServerVersionString());
|
||||||
std::string lua_version = fmt::format("Lua: v{}.{}.{}", LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
|
Application::Console().WriteRaw(LUA_RELEASE);
|
||||||
Application::Console().WriteRaw(lua_version);
|
|
||||||
std::string openssl_version = fmt::format("OpenSSL: v{}.{}.{}", OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH);
|
std::string openssl_version = fmt::format("OpenSSL: v{}.{}.{}", OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH);
|
||||||
Application::Console().WriteRaw(openssl_version);
|
Application::Console().WriteRaw(openssl_version);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-37
@@ -22,7 +22,6 @@
|
|||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
#include "Env.h"
|
|
||||||
#include "Profiling.h"
|
#include "Profiling.h"
|
||||||
#include "TLuaPlugin.h"
|
#include "TLuaPlugin.h"
|
||||||
#include "sol/object.hpp"
|
#include "sol/object.hpp"
|
||||||
@@ -66,7 +65,7 @@ TEST_CASE("TLuaEngine ctor & dtor") {
|
|||||||
void TLuaEngine::operator()() {
|
void TLuaEngine::operator()() {
|
||||||
RegisterThread("LuaEngine");
|
RegisterThread("LuaEngine");
|
||||||
// lua engine main thread
|
// lua engine main thread
|
||||||
beammp_infof("Lua v{}.{}.{}", LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
|
beammp_infof(LUA_RELEASE);
|
||||||
CollectAndInitPlugins();
|
CollectAndInitPlugins();
|
||||||
|
|
||||||
Application::SetSubsystemStatus("LuaEngine", Application::Status::Good);
|
Application::SetSubsystemStatus("LuaEngine", Application::Status::Good);
|
||||||
@@ -727,25 +726,6 @@ static void AddToTable(sol::table& table, const std::string& left, const T& valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mDisableMPSet = [] {
|
|
||||||
auto DisableMPSet = Env::Get(Env::Key::PROVIDER_DISABLE_MP_SET).value_or("false");
|
|
||||||
return DisableMPSet == "true" || DisableMPSet == "1";
|
|
||||||
}();
|
|
||||||
|
|
||||||
static auto GetSettingName = [](int id) -> const char* {
|
|
||||||
switch (id) {
|
|
||||||
case 0: return "Debug";
|
|
||||||
case 1: return "Private";
|
|
||||||
case 2: return "MaxCars";
|
|
||||||
case 3: return "MaxPlayers";
|
|
||||||
case 4: return "Map";
|
|
||||||
case 5: return "Name";
|
|
||||||
case 6: return "Description";
|
|
||||||
case 7: return "InformationPacket";
|
|
||||||
default: return "Unknown";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void JsonDecodeRecursive(sol::state_view& StateView, sol::table& table, const std::string& left, const nlohmann::json& right) {
|
static void JsonDecodeRecursive(sol::state_view& StateView, sol::table& table, const std::string& left, const nlohmann::json& right) {
|
||||||
switch (right.type()) {
|
switch (right.type()) {
|
||||||
case nlohmann::detail::value_t::null:
|
case nlohmann::detail::value_t::null:
|
||||||
@@ -877,15 +857,7 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
MPTable.set_function("GetPositionRaw", [&](int PID, int VID) -> std::pair<sol::table, std::string> {
|
MPTable.set_function("GetPositionRaw", [&](int PID, int VID) -> std::pair<sol::table, std::string> {
|
||||||
return Lua_GetPositionRaw(PID, VID);
|
return Lua_GetPositionRaw(PID, VID);
|
||||||
});
|
});
|
||||||
MPTable.set_function("SendChatMessage", [&](sol::variadic_args Args) {
|
MPTable.set_function("SendChatMessage", &LuaAPI::MP::SendChatMessage);
|
||||||
if (Args.size() == 2) {
|
|
||||||
LuaAPI::MP::SendChatMessage(Args.get<int>(0), Args.get<std::string>(1));
|
|
||||||
} else if (Args.size() == 3) {
|
|
||||||
LuaAPI::MP::SendChatMessage(Args.get<int>(0), Args.get<std::string>(1), Args.get<bool>(2));
|
|
||||||
} else {
|
|
||||||
beammp_lua_error("SendChatMessage expects 2 or 3 arguments.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
MPTable.set_function("SendNotification", [&](sol::variadic_args Args) {
|
MPTable.set_function("SendNotification", [&](sol::variadic_args Args) {
|
||||||
if (Args.size() == 2) {
|
if (Args.size() == 2) {
|
||||||
LuaAPI::MP::SendNotification(Args.get<int>(0), Args.get<std::string>(1), "", Args.get<std::string>(1));
|
LuaAPI::MP::SendNotification(Args.get<int>(0), Args.get<std::string>(1), "", Args.get<std::string>(1));
|
||||||
@@ -946,13 +918,7 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
MPTable.set_function("CancelEventTimer", [&](const std::string& EventName) {
|
MPTable.set_function("CancelEventTimer", [&](const std::string& EventName) {
|
||||||
mEngine->CancelEventTimers(EventName, mStateId);
|
mEngine->CancelEventTimers(EventName, mStateId);
|
||||||
});
|
});
|
||||||
if (mDisableMPSet) {
|
MPTable.set_function("Set", &LuaAPI::MP::Set);
|
||||||
MPTable.set_function("Set", [this](int ConfigID, sol::object NewValue) {
|
|
||||||
beammp_lua_errorf("A script ({}) tried to call MP.Set to change setting '{}' but this was blocked by your server provider.", mStateId, GetSettingName(ConfigID));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
MPTable.set_function("Set", &LuaAPI::MP::Set);
|
|
||||||
}
|
|
||||||
MPTable.set_function("Get", &LuaAPI::MP::Get);
|
MPTable.set_function("Get", &LuaAPI::MP::Get);
|
||||||
|
|
||||||
auto UtilTable = StateView.create_named_table("Util");
|
auto UtilTable = StateView.create_named_table("Util");
|
||||||
|
|||||||
+46
-145
@@ -38,10 +38,6 @@
|
|||||||
|
|
||||||
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
|
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
|
||||||
|
|
||||||
static constexpr uint8_t MAX_CONCURRENT_CONNECTIONS = 10;
|
|
||||||
static constexpr uint8_t MAX_GLOBAL_CONNECTIONS = 128;
|
|
||||||
static constexpr uint8_t READ_TIMEOUT_S = 10; //seconds
|
|
||||||
|
|
||||||
std::vector<uint8_t> StringToVector(const std::string& Str) {
|
std::vector<uint8_t> StringToVector(const std::string& Str) {
|
||||||
return std::vector<uint8_t>(Str.data(), Str.data() + Str.size());
|
return std::vector<uint8_t>(Str.data(), Str.data() + Str.size());
|
||||||
}
|
}
|
||||||
@@ -93,14 +89,14 @@ void TNetwork::UDPServerMain() {
|
|||||||
RegisterThread("UDPServer");
|
RegisterThread("UDPServer");
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
auto address = boost::asio::ip::make_address(Application::Settings.getAsString(Settings::Key::General_IP), ec);
|
auto address = ip::make_address(Application::Settings.getAsString(Settings::Key::General_IP), ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("Failed to parse IP: {}", ec.message());
|
beammp_errorf("Failed to parse IP: {}", ec.message());
|
||||||
Application::GracefullyShutdown();
|
Application::GracefullyShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::udp::endpoint UdpListenEndpoint(address, Application::Settings.getAsInt(Settings::Key::General_Port));
|
ip::udp::endpoint UdpListenEndpoint(address, Application::Settings.getAsInt(Settings::Key::General_Port));
|
||||||
|
|
||||||
mUDPSock.open(UdpListenEndpoint.protocol(), ec);
|
mUDPSock.open(UdpListenEndpoint.protocol(), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
@@ -125,13 +121,13 @@ void TNetwork::UDPServerMain() {
|
|||||||
+ std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + (" Clients"));
|
+ std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + (" Clients"));
|
||||||
while (!Application::IsShuttingDown()) {
|
while (!Application::IsShuttingDown()) {
|
||||||
try {
|
try {
|
||||||
boost::asio::ip::udp::endpoint remote_client_ep {};
|
ip::udp::endpoint remote_client_ep {};
|
||||||
std::vector<uint8_t> Data = UDPRcvFromClient(remote_client_ep);
|
std::vector<uint8_t> Data = UDPRcvFromClient(remote_client_ep);
|
||||||
if (Data.empty()) {
|
if (Data.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Data.size() == 1 && Data.at(0) == 'P') {
|
if (Data.size() == 1 && Data.at(0) == 'P') {
|
||||||
mUDPSock.send_to(boost::asio::const_buffer("P", 1), remote_client_ep, {}, ec);
|
mUDPSock.send_to(const_buffer("P", 1), remote_client_ep, {}, ec);
|
||||||
// ignore errors
|
// ignore errors
|
||||||
(void)ec;
|
(void)ec;
|
||||||
continue;
|
continue;
|
||||||
@@ -152,7 +148,7 @@ void TNetwork::UDPServerMain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Client->GetID() == ID) {
|
if (Client->GetID() == ID) {
|
||||||
if (Client->GetUDPAddr() == boost::asio::ip::udp::endpoint {} && !Client->IsUDPConnected() && !Client->GetMagic().empty()) {
|
if (Client->GetUDPAddr() == ip::udp::endpoint {} && !Client->IsUDPConnected() && !Client->GetMagic().empty()) {
|
||||||
if (Data.size() != 66) {
|
if (Data.size() != 66) {
|
||||||
beammp_debugf("Invalid size for UDP value. IP: {} ID: {}", remote_client_ep.address().to_string(), ID);
|
beammp_debugf("Invalid size for UDP value. IP: {} ID: {}", remote_client_ep.address().to_string(), ID);
|
||||||
return false;
|
return false;
|
||||||
@@ -192,16 +188,16 @@ void TNetwork::TCPServerMain() {
|
|||||||
RegisterThread("TCPServer");
|
RegisterThread("TCPServer");
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
auto address = boost::asio::ip::make_address(Application::Settings.getAsString(Settings::Key::General_IP), ec);
|
auto address = ip::make_address(Application::Settings.getAsString(Settings::Key::General_IP), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("Failed to parse IP: {}", ec.message());
|
beammp_errorf("Failed to parse IP: {}", ec.message());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::tcp::endpoint ListenEp(address,
|
ip::tcp::endpoint ListenEp(address,
|
||||||
uint16_t(Application::Settings.getAsInt(Settings::Key::General_Port)));
|
uint16_t(Application::Settings.getAsInt(Settings::Key::General_Port)));
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket Listener(mServer.IoCtx());
|
ip::tcp::socket Listener(mServer.IoCtx());
|
||||||
Listener.open(ListenEp.protocol(), ec);
|
Listener.open(ListenEp.protocol(), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("Failed to open socket: {}", ec.message());
|
beammp_errorf("Failed to open socket: {}", ec.message());
|
||||||
@@ -226,7 +222,7 @@ void TNetwork::TCPServerMain() {
|
|||||||
ec.message());
|
ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::tcp::acceptor Acceptor(mServer.IoCtx(), ListenEp);
|
ip::tcp::acceptor Acceptor(mServer.IoCtx(), ListenEp);
|
||||||
Acceptor.listen(socket_base::max_listen_connections, ec);
|
Acceptor.listen(socket_base::max_listen_connections, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("listen() failed, which is needed for the server to operate. "
|
beammp_errorf("listen() failed, which is needed for the server to operate. "
|
||||||
@@ -243,28 +239,15 @@ void TNetwork::TCPServerMain() {
|
|||||||
beammp_debug("shutdown during TCP wait for accept loop");
|
beammp_debug("shutdown during TCP wait for accept loop");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
boost::asio::ip::tcp::endpoint ClientEp;
|
ip::tcp::endpoint ClientEp;
|
||||||
boost::asio::ip::tcp::socket ClientSocket = Acceptor.accept(ClientEp, ec);
|
ip::tcp::socket ClientSocket = Acceptor.accept(ClientEp, ec);
|
||||||
std::string ClientIP = ClientEp.address().to_string();
|
if (ec) {
|
||||||
if (!ec) {
|
|
||||||
mClientMapMutex.lock();
|
|
||||||
if (mClientMap[ClientIP] >= MAX_CONCURRENT_CONNECTIONS) {
|
|
||||||
beammp_debugf("The connection was rejected for {}, as it had {} concurrent connections.", ClientIP, mClientMap[ClientIP]);
|
|
||||||
}
|
|
||||||
else if (mClientMap.size() >= MAX_GLOBAL_CONNECTIONS) {
|
|
||||||
beammp_debugf("The connection was rejected for {}, as there are {} global connections.", ClientIP, mClientMap.size());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TConnection Conn { std::move(ClientSocket), ClientEp };
|
|
||||||
std::thread ID(&TNetwork::Identify, this, std::move(Conn));
|
|
||||||
ID.detach(); // TODO: Add to a queue and attempt to join periodically
|
|
||||||
mClientMap[ClientIP]++;
|
|
||||||
}
|
|
||||||
mClientMapMutex.unlock();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
beammp_errorf("Failed to accept() new client: {}", ec.message());
|
beammp_errorf("Failed to accept() new client: {}", ec.message());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
TConnection Conn { std::move(ClientSocket), ClientEp };
|
||||||
|
std::thread ID(&TNetwork::Identify, this, std::move(Conn));
|
||||||
|
ID.detach();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
beammp_errorf("Exception in accept routine: {}", e.what());
|
beammp_errorf("Exception in accept routine: {}", e.what());
|
||||||
}
|
}
|
||||||
@@ -280,22 +263,11 @@ void TNetwork::Identify(TConnection&& RawConnection) {
|
|||||||
RegisterThreadAuto();
|
RegisterThreadAuto();
|
||||||
char Code;
|
char Code;
|
||||||
|
|
||||||
boost::system::error_code ec = ReadWithTimeout(RawConnection, &Code, 1, std::chrono::seconds(READ_TIMEOUT_S));
|
boost::system::error_code ec;
|
||||||
|
read(RawConnection.Socket, buffer(&Code, 1), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// TODO: is this right?!
|
// TODO: is this right?!
|
||||||
beammp_debug("Error occured reading code");
|
|
||||||
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
||||||
mClientMapMutex.lock();
|
|
||||||
{
|
|
||||||
std::string ClientIP = RawConnection.SockAddr.address().to_string();
|
|
||||||
if (mClientMap[ClientIP] > 0) {
|
|
||||||
mClientMap[ClientIP]--;
|
|
||||||
}
|
|
||||||
if (mClientMap[ClientIP] == 0) {
|
|
||||||
mClientMap.erase(ClientIP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mClientMapMutex.unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::shared_ptr<TClient> Client { nullptr };
|
std::shared_ptr<TClient> Client { nullptr };
|
||||||
@@ -306,7 +278,8 @@ void TNetwork::Identify(TConnection&& RawConnection) {
|
|||||||
beammp_errorf("Old download packet detected - the client is wildly out of date, this will be ignored");
|
beammp_errorf("Old download packet detected - the client is wildly out of date, this will be ignored");
|
||||||
return;
|
return;
|
||||||
} else if (Code == 'P') {
|
} else if (Code == 'P') {
|
||||||
boost::asio::write(RawConnection.Socket, boost::asio::buffer("P"), ec);
|
boost::system::error_code ec;
|
||||||
|
write(RawConnection.Socket, buffer("P"), ec);
|
||||||
return;
|
return;
|
||||||
} else if (Code == 'I') {
|
} else if (Code == 'I') {
|
||||||
const std::string Data = Application::Settings.getAsBool(Settings::Key::General_InformationPacket) ? THeartbeatThread::lastCall : "";
|
const std::string Data = Application::Settings.getAsBool(Settings::Key::General_InformationPacket) ? THeartbeatThread::lastCall : "";
|
||||||
@@ -318,25 +291,14 @@ void TNetwork::Identify(TConnection&& RawConnection) {
|
|||||||
std::memcpy(ToSend.data() + sizeof(Size), Data.data(), Data.size());
|
std::memcpy(ToSend.data() + sizeof(Size), Data.data(), Data.size());
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::asio::write(RawConnection.Socket, boost::asio::buffer(ToSend), ec);
|
write(RawConnection.Socket, buffer(ToSend), ec);
|
||||||
} else {
|
} else {
|
||||||
beammp_errorf("Invalid code got in Identify: '{}'", Code);
|
beammp_errorf("Invalid code got in Identify: '{}'", Code);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
beammp_errorf("Error during handling of code {} - client left in invalid state, closing socket: {}", Code, e.what());
|
beammp_errorf("Error during handling of code {} - client left in invalid state, closing socket: {}", Code, e.what());
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
RawConnection.Socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
|
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
||||||
mClientMapMutex.lock();
|
|
||||||
{
|
|
||||||
std::string ClientIP = RawConnection.SockAddr.address().to_string();
|
|
||||||
if (mClientMap[ClientIP] > 0) {
|
|
||||||
mClientMap[ClientIP]--;
|
|
||||||
}
|
|
||||||
if (mClientMap[ClientIP] == 0) {
|
|
||||||
mClientMap.erase(ClientIP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mClientMapMutex.unlock();
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("Failed to shutdown client socket: {}", ec.message());
|
beammp_debugf("Failed to shutdown client socket: {}", ec.message());
|
||||||
}
|
}
|
||||||
@@ -434,7 +396,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
try {
|
try {
|
||||||
nlohmann::json AuthRes = nlohmann::json::parse(AuthResStr);
|
nlohmann::json AuthRes = nlohmann::json::parse(AuthResStr);
|
||||||
|
|
||||||
if (AuthRes["username"].is_string() && AuthRes["username"].size() > 0 && AuthRes["roles"].is_string()
|
if (AuthRes["username"].is_string() && AuthRes["roles"].is_string()
|
||||||
&& AuthRes["guest"].is_boolean() && AuthRes["identifiers"].is_array()) {
|
&& AuthRes["guest"].is_boolean() && AuthRes["identifiers"].is_array()) {
|
||||||
|
|
||||||
Client->SetName(AuthRes["username"]);
|
Client->SetName(AuthRes["username"]);
|
||||||
@@ -468,7 +430,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
|
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
|
||||||
DisconnectClient(Cl, "Stale Client (not a real player)");
|
Cl->Disconnect("Stale Client (not a real player)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +493,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
return Client;
|
return Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TClient> TNetwork::CreateClient(boost::asio::ip::tcp::socket&& TCPSock) {
|
std::shared_ptr<TClient> TNetwork::CreateClient(ip::tcp::socket&& TCPSock) {
|
||||||
auto c = std::make_shared<TClient>(mServer, std::move(TCPSock));
|
auto c = std::make_shared<TClient>(mServer, std::move(TCPSock));
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -564,10 +526,10 @@ bool TNetwork::TCPSend(TClient& c, const std::vector<uint8_t>& Data, bool IsSync
|
|||||||
std::memcpy(ToSend.data(), &Size, sizeof(Size));
|
std::memcpy(ToSend.data(), &Size, sizeof(Size));
|
||||||
std::memcpy(ToSend.data() + sizeof(Size), Data.data(), Data.size());
|
std::memcpy(ToSend.data() + sizeof(Size), Data.data(), Data.size());
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::asio::write(Sock, boost::asio::buffer(ToSend), ec);
|
write(Sock, buffer(ToSend), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("write(): {}", ec.message());
|
beammp_debugf("write(): {}", ec.message());
|
||||||
DisconnectClient(c, "write() failed");
|
c.Disconnect("write() failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
c.UpdatePingTime();
|
c.UpdatePingTime();
|
||||||
@@ -585,7 +547,7 @@ std::vector<uint8_t> TNetwork::TCPRcv(TClient& c) {
|
|||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
std::array<uint8_t, sizeof(Header)> HeaderData;
|
std::array<uint8_t, sizeof(Header)> HeaderData;
|
||||||
boost::asio::read(Sock, boost::asio::buffer(HeaderData), ec);
|
read(Sock, buffer(HeaderData), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// TODO: handle this case (read failed)
|
// TODO: handle this case (read failed)
|
||||||
beammp_debugf("TCPRcv: Reading header failed: {}", ec.message());
|
beammp_debugf("TCPRcv: Reading header failed: {}", ec.message());
|
||||||
@@ -601,16 +563,14 @@ std::vector<uint8_t> TNetwork::TCPRcv(TClient& c) {
|
|||||||
|
|
||||||
std::vector<uint8_t> Data;
|
std::vector<uint8_t> Data;
|
||||||
// TODO: This is arbitrary, this needs to be handled another way
|
// TODO: This is arbitrary, this needs to be handled another way
|
||||||
bool isUnauthenticated = c.GetName().empty();
|
if (Header < int32_t(100 * MB)) {
|
||||||
int32_t maxHeaderSize = isUnauthenticated ? 4096 : int32_t(100 * MB);
|
|
||||||
if (Header < maxHeaderSize) {
|
|
||||||
Data.resize(Header);
|
Data.resize(Header);
|
||||||
} else {
|
} else {
|
||||||
ClientKick(c, "Header size limit exceeded");
|
ClientKick(c, "Header size limit exceeded");
|
||||||
beammp_warn("Client " + c.GetName() + " (" + std::to_string(c.GetID()) + ") sent header larger than expected - assuming malicious intent and disconnecting the client.");
|
beammp_warn("Client " + c.GetName() + " (" + std::to_string(c.GetID()) + ") sent header of >100MB - assuming malicious intent and disconnecting the client.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto N = boost::asio::read(Sock, boost::asio::buffer(Data), ec);
|
auto N = read(Sock, buffer(Data), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// TODO: handle this case properly
|
// TODO: handle this case properly
|
||||||
beammp_debugf("TCPRcv: Reading data failed: {}", ec.message());
|
beammp_debugf("TCPRcv: Reading data failed: {}", ec.message());
|
||||||
@@ -645,32 +605,7 @@ void TNetwork::ClientKick(TClient& c, const std::string& R) {
|
|||||||
if (!TCPSend(c, StringToVector("K" + R))) {
|
if (!TCPSend(c, StringToVector("K" + R))) {
|
||||||
beammp_debugf("tried to kick player '{}' (id {}), but was already disconnected", c.GetName(), c.GetID());
|
beammp_debugf("tried to kick player '{}' (id {}), but was already disconnected", c.GetName(), c.GetID());
|
||||||
}
|
}
|
||||||
DisconnectClient(c, "Kicked");
|
c.Disconnect("Kicked");
|
||||||
}
|
|
||||||
|
|
||||||
void TNetwork::DisconnectClient(const std::weak_ptr<TClient> &c, const std::string &R)
|
|
||||||
{
|
|
||||||
if (auto locked = c.lock()) {
|
|
||||||
DisconnectClient(*locked, R);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
beammp_debugf("Tried to disconnect a non existant client with reason: {}", R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TNetwork::DisconnectClient(TClient &c, const std::string &R)
|
|
||||||
{
|
|
||||||
if (c.IsDisconnected()) return;
|
|
||||||
std::string ClientIP = c.GetTCPSock().remote_endpoint().address().to_string();
|
|
||||||
mClientMapMutex.lock();
|
|
||||||
if (mClientMap[ClientIP] > 0) {
|
|
||||||
mClientMap[ClientIP]--;
|
|
||||||
}
|
|
||||||
if (mClientMap[ClientIP] == 0) {
|
|
||||||
mClientMap.erase(ClientIP);
|
|
||||||
}
|
|
||||||
mClientMapMutex.unlock();
|
|
||||||
c.Disconnect(R);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
||||||
@@ -695,7 +630,7 @@ void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
|||||||
} // end locked context
|
} // end locked context
|
||||||
// beammp_debug("sending a missed packet: " + QData);
|
// beammp_debug("sending a missed packet: " + QData);
|
||||||
if (!TCPSend(*Client, QData, true)) {
|
if (!TCPSend(*Client, QData, true)) {
|
||||||
DisconnectClient(Client, "Failed to TCPSend while clearing the missed packet queue");
|
Client->Disconnect("Failed to TCPSend while clearing the missed packet queue");
|
||||||
std::unique_lock lock(Client->MissedPacketQueueMutex());
|
std::unique_lock lock(Client->MissedPacketQueueMutex());
|
||||||
while (!Client->MissedPacketQueue().empty()) {
|
while (!Client->MissedPacketQueue().empty()) {
|
||||||
Client->MissedPacketQueue().pop();
|
Client->MissedPacketQueue().pop();
|
||||||
@@ -732,16 +667,10 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
auto res = TCPRcv(*Client);
|
auto res = TCPRcv(*Client);
|
||||||
if (res.empty()) {
|
if (res.empty()) {
|
||||||
beammp_debug("TCPRcv empty");
|
beammp_debug("TCPRcv empty");
|
||||||
DisconnectClient(Client, "TCPRcv failed");
|
Client->Disconnect("TCPRcv failed");
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
beammp_warnf("Failed to receive/parse packet via TCP from client {}: {}", Client->GetID(), e.what());
|
|
||||||
DisconnectClient(Client, "Failed to parse packet");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QueueSync.joinable())
|
if (QueueSync.joinable())
|
||||||
@@ -770,34 +699,6 @@ void TNetwork::UpdatePlayer(TClient& Client) {
|
|||||||
//(void)Respond(Client, Packet, true);
|
//(void)Respond(Client, Packet, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::system::error_code TNetwork::ReadWithTimeout(TConnection& Connection, void *Buf, size_t Len, std::chrono::steady_clock::duration Timeout)
|
|
||||||
{
|
|
||||||
io_context TimerIO;
|
|
||||||
steady_timer Timer(TimerIO);
|
|
||||||
Timer.expires_after(Timeout);
|
|
||||||
|
|
||||||
std::atomic<bool> TimedOut = false;
|
|
||||||
|
|
||||||
Timer.async_wait([&](const boost::system::error_code& ec) {
|
|
||||||
if (!ec) {
|
|
||||||
TimedOut = true;
|
|
||||||
Connection.Socket.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
std::thread TimerThread([&]() { TimerIO.run(); });
|
|
||||||
|
|
||||||
boost::system::error_code ReadEc;
|
|
||||||
boost::asio::read(Connection.Socket, boost::asio::buffer(Buf, Len), ReadEc);
|
|
||||||
|
|
||||||
TimerIO.stop();
|
|
||||||
TimerThread.join();
|
|
||||||
|
|
||||||
if (TimedOut.load()) {
|
|
||||||
return error::timed_out; // synthesize a clean timeout error
|
|
||||||
}
|
|
||||||
return ReadEc; //Succes!
|
|
||||||
}
|
|
||||||
|
|
||||||
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
||||||
std::shared_ptr<TClient> LockedClientPtr { nullptr };
|
std::shared_ptr<TClient> LockedClientPtr { nullptr };
|
||||||
try {
|
try {
|
||||||
@@ -825,7 +726,7 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
|||||||
Packet.clear();
|
Packet.clear();
|
||||||
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", c.GetID());
|
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", c.GetID());
|
||||||
LuaAPI::MP::Engine->WaitForAll(Futures);
|
LuaAPI::MP::Engine->WaitForAll(Futures);
|
||||||
DisconnectClient(c, "Already Disconnected (OnDisconnect)");
|
c.Disconnect("Already Disconnected (OnDisconnect)");
|
||||||
mServer.RemoveClient(ClientPtr);
|
mServer.RemoveClient(ClientPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,7 +834,7 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) {
|
|||||||
for (auto mod : mResourceManager.GetMods()) {
|
for (auto mod : mResourceManager.GetMods()) {
|
||||||
if (mod["file_name"].get<std::string>() == FileName && mod["protected"] == true) {
|
if (mod["file_name"].get<std::string>() == FileName && mod["protected"] == true) {
|
||||||
beammp_warn("Client tried to access protected file " + UnsafeName);
|
beammp_warn("Client tried to access protected file " + UnsafeName);
|
||||||
DisconnectClient(c, "Mod is protected thus cannot be downloaded");
|
c.Disconnect("Mod is protected thus cannot be downloaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -997,7 +898,7 @@ void TNetwork::SendFileToClient(TClient& c, size_t Size, const std::string& Name
|
|||||||
Data.resize(Split);
|
Data.resize(Split);
|
||||||
else
|
else
|
||||||
Data.resize(Size);
|
Data.resize(Size);
|
||||||
boost::asio::ip::tcp::socket* TCPSock = &c.GetTCPSock();
|
ip::tcp::socket* TCPSock = &c.GetTCPSock();
|
||||||
std::streamsize Sent = 0;
|
std::streamsize Sent = 0;
|
||||||
while (!c.IsDisconnected() && Sent < Size) {
|
while (!c.IsDisconnected() && Sent < Size) {
|
||||||
size_t Diff = Size - Sent;
|
size_t Diff = Size - Sent;
|
||||||
@@ -1006,7 +907,7 @@ void TNetwork::SendFileToClient(TClient& c, size_t Size, const std::string& Name
|
|||||||
f.read(reinterpret_cast<char*>(Data.data()), Split);
|
f.read(reinterpret_cast<char*>(Data.data()), Split);
|
||||||
if (!TCPSendRaw(c, *TCPSock, Data.data(), Split)) {
|
if (!TCPSendRaw(c, *TCPSock, Data.data(), Split)) {
|
||||||
if (!c.IsDisconnected())
|
if (!c.IsDisconnected())
|
||||||
DisconnectClient(c, "TCPSendRaw failed in mod download (1)");
|
c.Disconnect("TCPSendRaw failed in mod download (1)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Split;
|
Sent += Split;
|
||||||
@@ -1015,7 +916,7 @@ void TNetwork::SendFileToClient(TClient& c, size_t Size, const std::string& Name
|
|||||||
f.read(reinterpret_cast<char*>(Data.data()), Diff);
|
f.read(reinterpret_cast<char*>(Data.data()), Diff);
|
||||||
if (!TCPSendRaw(c, *TCPSock, Data.data(), int32_t(Diff))) {
|
if (!TCPSendRaw(c, *TCPSock, Data.data(), int32_t(Diff))) {
|
||||||
if (!c.IsDisconnected())
|
if (!c.IsDisconnected())
|
||||||
DisconnectClient(c, "TCPSendRaw failed in mod download (2)");
|
c.Disconnect("TCPSendRaw failed in mod download (2)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Diff;
|
Sent += Diff;
|
||||||
@@ -1024,9 +925,9 @@ void TNetwork::SendFileToClient(TClient& c, size_t Size, const std::string& Name
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TNetwork::TCPSendRaw(TClient& C, boost::asio::ip::tcp::socket& socket, const uint8_t* Data, size_t Size) {
|
bool TNetwork::TCPSendRaw(TClient& C, ip::tcp::socket& socket, const uint8_t* Data, size_t Size) {
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::asio::write(socket, boost::asio::buffer(Data, Size), ec);
|
write(socket, buffer(Data, Size), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("Failed to send raw data to client: {}", ec.message());
|
beammp_errorf("Failed to send raw data to client: {}", ec.message());
|
||||||
return false;
|
return false;
|
||||||
@@ -1167,20 +1068,20 @@ bool TNetwork::UDPSend(TClient& Client, std::vector<uint8_t> Data) {
|
|||||||
CompressProperly(Data);
|
CompressProperly(Data);
|
||||||
}
|
}
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
mUDPSock.send_to(boost::asio::buffer(Data), Addr, 0, ec);
|
mUDPSock.send_to(buffer(Data), Addr, 0, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("UDP sendto() failed: {}", ec.message());
|
beammp_debugf("UDP sendto() failed: {}", ec.message());
|
||||||
if (!Client.IsDisconnected())
|
if (!Client.IsDisconnected())
|
||||||
DisconnectClient(Client, "UDP send failed");
|
Client.Disconnect("UDP send failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> TNetwork::UDPRcvFromClient(boost::asio::ip::udp::endpoint& ClientEndpoint) {
|
std::vector<uint8_t> TNetwork::UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint) {
|
||||||
std::array<char, 1024> Ret {};
|
std::array<char, 1024> Ret {};
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
const auto Rcv = mUDPSock.receive_from(boost::asio::mutable_buffer(Ret.data(), Ret.size()), ClientEndpoint, 0, ec);
|
const auto Rcv = mUDPSock.receive_from(mutable_buffer(Ret.data(), Ret.size()), ClientEndpoint, 0, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("UDP recvfrom() failed: {}", ec.message());
|
beammp_errorf("UDP recvfrom() failed: {}", ec.message());
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
+4
-16
@@ -28,7 +28,6 @@
|
|||||||
#include <any>
|
#include <any>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
@@ -54,6 +53,7 @@ static std::optional<std::pair<int, int>> GetPidVid(const std::string& str) {
|
|||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("GetPidVid") {
|
TEST_CASE("GetPidVid") {
|
||||||
SUBCASE("Valid singledigit") {
|
SUBCASE("Valid singledigit") {
|
||||||
const auto MaybePidVid = GetPidVid("0-1");
|
const auto MaybePidVid = GetPidVid("0-1");
|
||||||
@@ -120,6 +120,7 @@ TEST_CASE("GetPidVid") {
|
|||||||
CHECK(!MaybePidVid);
|
CHECK(!MaybePidVid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
||||||
beammp_info("BeamMP Server v" + Application::ServerVersionString());
|
beammp_info("BeamMP Server v" + Application::ServerVersionString());
|
||||||
Application::SetSubsystemStatus("Server", Application::Status::Starting);
|
Application::SetSubsystemStatus("Server", Application::Status::Starting);
|
||||||
@@ -471,13 +472,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
auto BracketPos = Data.find('{');
|
Data = Data.substr(Data.find('{'));
|
||||||
if (BracketPos == std::string::npos) {
|
|
||||||
beammp_debugf("Invalid 'Or' packet body from client {}", c.GetID());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Data = Data.substr(BracketPos);
|
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", "", c.GetID(), VID, Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", "", c.GetID(), VID, Data));
|
||||||
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
||||||
}
|
}
|
||||||
@@ -506,14 +501,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
auto BracketPos = Data.find('[');
|
Data = Data.substr(Data.find('['));
|
||||||
if (BracketPos == std::string::npos) {
|
|
||||||
beammp_debugf("Invalid 'Op' packet body from client {}", c.GetID());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Data = Data.substr(BracketPos);
|
|
||||||
|
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
||||||
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -15,16 +15,12 @@
|
|||||||
"rapidjson",
|
"rapidjson",
|
||||||
"sol2",
|
"sol2",
|
||||||
"curl",
|
"curl",
|
||||||
"lua"
|
"luajit"
|
||||||
],
|
],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"name": "sol2",
|
"name": "sol2",
|
||||||
"version": "3.3.1"
|
"version": "3.3.1"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "lua",
|
|
||||||
"version": "5.3.5#6"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"builtin-baseline": "5bf0c55239da398b8c6f450818c9e28d36bf9966"
|
"builtin-baseline": "5bf0c55239da398b8c6f450818c9e28d36bf9966"
|
||||||
|
|||||||
Reference in New Issue
Block a user