Add lots of memory safety to client interface

This commit is contained in:
Lion Kortlepel 2020-11-08 02:50:17 +01:00
parent 96668add6e
commit 26383d5346
8 changed files with 38 additions and 29 deletions

View File

@ -14,6 +14,7 @@
#include <vector> #include <vector>
#include <chrono> #include <chrono>
#include <set> #include <set>
#include <algorithm>
struct VData{ struct VData{
int ID = -1; int ID = -1;
@ -57,17 +58,23 @@ public:
int GetID(); int GetID();
}; };
struct ClientInterface{ struct ClientInterface{
std::set<Client*> Clients; std::set<std::unique_ptr<Client>> Clients;
void RemoveClient(Client *c){ void RemoveClient(Client*& c){
Assert(c); Assert(c);
c->ClearCars(); c->ClearCars();
Clients.erase(c); auto Iter = std::find_if(Clients.begin(), Clients.end(), [&](auto& ptr) {
delete c; return c == ptr.get();
});
Assert(Iter != Clients.end());
if (Iter == Clients.end()) {
return;
}
Clients.erase(Iter);
c = nullptr; c = nullptr;
} }
void AddClient(Client *c){ void AddClient(Client*&& c){
Assert(c); Assert(c);
Clients.insert(c); Clients.insert(std::move(std::unique_ptr<Client>(c)));
} }
int Size(){ int Size(){
return int(Clients.size()); return int(Clients.size());

View File

@ -14,7 +14,7 @@
void WebsocketInit(); void WebsocketInit();
std::string GetPlayers(){ std::string GetPlayers(){
std::string Return; std::string Return;
for(Client* c : CI->Clients){ for(auto& c : CI->Clients){
if(c != nullptr){ if(c != nullptr){
Return += c->GetName() + ";"; Return += c->GetName() + ";";
} }

View File

@ -240,9 +240,10 @@ int lua_Sleep(lua_State* L) {
return 1; return 1;
} }
Client* GetClient(int ID) { Client* GetClient(int ID) {
for (Client* c : CI->Clients) { for (auto& c : CI->Clients) {
if (c != nullptr && c->GetID() == ID) if (c != nullptr && c->GetID() == ID) {
return c; return c.get();
}
} }
return nullptr; return nullptr;
} }
@ -295,7 +296,7 @@ int lua_GetDID(lua_State* L) {
int lua_GetAllPlayers(lua_State* L) { int lua_GetAllPlayers(lua_State* L) {
lua_newtable(L); lua_newtable(L);
int i = 1; int i = 1;
for (Client* c : CI->Clients) { for (auto& c : CI->Clients) {
if (c == nullptr) if (c == nullptr)
continue; continue;
lua_pushinteger(L, c->GetID()); lua_pushinteger(L, c->GetID());

View File

@ -81,7 +81,7 @@ void Check(Hold* S){
} }
int Max(){ int Max(){
int M = MaxPlayers; int M = MaxPlayers;
for(Client*c : CI->Clients){ for(auto& c : CI->Clients){
if(c != nullptr){ if(c != nullptr){
if(c->GetRole() == Sec("MDEV"))M++; if(c->GetRole() == Sec("MDEV"))M++;
} }
@ -94,8 +94,9 @@ void CreateClient(SOCKET TCPSock,const std::string &Name, const std::string &DID
c->SetName(Name); c->SetName(Name);
c->SetRole(Role); c->SetRole(Role);
c->SetDID(DID); c->SetDID(DID);
CI->AddClient(c); Client& Client = *c;
InitClient(c); CI->AddClient(std::move(c));
InitClient(&Client);
} }
std::pair<int,int> Parse(const std::string& msg){ std::pair<int,int> Parse(const std::string& msg){
std::stringstream ss(msg); std::stringstream ss(msg);
@ -175,7 +176,7 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
} }
DebugPrintTIDInternal(std::string("Client(") + Name + ")"); DebugPrintTIDInternal(std::string("Client(") + Name + ")");
debug(Sec("Name -> ") + Name + Sec(", Role -> ") + Role + Sec(", ID -> ") + DID); debug(Sec("Name -> ") + Name + Sec(", Role -> ") + Role + Sec(", ID -> ") + DID);
for(Client*c: CI->Clients){ for(auto& c : CI->Clients){
if(c != nullptr){ if(c != nullptr){
if(c->GetDID() == DID){ if(c->GetDID() == DID){
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__)); error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));

View File

@ -125,9 +125,9 @@ void SyncClient(Client*c){
Respond(c,Sec("Sn")+c->GetName(),true); Respond(c,Sec("Sn")+c->GetName(),true);
SendToAll(c,Sec("JWelcome ")+c->GetName()+"!",false,true); SendToAll(c,Sec("JWelcome ")+c->GetName()+"!",false,true);
TriggerLuaEvent(Sec("onPlayerJoin"),false,nullptr,std::unique_ptr<LuaArg>(new LuaArg{{c->GetID()}}),false); TriggerLuaEvent(Sec("onPlayerJoin"),false,nullptr,std::unique_ptr<LuaArg>(new LuaArg{{c->GetID()}}),false);
for (Client*client : CI->Clients) { for (auto& client : CI->Clients) {
if(client != nullptr){ if(client != nullptr){
if (client != c) { if (client.get() != c) {
for (VData *v : client->GetAllCars()) { for (VData *v : client->GetAllCars()) {
if(v != nullptr){ if(v != nullptr){
Respond(c, v->Data, true); Respond(c, v->Data, true);

View File

@ -12,7 +12,7 @@ int OpenID(){
bool found; bool found;
do { do {
found = true; found = true;
for (Client *c : CI->Clients){ for (auto& c : CI->Clients){
if(c != nullptr){ if(c != nullptr){
if(c->GetID() == ID){ if(c->GetID() == ID){
found = false; found = false;
@ -35,15 +35,15 @@ void Respond(Client*c, const std::string& MSG, bool Rel){
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){ void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
if (!Self)Assert(c); if (!Self)Assert(c);
char C = Data.at(0); char C = Data.at(0);
for(Client*client : CI->Clients){ for(auto& client : CI->Clients){
if(client != nullptr) { if(client != nullptr) {
if (Self || client != c) { if (Self || client.get() != c) {
if (client->isSynced) { if (client->isSynced) {
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
if (C == 'O' || C == 'T' || if (C == 'O' || C == 'T' ||
Data.length() > 1000)SendLarge(client, Data); Data.length() > 1000)SendLarge(client.get(), Data);
else TCPSend(client, Data); else TCPSend(client.get(), Data);
} else UDPSend(client, Data); } else UDPSend(client.get(), Data);
} }
} }
} }
@ -51,7 +51,7 @@ void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
} }
void UpdatePlayers(){ void UpdatePlayers(){
std::string Packet = Sec("Ss") + std::to_string(CI->Size())+"/"+std::to_string(MaxPlayers) + ":"; std::string Packet = Sec("Ss") + std::to_string(CI->Size())+"/"+std::to_string(MaxPlayers) + ":";
for (Client*c : CI->Clients) { for (auto& c : CI->Clients) {
if(c != nullptr)Packet += c->GetName() + ","; if(c != nullptr)Packet += c->GetName() + ",";
} }
Packet = Packet.substr(0,Packet.length()-1); Packet = Packet.substr(0,Packet.length()-1);

View File

@ -14,7 +14,7 @@ void Monitor() {
StatReport = "-"; StatReport = "-";
return; return;
} }
for (Client *c : CI->Clients) { for (auto& c : CI->Clients) {
if (c != nullptr && c->GetCarCount() > 0) { if (c != nullptr && c->GetCarCount() > 0) {
C++; C++;
V += c->GetCarCount(); V += c->GetCarCount();

View File

@ -311,11 +311,11 @@ void LOOP() {
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
uint8_t ID = Data.at(0) - 1; uint8_t ID = Data.at(0) - 1;
for (Client* c : CI->Clients) { for (auto& c : CI->Clients) {
if (c != nullptr && c->GetID() == ID) { if (c != nullptr && c->GetID() == ID) {
c->SetUDPAddr(client); c->SetUDPAddr(client);
c->isConnected = true; c->isConnected = true;
UDPParser(c, Data.substr(2)); UDPParser(c.get(), Data.substr(2));
} }
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -357,11 +357,11 @@ void LOOP() {
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
uint8_t ID = uint8_t(Data.at(0)) - 1; uint8_t ID = uint8_t(Data.at(0)) - 1;
for (Client* c : CI->Clients) { for (auto& c : CI->Clients) {
if (c != nullptr && c->GetID() == ID) { if (c != nullptr && c->GetID() == ID) {
c->SetUDPAddr(client); c->SetUDPAddr(client);
c->isConnected = true; c->isConnected = true;
UDPParser(c, Data.substr(2)); UDPParser(c.get(), Data.substr(2));
} }
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {