mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-03 08:15:35 +00:00
refactor client disconnect, client interation
anywhere a client is disconnected, TNetwork::Disconnect is called now. Nothing else is valid. ForEachClientWeak() was fully removed.
This commit is contained in:
parent
aa29d04b60
commit
130e1acdb3
@ -44,7 +44,6 @@ public:
|
|||||||
void SetIdentifier(const std::string& key, const std::string& value);
|
void SetIdentifier(const std::string& key, const std::string& value);
|
||||||
std::string GetCarData(int Ident);
|
std::string GetCarData(int Ident);
|
||||||
std::string GetCarPositionRaw(int Ident);
|
std::string GetCarPositionRaw(int Ident);
|
||||||
void Disconnect(std::string_view Reason);
|
|
||||||
bool IsDisconnected() const { return !TCPSocket->is_open(); }
|
bool IsDisconnected() const { return !TCPSocket->is_open(); }
|
||||||
// locks
|
// locks
|
||||||
void DeleteCar(int Ident);
|
void DeleteCar(int Ident);
|
||||||
@ -75,7 +74,12 @@ public:
|
|||||||
Sync<std::queue<std::vector<uint8_t>>> MissedPacketsQueue;
|
Sync<std::queue<std::vector<uint8_t>>> MissedPacketsQueue;
|
||||||
Sync<std::chrono::time_point<std::chrono::high_resolution_clock>> LastPingTime;
|
Sync<std::chrono::time_point<std::chrono::high_resolution_clock>> LastPingTime;
|
||||||
|
|
||||||
|
friend class TNetwork;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// ONLY call after the client has been cleaned up, all cars deleted, etc.
|
||||||
|
void CloseSockets(std::string_view Reason);
|
||||||
|
|
||||||
void InsertVehicle(int ID, const std::string& Data);
|
void InsertVehicle(int ID, const std::string& Data);
|
||||||
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
|
@ -19,6 +19,9 @@ public:
|
|||||||
std::shared_ptr<TClient> CreateClient(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 Disconnect(const std::shared_ptr<TClient>& ClientPtr);
|
||||||
|
void Disconnect(const std::weak_ptr<TClient>& ClientPtr);
|
||||||
|
void Disconnect(TClient& Client);
|
||||||
[[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);
|
||||||
@ -43,14 +46,11 @@ private:
|
|||||||
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);
|
||||||
void OnDisconnect(const std::shared_ptr<TClient>& ClientPtr);
|
|
||||||
void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr);
|
|
||||||
void OnDisconnect(TClient& Client);
|
|
||||||
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, ip::tcp::socket& socket, const uint8_t* Data, size_t Size);
|
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);
|
void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name);
|
||||||
static const uint8_t* SendSplit(TClient& c, ip::tcp::socket& Socket, const uint8_t* DataPtr, size_t Size);
|
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);
|
||||||
|
@ -24,7 +24,6 @@ public:
|
|||||||
void RemoveClient(const std::weak_ptr<TClient>&);
|
void RemoveClient(const std::weak_ptr<TClient>&);
|
||||||
void RemoveClient(TClient&);
|
void RemoveClient(TClient&);
|
||||||
// in Fn, return true to continue, return false to break
|
// in Fn, return true to continue, return false to break
|
||||||
[[deprecated("Use ForEachClient instead")]] void ForEachClientWeak(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
|
|
||||||
void ForEachClient(const std::function<bool(const std::shared_ptr<TClient>&)> Fn);
|
void ForEachClient(const std::function<bool(const std::shared_ptr<TClient>&)> Fn);
|
||||||
size_t ClientCount() const;
|
size_t ClientCount() const;
|
||||||
|
|
||||||
|
@ -51,17 +51,25 @@ std::string TClient::GetCarPositionRaw(int Ident) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TClient::Disconnect(std::string_view Reason) {
|
void TClient::CloseSockets(std::string_view Reason) {
|
||||||
auto LockedSocket = TCPSocket.synchronize();
|
auto LockedSocket = TCPSocket.synchronize();
|
||||||
beammp_debugf("Disconnecting client {} for reason: {}", int(ID), Reason);
|
beammp_debugf("Disconnecting client {} for reason: {}", int(ID), Reason);
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
LockedSocket->shutdown(socket_base::shutdown_both, ec);
|
LockedSocket->shutdown(socket_base::shutdown_both, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("Failed to shutdown client socket: {}", ec.message());
|
beammp_debugf("Failed to shutdown client socket of client {}: {}", ID.get(), ec.message());
|
||||||
}
|
}
|
||||||
LockedSocket->close(ec);
|
LockedSocket->close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("Failed to close client socket: {}", ec.message());
|
beammp_debugf("Failed to close client socket of client {}: {}", ID.get(), ec.message());
|
||||||
|
}
|
||||||
|
DownSocket->shutdown(socket_base::shutdown_both, ec);
|
||||||
|
if (ec) {
|
||||||
|
beammp_debugf("Failed to shutdown client download socket of client {}: {}", ID.get(), ec.message());
|
||||||
|
}
|
||||||
|
DownSocket->close(ec);
|
||||||
|
if (ec) {
|
||||||
|
beammp_debugf("Failed to close client download socket of client {}: {}", ID.get(), ec.message());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ static inline std::pair<bool, std::string> InternalTriggerClientEvent(int Player
|
|||||||
auto c = MaybeClient.value();
|
auto c = MaybeClient.value();
|
||||||
if (!LuaAPI::MP::Engine->Network().Respond(*c, StringToVector(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().Disconnect(*c);
|
||||||
return { false, "Respond failed, dropping client" };
|
return { false, "Respond failed, dropping client" };
|
||||||
}
|
}
|
||||||
return { true, "" };
|
return { true, "" };
|
||||||
@ -169,7 +169,8 @@ std::pair<bool, std::string> LuaAPI::MP::SendChatMessage(int ID, const std::stri
|
|||||||
LogChatMessage("<Server> (to \"" + c->Name.get() + "\")", -1, Message);
|
LogChatMessage("<Server> (to \"" + c->Name.get() + "\")", -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?
|
beammp_infof("Disconnecting client {} for failure to receive a chat message (TCP disconnect)", c->Name.get());
|
||||||
|
Engine->Network().Disconnect(c);
|
||||||
}
|
}
|
||||||
Result.first = true;
|
Result.first = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -266,15 +266,12 @@ void TConsole::Command_Kick(const std::string&, const std::vector<std::string>&
|
|||||||
std::for_each(Name2.begin(), Name2.end(), [](char& c) { c = char(std::tolower(char(c))); });
|
std::for_each(Name2.begin(), Name2.end(), [](char& c) { c = char(std::tolower(char(c))); });
|
||||||
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
||||||
};
|
};
|
||||||
mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](const std::shared_ptr<TClient>& Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (NameCompare(Client->Name.get(), Name)) {
|
||||||
auto locked = Client.lock();
|
mLuaEngine->Network().ClientKick(*Client, Reason);
|
||||||
if (NameCompare(locked->Name.get(), Name)) {
|
|
||||||
mLuaEngine->Network().ClientKick(*locked, Reason);
|
|
||||||
Kicked = true;
|
Kicked = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!Kicked) {
|
if (!Kicked) {
|
||||||
@ -364,13 +361,10 @@ void TConsole::Command_List(const std::string&, const std::vector<std::string>&
|
|||||||
} else {
|
} else {
|
||||||
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().ForEachClientWeak([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](const std::shared_ptr<TClient>& Client) -> bool {
|
||||||
if (!Client.expired()) {
|
ss << std::left << std::setw(25) << Client->Name.get()
|
||||||
auto locked = Client.lock();
|
<< std::setw(6) << Client->ID.get()
|
||||||
ss << std::left << std::setw(25) << locked->Name.get()
|
<< std::setw(6) << Client->GetCarCount() << "\n";
|
||||||
<< std::setw(6) << locked->ID.get()
|
|
||||||
<< std::setw(6) << locked->GetCarCount() << "\n";
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
auto Str = ss.str();
|
auto Str = ss.str();
|
||||||
|
@ -497,11 +497,8 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) {
|
|||||||
|
|
||||||
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().ForEachClientWeak([&](std::weak_ptr<TClient> Client) -> bool {
|
mEngine->Server().ForEachClient([&](const std::shared_ptr<TClient>& Client) -> bool {
|
||||||
if (!Client.expired()) {
|
Result[Client->ID.get()] = Client->Name.get();
|
||||||
auto locked = Client.lock();
|
|
||||||
Result[locked->ID.get()] = locked->Name.get();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
return Result;
|
return Result;
|
||||||
@ -509,13 +506,10 @@ 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->ForEachClientWeak([&Id, &Name](std::weak_ptr<TClient> Client) -> bool {
|
mEngine->mServer->ForEachClient([&Id, &Name](const std::shared_ptr<TClient>& Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (Client->Name.get() == Name) {
|
||||||
auto locked = Client.lock();
|
Id = Client->ID.get();
|
||||||
if (locked->Name.get() == Name) {
|
return false;
|
||||||
Id = locked->ID.get();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -246,7 +246,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!TCPSend(*Client, StringToVector("A"))) { // changed to A for Accepted version
|
if (!TCPSend(*Client, StringToVector("A"))) { // changed to A for Accepted version
|
||||||
OnDisconnect(Client);
|
Disconnect(Client);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
|
|
||||||
if (!Application::Settings.Password.empty()) { // ask password
|
if (!Application::Settings.Password.empty()) { // ask password
|
||||||
if (!TCPSend(*Client, StringToVector("S"))) {
|
if (!TCPSend(*Client, StringToVector("S"))) {
|
||||||
OnDisconnect(Client);
|
Disconnect(Client);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
beammp_info("Waiting for password");
|
beammp_info("Waiting for password");
|
||||||
@ -320,20 +320,11 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beammp_debug("Name-> " + Client->Name.get() + ", Guest-> " + std::to_string(Client->IsGuest.get()) + ", Roles-> " + Client->Role.get());
|
beammp_debug("Name-> " + Client->Name.get() + ", Guest-> " + std::to_string(Client->IsGuest.get()) + ", Roles-> " + Client->Role.get());
|
||||||
mServer.ForEachClientWeak([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::shared_ptr<TClient>& Cl) -> bool {
|
||||||
std::shared_ptr<TClient> Cl;
|
|
||||||
{
|
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
|
||||||
if (!ClientPtr.expired()) {
|
|
||||||
Cl = ClientPtr.lock();
|
|
||||||
} else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Cl->Name.get() == Client->Name.get() && Cl->IsGuest == Client->IsGuest) {
|
if (Cl->Name.get() == Client->Name.get() && Cl->IsGuest == Client->IsGuest) {
|
||||||
Cl->Disconnect("Stale Client (not a real player)");
|
Disconnect(Cl);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -368,7 +359,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
TCPClient(Client);
|
TCPClient(Client);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
beammp_infof("Client {} disconnected: {}", Client->ID.get(), e.what());
|
beammp_infof("Client {} disconnected: {}", Client->ID.get(), e.what());
|
||||||
OnDisconnect(Client);
|
Disconnect(Client);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -412,7 +403,7 @@ bool TNetwork::TCPSend(TClient& c, const std::vector<uint8_t>& Data, bool IsSync
|
|||||||
write(*c.TCPSocket.synchronize(), buffer(ToSend), ec);
|
write(*c.TCPSocket.synchronize(), buffer(ToSend), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("write(): {}", ec.message());
|
beammp_debugf("write(): {}", ec.message());
|
||||||
c.Disconnect("write() failed");
|
Disconnect(c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
c.UpdatePingTime();
|
c.UpdatePingTime();
|
||||||
@ -477,7 +468,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.Name.get(), c.ID.get());
|
beammp_debugf("tried to kick player '{}' (id {}), but was already disconnected", c.Name.get(), c.ID.get());
|
||||||
}
|
}
|
||||||
c.Disconnect("Kicked");
|
Disconnect(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
||||||
@ -502,7 +493,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)) {
|
||||||
Client->Disconnect("Failed to TCPSend while clearing the missed packet queue");
|
Disconnect(Client);
|
||||||
auto Lock = Client->MissedPacketsQueue;
|
auto Lock = Client->MissedPacketsQueue;
|
||||||
while (!Lock->empty()) {
|
while (!Lock->empty()) {
|
||||||
Lock->pop();
|
Lock->pop();
|
||||||
@ -539,7 +530,7 @@ 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");
|
||||||
Client->Disconnect("TCPRcv failed");
|
Disconnect(Client);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this);
|
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this);
|
||||||
@ -550,7 +541,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
|
|
||||||
if (!c.expired()) {
|
if (!c.expired()) {
|
||||||
auto Client = c.lock();
|
auto Client = c.lock();
|
||||||
OnDisconnect(c);
|
Disconnect(c);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
beammp_warn("client expired in TCPClient, should never happen");
|
beammp_warn("client expired in TCPClient, should never happen");
|
||||||
@ -569,7 +560,7 @@ void TNetwork::UpdatePlayer(TClient& Client) {
|
|||||||
//(void)Respond(Client, Packet, true);
|
//(void)Respond(Client, Packet, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
void TNetwork::Disconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
||||||
// this is how one checks that the ClientPtr is not empty (as opposed to expired)
|
// this is how one checks that the ClientPtr is not empty (as opposed to expired)
|
||||||
if (ClientPtr.owner_before(std::weak_ptr<TClient> {})) {
|
if (ClientPtr.owner_before(std::weak_ptr<TClient> {})) {
|
||||||
return;
|
return;
|
||||||
@ -578,37 +569,37 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr) {
|
|||||||
try {
|
try {
|
||||||
LockedClientPtr = ClientPtr.lock();
|
LockedClientPtr = ClientPtr.lock();
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
beammp_warn("Client expired in OnDisconnect, this is unexpected");
|
beammp_warn("Client expired in CloseSockets, this is unexpected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
beammp_assert(LockedClientPtr != nullptr);
|
beammp_assert(LockedClientPtr != nullptr);
|
||||||
TClient& c = *LockedClientPtr;
|
TClient& c = *LockedClientPtr;
|
||||||
OnDisconnect(c);
|
Disconnect(c);
|
||||||
}
|
}
|
||||||
void TNetwork::OnDisconnect(TClient& c) {
|
void TNetwork::Disconnect(TClient& Client) {
|
||||||
beammp_info(c.Name.get() + (" Connection Terminated"));
|
beammp_info(Client.Name.get() + (" Connection Terminated"));
|
||||||
std::string Packet;
|
std::string Packet;
|
||||||
{
|
{
|
||||||
auto Locked = c.VehicleData.synchronize();
|
auto Locked = Client.VehicleData.synchronize();
|
||||||
for (auto& v : *Locked) {
|
for (auto& v : *Locked) {
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", c.ID.get(), v.ID()));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", Client.ID.get(), v.ID()));
|
||||||
Packet = "Od:" + std::to_string(c.ID.get()) + "-" + std::to_string(v.ID());
|
Packet = "Od:" + std::to_string(Client.ID.get()) + "-" + std::to_string(v.ID());
|
||||||
SendToAll(&c, StringToVector(Packet), false, true);
|
SendToAll(&Client, StringToVector(Packet), false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Packet = ("L") + c.Name.get() + (" left the server!");
|
Packet = ("L") + Client.Name.get() + (" left the server!");
|
||||||
SendToAll(&c, StringToVector(Packet), false, true);
|
SendToAll(&Client, StringToVector(Packet), false, true);
|
||||||
Packet.clear();
|
Packet.clear();
|
||||||
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", c.ID.get());
|
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", Client.ID.get());
|
||||||
TLuaEngine::WaitForAll(Futures);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
c.Disconnect("Already Disconnected (OnDisconnect)");
|
Client.CloseSockets("Normal disconnect");
|
||||||
mServer.RemoveClient(c);
|
mServer.RemoveClient(Client);
|
||||||
}
|
}
|
||||||
void TNetwork::OnDisconnect(const std::shared_ptr<TClient>& ClientPtr) {
|
void TNetwork::Disconnect(const std::shared_ptr<TClient>& ClientPtr) {
|
||||||
if (ClientPtr == nullptr) {
|
if (ClientPtr == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OnDisconnect(*ClientPtr);
|
Disconnect(*ClientPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
||||||
@ -674,7 +665,8 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) {
|
|||||||
|
|
||||||
if (!fs::path(UnsafeName).has_filename()) {
|
if (!fs::path(UnsafeName).has_filename()) {
|
||||||
if (!TCPSend(c, StringToVector("CO"))) {
|
if (!TCPSend(c, StringToVector("CO"))) {
|
||||||
OnDisconnect(c);
|
Disconnect(c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
beammp_warn("File " + UnsafeName + " is not a file!");
|
beammp_warn("File " + UnsafeName + " is not a file!");
|
||||||
return;
|
return;
|
||||||
@ -684,14 +676,16 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) {
|
|||||||
|
|
||||||
if (!std::filesystem::exists(FileName)) {
|
if (!std::filesystem::exists(FileName)) {
|
||||||
if (!TCPSend(c, StringToVector("CO"))) {
|
if (!TCPSend(c, StringToVector("CO"))) {
|
||||||
OnDisconnect(c);
|
Disconnect(c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
beammp_warn("File " + UnsafeName + " could not be accessed!");
|
beammp_warn("File " + UnsafeName + " could not be accessed!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TCPSend(c, StringToVector("AG"))) {
|
if (!TCPSend(c, StringToVector("AG"))) {
|
||||||
OnDisconnect(c);
|
Disconnect(c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for connections
|
/// Wait for connections
|
||||||
@ -704,7 +698,7 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) {
|
|||||||
if (!c.DownSocket->is_open()) {
|
if (!c.DownSocket->is_open()) {
|
||||||
beammp_error("Client doesn't have a download socket!");
|
beammp_error("Client doesn't have a download socket!");
|
||||||
if (!c.IsDisconnected())
|
if (!c.IsDisconnected())
|
||||||
c.Disconnect("Missing download socket");
|
Disconnect(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,7 +788,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
|||||||
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())
|
||||||
c.Disconnect("TCPSendRaw failed in mod download (1)");
|
Disconnect(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Split;
|
Sent += Split;
|
||||||
@ -803,7 +797,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
|||||||
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())
|
||||||
c.Disconnect("TCPSendRaw failed in mod download (2)");
|
Disconnect(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Diff;
|
Sent += Diff;
|
||||||
@ -818,7 +812,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
|||||||
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())
|
||||||
c.Disconnect("TCPSendRaw failed in mod download (1)");
|
Disconnect(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Split;
|
Sent += Split;
|
||||||
@ -827,7 +821,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
|||||||
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())
|
||||||
c.Disconnect("TCPSendRaw failed in mod download (2)");
|
Disconnect(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sent += Diff;
|
Sent += Diff;
|
||||||
@ -931,7 +925,7 @@ void TNetwork::SendToAll(TClient* c, const std::vector<uint8_t>& Data, bool Self
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!UDPSend(*Client, Data)) {
|
if (!UDPSend(*Client, Data)) {
|
||||||
OnDisconnect(Client);
|
Disconnect(Client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -957,7 +951,7 @@ bool TNetwork::UDPSend(TClient& Client, std::vector<uint8_t> Data) {
|
|||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_debugf("UDP sendto() failed: {}", ec.message());
|
beammp_debugf("UDP sendto() failed: {}", ec.message());
|
||||||
if (!Client.IsDisconnected())
|
if (!Client.IsDisconnected())
|
||||||
Client.Disconnect("UDP send failed");
|
Disconnect(Client);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -33,15 +33,7 @@ void TPPSMonitor::operator()() {
|
|||||||
Application::SetPPS("-");
|
Application::SetPPS("-");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mServer.ForEachClientWeak([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::shared_ptr<TClient>& c) -> bool {
|
||||||
std::shared_ptr<TClient> c;
|
|
||||||
{
|
|
||||||
ReadLock Lock(mServer.GetClientMutex());
|
|
||||||
if (!ClientPtr.expired()) {
|
|
||||||
c = ClientPtr.lock();
|
|
||||||
} else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c->GetCarCount() > 0) {
|
if (c->GetCarCount() > 0) {
|
||||||
C++;
|
C++;
|
||||||
V += c->GetCarCount();
|
V += c->GetCarCount();
|
||||||
|
@ -171,19 +171,6 @@ void TServer::ForEachClient(const std::function<bool(const std::shared_ptr<TClie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::ForEachClientWeak(const std::function<bool(std::weak_ptr<TClient>)>& Fn) {
|
|
||||||
decltype(mClients) Clients;
|
|
||||||
{
|
|
||||||
ReadLock lock(mClientsMutex);
|
|
||||||
Clients = mClients;
|
|
||||||
}
|
|
||||||
for (auto& Client : Clients) {
|
|
||||||
if (!Fn(Client)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t TServer::ClientCount() const {
|
size_t TServer::ClientCount() const {
|
||||||
ReadLock Lock(mClientsMutex);
|
ReadLock Lock(mClientsMutex);
|
||||||
return mClients.size();
|
return mClients.size();
|
||||||
@ -224,7 +211,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
case 'p':
|
case 'p':
|
||||||
if (!Network.Respond(*LockedClient, StringToVector("p"), false)) {
|
if (!Network.Respond(*LockedClient, StringToVector("p"), false)) {
|
||||||
// failed to send
|
// failed to send
|
||||||
LockedClient->Disconnect("Failed to send ping");
|
Disconnect(LockedClient);
|
||||||
} else {
|
} else {
|
||||||
Network.UpdatePlayer(*LockedClient);
|
Network.UpdatePlayer(*LockedClient);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user