From 19d264ec11a4d29a0beda58c14b90eea6be4073e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 25 Jul 2022 19:35:08 +0200 Subject: [PATCH] Implement RCON_PasswordChanged_f and ConVar improvements * Changing RCON passwords on the server now closes all connections and re-initializes the system. * Fully mapped out VFTable interface for IConVar* (used for ConVar callbacks, see callback.cpp). --- r5dev/engine/client/cl_rcon.cpp | 29 ++++-- r5dev/engine/client/cl_rcon.h | 4 +- r5dev/engine/debugoverlay.cpp | 3 - r5dev/engine/host_state.cpp | 9 +- r5dev/engine/server/sv_rcon.cpp | 39 +++++++-- r5dev/engine/server/sv_rcon.h | 4 +- r5dev/public/include/iconvar.h | 121 ++++++++++++++++++++++++++ r5dev/squirrel/sqvm.cpp | 8 +- r5dev/tier0/dbg.cpp | 12 +-- r5dev/tier1/IConVar.cpp | 9 +- r5dev/tier1/IConVar.h | 98 +++------------------ r5dev/vproj/clientsdk.vcxproj | 1 + r5dev/vproj/clientsdk.vcxproj.filters | 3 + r5dev/vproj/dedicated.vcxproj | 1 + r5dev/vproj/dedicated.vcxproj.filters | 3 + r5dev/vproj/gamesdk.vcxproj | 1 + r5dev/vproj/gamesdk.vcxproj.filters | 3 + r5dev/vstdlib/callback.cpp | 51 ++++++++--- r5dev/vstdlib/callback.h | 3 + 19 files changed, 264 insertions(+), 138 deletions(-) create mode 100644 r5dev/public/include/iconvar.h diff --git a/r5dev/engine/client/cl_rcon.cpp b/r5dev/engine/client/cl_rcon.cpp index f8513cba..b3e62305 100644 --- a/r5dev/engine/client/cl_rcon.cpp +++ b/r5dev/engine/client/cl_rcon.cpp @@ -19,12 +19,9 @@ //----------------------------------------------------------------------------- void CRConClient::Init(void) { - if (std::strlen(rcon_password->GetString()) < 8) + if (!m_bInitialized) { - if (std::strlen(rcon_password->GetString()) > 0) - { - DevMsg(eDLL_T::CLIENT, "Remote server access requires a password of at least 8 characters\n"); - } + this->SetPassword(rcon_password->GetString()); } m_bInitialized = true; } @@ -40,6 +37,24 @@ void CRConClient::Shutdown(void) } } +//----------------------------------------------------------------------------- +// Purpose: changes the password +// Input : *pszPassword - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool CRConClient::SetPassword(const char* pszPassword) +{ + if (std::strlen(pszPassword) < 8) + { + if (std::strlen(pszPassword) > 0) + { + DevMsg(eDLL_T::CLIENT, "Remote server access requires a password of at least 8 characters\n"); + } + return false; + } + return true; +} + //----------------------------------------------------------------------------- // Purpose: client rcon main processing loop //----------------------------------------------------------------------------- @@ -339,3 +354,7 @@ bool CRConClient::IsConnected(void) const } /////////////////////////////////////////////////////////////////////////////// CRConClient* g_pRConClient = new CRConClient(); +CRConClient* RCONClient() +{ + return g_pRConClient; +} \ No newline at end of file diff --git a/r5dev/engine/client/cl_rcon.h b/r5dev/engine/client/cl_rcon.h index 74696dba..9430a3d3 100644 --- a/r5dev/engine/client/cl_rcon.h +++ b/r5dev/engine/client/cl_rcon.h @@ -13,6 +13,7 @@ public: void Init(void); void Shutdown(void); + bool SetPassword(const char* pszPassword); void RunFrame(void); bool Connect(void); @@ -38,4 +39,5 @@ private: bool m_bInitialized = false; bool m_bConnEstablished = false; }; -extern CRConClient* g_pRConClient; \ No newline at end of file +extern CRConClient* g_pRConClient; +CRConClient* RCONClient(); \ No newline at end of file diff --git a/r5dev/engine/debugoverlay.cpp b/r5dev/engine/debugoverlay.cpp index 419171f5..dda1e94a 100644 --- a/r5dev/engine/debugoverlay.cpp +++ b/r5dev/engine/debugoverlay.cpp @@ -238,9 +238,6 @@ void DrawOverlay(OverlayBase_t* pOverlay) LeaveCriticalSection(&*s_OverlayMutex); } -#ifndef CLIENT_DLL -#endif // !CLIENT_DLL - //------------------------------------------------------------------------------ // Purpose : overlay drawing entrypoint // Input : bDraw - diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 19a31073..88b55579 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -59,9 +59,9 @@ FORCEINLINE void CHostState::FrameUpdate(CHostState* pHostState, double flCurren bInitialized = true; } #ifdef DEDICATED - g_pRConServer->RunFrame(); + RCONServer()->RunFrame(); #else // - g_pRConClient->RunFrame(); + RCONClient()->RunFrame(); #endif // DEDICATED HostStates_t oldState{}; @@ -179,11 +179,6 @@ FORCEINLINE void CHostState::Setup(void) { g_pHostState->LoadConfig(); g_pConVar->PurgeHostNames(); -#ifdef DEDICATED - g_pRConServer->Init(); -#else // - g_pRConClient->Init(); -#endif // DEDICATED std::thread think(&CHostState::Think, this); think.detach(); diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index d6bee682..2f528a7a 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -21,19 +21,16 @@ //----------------------------------------------------------------------------- void CRConServer::Init(void) { - if (std::strlen(rcon_password->GetString()) < 8) + if (!m_bInitialized) { - if (std::strlen(rcon_password->GetString()) > 0) + if (!this->SetPassword(rcon_password->GetString())) { - Warning(eDLL_T::SERVER, "Remote server access requires a password of at least 8 characters\n"); + return; } - this->Shutdown(); - return; } m_pAdr2->SetIPAndPort(rcon_address->GetString(), hostport->GetString()); m_pSocket->CreateListenSocket(*m_pAdr2, false); - m_svPasswordHash = sha256(rcon_password->GetString()); DevMsg(eDLL_T::SERVER, "Remote server access initialized\n"); m_bInitialized = true; @@ -85,6 +82,32 @@ void CRConServer::Think(void) } } +//----------------------------------------------------------------------------- +// Purpose: changes the password +// Input : *pszPassword - +// Output : true on success, false otherwise +//----------------------------------------------------------------------------- +bool CRConServer::SetPassword(const char* pszPassword) +{ + m_bInitialized = false; + m_pSocket->CloseAllAcceptedSockets(); + + if (std::strlen(pszPassword) < 8) + { + if (std::strlen(pszPassword) > 0) + { + Warning(eDLL_T::SERVER, "Remote server access requires a password of at least 8 characters\n"); + } + this->Shutdown(); + return false; + } + m_svPasswordHash = sha256(pszPassword); + DevMsg(eDLL_T::SERVER, "Password hash ('%s')\n", m_svPasswordHash.c_str()); + + m_bInitialized = true; + return true; +} + //----------------------------------------------------------------------------- // Purpose: server RCON main loop (run this every frame) //----------------------------------------------------------------------------- @@ -465,3 +488,7 @@ void CRConServer::CloseNonAuthConnection(void) } /////////////////////////////////////////////////////////////////////////////// CRConServer* g_pRConServer = new CRConServer(); +CRConServer* RCONServer() +{ + return g_pRConServer; +} diff --git a/r5dev/engine/server/sv_rcon.h b/r5dev/engine/server/sv_rcon.h index c9edc712..550f6eb0 100644 --- a/r5dev/engine/server/sv_rcon.h +++ b/r5dev/engine/server/sv_rcon.h @@ -16,6 +16,7 @@ public: void Init(void); void Shutdown(void); + bool SetPassword(const char* pszPassword); void Think(void); void RunFrame(void); @@ -47,4 +48,5 @@ private: std::vector m_vBannedAddress; std::string m_svPasswordHash; }; -extern CRConServer* g_pRConServer; \ No newline at end of file +extern CRConServer* g_pRConServer; +CRConServer* RCONServer(); \ No newline at end of file diff --git a/r5dev/public/include/iconvar.h b/r5dev/public/include/iconvar.h new file mode 100644 index 00000000..a214c440 --- /dev/null +++ b/r5dev/public/include/iconvar.h @@ -0,0 +1,121 @@ +#ifndef ICONVAR_H +#define ICONVAR_H + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class IConVar; +class CCommand; + +//----------------------------------------------------------------------------- +// Command to ConVars and ConCommands +//----------------------------------------------------------------------------- +// ConVar systems +#define FCVAR_NONE 0 // The default, no flags at all +#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc. +#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined. +#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL +#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL +#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out. + +// ConVar only +#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value +#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. +#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc +#define FCVAR_NOTIFY (1<<8) // notifies players when changed +#define FCVAR_USERINFO (1<<9) // changes the client's info string + +#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). + +#define FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS (1<<10) // When on concommands this allows remote clients to execute this cmd on the server. + // We are changing the default behavior of concommands to disallow execution by remote clients without + // this flag due to the number existing concommands that can lag or crash the server when clients abuse them. + +#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log +#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar + +// It's a ConVar that's shared between the client and the server. +// At signon, the values of all such ConVars are sent from the server to the client (skipped for local client, of course ) +// If a change is requested it must come from the console (i.e., no remote client changes) +// If a value is changed while a server is active, it's replicated to all connected clients +#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time +#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats +#define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated +#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file +#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles +#define FCVAR_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players +#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers +#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload +#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload + +#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server +#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread +#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // cvar written to config.cfg on the Xbox + +#define FCVAR_SERVER_CAN_EXECUTE (1<<28) // the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd. +#define FCVAR_SERVER_CANNOT_QUERY (1<<29) // If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue). +#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command. + +/* +class ConVar : ConCommandBase, IConVar; [MI] (#classinformer) +dq offset ? ? _R4ConVar@@6B@; const ConVar::`RTTI Complete Object Locator' + +dq offset ??_G__ExceptionPtr@@QEAAPEAXI@Z_0; 0 Index +dq offset sub_1401F9930 +dq offset loc_14046FE90 +dq offset ConVar__AddFlags +dq offset ConVar__RemoveFlags +dq offset sub_14046FEA0 +dq offset loc_14046FF70 +dq offset ConVar__GetHelpString +dq offset sub_14046FEC0 +dq offset sub_14046FEE0 +dq offset ConVar__IsRegistered +dq offset ConVar__GetDllIdentifier +dq offset sub_14046F3F0 +dq offset sub_14046F470 +dq offset ConVar__InternalSetFloatValue; The one below also does something similar +dq offset sub_140470340 +dq offset sub_140470420; Seems to be InternalSetInt below maybe ? +dq offset sub_140470510 +dq offset nullsub +dq offset sub_140470300 +dq offset sub_1404701A0 +dq offset RegisterConVar; #STR: "Convar '%s' is flagged as both FCVAR_ARCHIVE and FCVAR_ARC +*/ + +//----------------------------------------------------------------------------- +// Called when a ConVar changes value +// NOTE: For FCVAR_NEVER_AS_STRING ConVars, pOldValue == NULL +//----------------------------------------------------------------------------- +typedef void (*FnChangeCallback_t)(IConVar* var, const char* pOldValue, float flOldValue); + + +//----------------------------------------------------------------------------- +// Abstract interface for ConVars +//----------------------------------------------------------------------------- +abstract_class IConVar +{ +public: + virtual ~IConVar() = 0; + + // Value set + virtual void SetValue(const char* pValue) = 0; + virtual void SetValue(float flValue) = 0; + virtual void SetValue(int nValue) = 0; + + // Return name of command + virtual const char* GetName(void) const = 0; + + // Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars + virtual const char* GetBaseName(void) const = 0; + + // Accessors.. not as efficient as using GetState()/GetInfo() + // if you call these methods multiple times on the same IConVar + virtual bool IsFlagSet(int nFlag) const = 0; + + virtual int GetSplitScreenPlayerSlot() const = 0; +}; + + +#endif // ICONVAR_H diff --git a/r5dev/squirrel/sqvm.cpp b/r5dev/squirrel/sqvm.cpp index 0c1e48f8..7fcd483f 100644 --- a/r5dev/squirrel/sqvm.cpp +++ b/r5dev/squirrel/sqvm.cpp @@ -89,7 +89,7 @@ SQRESULT SQVM_PrintFunc(HSQUIRRELVM v, SQChar* fmt, ...) { wconsole->debug(vmStr); #ifdef DEDICATED - g_pRConServer->Send(vmStr); + RCONServer()->Send(vmStr); #endif // DEDICATED } else @@ -135,7 +135,7 @@ SQRESULT SQVM_PrintFunc(HSQUIRRELVM v, SQChar* fmt, ...) vmStrAnsi.append(buf); wconsole->debug(vmStrAnsi); #ifdef DEDICATED - g_pRConServer->Send(vmStrAnsi); + RCONServer()->Send(vmStrAnsi); #endif // DEDICATED } @@ -229,7 +229,7 @@ SQRESULT SQVM_WarningFunc(HSQUIRRELVM v, SQInteger a2, SQInteger a3, SQInteger* { wconsole->debug(vmStr); #ifdef DEDICATED - g_pRConServer->Send(vmStr); + RCONServer()->Send(vmStr); #endif // DEDICATED } else @@ -239,7 +239,7 @@ SQRESULT SQVM_WarningFunc(HSQUIRRELVM v, SQInteger a2, SQInteger a3, SQInteger* vmStrAnsi.append(svConstructor); wconsole->debug(vmStrAnsi); #ifdef DEDICATED - g_pRConServer->Send(vmStrAnsi); + RCONServer()->Send(vmStrAnsi); #endif // DEDICATED } diff --git a/r5dev/tier0/dbg.cpp b/r5dev/tier0/dbg.cpp index a986d734..293f0a79 100644 --- a/r5dev/tier0/dbg.cpp +++ b/r5dev/tier0/dbg.cpp @@ -132,7 +132,7 @@ void DevMsg(eDLL_T context, const char* fmt, ...) { wconsole->debug(svOut); #ifdef DEDICATED - g_pRConServer->Send(svOut); + RCONServer()->Send(svOut); #endif // DEDICATED } else @@ -147,7 +147,7 @@ void DevMsg(eDLL_T context, const char* fmt, ...) } wconsole->debug(svAnsiOut); #ifdef DEDICATED - g_pRConServer->Send(svAnsiOut); + RCONServer()->Send(svAnsiOut); #endif // DEDICATED } @@ -240,7 +240,7 @@ void Warning(eDLL_T context, const char* fmt, ...) { wconsole->debug(svOut); #ifdef DEDICATED - g_pRConServer->Send(svOut); + RCONServer()->Send(svOut); #endif // DEDICATED } else @@ -256,7 +256,7 @@ void Warning(eDLL_T context, const char* fmt, ...) } wconsole->debug(svAnsiOut); #ifdef DEDICATED - g_pRConServer->Send(svAnsiOut); + RCONServer()->Send(svAnsiOut); #endif // DEDICATED } @@ -317,7 +317,7 @@ void Error(eDLL_T context, const char* fmt, ...) { wconsole->debug(svOut); #ifdef DEDICATED - g_pRConServer->Send(svOut); + RCONServer()->Send(svOut); #endif // DEDICATED } else @@ -333,7 +333,7 @@ void Error(eDLL_T context, const char* fmt, ...) } wconsole->debug(svAnsiOut); #ifdef DEDICATED - g_pRConServer->Send(svAnsiOut); + RCONServer()->Send(svAnsiOut); #endif // DEDICATED } diff --git a/r5dev/tier1/IConVar.cpp b/r5dev/tier1/IConVar.cpp index 6e5965b4..2574ec30 100644 --- a/r5dev/tier1/IConVar.cpp +++ b/r5dev/tier1/IConVar.cpp @@ -15,13 +15,13 @@ //----------------------------------------------------------------------------- // Purpose: construct/allocate //----------------------------------------------------------------------------- -ConVar::ConVar(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString, bool bMin, float fMin, bool bMax, float fMax, void* pCallback, const char* pszUsageString) +ConVar::ConVar(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString) { ConVar* pNewConVar = MemAllocSingleton()->Alloc(sizeof(ConVar)); // Allocate new memory with StdMemAlloc else we crash. memset(pNewConVar, '\0', sizeof(ConVar)); // Set all to null. - pNewConVar->m_pConCommandBaseVTable = g_pConVarVtable.RCast(); - pNewConVar->m_pIConVarVTable = g_pIConVarVtable.RCast(); + pNewConVar->m_pConCommandBaseVFTable = g_pConVarVFTable.RCast(); + pNewConVar->m_pIConVarVFTable = g_pIConVarVFTable.RCast(); ConVar_Register(pNewConVar, pszName, pszDefaultValue, nFlags, pszHelpString, bMin, fMin, bMax, fMax, pCallback, pszUsageString); *this = *pNewConVar; @@ -54,9 +54,8 @@ void ConVar::Init(void) const cm_unset_dev_cmdquery = new ConVar("cm_unset_dev_cmdquery" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Returns false on all FCVAR_DEVELOPMENTONLY ConVar/ConCommand queries ( !warning! ).", false, 0.f, false, 0.f, nullptr, nullptr); cm_unset_cheat_cmdquery = new ConVar("cm_unset_cheat_cmdquery", "0", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Returns false on all FCVAR_DEVELOPMENTONLY and FCVAR_CHEAT ConVar/ConCommand queries ( !warning! ).", false, 0.f, false, 0.f, nullptr, nullptr); - // TODO: RconPasswordChanged_f rcon_address = new ConVar("rcon_address", "::", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access address.", false, 0.f, false, 0.f, nullptr, nullptr); - rcon_password = new ConVar("rcon_password", "" , FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon is disabled if empty).", false, 0.f, false, 0.f, nullptr, nullptr); + rcon_password = new ConVar("rcon_password", "" , FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon is disabled if empty).", false, 0.f, false, 0.f, &RCON_PasswordChanged_f, nullptr); r_debug_overlay_nodecay = new ConVar("r_debug_overlay_nodecay" , "0", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Keeps all debug overlays alive regardless of their lifetime. Use command 'clear_debug_overlays' to clear everything.", false, 0.f, false, 0.f, nullptr, nullptr); r_debug_overlay_invisible = new ConVar("r_debug_overlay_invisible" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Show invisible debug overlays (alpha < 1 = 255).", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/tier1/IConVar.h b/r5dev/tier1/IConVar.h index bfc25173..1cbb857c 100644 --- a/r5dev/tier1/IConVar.h +++ b/r5dev/tier1/IConVar.h @@ -1,83 +1,7 @@ #pragma once #include "tier1/cmd.h" #include "mathlib/color.h" - -//----------------------------------------------------------------------------- -// Command to ConVars and ConCommands -//----------------------------------------------------------------------------- -// ConVar systems -#define FCVAR_NONE 0 // The default, no flags at all -#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc. -#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined. -#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL -#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL -#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out. - -// ConVar only -#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value -#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. -#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc -#define FCVAR_NOTIFY (1<<8) // notifies players when changed -#define FCVAR_USERINFO (1<<9) // changes the client's info string - -#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). - -#define FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS (1<<10) // When on concommands this allows remote clients to execute this cmd on the server. - // We are changing the default behavior of concommands to disallow execution by remote clients without - // this flag due to the number existing concommands that can lag or crash the server when clients abuse them. - -#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log -#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar - -// It's a ConVar that's shared between the client and the server. -// At signon, the values of all such ConVars are sent from the server to the client (skipped for local client, of course ) -// If a change is requested it must come from the console (i.e., no remote client changes) -// If a value is changed while a server is active, it's replicated to all connected clients -#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time -#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats -#define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated -#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file -#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles -#define FCVAR_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players -#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers -#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload -#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload - -#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server -#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread -#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // cvar written to config.cfg on the Xbox - -#define FCVAR_SERVER_CAN_EXECUTE (1<<28) // the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd. -#define FCVAR_SERVER_CANNOT_QUERY (1<<29) // If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue). -#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command. - -/* -class ConVar : ConCommandBase, IConVar; [MI] (#classinformer) -dq offset ? ? _R4ConVar@@6B@; const ConVar::`RTTI Complete Object Locator' - -dq offset ??_G__ExceptionPtr@@QEAAPEAXI@Z_0; 0 Index -dq offset sub_1401F9930 -dq offset loc_14046FE90 -dq offset ConVar__AddFlags -dq offset ConVar__RemoveFlags -dq offset sub_14046FEA0 -dq offset loc_14046FF70 -dq offset ConVar__GetHelpString -dq offset sub_14046FEC0 -dq offset sub_14046FEE0 -dq offset ConVar__IsRegistered -dq offset ConVar__GetDllIdentifier -dq offset sub_14046F3F0 -dq offset sub_14046F470 -dq offset ConVar__InternalSetFloatValue; The one below also does something similar -dq offset sub_140470340 -dq offset sub_140470420; Seems to be InternalSetInt below maybe ? -dq offset sub_140470510 -dq offset nullsub -dq offset sub_140470300 -dq offset sub_1404701A0 -dq offset RegisterConVar; #STR: "Convar '%s' is flagged as both FCVAR_ARCHIVE and FCVAR_ARC -*/ +#include "public/include/iconvar.h" //----------------------------------------------------------------------------- // Purpose: A console variable @@ -87,7 +11,7 @@ class ConVar : public ConCommandBase public: ConVar(void){}; ConVar(const char* pszName, const char* pszDefaultValue, int nFlags, const char*pszHelpString, - bool bMin, float fMin, bool bMax, float fMax, void* pCallback, const char* pszUsageString); + bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString); ~ConVar(void); void Init(void) const; @@ -159,7 +83,7 @@ public: int64_t m_iTimesChanged; }; - void* m_pIConVarVTable {}; //0x0040 + IConVar* m_pIConVarVFTable{}; //0x0040 ConVar* m_pParent {}; //0x0048 const char* m_pszDefaultValue{}; //0x0050 CVValue_t m_Value {}; //0c0058 @@ -178,10 +102,10 @@ inline CMemory p_ConVar_SetInfo; inline auto ConVar_SetInfo = p_ConVar_SetInfo.RCast(); inline CMemory p_ConVar_Register; -inline auto ConVar_Register = p_ConVar_Register.RCast(); +inline auto ConVar_Register = p_ConVar_Register.RCast(); -inline CMemory g_pConVarVtable; -inline CMemory g_pIConVarVtable; +inline CMemory g_pConVarVFTable; +inline CMemory g_pIConVarVFTable; /////////////////////////////////////////////////////////////////////////////// void IConVar_Attach(); @@ -197,8 +121,8 @@ class VConVar : public IDetour spdlog::debug("| FUN: IConVar::IsFlagSet : {:#18x} |\n", p_IConVar_IsFlagSet.GetPtr()); spdlog::debug("| FUN: IConVar::SetInfo : {:#18x} |\n", p_ConVar_SetInfo.GetPtr()); spdlog::debug("| FUN: IConVar::Register : {:#18x} |\n", p_ConVar_Register.GetPtr()); - spdlog::debug("| VAR: g_pConVarVtable : {:#18x} |\n", g_pConVarVtable.GetPtr()); - spdlog::debug("| VAR: g_pIConVarVtable : {:#18x} |\n", g_pIConVarVtable.GetPtr()); + spdlog::debug("| VAR: g_pConVarVtable : {:#18x} |\n", g_pConVarVFTable.GetPtr()); + spdlog::debug("| VAR: g_pIConVarVtable : {:#18x} |\n", g_pIConVarVFTable.GetPtr()); spdlog::debug("+----------------------------------------------------------------+\n"); } virtual void GetFun(void) const @@ -212,13 +136,13 @@ class VConVar : public IDetour #endif IConVar_IsFlagSet = p_IConVar_IsFlagSet.RCast(); /*48 8B 41 48 85 50 38*/ ConVar_SetInfo = p_ConVar_SetInfo.RCast(); /*40 53 48 83 EC 60 48 8B D9 C6 41 10 00 33 C9 48 8D 05 ? ? ? ? 48 89 4C 24 ? 0F 57 C0 48 89 4C 24 ? 48 89 03 48 8D 05 ? ? ? ? 48 89 43 40*/ - ConVar_Register = p_ConVar_Register.RCast(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 40 F3 0F 10 84 24 ? ? ? ?*/ + ConVar_Register = p_ConVar_Register.RCast(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 40 F3 0F 10 84 24 ? ? ? ?*/ } virtual void GetVar(void) const { - g_pConVarVtable = p_ConVar_SetInfo.Offset(0x00).FindPatternSelf("48 8D 05", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); // Get vtable ptr for ConVar table. - g_pIConVarVtable = p_ConVar_SetInfo.Offset(0x16).FindPatternSelf("48 8D 05", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); // Get vtable ptr for ICvar table. + g_pConVarVFTable = p_ConVar_SetInfo.Offset(0x00).FindPatternSelf("48 8D 05", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); // Get vtable ptr for ConVar table. + g_pIConVarVFTable = p_ConVar_SetInfo.Offset(0x16).FindPatternSelf("48 8D 05", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); // Get vtable ptr for ICvar table. } virtual void GetCon(void) const { } virtual void Attach(void) const { } diff --git a/r5dev/vproj/clientsdk.vcxproj b/r5dev/vproj/clientsdk.vcxproj index ec4f624b..773fe198 100644 --- a/r5dev/vproj/clientsdk.vcxproj +++ b/r5dev/vproj/clientsdk.vcxproj @@ -243,6 +243,7 @@ + diff --git a/r5dev/vproj/clientsdk.vcxproj.filters b/r5dev/vproj/clientsdk.vcxproj.filters index 348f42e1..1338a212 100644 --- a/r5dev/vproj/clientsdk.vcxproj.filters +++ b/r5dev/vproj/clientsdk.vcxproj.filters @@ -1646,6 +1646,9 @@ sdk\game\client + + sdk\tier1 + diff --git a/r5dev/vproj/dedicated.vcxproj b/r5dev/vproj/dedicated.vcxproj index b8bb06b3..afc8e445 100644 --- a/r5dev/vproj/dedicated.vcxproj +++ b/r5dev/vproj/dedicated.vcxproj @@ -216,6 +216,7 @@ + diff --git a/r5dev/vproj/dedicated.vcxproj.filters b/r5dev/vproj/dedicated.vcxproj.filters index 6cfe03d6..e0b78f86 100644 --- a/r5dev/vproj/dedicated.vcxproj.filters +++ b/r5dev/vproj/dedicated.vcxproj.filters @@ -1176,6 +1176,9 @@ sdk\public\include + + sdk\public\include + diff --git a/r5dev/vproj/gamesdk.vcxproj b/r5dev/vproj/gamesdk.vcxproj index fbafbebb..53a73118 100644 --- a/r5dev/vproj/gamesdk.vcxproj +++ b/r5dev/vproj/gamesdk.vcxproj @@ -267,6 +267,7 @@ + diff --git a/r5dev/vproj/gamesdk.vcxproj.filters b/r5dev/vproj/gamesdk.vcxproj.filters index 3dff4ff2..101f8259 100644 --- a/r5dev/vproj/gamesdk.vcxproj.filters +++ b/r5dev/vproj/gamesdk.vcxproj.filters @@ -1736,6 +1736,9 @@ sdk\game\shared + + sdk\public\include + diff --git a/r5dev/vstdlib/callback.cpp b/r5dev/vstdlib/callback.cpp index 12477fe8..c3cfbc96 100644 --- a/r5dev/vstdlib/callback.cpp +++ b/r5dev/vstdlib/callback.cpp @@ -9,6 +9,9 @@ #include "tier0/fasttimer.h" #include "tier1/cvar.h" #include "tier1/IConVar.h" +#ifdef DEDICATED +#include "engine/server/sv_rcon.h" +#endif // DEDICATED #ifndef DEDICATED #include "engine/client/cl_rcon.h" #endif // !DEDICATED @@ -733,44 +736,44 @@ void RCON_CmdQuery_f(const CCommand& args) { if (args.ArgC() < 2) { - if (g_pRConClient->IsInitialized() - && !g_pRConClient->IsConnected() + if (RCONClient()->IsInitialized() + && !RCONClient()->IsConnected() && strlen(rcon_address->GetString()) > 0) { - g_pRConClient->Connect(); + RCONClient()->Connect(); } } else { - if (!g_pRConClient->IsInitialized()) + if (!RCONClient()->IsInitialized()) { Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: uninitialized\n"); return; } - else if (g_pRConClient->IsConnected()) + else if (RCONClient()->IsConnected()) { if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value. { string svCmdQuery; if (args.ArgC() > 2) { - svCmdQuery = g_pRConClient->Serialize(args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + svCmdQuery = RCONClient()->Serialize(args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); } else // Use 'rcon_password' ConVar as password. { - svCmdQuery = g_pRConClient->Serialize(rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + svCmdQuery = RCONClient()->Serialize(rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); } - g_pRConClient->Send(svCmdQuery); + RCONClient()->Send(svCmdQuery); return; } else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server. { - g_pRConClient->Disconnect(); + RCONClient()->Disconnect(); return; } - string svCmdQuery = g_pRConClient->Serialize(args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); - g_pRConClient->Send(svCmdQuery); + string svCmdQuery = RCONClient()->Serialize(args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); + RCONClient()->Send(svCmdQuery); return; } else @@ -790,14 +793,36 @@ RCON_Disconnect_f */ void RCON_Disconnect_f(const CCommand& args) { - if (g_pRConClient->IsConnected()) + if (RCONClient()->IsConnected()) { - g_pRConClient->Disconnect(); + RCONClient()->Disconnect(); DevMsg(eDLL_T::CLIENT, "User closed RCON connection\n"); } } #endif // !DEDICATED +/* +===================== +RCON_PasswordChanged_f + + Change password on RCON server + and RCON client +===================== +*/ +void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { +#ifndef DEDICATED + RCONClient()->SetPassword(pConVarRef->GetString()); + RCONClient()->Init(); +#elif DEDICATED + RCONServer()->SetPassword(pConVarRef->GetString()); + RCONServer()->Init(); +#endif // DEDICATED + } +} + /* ===================== SQVM_ServerScript_f diff --git a/r5dev/vstdlib/callback.h b/r5dev/vstdlib/callback.h index 6df2098b..22bf910c 100644 --- a/r5dev/vstdlib/callback.h +++ b/r5dev/vstdlib/callback.h @@ -40,7 +40,10 @@ void NET_GenerateKey_f(const CCommand& args); void RCON_CmdQuery_f(const CCommand& args); void RCON_Disconnect_f(const CCommand& args); #endif // !DEDICATED +void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); +#ifndef CLIENT_DLL void SQVM_ServerScript_f(const CCommand& args); +#endif // !CLIENT_DLL #ifndef DEDICATED void SQVM_ClientScript_f(const CCommand& args); void SQVM_UIScript_f(const CCommand& args);