mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +00:00
Decreased the scope of read mutex
This commit is contained in:
parent
24994d7dde
commit
f323d50e34
@ -26,7 +26,7 @@ public:
|
||||
|
||||
static void GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TNetwork& Network);
|
||||
static void HandleEvent(TClient& c, const std::string& Data);
|
||||
|
||||
RWMutex& GetClientMutex() const { return mClientsMutex; }
|
||||
private:
|
||||
TClientSet mClients;
|
||||
mutable RWMutex mClientsMutex;
|
||||
|
@ -99,6 +99,7 @@ THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& S
|
||||
std::string THeartbeatThread::GetPlayers() {
|
||||
std::string Return;
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
Return += ClientPtr.lock()->GetName() + ";";
|
||||
}
|
||||
|
@ -233,6 +233,7 @@ int lua_Sleep(lua_State* L) {
|
||||
std::optional<std::weak_ptr<TClient>> GetClient(TServer& Server, int ID) {
|
||||
std::optional<std::weak_ptr<TClient>> MaybeClient { std::nullopt };
|
||||
Server.ForEachClient([&](std::weak_ptr<TClient> CPtr) -> bool {
|
||||
ReadLock Lock(Server.GetClientMutex());
|
||||
if (!CPtr.expired()) {
|
||||
auto C = CPtr.lock();
|
||||
if (C->GetID() == ID) {
|
||||
@ -294,9 +295,13 @@ int lua_GetGuest(lua_State* L) {
|
||||
int lua_GetAllPlayers(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
Engine().Server().ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
if (ClientPtr.expired())
|
||||
return true;
|
||||
auto Client = ClientPtr.lock();
|
||||
std::shared_ptr<TClient> Client;
|
||||
{
|
||||
ReadLock Lock(Engine().Server().GetClientMutex());
|
||||
if (ClientPtr.expired())
|
||||
return true;
|
||||
Client = ClientPtr.lock();
|
||||
}
|
||||
lua_pushinteger(L, Client->GetID());
|
||||
lua_pushstring(L, Client->GetName().c_str());
|
||||
lua_settable(L, -3);
|
||||
|
113
src/TNetwork.cpp
113
src/TNetwork.cpp
@ -83,15 +83,21 @@ void TNetwork::UDPServerMain() {
|
||||
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
|
||||
uint8_t ID = uint8_t(Data.at(0)) - 1;
|
||||
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
||||
if (!ClientPtr.expired()) {
|
||||
auto Client = ClientPtr.lock();
|
||||
if (Client->GetID() == ID) {
|
||||
Client->UpdatePingTime();
|
||||
Client->SetUDPAddr(client);
|
||||
Client->SetIsConnected(true);
|
||||
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this);
|
||||
}
|
||||
std::shared_ptr<TClient> Client;
|
||||
{
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
Client = ClientPtr.lock();
|
||||
}else return true;
|
||||
}
|
||||
|
||||
if (Client->GetID() == ID) {
|
||||
Client->UpdatePingTime();
|
||||
Client->SetUDPAddr(client);
|
||||
Client->SetIsConnected(true);
|
||||
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
@ -227,6 +233,7 @@ void TNetwork::HandleDownload(SOCKET TCPSock) {
|
||||
}
|
||||
auto ID = uint8_t(D);
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
auto c = ClientPtr.lock();
|
||||
if (c->GetID() == ID) {
|
||||
@ -300,17 +307,22 @@ void TNetwork::Authentication(SOCKET TCPSock) {
|
||||
debug("Name -> " + Client->GetName() + ", Guest -> " + std::to_string(Client->IsGuest()) + ", Roles -> " + Client->GetRoles());
|
||||
debug("There are " + std::to_string(mServer.ClientCount()) + " known clients");
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
if (!ClientPtr.expired()) {
|
||||
auto Cl = ClientPtr.lock();
|
||||
info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles());
|
||||
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
|
||||
info("New client matched with current iteration");
|
||||
info("Old client (" + Cl->GetName() + ") kicked: Reconnecting");
|
||||
CloseSocketProper(Cl->GetTCPSock());
|
||||
Cl->SetStatus(-2);
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<TClient> Cl;
|
||||
{
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
Cl = ClientPtr.lock();
|
||||
} else return true;
|
||||
}
|
||||
info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles());
|
||||
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
|
||||
info("New client matched with current iteration");
|
||||
info("Old client (" + Cl->GetName() + ") kicked: Reconnecting");
|
||||
CloseSocketProper(Cl->GetTCPSock());
|
||||
Cl->SetStatus(-2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -531,6 +543,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
||||
void TNetwork::UpdatePlayer(TClient& Client) {
|
||||
std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.MaxPlayers) + ":";
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
auto c = ClientPtr.lock();
|
||||
Packet += c->GetName() + ",";
|
||||
@ -576,6 +589,7 @@ int TNetwork::OpenID() {
|
||||
do {
|
||||
found = true;
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
auto c = ClientPtr.lock();
|
||||
if (c->GetID() == ID) {
|
||||
@ -794,25 +808,30 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
||||
bool Return = false;
|
||||
bool res = true;
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
if (!ClientPtr.expired()) {
|
||||
auto client = ClientPtr.lock();
|
||||
TClient::TSetOfVehicleData VehicleData;
|
||||
{ // Vehicle Data Lock Scope
|
||||
auto LockedData = client->GetAllCars();
|
||||
VehicleData = LockedData.VehicleData;
|
||||
} // End Vehicle Data Lock Scope
|
||||
if (client != LockedClient) {
|
||||
for (auto& v : VehicleData) {
|
||||
if (LockedClient->GetStatus() < 0) {
|
||||
Return = true;
|
||||
res = false;
|
||||
return false;
|
||||
}
|
||||
res = Respond(*LockedClient, v.Data(), true, true);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
std::shared_ptr<TClient> client;
|
||||
{
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
client = ClientPtr.lock();
|
||||
} else return true;
|
||||
}
|
||||
TClient::TSetOfVehicleData VehicleData;
|
||||
{ // Vehicle Data Lock Scope
|
||||
auto LockedData = client->GetAllCars();
|
||||
VehicleData = LockedData.VehicleData;
|
||||
} // End Vehicle Data Lock Scope
|
||||
if (client != LockedClient) {
|
||||
for (auto& v : VehicleData) {
|
||||
if (LockedClient->GetStatus() < 0) {
|
||||
Return = true;
|
||||
res = false;
|
||||
return false;
|
||||
}
|
||||
res = Respond(*LockedClient, v.Data(), true, true);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
LockedClient->SetIsSyncing(false);
|
||||
@ -830,19 +849,23 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
|
||||
char C = Data.at(0);
|
||||
bool ret = true;
|
||||
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
||||
if (!ClientPtr.expired()) {
|
||||
auto Client = ClientPtr.lock();
|
||||
if (Self || Client.get() != c) {
|
||||
if (Client->IsSynced() || Client->IsSyncing()) {
|
||||
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
|
||||
if (C == 'O' || C == 'T' || Data.length() > 1000) {
|
||||
ret = SendLarge(*Client, Data);
|
||||
} else {
|
||||
ret = TCPSend(*Client, Data);
|
||||
}
|
||||
std::shared_ptr<TClient> Client;
|
||||
{
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
Client = ClientPtr.lock();
|
||||
}else return true;
|
||||
}
|
||||
if (Self || Client.get() != c) {
|
||||
if (Client->IsSynced() || Client->IsSyncing()) {
|
||||
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
|
||||
if (C == 'O' || C == 'T' || Data.length() > 1000) {
|
||||
ret = SendLarge(*Client, Data);
|
||||
} else {
|
||||
ret = UDPSend(*Client, Data);
|
||||
ret = TCPSend(*Client, Data);
|
||||
}
|
||||
} else {
|
||||
ret = UDPSend(*Client, Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,21 +31,26 @@ void TPPSMonitor::operator()() {
|
||||
continue;
|
||||
}
|
||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||
if (!ClientPtr.expired()) {
|
||||
auto c = ClientPtr.lock();
|
||||
if (c->GetCarCount() > 0) {
|
||||
C++;
|
||||
V += c->GetCarCount();
|
||||
}
|
||||
if (!c->IsSynced() || c->IsSyncing()) {
|
||||
c->UpdatePingTime();
|
||||
}
|
||||
// kick on "no ping"
|
||||
if (c->SecondsSinceLastPing() > 60 && c->IsSynced() && !c->IsSyncing()) {
|
||||
debug("client " + std::string("(") + std::to_string(c->GetID()) + ")" + c->GetName() + " timing out: " + std::to_string(c->SecondsSinceLastPing()) + ", pps: " + Application::PPS());
|
||||
TimedOutClients.push_back(c);
|
||||
}
|
||||
std::shared_ptr<TClient> c;
|
||||
{
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
c = ClientPtr.lock();
|
||||
} else return true;
|
||||
}
|
||||
if (c->GetCarCount() > 0) {
|
||||
C++;
|
||||
V += c->GetCarCount();
|
||||
}
|
||||
if (!c->IsSynced() || c->IsSyncing()) {
|
||||
c->UpdatePingTime();
|
||||
}
|
||||
// kick on "no ping"
|
||||
if (c->SecondsSinceLastPing() > 60 && c->IsSynced() && !c->IsSyncing()) {
|
||||
debug("client " + std::string("(") + std::to_string(c->GetID()) + ")" + c->GetName() + " timing out: " + std::to_string(c->SecondsSinceLastPing()) + ", pps: " + Application::PPS());
|
||||
TimedOutClients.push_back(c);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
for (auto& ClientToKick : TimedOutClients) {
|
||||
|
@ -48,7 +48,6 @@ std::weak_ptr<TClient> TServer::InsertNewClient() {
|
||||
}
|
||||
|
||||
void TServer::ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn) {
|
||||
ReadLock Lock(mClientsMutex);
|
||||
for (auto& Client : mClients) {
|
||||
if (!Fn(Client)) {
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user