replace tcp networking with boost::asio tcp networking

This commit is contained in:
Lion Kortlepel 2022-10-05 15:44:32 +02:00
parent 7446526a19
commit 7d2e4d4581
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
9 changed files with 388 additions and 453 deletions

View File

@ -20,9 +20,8 @@ class TServer;
#endif // WINDOWS #endif // WINDOWS
struct TConnection final { struct TConnection final {
SOCKET Socket; ip::tcp::socket Socket;
struct sockaddr SockAddr; ip::tcp::endpoint SockAddr;
socklen_t SockAddrLen;
}; };
class TClient final { class TClient final {
@ -34,8 +33,9 @@ public:
std::unique_lock<std::mutex> Lock; std::unique_lock<std::mutex> Lock;
}; };
explicit TClient(TServer& Server); TClient(TServer& Server, ip::tcp::socket&& Socket);
TClient(const TClient&) = delete; TClient(const TClient&) = delete;
~TClient();
TClient& operator=(const TClient&) = delete; TClient& operator=(const TClient&) = delete;
void AddNewCar(int Ident, const std::string& Data); void AddNewCar(int Ident, const std::string& Data);
@ -48,16 +48,19 @@ public:
std::string GetCarData(int Ident); std::string GetCarData(int Ident);
std::string GetCarPositionRaw(int Ident); std::string GetCarPositionRaw(int Ident);
void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; } void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; }
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; } void SetDownSock(ip::tcp::socket&& CSock) { mDownSocket = std::move(CSock); }
void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; } void SetTCPSock(ip::tcp::socket&& CSock) { mSocket = std::move(CSock); }
void SetStatus(int Status) { mStatus = Status; } void Disconnect(std::string_view Reason);
bool IsDisconnected() const { return !mSocket.is_open(); }
// locks // locks
void DeleteCar(int Ident); void DeleteCar(int Ident);
[[nodiscard]] const std::unordered_map<std::string, std::string>& GetIdentifiers() const { return mIdentifiers; } [[nodiscard]] const std::unordered_map<std::string, std::string>& GetIdentifiers() const { return mIdentifiers; }
[[nodiscard]] const ip::udp::endpoint& GetUDPAddr() const { return mUDPAddress; } [[nodiscard]] const ip::udp::endpoint& GetUDPAddr() const { return mUDPAddress; }
[[nodiscard]] ip::udp::endpoint& GetUDPAddr() { return mUDPAddress; } [[nodiscard]] ip::udp::endpoint& GetUDPAddr() { return mUDPAddress; }
[[nodiscard]] SOCKET GetDownSock() const { return mSocket[1]; } [[nodiscard]] ip::tcp::socket& GetDownSock() { return mDownSocket; }
[[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; } [[nodiscard]] const ip::tcp::socket& GetDownSock() const { return mDownSocket; }
[[nodiscard]] ip::tcp::socket& GetTCPSock() { return mSocket; }
[[nodiscard]] const ip::tcp::socket& GetTCPSock() const { return mSocket; }
[[nodiscard]] std::string GetRoles() const { return mRole; } [[nodiscard]] std::string GetRoles() const { return mRole; }
[[nodiscard]] std::string GetName() const { return mName; } [[nodiscard]] std::string GetName() const { return mName; }
void SetUnicycleID(int ID) { mUnicycleID = ID; } void SetUnicycleID(int ID) { mUnicycleID = ID; }
@ -65,7 +68,6 @@ public:
[[nodiscard]] int GetOpenCarID() const; [[nodiscard]] int GetOpenCarID() const;
[[nodiscard]] int GetCarCount() const; [[nodiscard]] int GetCarCount() const;
void ClearCars(); void ClearCars();
[[nodiscard]] int GetStatus() const { return mStatus; }
[[nodiscard]] int GetID() const { return mID; } [[nodiscard]] int GetID() const { return mID; }
[[nodiscard]] int GetUnicycleID() const { return mUnicycleID; } [[nodiscard]] int GetUnicycleID() const { return mUnicycleID; }
[[nodiscard]] bool IsConnected() const { return mIsConnected; } [[nodiscard]] bool IsConnected() const { return mIsConnected; }
@ -75,9 +77,9 @@ public:
void SetIsGuest(bool NewIsGuest) { mIsGuest = NewIsGuest; } void SetIsGuest(bool NewIsGuest) { mIsGuest = NewIsGuest; }
void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; } void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; }
void SetIsSyncing(bool NewIsSyncing) { mIsSyncing = NewIsSyncing; } void SetIsSyncing(bool NewIsSyncing) { mIsSyncing = NewIsSyncing; }
void EnqueuePacket(const std::string& Packet); void EnqueuePacket(const std::vector<uint8_t>& Packet);
[[nodiscard]] std::queue<std::string>& MissedPacketQueue() { return mPacketsSync; } [[nodiscard]] std::queue<std::vector<uint8_t>>& MissedPacketQueue() { return mPacketsSync; }
[[nodiscard]] const std::queue<std::string>& MissedPacketQueue() const { return mPacketsSync; } [[nodiscard]] const std::queue<std::vector<uint8_t>>& MissedPacketQueue() const { return mPacketsSync; }
[[nodiscard]] size_t MissedPacketQueueSize() const { return mPacketsSync.size(); } [[nodiscard]] size_t MissedPacketQueueSize() const { return mPacketsSync.size(); }
[[nodiscard]] std::mutex& MissedPacketQueueMutex() const { return mMissedPacketsMutex; } [[nodiscard]] std::mutex& MissedPacketQueueMutex() const { return mMissedPacketsMutex; }
void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; } void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; }
@ -93,7 +95,7 @@ private:
bool mIsSynced = false; bool mIsSynced = false;
bool mIsSyncing = false; bool mIsSyncing = false;
mutable std::mutex mMissedPacketsMutex; mutable std::mutex mMissedPacketsMutex;
std::queue<std::string> mPacketsSync; std::queue<std::vector<uint8_t>> mPacketsSync;
std::unordered_map<std::string, std::string> mIdentifiers; std::unordered_map<std::string, std::string> mIdentifiers;
bool mIsGuest = false; bool mIsGuest = false;
mutable std::mutex mVehicleDataMutex; mutable std::mutex mVehicleDataMutex;
@ -101,12 +103,12 @@ private:
TSetOfVehicleData mVehicleData; TSetOfVehicleData mVehicleData;
SparseArray<std::string> mVehiclePosition; SparseArray<std::string> mVehiclePosition;
std::string mName = "Unknown Client"; std::string mName = "Unknown Client";
SOCKET mSocket[2] { SOCKET(0), SOCKET(0) }; ip::tcp::socket mSocket;
ip::tcp::socket mDownSocket;
ip::udp::endpoint mUDPAddress {}; ip::udp::endpoint mUDPAddress {};
int mUnicycleID = -1; int mUnicycleID = -1;
std::string mRole; std::string mRole;
std::string mDID; std::string mDID;
int mStatus = 0;
int mID = -1; int mID = -1;
std::chrono::time_point<std::chrono::high_resolution_clock> mLastPingTime; std::chrono::time_point<std::chrono::high_resolution_clock> mLastPingTime;
}; };

