From 58cadb529b59a92fd7e032ea1fab14582a631a6e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 19 Sep 2022 01:28:43 +0200 Subject: [PATCH] 'Bad behaving player' systems improvement * Use 'CClient::Disconnect(..)' for all kicks and bans (this automatically clears the entire CClient slot, and removes the net channel). * Only force disconnect when 'CNetChan::m_nSignonState' has a value that is not NULL. * Clear the ServerPlayer slot on 'CClient::Disconnect(..)' and 'CClient::Connect(..)'. * Only kick player for NetChannel overflow when value exceeds processing budget (not equals). --- r5dev/engine/client/client.cpp | 38 +++++++++++++++++++------------ r5dev/engine/client/client.h | 18 +++++++++++---- r5dev/engine/net_chan.cpp | 7 +++--- r5dev/networksystem/bansystem.cpp | 16 ++++++------- r5dev/server/vengineserver_impl.h | 5 ++++ 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index 775e26e6..2ceca251 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -9,6 +9,7 @@ // /////////////////////////////////////////////////////////////////////////////////// #include "core/stdafx.h" +#include "engine/server/server.h" #include "engine/client/client.h" //--------------------------------------------------------------------------------- @@ -207,16 +208,18 @@ bool CClient::IsHumanPlayer(void) const //--------------------------------------------------------------------------------- void CClient::Clear(void) { + g_ServerPlayer[GetUserID()].Reset(); // Reset ServerPlayer slot. v_CClient_Clear(this); } //--------------------------------------------------------------------------------- // Purpose: throw away any residual garbage in the channel -// Input : *pBaseClient - +// Input : *pClient - //--------------------------------------------------------------------------------- -void CClient::VClear(CClient* pBaseClient) +void CClient::VClear(CClient* pClient) { - v_CClient_Clear(pBaseClient); + g_ServerPlayer[pClient->GetUserID()].Reset(); // Reset ServerPlayer slot. + v_CClient_Clear(pClient); } //--------------------------------------------------------------------------------- @@ -247,28 +250,33 @@ bool CClient::Connect(const char* szName, void* pNetChannel, bool bFakePlayer, v //--------------------------------------------------------------------------------- bool CClient::VConnect(CClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize) { - return v_CClient_Connect(pClient, szName, pNetChannel, bFakePlayer, a5, szMessage, nMessageSize); + bool bResult = v_CClient_Connect(pClient, szName, pNetChannel, bFakePlayer, a5, szMessage, nMessageSize); + g_ServerPlayer[pClient->GetUserID()].Reset(); // Reset ServerPlayer slot. + return bResult; } //--------------------------------------------------------------------------------- // Purpose: disconnect client -// Input : nBadRep - +// Input : nRepLvl - // *szReason - // ... - //--------------------------------------------------------------------------------- -void CClient::Disconnect(int nBadRep/*!!ENUM!!*/, const char* szReason, ...) +void CClient::Disconnect(const Reputation_t nRepLvl, const char* szReason, ...) { - char szBuf[1024]; - {///////////////////////////// - va_list vArgs{}; - va_start(vArgs, szReason); + if (m_nSignonState != SIGNONSTATE::SIGNONSTATE_NONE) + { + char szBuf[1024]; + {///////////////////////////// + va_list vArgs{}; + va_start(vArgs, szReason); - vsnprintf(szBuf, sizeof(szBuf), szReason, vArgs); + vsnprintf(szBuf, sizeof(szBuf), szReason, vArgs); - szBuf[sizeof(szBuf) - 1] = '\0'; - va_end(vArgs); - }///////////////////////////// - v_CClient_Disconnect(this, nBadRep, szBuf); + szBuf[sizeof(szBuf) - 1] = '\0'; + va_end(vArgs); + }///////////////////////////// + v_CClient_Disconnect(this, nRepLvl, szBuf); + } } /////////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index 9f29a9c5..5de6b826 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -3,6 +3,16 @@ #include "common/protocol.h" #include "engine/net_chan.h" +//----------------------------------------------------------------------------- +// Enumerations +//----------------------------------------------------------------------------- +enum Reputation_t +{ + REP_NONE = 0, + REP_REMOVE_ONLY, + REP_MARK +}; + //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- @@ -38,10 +48,10 @@ public: bool IsFakeClient(void) const; bool IsHumanPlayer(void) const; bool Connect(const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize); - void Disconnect(int nBadRep /*!!ENUM!!*/, const char* szReason, ...); + void Disconnect(const Reputation_t nRepLvl, const char* szReason, ...); static bool VConnect(CClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize); void Clear(void); - static void VClear(CClient* pBaseClient); + static void VClear(CClient* pClient); private: uint32_t m_nUserID; //0x0010 @@ -91,7 +101,7 @@ inline CMemory p_CClient_Connect; inline auto v_CClient_Connect = p_CClient_Connect.RCast(); inline CMemory p_CClient_Disconnect; -inline auto v_CClient_Disconnect = p_CClient_Disconnect.RCast(); +inline auto v_CClient_Disconnect = p_CClient_Disconnect.RCast(); inline CMemory p_CClient_Clear; inline auto v_CClient_Clear = p_CClient_Clear.RCast(); @@ -122,7 +132,7 @@ class VClient : public IDetour p_CClient_Clear = g_GameDll.FindPatternSIMD(reinterpret_cast("\x40\x53\x41\x56\x41\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x89\x74"), "xxxxxxxxxxxxxxxx"); v_CClient_Connect = p_CClient_Connect.RCast(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 20 41 0F B6 E9*/ - v_CClient_Disconnect = p_CClient_Disconnect.RCast(); /*48 8B C4 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 49 8B F8 8B F2*/ + v_CClient_Disconnect = p_CClient_Disconnect.RCast(); /*48 8B C4 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 49 8B F8 8B F2*/ v_CClient_Clear = p_CClient_Clear.RCast(); /*40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74*/ } virtual void GetVar(void) const diff --git a/r5dev/engine/net_chan.cpp b/r5dev/engine/net_chan.cpp index d308d7c3..12639b95 100644 --- a/r5dev/engine/net_chan.cpp +++ b/r5dev/engine/net_chan.cpp @@ -223,8 +223,7 @@ bool CNetChan::ProcessMessages(CNetChan* pChan, bf_read* pMsg) const bool bResult = v_NetChan_ProcessMessages(pChan, pMsg); CClient* pClient = reinterpret_cast(pChan->m_MessageHandler); - uint16_t nSlot = pClient->GetUserID(); - ServerPlayer_t* pSlot = &g_ServerPlayer[nSlot]; + ServerPlayer_t* pSlot = &g_ServerPlayer[pClient->GetUserID()]; if (flStartTime - pSlot->m_flLastNetProcessTime >= 1.0 || pSlot->m_flLastNetProcessTime == -1.0) @@ -235,10 +234,10 @@ bool CNetChan::ProcessMessages(CNetChan* pChan, bf_read* pMsg) pSlot->m_flCurrentNetProcessTime += (Plat_FloatTime() * 1000) - (flStartTime * 1000); - if (pSlot->m_flCurrentNetProcessTime >= + if (pSlot->m_flCurrentNetProcessTime > net_processLimit->GetDouble()) { - pClient->Disconnect(2, "#DISCONNECT_NETCHAN_OVERFLOW"); + pClient->Disconnect(REP_MARK, "#DISCONNECT_NETCHAN_OVERFLOW"); return false; } diff --git a/r5dev/networksystem/bansystem.cpp b/r5dev/networksystem/bansystem.cpp index 7b8ce776..d53ab5da 100644 --- a/r5dev/networksystem/bansystem.cpp +++ b/r5dev/networksystem/bansystem.cpp @@ -223,11 +223,11 @@ void CBanSystem::BanListCheck(void) string svIpAddress = pNetChan->GetAddress(); - Warning(eDLL_T::SERVER, "Removing client '%s' from slot '%hu' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), pClient->GetHandle(), pClient->GetNucleusID()); + Warning(eDLL_T::SERVER, "Removing client '%s' from slot '%i' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), c, pClient->GetNucleusID()); if (AddEntry(svIpAddress, pClient->GetNucleusID()) && !bSave) bSave = true; - NET_RemoveChannel(pClient, c, m_vRefuseList[i].first.c_str(), 0, true); + pClient->Disconnect(Reputation_t::REP_MARK, m_vRefuseList[i].first.c_str()); } } @@ -299,7 +299,7 @@ void CBanSystem::KickPlayerByName(const string& svPlayerName) if (strlen(pNetChan->GetName()) > 0) { if (svPlayerName.compare(pNetChan->GetName()) == NULL) // Our wanted name? - NET_RemoveChannel(pClient, i, "Kicked from server", 0, true); + pClient->Disconnect(REP_MARK, "Kicked from server"); } } } @@ -344,14 +344,14 @@ void CBanSystem::KickPlayerById(const string& svHandle) continue; } - NET_RemoveChannel(pClient, i, "Kicked from server", 0, true); + pClient->Disconnect(REP_MARK, "Kicked from server"); } else { if (svHandle.compare(pNetChan->GetAddress()) != NULL) continue; - NET_RemoveChannel(pClient, i, "Kicked from server", 0, true); + pClient->Disconnect(REP_MARK, "Kicked from server"); } } } @@ -386,7 +386,7 @@ void CBanSystem::BanPlayerByName(const string& svPlayerName) if (AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) bSave = true; - NET_RemoveChannel(pClient, i, "Banned from server", 0, true); + pClient->Disconnect(REP_MARK, "Banned from server"); } } } @@ -441,7 +441,7 @@ void CBanSystem::BanPlayerById(const string& svHandle) bSave = true; Save(); - NET_RemoveChannel(pClient, i, "Banned from server", 0, true); + pClient->Disconnect(REP_MARK, "Banned from server"); } else { @@ -452,7 +452,7 @@ void CBanSystem::BanPlayerById(const string& svHandle) bSave = true; Save(); - NET_RemoveChannel(pClient, i, "Banned from server", 0, true); + pClient->Disconnect(REP_MARK, "Banned from server"); } } diff --git a/r5dev/server/vengineserver_impl.h b/r5dev/server/vengineserver_impl.h index ab6010c1..91291454 100644 --- a/r5dev/server/vengineserver_impl.h +++ b/r5dev/server/vengineserver_impl.h @@ -28,6 +28,11 @@ void IVEngineServer_Detach(); struct ServerPlayer_t { + ServerPlayer_t(void) + : m_flCurrentNetProcessTime(0.0) + , m_flLastNetProcessTime(0.0) + , m_bPersistenceEnabled(false) + {} inline void Reset(void) { m_flCurrentNetProcessTime = 0.0;