mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-10-25 21:40:09 +00:00
fix std::weak_ptr locking and expiry checks
You're supposed to .lock() instead of TOCTOU checking, of course. Not sure what I was thinking when I built that. .lock() returns a default constructed std::shared_ptr on error, which is `false` via `operator bool`.
This commit is contained in:
8 files changed
+260
-229
No files matched your search
+1
-2
@@ -178,8 +178,7 @@ std::optional<std::weak_ptr<TClient>> GetClient(TServer& Server, int ID) {
|
|||||||
std::optional<std::weak_ptr<TClient>> MaybeClient { std::nullopt };
|
std::optional<std::weak_ptr<TClient>> MaybeClient { std::nullopt };
|
||||||
Server.ForEachClient([&](std::weak_ptr<TClient> CPtr) -> bool {
|
Server.ForEachClient([&](std::weak_ptr<TClient> CPtr) -> bool {
|
||||||
ReadLock Lock(Server.GetClientMutex());
|
ReadLock Lock(Server.GetClientMutex());
|
||||||
if (!CPtr.expired()) {
|
if (auto C = CPtr.lock()) {
|
||||||
auto C = CPtr.lock();
|
|
||||||
if (C->GetID() == ID) {
|
if (C->GetID() == ID) {
|
||||||
MaybeClient = CPtr;
|
MaybeClient = CPtr;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+98
-73
@@ -143,22 +143,23 @@ static inline std::pair<bool, std::string> InternalTriggerClientEvent(int Player
|
|||||||
return { true, "" };
|
return { true, "" };
|
||||||
} else {
|
} else {
|
||||||
auto MaybeClient = GetClient(LuaAPI::MP::Engine->Server(), PlayerID);
|
auto MaybeClient = GetClient(LuaAPI::MP::Engine->Server(), PlayerID);
|
||||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
beammp_lua_errorf("TriggerClientEvent invalid Player ID '{}'", PlayerID);
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
return { false, "Invalid Player ID" };
|
if (!c->IsSyncing() && !c->IsSynced()) {
|
||||||
}
|
return { false, "Player hasn't joined yet" };
|
||||||
auto c = MaybeClient.value().lock();
|
}
|
||||||
|
|
||||||
if (!c->IsSyncing() && !c->IsSynced()) {
|
if (!LuaAPI::MP::Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
return { false, "Player hasn't joined yet" };
|
beammp_lua_errorf("Respond failed, dropping client {}", PlayerID);
|
||||||
|
LuaAPI::MP::Engine->Network().ClientKick(*c, "Disconnected after failing to receive packets");
|
||||||
|
return { false, "Respond failed, dropping client" };
|
||||||
|
}
|
||||||
|
return { true, "" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LuaAPI::MP::Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
beammp_lua_errorf("TriggerClientEvent invalid Player ID '{}'", PlayerID);
|
||||||
beammp_lua_errorf("Respond failed, dropping client {}", PlayerID);
|
return { false, "Invalid Player ID" };
|
||||||
LuaAPI::MP::Engine->Network().ClientKick(*c, "Disconnected after failing to receive packets");
|
|
||||||
return { false, "Respond failed, dropping client" };
|
|
||||||
}
|
|
||||||
return { true, "" };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,13 +170,15 @@ std::pair<bool, std::string> LuaAPI::MP::TriggerClientEvent(int PlayerID, const
|
|||||||
|
|
||||||
std::pair<bool, std::string> LuaAPI::MP::DropPlayer(int ID, std::optional<std::string> MaybeReason) {
|
std::pair<bool, std::string> LuaAPI::MP::DropPlayer(int ID, std::optional<std::string> MaybeReason) {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
beammp_lua_errorf("Tried to drop client with id {}, who doesn't exist", ID);
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
return { false, "Player does not exist" };
|
LuaAPI::MP::Engine->Network().ClientKick(*c, MaybeReason.value_or("No reason"));
|
||||||
|
return { true, "" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto c = MaybeClient.value().lock();
|
|
||||||
LuaAPI::MP::Engine->Network().ClientKick(*c, MaybeReason.value_or("No reason"));
|
beammp_lua_errorf("Tried to drop client with id {}, who doesn't exist", ID);
|
||||||
return { true, "" };
|
return { false, "Player does not exist" };
|
||||||
}
|
}
|
||||||
|
|
||||||
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, const bool& LogChat) {
|
||||||
@@ -189,21 +192,26 @@ std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::stri
|
|||||||
Result.first = true;
|
Result.first = true;
|
||||||
} else {
|
} else {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
auto c = MaybeClient.value().lock();
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
if (!c->IsSynced()) {
|
if (!c->IsSynced()) {
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Player still syncing data";
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
if (LogChat) {
|
||||||
|
LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message);
|
||||||
|
}
|
||||||
|
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
|
beammp_errorf("Failed to send chat message back to sender (id {}) - did the sender disconnect?", ID);
|
||||||
|
// TODO: should we return an error here?
|
||||||
|
}
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
beammp_lua_error("SendChatMessage invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
Result.second = "Player still syncing data";
|
Result.second = "Invalid Player ID";
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
if (LogChat) {
|
|
||||||
LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, Message);
|
|
||||||
}
|
|
||||||
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
|
||||||
beammp_errorf("Failed to send chat message back to sender (id {}) - did the sender disconnect?", ID);
|
|
||||||
// TODO: should we return an error here?
|
|
||||||
}
|
|
||||||
Result.first = true;
|
|
||||||
} else {
|
} else {
|
||||||
beammp_lua_error("SendChatMessage invalid argument [1] invalid ID");
|
beammp_lua_error("SendChatMessage invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
@@ -223,18 +231,23 @@ std::pair<bool, std::string> LuaAPI::MP::SendNotification(int ID, const std::str
|
|||||||
} else {
|
} else {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (MaybeClient) {
|
if (MaybeClient) {
|
||||||
auto c = MaybeClient.value().lock();
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
if (!c->IsSynced()) {
|
if (!c->IsSynced()) {
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Player is not synced yet";
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
|
beammp_errorf("Failed to send notification to player (id {}) - did the player disconnect?", ID);
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Failed to send packet";
|
||||||
|
}
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
beammp_lua_error("SendNotification invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
Result.second = "Player is not synced yet";
|
Result.second = "Invalid Player ID";
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
|
||||||
beammp_errorf("Failed to send notification to player (id {}) - did the player disconnect?", ID);
|
|
||||||
Result.first = false;
|
|
||||||
Result.second = "Failed to send packet";
|
|
||||||
}
|
|
||||||
Result.first = true;
|
|
||||||
} else {
|
} else {
|
||||||
beammp_lua_error("SendNotification invalid argument [1] invalid ID");
|
beammp_lua_error("SendNotification invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
@@ -265,18 +278,23 @@ std::pair<bool, std::string> LuaAPI::MP::ConfirmationDialog(int ID, const std::s
|
|||||||
} else {
|
} else {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (MaybeClient) {
|
if (MaybeClient) {
|
||||||
auto c = MaybeClient.value().lock();
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
if (!c->IsSynced()) {
|
if (!c->IsSynced()) {
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Player is not synced yet";
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
|
beammp_errorf("Failed to send confirmation dialog to player (id {}) - did the player disconnect?", ID);
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Failed to send packet";
|
||||||
|
}
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
beammp_lua_error("ConfirmationDialog invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
Result.second = "Player is not synced yet";
|
Result.second = "Invalid Player ID";
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
|
||||||
beammp_errorf("Failed to send confirmation dialog to player (id {}) - did the player disconnect?", ID);
|
|
||||||
Result.first = false;
|
|
||||||
Result.second = "Failed to send packet";
|
|
||||||
}
|
|
||||||
Result.first = true;
|
|
||||||
} else {
|
} else {
|
||||||
beammp_lua_error("ConfirmationDialog invalid argument [1] invalid ID");
|
beammp_lua_error("ConfirmationDialog invalid argument [1] invalid ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
@@ -290,22 +308,27 @@ std::pair<bool, std::string> LuaAPI::MP::ConfirmationDialog(int ID, const std::s
|
|||||||
std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
|
std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
|
||||||
std::pair<bool, std::string> Result;
|
std::pair<bool, std::string> Result;
|
||||||
auto MaybeClient = GetClient(Engine->Server(), PID);
|
auto MaybeClient = GetClient(Engine->Server(), PID);
|
||||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
|
if (c->GetCarData(VID) != nlohmann::detail::value_t::null) {
|
||||||
|
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
||||||
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", PID, VID));
|
||||||
|
Engine->Network().SendToAll(nullptr, StringToVector(Destroy), true, true);
|
||||||
|
c->DeleteCar(VID);
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Vehicle does not exist";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
beammp_lua_error("RemoveVehicle invalid Player ID");
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Invalid Player ID";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
beammp_lua_error("RemoveVehicle invalid Player ID");
|
beammp_lua_error("RemoveVehicle invalid Player ID");
|
||||||
Result.first = false;
|
Result.first = false;
|
||||||
Result.second = "Invalid Player ID";
|
Result.second = "Invalid Player ID";
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
auto c = MaybeClient.value().lock();
|
|
||||||
if (c->GetCarData(VID) != nlohmann::detail::value_t::null) {
|
|
||||||
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", PID, VID));
|
|
||||||
Engine->Network().SendToAll(nullptr, StringToVector(Destroy), true, true);
|
|
||||||
c->DeleteCar(VID);
|
|
||||||
Result.first = true;
|
|
||||||
} else {
|
|
||||||
Result.first = false;
|
|
||||||
Result.second = "Vehicle does not exist";
|
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@@ -412,20 +435,22 @@ void LuaAPI::MP::Sleep(size_t Ms) {
|
|||||||
|
|
||||||
bool LuaAPI::MP::IsPlayerConnected(int ID) {
|
bool LuaAPI::MP::IsPlayerConnected(int ID) {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
return MaybeClient.value().lock()->IsUDPConnected();
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
} else {
|
return c->IsUDPConnected();
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LuaAPI::MP::IsPlayerGuest(int ID) {
|
bool LuaAPI::MP::IsPlayerGuest(int ID) {
|
||||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
return MaybeClient.value().lock()->IsGuest();
|
if (auto c = MaybeClient.value().lock()) {
|
||||||
} else {
|
return c->IsGuest();
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaAPI::MP::PrintRaw(sol::variadic_args Args) {
|
void LuaAPI::MP::PrintRaw(sol::variadic_args Args) {
|
||||||
|
|||||||
+16
-20
@@ -296,8 +296,7 @@ void TConsole::Command_NetTest(const std::string& cmd, const std::vector<std::st
|
|||||||
unsigned int status = 0;
|
unsigned int status = 0;
|
||||||
|
|
||||||
std::string T = Http::GET(
|
std::string T = Http::GET(
|
||||||
Application::GetServerCheckUrl() + "/api/v2/beammp/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_Port)), &status
|
Application::GetServerCheckUrl() + "/api/v2/beammp/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_Port)), &status);
|
||||||
);
|
|
||||||
|
|
||||||
beammp_debugf("Status and response from Server Check API: {0}, {1}", status, T);
|
beammp_debugf("Status and response from Server Check API: {0}, {1}", status, T);
|
||||||
|
|
||||||
@@ -334,10 +333,9 @@ void TConsole::Command_Kick(const std::string&, const std::vector<std::string>&
|
|||||||
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
||||||
};
|
};
|
||||||
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (auto Locked = Client.lock()) {
|
||||||
auto locked = Client.lock();
|
if (NameCompare(Locked->GetName(), Name)) {
|
||||||
if (NameCompare(locked->GetName(), Name)) {
|
mLuaEngine->Network().ClientKick(*Locked, Reason);
|
||||||
mLuaEngine->Network().ClientKick(*locked, Reason);
|
|
||||||
Kicked = true;
|
Kicked = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -356,7 +354,7 @@ std::tuple<std::string, std::vector<std::string>> TConsole::ParseCommand(const s
|
|||||||
// It correctly splits arguments, including respecting single and double quotes, as well as backticks
|
// It correctly splits arguments, including respecting single and double quotes, as well as backticks
|
||||||
auto End_i = CommandWithArgs.find_first_of(' ');
|
auto End_i = CommandWithArgs.find_first_of(' ');
|
||||||
std::string Command = CommandWithArgs.substr(0, End_i);
|
std::string Command = CommandWithArgs.substr(0, End_i);
|
||||||
std::string ArgsStr {};
|
std::string ArgsStr { };
|
||||||
if (End_i != std::string::npos) {
|
if (End_i != std::string::npos) {
|
||||||
ArgsStr = CommandWithArgs.substr(End_i);
|
ArgsStr = CommandWithArgs.substr(End_i);
|
||||||
}
|
}
|
||||||
@@ -566,11 +564,10 @@ void TConsole::Command_List(const std::string&, const std::vector<std::string>&
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::left << std::setw(25) << "Name" << std::setw(6) << "ID" << std::setw(6) << "Cars" << std::endl;
|
ss << std::left << std::setw(25) << "Name" << std::setw(6) << "ID" << std::setw(6) << "Cars" << std::endl;
|
||||||
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (auto Locked = Client.lock()) {
|
||||||
auto locked = Client.lock();
|
ss << std::left << std::setw(25) << Locked->GetName()
|
||||||
ss << std::left << std::setw(25) << locked->GetName()
|
<< std::setw(6) << Locked->GetID()
|
||||||
<< std::setw(6) << locked->GetID()
|
<< std::setw(6) << Locked->GetCarCount() << "\n";
|
||||||
<< std::setw(6) << locked->GetCarCount() << "\n";
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -593,8 +590,7 @@ void TConsole::Command_Status(const std::string&, const std::vector<std::string>
|
|||||||
size_t MissedPacketQueueSum = 0;
|
size_t MissedPacketQueueSum = 0;
|
||||||
int LargestSecondsSinceLastPing = 0;
|
int LargestSecondsSinceLastPing = 0;
|
||||||
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (auto Locked = Client.lock()) {
|
||||||
auto Locked = Client.lock();
|
|
||||||
CarCount += Locked->GetCarCount();
|
CarCount += Locked->GetCarCount();
|
||||||
ConnectedCount += Locked->IsUDPConnected() ? 1 : 0;
|
ConnectedCount += Locked->IsUDPConnected() ? 1 : 0;
|
||||||
GuestCount += Locked->IsGuest() ? 1 : 0;
|
GuestCount += Locked->IsGuest() ? 1 : 0;
|
||||||
@@ -613,11 +609,11 @@ void TConsole::Command_Status(const std::string&, const std::vector<std::string>
|
|||||||
size_t SystemsBad = 0;
|
size_t SystemsBad = 0;
|
||||||
size_t SystemsShuttingDown = 0;
|
size_t SystemsShuttingDown = 0;
|
||||||
size_t SystemsShutdown = 0;
|
size_t SystemsShutdown = 0;
|
||||||
std::string SystemsBadList {};
|
std::string SystemsBadList { };
|
||||||
std::string SystemsGoodList {};
|
std::string SystemsGoodList { };
|
||||||
std::string SystemsStartingList {};
|
std::string SystemsStartingList { };
|
||||||
std::string SystemsShuttingDownList {};
|
std::string SystemsShuttingDownList { };
|
||||||
std::string SystemsShutdownList {};
|
std::string SystemsShutdownList { };
|
||||||
auto Statuses = Application::GetSubsystemStatuses();
|
auto Statuses = Application::GetSubsystemStatuses();
|
||||||
for (const auto& NameStatusPair : Statuses) {
|
for (const auto& NameStatusPair : Statuses) {
|
||||||
switch (NameStatusPair.second) {
|
switch (NameStatusPair.second) {
|
||||||
@@ -847,7 +843,7 @@ void TConsole::InitializeCommandline() {
|
|||||||
if (!mLuaEngine) {
|
if (!mLuaEngine) {
|
||||||
beammp_info("Lua not started yet, please try again in a second");
|
beammp_info("Lua not started yet, please try again in a second");
|
||||||
} else {
|
} else {
|
||||||
std::string prefix {}; // stores non-table part of input
|
std::string prefix { }; // stores non-table part of input
|
||||||
for (size_t i = stub.length(); i > 0; i--) { // separate table from input
|
for (size_t i = stub.length(); i > 0; i--) { // separate table from input
|
||||||
if (!std::isalnum(stub[i - 1]) && stub[i - 1] != '_' && stub[i - 1] != '.') {
|
if (!std::isalnum(stub[i - 1]) && stub[i - 1] != '_' && stub[i - 1] != '.') {
|
||||||
prefix = stub.substr(0, i);
|
prefix = stub.substr(0, i);
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ std::string THeartbeatThread::GetPlayers() {
|
|||||||
std::string Return;
|
std::string Return;
|
||||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto Client = ClientPtr.lock()) {
|
||||||
Return += ClientPtr.lock()->GetName() + ";";
|
Return += Client->GetName() + ";";
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
+84
-79
@@ -120,7 +120,7 @@ void TLuaEngine::operator()() {
|
|||||||
std::unique_lock StateLock(mLuaStatesMutex);
|
std::unique_lock StateLock(mLuaStatesMutex);
|
||||||
std::unique_lock Lock2(mResultsToCheckMutex);
|
std::unique_lock Lock2(mResultsToCheckMutex);
|
||||||
for (auto& Handler : Handlers) {
|
for (auto& Handler : Handlers) {
|
||||||
auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCallFromCustomEvent(Handler, {}, Timer.EventName, Timer.Strategy);
|
auto Res = mLuaStates[Timer.StateId]->EnqueueFunctionCallFromCustomEvent(Handler, { }, Timer.EventName, Timer.Strategy);
|
||||||
if (Res) {
|
if (Res) {
|
||||||
mResultsToCheck.push_back(Res);
|
mResultsToCheck.push_back(Res);
|
||||||
mResultsToCheckCond.notify_one();
|
mResultsToCheckCond.notify_one();
|
||||||
@@ -268,7 +268,7 @@ std::vector<std::string> TLuaEngine::StateThreadData::GetStateTableKeys(const st
|
|||||||
auto globals = mStateView.globals();
|
auto globals = mStateView.globals();
|
||||||
|
|
||||||
sol::table current = globals;
|
sol::table current = globals;
|
||||||
std::vector<std::string> Result {};
|
std::vector<std::string> Result { };
|
||||||
|
|
||||||
for (const auto& [key, value] : current) {
|
for (const auto& [key, value] : current) {
|
||||||
std::string s = key.as<std::string>();
|
std::string s = key.as<std::string>();
|
||||||
@@ -471,7 +471,7 @@ std::vector<sol::object> TLuaEngine::StateThreadData::JsonStringToArray(JsonStri
|
|||||||
auto LocalTable = Lua_JsonDecode(Str.value).as<std::vector<sol::object>>();
|
auto LocalTable = Lua_JsonDecode(Str.value).as<std::vector<sol::object>>();
|
||||||
for (auto& value : LocalTable) {
|
for (auto& value : LocalTable) {
|
||||||
if (value.is<std::string>() && value.as<std::string>() == BEAMMP_INTERNAL_NIL) {
|
if (value.is<std::string>() && value.as<std::string>() == BEAMMP_INTERNAL_NIL) {
|
||||||
value = sol::object {};
|
value = sol::object { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LocalTable;
|
return LocalTable;
|
||||||
@@ -613,36 +613,37 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string&
|
|||||||
|
|
||||||
sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) {
|
sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) {
|
||||||
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
auto IDs = MaybeClient.value().lock()->GetIdentifiers();
|
if (std::shared_ptr<TClient> Locked = MaybeClient.value().lock()) {
|
||||||
if (IDs.empty()) {
|
auto IDs = Locked->GetIdentifiers();
|
||||||
return sol::lua_nil;
|
if (IDs.empty()) {
|
||||||
|
return sol::lua_nil;
|
||||||
|
}
|
||||||
|
sol::table Result = mStateView.create_table();
|
||||||
|
for (const auto& Pair : IDs) {
|
||||||
|
Result.set(Pair.first, Pair.second);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
sol::table Result = mStateView.create_table();
|
|
||||||
for (const auto& Pair : IDs) {
|
|
||||||
Result.set(Pair.first, Pair.second);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
} else {
|
|
||||||
return sol::lua_nil;
|
|
||||||
}
|
}
|
||||||
|
return sol::lua_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::variant<std::string, sol::nil_t> TLuaEngine::StateThreadData::Lua_GetPlayerRole(int ID) {
|
std::variant<std::string, sol::nil_t> TLuaEngine::StateThreadData::Lua_GetPlayerRole(int ID) {
|
||||||
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
||||||
if (MaybeClient) {
|
if (MaybeClient) {
|
||||||
return MaybeClient.value().lock()->GetRoles();
|
if (auto Locked = MaybeClient.value().lock()) {
|
||||||
} else {
|
return Locked->GetRoles();
|
||||||
return sol::nil;
|
}
|
||||||
}
|
}
|
||||||
|
return sol::nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() {
|
sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() {
|
||||||
sol::table Result = mStateView.create_table();
|
sol::table Result = mStateView.create_table();
|
||||||
mEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
mEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (auto Locked = Client.lock()) {
|
||||||
auto locked = Client.lock();
|
Result[Locked->GetID()] = Locked->GetName();
|
||||||
Result[locked->GetID()] = locked->GetName();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -652,10 +653,9 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() {
|
|||||||
int TLuaEngine::StateThreadData::Lua_GetPlayerIDByName(const std::string& Name) {
|
int TLuaEngine::StateThreadData::Lua_GetPlayerIDByName(const std::string& Name) {
|
||||||
int Id = -1;
|
int Id = -1;
|
||||||
mEngine->mServer->ForEachClient([&Id, &Name](std::weak_ptr<TClient> Client) -> bool {
|
mEngine->mServer->ForEachClient([&Id, &Name](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (auto Locked = Client.lock()) {
|
||||||
auto locked = Client.lock();
|
if (Locked->GetName() == Name) {
|
||||||
if (locked->GetName() == Name) {
|
Id = Locked->GetID();
|
||||||
Id = locked->GetID();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -692,60 +692,59 @@ sol::table TLuaEngine::StateThreadData::Lua_FS_ListDirectories(const std::string
|
|||||||
|
|
||||||
std::string TLuaEngine::StateThreadData::Lua_GetPlayerName(int ID) {
|
std::string TLuaEngine::StateThreadData::Lua_GetPlayerName(int ID) {
|
||||||
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
return MaybeClient.value().lock()->GetName();
|
if (auto Locked = MaybeClient.value().lock()) {
|
||||||
} else {
|
return Locked->GetName();
|
||||||
return "";
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table TLuaEngine::StateThreadData::Lua_GetPlayerVehicles(int ID) {
|
sol::table TLuaEngine::StateThreadData::Lua_GetPlayerVehicles(int ID) {
|
||||||
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
auto Client = MaybeClient.value().lock();
|
if (auto Client = MaybeClient.value().lock()) {
|
||||||
TClient::TSetOfVehicleData VehicleData;
|
TClient::TSetOfVehicleData VehicleData;
|
||||||
{ // Vehicle Data Lock Scope
|
{ // Vehicle Data Lock Scope
|
||||||
auto LockedData = Client->GetAllCars();
|
auto LockedData = Client->GetAllCars();
|
||||||
VehicleData = *LockedData.VehicleData;
|
VehicleData = *LockedData.VehicleData;
|
||||||
} // End Vehicle Data Lock Scope
|
} // End Vehicle Data Lock Scope
|
||||||
if (VehicleData.empty()) {
|
if (VehicleData.empty()) {
|
||||||
return sol::lua_nil;
|
return sol::lua_nil;
|
||||||
|
}
|
||||||
|
sol::state_view StateView(mState);
|
||||||
|
sol::table Result = StateView.create_table();
|
||||||
|
for (const auto& v : VehicleData) {
|
||||||
|
Result[v.ID()] = v.DataAsPacket(Client->GetRoles(), Client->GetName(), Client->GetID()).substr(3);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
sol::state_view StateView(mState);
|
}
|
||||||
sol::table Result = StateView.create_table();
|
return sol::lua_nil;
|
||||||
for (const auto& v : VehicleData) {
|
|
||||||
Result[v.ID()] = v.DataAsPacket(Client->GetRoles(), Client->GetName(), Client->GetID()).substr(3);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
} else
|
|
||||||
return sol::lua_nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<sol::table, std::string> TLuaEngine::StateThreadData::Lua_GetPositionRaw(int PID, int VID) {
|
std::pair<sol::table, std::string> TLuaEngine::StateThreadData::Lua_GetPositionRaw(int PID, int VID) {
|
||||||
std::pair<sol::table, std::string> Result;
|
std::pair<sol::table, std::string> Result;
|
||||||
auto MaybeClient = GetClient(mEngine->Server(), PID);
|
auto MaybeClient = GetClient(mEngine->Server(), PID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient) {
|
||||||
auto Client = MaybeClient.value().lock();
|
if (auto Client = MaybeClient.value().lock()) {
|
||||||
std::string VehiclePos = Client->GetCarPositionRaw(VID);
|
std::string VehiclePos = Client->GetCarPositionRaw(VID);
|
||||||
|
|
||||||
if (VehiclePos.empty()) {
|
if (VehiclePos.empty()) {
|
||||||
// return std::make_tuple(sol::lua_nil, sol::make_object(StateView, "Vehicle not found"));
|
Result.second = "Vehicle not found";
|
||||||
Result.second = "Vehicle not found";
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::table t = Lua_JsonDecode(VehiclePos);
|
||||||
|
if (t == sol::lua_nil) {
|
||||||
|
Result.second = "Packet decode failed";
|
||||||
|
}
|
||||||
|
Result.first = t;
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table t = Lua_JsonDecode(VehiclePos);
|
|
||||||
if (t == sol::lua_nil) {
|
|
||||||
Result.second = "Packet decode failed";
|
|
||||||
}
|
|
||||||
// return std::make_tuple(Result, sol::make_object(StateView, sol::lua_nil));
|
|
||||||
Result.first = t;
|
|
||||||
return Result;
|
|
||||||
} else {
|
|
||||||
// return std::make_tuple(sol::lua_nil, sol::make_object(StateView, "Client expired"));
|
|
||||||
Result.second = "No such player";
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
Result.second = "No such player";
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table TLuaEngine::StateThreadData::Lua_HttpCreateConnection(const std::string& host, uint16_t port) {
|
sol::table TLuaEngine::StateThreadData::Lua_HttpCreateConnection(const std::string& host, uint16_t port) {
|
||||||
@@ -786,22 +785,31 @@ static bool mDisableMPSet = [] {
|
|||||||
|
|
||||||
static auto GetSettingName = [](int id) -> const char* {
|
static auto GetSettingName = [](int id) -> const char* {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0: return "Debug";
|
case 0:
|
||||||
case 1: return "Private";
|
return "Debug";
|
||||||
case 2: return "MaxCars";
|
case 1:
|
||||||
case 3: return "MaxPlayers";
|
return "Private";
|
||||||
case 4: return "Map";
|
case 2:
|
||||||
case 5: return "Name";
|
return "MaxCars";
|
||||||
case 6: return "Description";
|
case 3:
|
||||||
case 7: return "InformationPacket";
|
return "MaxPlayers";
|
||||||
default: return "Unknown";
|
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:
|
||||||
AddToTable(table, left, sol::lua_nil_t {});
|
AddToTable(table, left, sol::lua_nil_t { });
|
||||||
return;
|
return;
|
||||||
case nlohmann::detail::value_t::object: {
|
case nlohmann::detail::value_t::object: {
|
||||||
auto value = table.create();
|
auto value = table.create();
|
||||||
@@ -949,12 +957,9 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
beammp_lua_error("SendNotification expects 2, 3 or 4 arguments.");
|
beammp_lua_error("SendNotification expects 2, 3 or 4 arguments.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
MPTable.set_function("ConfirmationDialog", sol::overload(
|
MPTable.set_function("ConfirmationDialog", sol::overload(&LuaAPI::MP::ConfirmationDialog, [&](const int& ID, const std::string& Title, const std::string& Body, const sol::table& Buttons, const std::string& InteractionID) {
|
||||||
&LuaAPI::MP::ConfirmationDialog,
|
LuaAPI::MP::ConfirmationDialog(ID, Title, Body, Buttons, InteractionID);
|
||||||
[&](const int& ID, const std::string& Title, const std::string& Body, const sol::table& Buttons, const std::string& InteractionID) {
|
}));
|
||||||
LuaAPI::MP::ConfirmationDialog(ID, Title, Body, Buttons, InteractionID);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
MPTable.set_function("GetPlayers", [&]() -> sol::table {
|
MPTable.set_function("GetPlayers", [&]() -> sol::table {
|
||||||
return Lua_GetPlayers();
|
return Lua_GetPlayers();
|
||||||
});
|
});
|
||||||
|
|||||||
+44
-36
@@ -101,8 +101,8 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R
|
|||||||
Application::RegisterShutdownHandler([&] {
|
Application::RegisterShutdownHandler([&] {
|
||||||
beammp_debug("Kicking all players due to shutdown");
|
beammp_debug("Kicking all players due to shutdown");
|
||||||
Server.ForEachClient([&](std::weak_ptr<TClient> client) -> bool {
|
Server.ForEachClient([&](std::weak_ptr<TClient> client) -> bool {
|
||||||
if (!client.expired()) {
|
if (auto Locked = client.lock()) {
|
||||||
ClientKick(*client.lock(), "Server shutdown");
|
ClientKick(*Locked, "Server shutdown");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -181,8 +181,8 @@ void TNetwork::UDPServerMain() {
|
|||||||
std::shared_ptr<TClient> Client;
|
std::shared_ptr<TClient> Client;
|
||||||
{
|
{
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto Locked = ClientPtr.lock()) {
|
||||||
Client = ClientPtr.lock();
|
Client = std::move(Locked);
|
||||||
} else
|
} else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -489,8 +489,8 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
std::shared_ptr<TClient> Cl;
|
std::shared_ptr<TClient> Cl;
|
||||||
{
|
{
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto Locked = ClientPtr.lock()) {
|
||||||
Cl = ClientPtr.lock();
|
Cl = std::move(Locked);
|
||||||
} else
|
} else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -712,8 +712,11 @@ void TNetwork::DisconnectClient(TClient& c, const std::string& R) {
|
|||||||
|
|
||||||
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
||||||
RegisterThreadAuto();
|
RegisterThreadAuto();
|
||||||
while (!c.expired()) {
|
while (true) {
|
||||||
auto Client = c.lock();
|
auto Client = c.lock();
|
||||||
|
if (!Client) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (Client->IsDisconnected()) {
|
if (Client->IsDisconnected()) {
|
||||||
beammp_debug("client is disconnected, breaking client loop");
|
beammp_debug("client is disconnected, breaking client loop");
|
||||||
break;
|
break;
|
||||||
@@ -747,20 +750,29 @@ void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
||||||
// TODO: the c.expired() might cause issues here, remove if you end up here with your debugger
|
if (auto Client = c.lock()) {
|
||||||
if (c.expired() || c.lock()->IsDisconnected()) {
|
if (Client->IsDisconnected()) {
|
||||||
|
mServer.RemoveClient(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mServer.RemoveClient(c);
|
mServer.RemoveClient(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OnConnect(c);
|
OnConnect(c);
|
||||||
RegisterThread("(" + std::to_string(c.lock()->GetID()) + ") \"" + c.lock()->GetName() + "\"");
|
if (auto Client = c.lock()) {
|
||||||
|
RegisterThread("(" + std::to_string(Client->GetID()) + ") \"" + Client->GetName() + "\"");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::jthread QueueSync(&TNetwork::Looper, this, c);
|
std::jthread QueueSync(&TNetwork::Looper, this, c);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (c.expired())
|
|
||||||
break;
|
|
||||||
auto Client = c.lock();
|
auto Client = c.lock();
|
||||||
|
if (!Client) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (Client->IsDisconnected()) {
|
if (Client->IsDisconnected()) {
|
||||||
beammp_debug("client status < 0, breaking client loop");
|
beammp_debug("client status < 0, breaking client loop");
|
||||||
break;
|
break;
|
||||||
@@ -781,8 +793,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c.expired()) {
|
if (auto Client = c.lock()) {
|
||||||
auto Client = c.lock();
|
|
||||||
OnDisconnect(c);
|
OnDisconnect(c);
|
||||||
} else {
|
} else {
|
||||||
beammp_warn("client expired in TCPClient, should never happen");
|
beammp_warn("client expired in TCPClient, should never happen");
|
||||||
@@ -793,8 +804,7 @@ void TNetwork::UpdatePlayer(TClient& Client) {
|
|||||||
std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + ":";
|
std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + ":";
|
||||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto c = ClientPtr.lock()) {
|
||||||
auto c = ClientPtr.lock();
|
|
||||||
Packet += c->GetName() + ",";
|
Packet += c->GetName() + ",";
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -937,14 +947,11 @@ TEST_CASE("ReadSocketWithTimeout can timeout then retry successfully") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
||||||
std::shared_ptr<TClient> LockedClientPtr { nullptr };
|
auto LockedClientPtr = ClientPtr.lock();
|
||||||
try {
|
if (!LockedClientPtr) {
|
||||||
LockedClientPtr = ClientPtr.lock();
|
|
||||||
} catch (const std::exception&) {
|
|
||||||
beammp_warn("Client expired in OnDisconnect, this is unexpected");
|
beammp_warn("Client expired in OnDisconnect, this is unexpected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
beammp_assert(LockedClientPtr != nullptr);
|
|
||||||
TClient& c = *LockedClientPtr;
|
TClient& c = *LockedClientPtr;
|
||||||
beammp_info(c.GetName() + (" Connection Terminated"));
|
beammp_info(c.GetName() + (" Connection Terminated"));
|
||||||
std::string Packet;
|
std::string Packet;
|
||||||
@@ -975,8 +982,7 @@ int TNetwork::OpenID() {
|
|||||||
found = true;
|
found = true;
|
||||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto c = ClientPtr.lock()) {
|
||||||
auto c = ClientPtr.lock();
|
|
||||||
if (c->GetID() == ID) {
|
if (c->GetID() == ID) {
|
||||||
found = false;
|
found = false;
|
||||||
ID++;
|
ID++;
|
||||||
@@ -989,9 +995,11 @@ int TNetwork::OpenID() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
||||||
beammp_assert(!c.expired());
|
|
||||||
beammp_info("Client connected");
|
|
||||||
auto LockedClient = c.lock();
|
auto LockedClient = c.lock();
|
||||||
|
if (!LockedClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
beammp_info("Client connected");
|
||||||
LockedClient->SetID(OpenID());
|
LockedClient->SetID(OpenID());
|
||||||
beammp_info("Assigned ID " + std::to_string(LockedClient->GetID()) + " to " + LockedClient->GetName());
|
beammp_info("Assigned ID " + std::to_string(LockedClient->GetID()) + " to " + LockedClient->GetName());
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerConnecting", "", LockedClient->GetID()));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerConnecting", "", LockedClient->GetID()));
|
||||||
@@ -1218,10 +1226,10 @@ bool TNetwork::Respond(TClient& c, const std::vector<uint8_t>& MSG, bool Rel, bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
||||||
if (c.expired()) {
|
auto LockedClient = c.lock();
|
||||||
|
if (!LockedClient) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto LockedClient = c.lock();
|
|
||||||
if (LockedClient->IsSynced())
|
if (LockedClient->IsSynced())
|
||||||
return true;
|
return true;
|
||||||
// Syncing, later set isSynced
|
// Syncing, later set isSynced
|
||||||
@@ -1240,8 +1248,8 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
|||||||
std::shared_ptr<TClient> client;
|
std::shared_ptr<TClient> client;
|
||||||
{
|
{
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto Locked = ClientPtr.lock()) {
|
||||||
client = ClientPtr.lock();
|
client = std::move(Locked);
|
||||||
} else
|
} else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1278,14 +1286,14 @@ void TNetwork::SendToAll(TClient* c, const std::vector<uint8_t>& Data, bool Self
|
|||||||
char C = Data.at(0);
|
char C = Data.at(0);
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
||||||
std::shared_ptr<TClient> Client;
|
std::shared_ptr<TClient> Client { nullptr };
|
||||||
try {
|
{
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
Client = ClientPtr.lock();
|
if (auto Locked = ClientPtr.lock()) {
|
||||||
} catch (const std::exception&) {
|
Client = std::move(Locked);
|
||||||
// continue
|
} else {
|
||||||
beammp_warn("Client expired, shouldn't happen - if a client disconnected recently, you can ignore this");
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
if (Self || Client.get() != c) {
|
if (Self || Client.get() != c) {
|
||||||
if (Client->IsSynced() || Client->IsSyncing()) {
|
if (Client->IsSynced() || Client->IsSyncing()) {
|
||||||
|
|||||||
+2
-2
@@ -55,8 +55,8 @@ void TPPSMonitor::operator()() {
|
|||||||
std::shared_ptr<TClient> c;
|
std::shared_ptr<TClient> c;
|
||||||
{
|
{
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
ReadLock Lock(mServer.GetClientMutex());
|
||||||
if (!ClientPtr.expired()) {
|
if (auto Locked = ClientPtr.lock()) {
|
||||||
c = ClientPtr.lock();
|
c = std::move(Locked);
|
||||||
} else
|
} else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-15
@@ -127,19 +127,15 @@ TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TServer::RemoveClient(const std::weak_ptr<TClient>& WeakClientPtr) {
|
void TServer::RemoveClient(const std::weak_ptr<TClient>& WeakClientPtr) {
|
||||||
std::shared_ptr<TClient> LockedClientPtr { nullptr };
|
auto LockedClientPtr = WeakClientPtr.lock();
|
||||||
try {
|
if (!LockedClientPtr) {
|
||||||
LockedClientPtr = WeakClientPtr.lock();
|
|
||||||
} catch (const std::exception&) {
|
|
||||||
// silently fail, as there's nothing to do
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
beammp_assert(LockedClientPtr != nullptr);
|
|
||||||
TClient& Client = *LockedClientPtr;
|
TClient& Client = *LockedClientPtr;
|
||||||
beammp_debug("removing client " + Client.GetName() + " (" + std::to_string(ClientCount()) + ")");
|
beammp_debug("removing client " + Client.GetName() + " (" + std::to_string(ClientCount()) + ")");
|
||||||
Client.ClearCars();
|
Client.ClearCars();
|
||||||
WriteLock Lock(mClientsMutex);
|
WriteLock Lock(mClientsMutex);
|
||||||
mClients.erase(WeakClientPtr.lock());
|
mClients.erase(LockedClientPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn) {
|
void TServer::ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn) {
|
||||||
@@ -167,14 +163,16 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
try {
|
try {
|
||||||
Packet = DeComp(Packet);
|
Packet = DeComp(Packet);
|
||||||
} catch (const InvalidDataError& ) {
|
} catch (const InvalidDataError& ) {
|
||||||
auto LockedClient = Client.lock();
|
if (auto LockedClient = Client.lock()) {
|
||||||
beammp_errorf("Failed to decompress packet from client {}. The client sent invalid data and will now be disconnected.", LockedClient->GetID());
|
beammp_errorf("Failed to decompress packet from client {}. The client sent invalid data and will now be disconnected.", LockedClient->GetID());
|
||||||
Network.ClientKick(*LockedClient, "Sent invalid compressed packet (this is likely a bug on your end)");
|
Network.ClientKick(*LockedClient, "Sent invalid compressed packet (this is likely a bug on your end)");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} catch (const std::runtime_error& e) {
|
} catch (const std::runtime_error& e) {
|
||||||
auto LockedClient = Client.lock();
|
if (auto LockedClient = Client.lock()) {
|
||||||
beammp_errorf("Failed to decompress packet from client {}: {}. The server might be out of RAM! The client will now be disconnected.", LockedClient->GetID(), e.what());
|
beammp_errorf("Failed to decompress packet from client {}: {}. The server might be out of RAM! The client will now be disconnected.", LockedClient->GetID(), e.what());
|
||||||
Network.ClientKick(*LockedClient, "Decompression failed (likely a server-side problem)");
|
Network.ClientKick(*LockedClient, "Decompression failed (likely a server-side problem)");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,10 +180,10 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Client.expired()) {
|
auto LockedClient = Client.lock();
|
||||||
|
if (!LockedClient) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto LockedClient = Client.lock();
|
|
||||||
|
|
||||||
std::any Res;
|
std::any Res;
|
||||||
char Code = Packet.at(0);
|
char Code = Packet.at(0);
|
||||||
|
|||||||
Reference in new issue
Block a user