View File

@ -80,7 +80,7 @@ public:
static TConsole& Console() { return *mConsole; } static TConsole& Console() { return *mConsole; }
static std::string ServerVersionString(); static std::string ServerVersionString();
static const Version& ServerVersion() { return mVersion; } static const Version& ServerVersion() { return mVersion; }
static std::string ClientVersionString() { return "2.0"; } static uint8_t ClientMajorVersion() { return 2; }
static std::string PPS() { return mPPS; } static std::string PPS() { return mPPS; }
static void SetPPS(const std::string& NewPPS) { mPPS = NewPPS; } static void SetPPS(const std::string& NewPPS) { mPPS = NewPPS; }

View File

@ -13,19 +13,18 @@ class TNetwork {
public: public:
TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager); TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager);
[[nodiscard]] bool TCPSend(TClient& c, const std::string& Data, bool IsSync = false); [[nodiscard]] bool TCPSend(TClient& c, const std::vector<uint8_t>& Data, bool IsSync = false);
[[nodiscard]] bool SendLarge(TClient& c, std::string Data, bool isSync = false); [[nodiscard]] bool SendLarge(TClient& c, std::vector<uint8_t> Data, bool isSync = false);
[[nodiscard]] bool Respond(TClient& c, const std::string& 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(SOCKET TCPSock); std::shared_ptr<TClient> CreateClient(ip::tcp::socket&& TCPSock);
std::string 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);
[[nodiscard]] bool SyncClient(const std::weak_ptr<TClient>& c); [[nodiscard]] bool SyncClient(const std::weak_ptr<TClient>& c);
void Identify(const TConnection& client); void Identify(TConnection&& client);
void Authentication(const TConnection& ClientConnection); std::shared_ptr<TClient> Authentication(TConnection&& ClientConnection);
[[nodiscard]] bool CheckBytes(TClient& c, int32_t BytesRcv);
void SyncResources(TClient& c); void SyncResources(TClient& c);
[[nodiscard]] bool UDPSend(TClient& Client, std::string Data); [[nodiscard]] bool UDPSend(TClient& Client, std::vector<uint8_t> Data);
void SendToAll(TClient* c, const std::string& 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);
private: private:
@ -34,22 +33,23 @@ private:
TServer& mServer; TServer& mServer;
TPPSMonitor& mPPSMonitor; TPPSMonitor& mPPSMonitor;
io_context mIoCtx;
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::string UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint); std::vector<uint8_t> UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint);
void HandleDownload(SOCKET TCPSock); void HandleDownload(TConnection&& TCPSock);
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);
int OpenID(); int OpenID();
void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked); void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr);
void Parse(TClient& c, const std::string& 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, SOCKET socket, char* Data, int32_t Size); static bool TCPSendRaw(TClient& C, ip::tcp::socket& socket, const uint8_t* Data, size_t Size);
static void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name); static void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name);
static uint8_t* SendSplit(TClient& c, SOCKET Socket, 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::vector<uint8_t> StringToVector(const std::string& Str);

View File

@ -8,6 +8,8 @@
#include <mutex> #include <mutex>
#include <unordered_set> #include <unordered_set>
#include "BoostAliases.h"
class TClient; class TClient;
class TNetwork; class TNetwork;
class TPPSMonitor; class TPPSMonitor;
@ -19,19 +21,22 @@ public:
TServer(const std::vector<std::string_view>& Arguments); TServer(const std::vector<std::string_view>& Arguments);
void InsertClient(const std::shared_ptr<TClient>& Ptr); void InsertClient(const std::shared_ptr<TClient>& Ptr);
std::weak_ptr<TClient> InsertNewClient();
void RemoveClient(const std::weak_ptr<TClient>&); void RemoveClient(const std::weak_ptr<TClient>&);
// in Fn, return true to continue, return false to break // in Fn, return true to continue, return false to break
void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn); void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
size_t ClientCount() const; size_t ClientCount() const;
static void GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TNetwork& Network); static void GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network);
static void HandleEvent(TClient& c, const std::string& Data); static void HandleEvent(TClient& c, const std::string& Data);
RWMutex& GetClientMutex() const { return mClientsMutex; } RWMutex& GetClientMutex() const { return mClientsMutex; }
const TScopedTimer UptimeTimer; const TScopedTimer UptimeTimer;
// asio io context
io_context& IoCtx() { return mIoCtx; }
private: private:
io_context mIoCtx {};
TClientSet mClients; TClientSet mClients;
mutable RWMutex mClientsMutex; mutable RWMutex mClientsMutex;
static void ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network); static void ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network);
@ -40,3 +45,11 @@ private:
static void Apply(TClient& c, int VID, const std::string& pckt); static void Apply(TClient& c, int VID, const std::string& pckt);
static void HandlePosition(TClient& c, const std::string& Packet); static void HandlePosition(TClient& c, const std::string& Packet);
}; };
struct BufferView {
uint8_t* Data { nullptr };
size_t Size { 0 };
const uint8_t* data() const { return Data; }
uint8_t* data() { return Data; }
size_t size() const { return Size; }
};

