diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 42114793..013b0075 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -526,15 +526,23 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData* pData) } //----------------------------------------------------------------------------- -// Purpose: close specific connection +// Purpose: close connection on current index //----------------------------------------------------------------------------- void CRConServer::Disconnect(const char* szReason) // NETMGR { - CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex); + Disconnect(m_nConnIndex, szReason); +} + +//----------------------------------------------------------------------------- +// Purpose: close specific connection by index +//----------------------------------------------------------------------------- +void CRConServer::Disconnect(const int nIndex, const char* szReason) // NETMGR +{ + CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(nIndex); if (pData->m_bAuthorized || sv_rcon_debug->GetBool()) { // Inform server owner when authenticated connection has been closed. - netadr_t netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex); + netadr_t netAdr = m_Socket.GetAcceptedSocketAddress(nIndex); if (!szReason) { szReason = "unknown reason"; @@ -544,7 +552,7 @@ void CRConServer::Disconnect(const char* szReason) // NETMGR m_nAuthConnections--; } - m_Socket.CloseAcceptedSocket(m_nConnIndex); + m_Socket.CloseAcceptedSocket(nIndex); } //----------------------------------------------------------------------------- @@ -597,6 +605,14 @@ bool CRConServer::IsInitialized(void) const return m_bInitialized; } +//----------------------------------------------------------------------------- +// Purpose: returns the number of authenticated connections +//----------------------------------------------------------------------------- +int CRConServer::GetAuthenticatedCount(void) const +{ + return m_nAuthConnections; +} + /////////////////////////////////////////////////////////////////////////////// CRConServer g_RCONServer; CRConServer* RCONServer() // Singleton RCON Server. diff --git a/r5dev/engine/server/sv_rcon.h b/r5dev/engine/server/sv_rcon.h index bc256891..35222c3e 100644 --- a/r5dev/engine/server/sv_rcon.h +++ b/r5dev/engine/server/sv_rcon.h @@ -34,7 +34,6 @@ public: const int nMessageType = static_cast(LogType_t::LOG_NET)) const; bool SendToAll(const char* pMsgBuf, const int nMsgLen) const; - bool Serialize(vector& vecBuf, const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType, const int nMessageId = static_cast(eDLL_T::NETCON), const int nMessageType = static_cast(LogType_t::LOG_NET)) const; @@ -47,11 +46,14 @@ public: bool CheckForBan(CConnectedNetConsoleData* pData); virtual void Disconnect(const char* szReason = nullptr) override; + void Disconnect(const int nIndex, const char* szReason = nullptr); void CloseNonAuthConnection(void); bool ShouldSend(const sv_rcon::response_t responseType) const; bool IsInitialized(void) const; + int GetAuthenticatedCount(void) const; + private: int m_nConnIndex; int m_nAuthConnections; diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp index 64fd032a..0f33b96d 100644 --- a/r5dev/tier1/cvar.cpp +++ b/r5dev/tier1/cvar.cpp @@ -350,7 +350,7 @@ void ConVar::StaticInit(void) sv_rcon_maxfailures = ConVar::StaticCreate("sv_rcon_maxfailures", "10", FCVAR_RELEASE, "Max number of times a user can fail rcon authentication before being banned.", true, 1.f, false, 0.f, nullptr, nullptr); sv_rcon_maxignores = ConVar::StaticCreate("sv_rcon_maxignores" , "15", FCVAR_RELEASE, "Max number of times a user can ignore the instruction message before being banned.", true, 1.f, false, 0.f, nullptr, nullptr); sv_rcon_maxsockets = ConVar::StaticCreate("sv_rcon_maxsockets" , "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets.", true, 1.f, false, 0.f, nullptr, nullptr); - sv_rcon_maxconnections = ConVar::StaticCreate("sv_rcon_maxconnections" , "1" , FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket.", true, 1.f, false, 0.f, nullptr, nullptr); + sv_rcon_maxconnections = ConVar::StaticCreate("sv_rcon_maxconnections" , "1" , FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket.", true, 1.f, false, 0.f, &RCON_ConnectionCountChanged_f, nullptr); sv_rcon_maxpacketsize = ConVar::StaticCreate("sv_rcon_maxpacketsize" , "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command packet from a non-authenticated net console.", true, 0.f, false, 0.f, nullptr, nullptr); sv_rcon_whitelist_address = ConVar::StaticCreate("sv_rcon_whitelist_address", "" , FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts.", false, 0.f, false, 0.f, &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); diff --git a/r5dev/vstdlib/callback.cpp b/r5dev/vstdlib/callback.cpp index 10451c54..42a28bcc 100644 --- a/r5dev/vstdlib/callback.cpp +++ b/r5dev/vstdlib/callback.cpp @@ -979,7 +979,51 @@ void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString, flo if (!RCONServer()->SetWhiteListAddress(pConVarRef->GetString())) { - Warning(eDLL_T::COMMON, "Failed to set RCON whitelist address: %s\n", pConVarRef->GetString()); + Warning(eDLL_T::SERVER, "Failed to set RCON whitelist address: %s\n", pConVarRef->GetString()); + } + } +} + +/* +===================== +RCON_ConnectionCountChanged_f + + Change max connection + count on RCON server +===================== +*/ +void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue) +{ + if (!RCONServer()->IsInitialized()) + return; // Not initialized; no sockets at this point. + + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetCommandName())) + { + if (strcmp(pOldString, pConVarRef->GetString()) == NULL) + return; // Same count. + + const int maxCount = pConVarRef->GetInt(); + + int count = RCONServer()->GetAuthenticatedCount(); + CSocketCreator* pCreator = RCONServer()->GetSocketCreator(); + + if (count < maxCount) + { + if (!pCreator->IsListening()) + { + pCreator->CreateListenSocket(*RCONServer()->GetNetAddress()); + } + } + else + { + while (count > maxCount) + { + RCONServer()->Disconnect(count-1, "too many authenticated sockets"); + count = RCONServer()->GetAuthenticatedCount(); + } + + pCreator->CloseListenSocket(); + RCONServer()->CloseNonAuthConnection(); } } } diff --git a/r5dev/vstdlib/callback.h b/r5dev/vstdlib/callback.h index 85b822ea..9b8784ef 100644 --- a/r5dev/vstdlib/callback.h +++ b/r5dev/vstdlib/callback.h @@ -53,6 +53,7 @@ void RCON_Disconnect_f(const CCommand& args); void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); #ifndef CLIENT_DLL void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); +void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void SQVM_ServerScript_f(const CCommand& args); #endif // !CLIENT_DLL #ifndef DEDICATED