View File

@ -2,6 +2,7 @@
#include "CustomAssert.h" #include "CustomAssert.h"
#include "TServer.h" #include "TServer.h"
#include <boost/system/detail/error_code.hpp>
#include <memory> #include <memory>
#include <optional> #include <optional>
@ -49,16 +50,27 @@ TClient::TVehicleDataLockPair TClient::GetAllCars() {
std::string TClient::GetCarPositionRaw(int Ident) { std::string TClient::GetCarPositionRaw(int Ident) {
std::unique_lock lock(mVehiclePositionMutex); std::unique_lock lock(mVehiclePositionMutex);
try try {
{
return mVehiclePosition.at(Ident); return mVehiclePosition.at(Ident);
} } catch (const std::out_of_range& oor) {
catch (const std::out_of_range& oor) {
return ""; return "";
} }
return ""; return "";
} }
void TClient::Disconnect(std::string_view Reason) {
beammp_debugf("Disconnecting client {} for reason: {}", GetID(), Reason);
boost::system::error_code ec;
mSocket.shutdown(socket_base::shutdown_both, ec);
if (ec) {
beammp_warnf("Failed to shutdown client socket: {}", ec.what());
}
mSocket.close(ec);
if (ec) {
beammp_warnf("Failed to close client socket: {}", ec.what());
}
}
void TClient::SetCarPosition(int Ident, const std::string& Data) { void TClient::SetCarPosition(int Ident, const std::string& Data) {
std::unique_lock lock(mVehiclePositionMutex); std::unique_lock lock(mVehiclePositionMutex);
mVehiclePosition[Ident] = Data; mVehiclePosition[Ident] = Data;
@ -98,16 +110,22 @@ TServer& TClient::Server() const {
return mServer; return mServer;
} }
void TClient::EnqueuePacket(const std::string& Packet) { void TClient::EnqueuePacket(const std::vector<uint8_t>& Packet) {
std::unique_lock Lock(mMissedPacketsMutex); std::unique_lock Lock(mMissedPacketsMutex);
mPacketsSync.push(Packet); mPacketsSync.push(Packet);
} }
TClient::TClient(TServer& Server) TClient::TClient(TServer& Server, ip::tcp::socket&& Socket)
: mServer(Server) : mServer(Server)
, mSocket(std::move(Socket))
, mDownSocket(ip::tcp::socket(Server.IoCtx()))
, mLastPingTime(std::chrono::high_resolution_clock::now()) { , mLastPingTime(std::chrono::high_resolution_clock::now()) {
} }
TClient::~TClient() {
beammp_debugf("client destroyed: {} ('{}')", this->GetID(), this->GetName());
}
void TClient::UpdatePingTime() { void TClient::UpdatePingTime() {
mLastPingTime = std::chrono::high_resolution_clock::now(); mLastPingTime = std::chrono::high_resolution_clock::now();
} }

View File

@ -116,7 +116,7 @@ TEST_CASE("LuaAPI::MP::GetServerVersion") {
static inline std::pair<bool, std::string> InternalTriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data) { static inline std::pair<bool, std::string> InternalTriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data) {
std::string Packet = "E:" + EventName + ":" + Data; std::string Packet = "E:" + EventName + ":" + Data;
if (PlayerID == -1) { if (PlayerID == -1) {
LuaAPI::MP::Engine->Network().SendToAll(nullptr, Packet, true, true); LuaAPI::MP::Engine->Network().SendToAll(nullptr, StringToVector(Packet), true, true);
return { true, "" }; return { true, "" };
} else { } else {
auto MaybeClient = GetClient(LuaAPI::MP::Engine->Server(), PlayerID); auto MaybeClient = GetClient(LuaAPI::MP::Engine->Server(), PlayerID);
@ -125,7 +125,7 @@ static inline std::pair<bool, std::string> InternalTriggerClientEvent(int Player
return { false, "Invalid Player ID" }; return { false, "Invalid Player ID" };
} }
auto c = MaybeClient.value().lock(); auto c = MaybeClient.value().lock();
if (!LuaAPI::MP::Engine->Network().Respond(*c, Packet, true)) { if (!LuaAPI::MP::Engine->Network().Respond(*c, StringToVector(Packet), true)) {
beammp_lua_errorf("Respond failed, dropping client {}", PlayerID); beammp_lua_errorf("Respond failed, dropping client {}", PlayerID);
LuaAPI::MP::Engine->Network().ClientKick(*c, "Disconnected after failing to receive packets"); LuaAPI::MP::Engine->Network().ClientKick(*c, "Disconnected after failing to receive packets");
return { false, "Respond failed, dropping client" }; return { false, "Respond failed, dropping client" };
@ -155,7 +155,7 @@ std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::stri
std::string Packet = "C:Server: " + Message; std::string Packet = "C:Server: " + Message;
if (ID == -1) { if (ID == -1) {
LogChatMessage("<Server> (to everyone) ", -1, Message); LogChatMessage("<Server> (to everyone) ", -1, Message);
Engine->Network().SendToAll(nullptr, Packet, true, true); Engine->Network().SendToAll(nullptr, StringToVector(Packet), true, true);
Result.first = true; Result.first = true;
} else { } else {
auto MaybeClient = GetClient(Engine->Server(), ID); auto MaybeClient = GetClient(Engine->Server(), ID);
@ -167,7 +167,7 @@ std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::stri
return Result; return Result;
} }
LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message); LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message);
if (!Engine->Network().Respond(*c, 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?
} }
@ -194,7 +194,7 @@ std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
auto c = MaybeClient.value().lock(); auto c = MaybeClient.value().lock();
if (!c->GetCarData(VID).empty()) { if (!c->GetCarData(VID).empty()) {
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID); std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
Engine->Network().SendToAll(nullptr, Destroy, true, true); Engine->Network().SendToAll(nullptr, StringToVector(Destroy), true, true);
c->DeleteCar(VID); c->DeleteCar(VID);
Result.first = true; Result.first = true;
} else { } else {
@ -526,7 +526,7 @@ static void JsonEncodeRecursive(nlohmann::json& json, const sol::object& left, c
beammp_lua_error("json serialize will not go deeper than 100 nested tables, internal references assumed, aborted this path"); beammp_lua_error("json serialize will not go deeper than 100 nested tables, internal references assumed, aborted this path");
return; return;
} }
std::string key{}; std::string key {};
switch (left.get_type()) { switch (left.get_type()) {
case sol::type::lua_nil: case sol::type::lua_nil:
case sol::type::none: case sol::type::none:

View File

@ -148,7 +148,7 @@ std::string THeartbeatThread::GenerateCall() {
<< "&map=" << Application::Settings.MapName << "&map=" << Application::Settings.MapName
<< "&private=" << (Application::Settings.Private ? "true" : "false") << "&private=" << (Application::Settings.Private ? "true" : "false")
<< "&version=" << Application::ServerVersionString() << "&version=" << Application::ServerVersionString()
<< "&clientversion=" << Application::ClientVersionString() << "&clientversion=" << Application::ClientMajorVersion()
<< "&name=" << Application::Settings.ServerName << "&name=" << Application::Settings.ServerName
<< "&modlist=" << mResourceManager.TrimmedList() << "&modlist=" << mResourceManager.TrimmedList()
<< "&modstotalsize=" << mResourceManager.MaxModSize() << "&modstotalsize=" << mResourceManager.MaxModSize()

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
#include "TNetwork.h" #include "TNetwork.h"
#include "TPPSMonitor.h" #include "TPPSMonitor.h"
#include <TLuaPlugin.h> #include <TLuaPlugin.h>
#include <algorithm>
#include <any> #include <any>
#include <sstream> #include <sstream>
@ -102,13 +103,6 @@ void TServer::RemoveClient(const std::weak_ptr<TClient>& WeakClientPtr) {
} }
} }
std::weak_ptr<TClient> TServer::InsertNewClient() {
beammp_debug("inserting new client (" + std::to_string(ClientCount()) + ")");
WriteLock Lock(mClientsMutex);
auto [Iter, Replaced] = mClients.insert(std::make_shared<TClient>(*this));
return *Iter;
}
void TServer::ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn) { void TServer::ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn) {
decltype(mClients) Clients; decltype(mClients) Clients;
{ {
@ -127,12 +121,11 @@ size_t TServer::ClientCount() const {
return mClients.size(); return mClients.size();
} }
void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TNetwork& Network) { void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network) {
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) { constexpr std::string_view ABG = "ABG:";
// abort(); if (Packet.size() >= ABG.size() && std::equal(Packet.begin(), Packet.begin() + ABG.size(), ABG.begin(), ABG.end())) {
} Packet.erase(Packet.begin(), Packet.begin() + ABG.size());
if (Packet.substr(0, 4) == "ABG:") { Packet = DeComp(Packet);
Packet = DeComp(Packet.substr(4));
} }
if (Packet.empty()) { if (Packet.empty()) {
return; return;
@ -146,6 +139,8 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
std::any Res; std::any Res;
char Code = Packet.at(0); char Code = Packet.at(0);
std::string StringPacket(reinterpret_cast<const char*>(Packet.data()), Packet.size());
// V to Y // V to Y
if (Code <= 89 && Code >= 86) { if (Code <= 89 && Code >= 86) {
PPSMonitor.IncrementInternalPPS(); PPSMonitor.IncrementInternalPPS();
@ -154,38 +149,34 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
} }
switch (Code) { switch (Code) {
case 'H': // initial connection case 'H': // initial connection
beammp_trace(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")");
if (!Network.SyncClient(Client)) { if (!Network.SyncClient(Client)) {
// TODO handle // TODO handle
} }
return; return;
case 'p': case 'p':
if (!Network.Respond(*LockedClient, ("p"), false)) { if (!Network.Respond(*LockedClient, StringToVector("p"), false)) {
// failed to send // failed to send
if (LockedClient->GetStatus() > -1) { LockedClient->Disconnect("Failed to send ping");
LockedClient->SetStatus(-1);
}
} else { } else {
Network.UpdatePlayer(*LockedClient); Network.UpdatePlayer(*LockedClient);
} }
return; return;
case 'O': case 'O':
if (Packet.length() > 1000) { if (Packet.size() > 1000) {
beammp_debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.length())); beammp_debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.size()));
} }
ParseVehicle(*LockedClient, Packet, Network); ParseVehicle(*LockedClient, StringPacket, Network);
return; return;
case 'J': case 'J':
beammp_trace(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
Network.SendToAll(LockedClient.get(), Packet, false, true); Network.SendToAll(LockedClient.get(), Packet, false, true);
return; return;
case 'C': { case 'C': {
beammp_trace(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); if (Packet.size() < 4 || std::find(Packet.begin() + 3, Packet.end(), ':') == Packet.end())
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
break; break;
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", "", LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 2)); const auto PacketAsString = std::string(reinterpret_cast<const char*>(Packet.data()), Packet.size());
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", "", LockedClient->GetID(), LockedClient->GetName(), PacketAsString.substr(PacketAsString.find(':', 3) + 2));
TLuaEngine::WaitForAll(Futures); TLuaEngine::WaitForAll(Futures);
LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), Packet.substr(Packet.find(':', 3) + 1)); LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), PacketAsString.substr(PacketAsString.find(':', 3) + 1));
if (std::any_of(Futures.begin(), Futures.end(), if (std::any_of(Futures.begin(), Futures.end(),
[](const std::shared_ptr<TLuaResult>& Elem) { [](const std::shared_ptr<TLuaResult>& Elem) {
return !Elem->Error return !Elem->Error
@ -198,8 +189,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
return; return;
} }
case 'E': case 'E':
beammp_trace(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); HandleEvent(*LockedClient, StringPacket);
HandleEvent(*LockedClient, Packet);
return; return;
case 'N': case 'N':
beammp_trace("got 'N' packet (" + std::to_string(Packet.size()) + ")"); beammp_trace("got 'N' packet (" + std::to_string(Packet.size()) + ")");
@ -209,7 +199,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
PPSMonitor.IncrementInternalPPS(); PPSMonitor.IncrementInternalPPS();
Network.SendToAll(LockedClient.get(), Packet, false, false); Network.SendToAll(LockedClient.get(), Packet, false, false);
HandlePosition(*LockedClient, Packet); HandlePosition(*LockedClient, StringPacket);
default: default:
return; return;
} }
@ -275,13 +265,13 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
if (ShouldSpawn(c, CarJson, CarID) && !ShouldntSpawn) { if (ShouldSpawn(c, CarJson, CarID) && !ShouldntSpawn) {
c.AddNewCar(CarID, Packet); c.AddNewCar(CarID, Packet);
Network.SendToAll(nullptr, Packet, true, true); Network.SendToAll(nullptr, StringToVector(Packet), true, true);
} else { } else {
if (!Network.Respond(c, Packet, true)) { if (!Network.Respond(c, StringToVector(Packet), true)) {
// TODO: handle // TODO: handle
} }
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(CarID); std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(CarID);
if (!Network.Respond(c, Destroy, true)) { if (!Network.Respond(c, StringToVector(Destroy), true)) {
// TODO: handle // TODO: handle
} }
beammp_debugf("{} (force : car limit/lua) removed ID {}", c.GetName(), CarID); beammp_debugf("{} (force : car limit/lua) removed ID {}", c.GetName(), CarID);
@ -306,14 +296,14 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
FoundPos = FoundPos == std::string::npos ? 0 : FoundPos; // attempt at sanitizing this FoundPos = FoundPos == std::string::npos ? 0 : FoundPos; // attempt at sanitizing this
if ((c.GetUnicycleID() != VID || IsUnicycle(c, Packet.substr(FoundPos))) if ((c.GetUnicycleID() != VID || IsUnicycle(c, Packet.substr(FoundPos)))
&& !ShouldntAllow) { && !ShouldntAllow) {
Network.SendToAll(&c, Packet, false, true); Network.SendToAll(&c, StringToVector(Packet), false, true);
Apply(c, VID, Packet); Apply(c, VID, Packet);
} else { } else {
if (c.GetUnicycleID() == VID) { if (c.GetUnicycleID() == VID) {
c.SetUnicycleID(-1); c.SetUnicycleID(-1);
} }
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID); std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID);
Network.SendToAll(nullptr, Destroy, true, true); Network.SendToAll(nullptr, StringToVector(Destroy), true, true);
c.DeleteCar(VID); c.DeleteCar(VID);
} }
} }
@ -329,7 +319,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
if (c.GetUnicycleID() == VID) { if (c.GetUnicycleID() == VID) {
c.SetUnicycleID(-1); c.SetUnicycleID(-1);
} }
Network.SendToAll(nullptr, Packet, true, true); Network.SendToAll(nullptr, StringToVector(Packet), true, true);
// TODO: should this trigger on all vehicle deletions? // TODO: should this trigger on all vehicle deletions?
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", c.GetID(), VID)); LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", c.GetID(), VID));
c.DeleteCar(VID); c.DeleteCar(VID);
@ -347,16 +337,16 @@ 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()) {
Data = Data.substr(Data.find('{')); Data = Data.substr(Data.find('{'));
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, Packet, false, true); Network.SendToAll(&c, StringToVector(Packet), false, true);
} }
return; return;
} }
case 't': case 't':
beammp_trace(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); beammp_trace(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
Network.SendToAll(&c, Packet, false, true); Network.SendToAll(&c, StringToVector(Packet), false, true);
return; return;
case 'm': case 'm':
Network.SendToAll(&c, Packet, true, true); Network.SendToAll(&c, StringToVector(Packet), true, true);
return; return;
default: default:
beammp_trace(std::string(("possibly not implemented: '") + Packet + ("' (") + std::to_string(Packet.size()) + (")"))); beammp_trace(std::string(("possibly not implemented: '") + Packet + ("' (") + std::to_string(Packet.size()) + (")")));