Initial game client RCON implementation

This commit is contained in:
Amos 2022-02-14 23:16:24 +01:00
parent 976e8d9a41
commit 10174a6206
13 changed files with 671 additions and 103 deletions

View File

@ -7,6 +7,7 @@
#include "client/client.h"
#include "client/cdll_engine_int.h"
#include "engine/net_chan.h"
#include "engine/cl_rcon.h"
#include "public/include/bansystem.h"
#include "vpc/keyvalues.h"
#include "gameui/IConsole.h"
@ -31,15 +32,17 @@ void __fastcall HFrameStageNotify(CHLClient* rcx, ClientFrameStage_t frameStage)
if (!g_pCmdLine->CheckParm("-devsdk"))
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_server.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_client.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_client.cfg\"");
}
else // Development configs.
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_server_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_client_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_server_dev.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_client_dev.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_dev.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_client_dev.cfg\"");
}
*(bool*)m_bRestrictServerCommands = true; // Restrict commands.
@ -51,6 +54,7 @@ void __fastcall HFrameStageNotify(CHLClient* rcx, ClientFrameStage_t frameStage)
HNET_GenerateKey();
}
g_pCVar->FindVar("net_usesocketsforloopback")->SetValue(1);
g_pRConClient->Init();
bInitialized = true;
}
@ -96,6 +100,7 @@ void __fastcall HFrameStageNotify(CHLClient* rcx, ClientFrameStage_t frameStage)
}
}
g_pIConsole->Think();
g_pRConClient->RunFrame();
CHLClient_FrameStageNotify(rcx, (int)frameStage);
}

View File

@ -1,14 +1,296 @@
//===========================================================================//
//
// Purpose: Implementation of the rcon client
//
//
// Purpose: Implementation of the rcon client.
//
//===========================================================================//
#include "core/stdafx.h"
#include "tier0/IConVar.h"
#include "tier0/cmd.h"
#include "tier0/cvar.h"
#include "protoc/sv_rcon.pb.h"
#include "protoc/cl_rcon.pb.h"
#include "engine/cl_rcon.h"
#include "engine/sys_utils.h"
#include "common/igameserverdata.h"
// TODO..
//-----------------------------------------------------------------------------
// Purpose: NETCON systems init
//-----------------------------------------------------------------------------
void CRConClient::Init(void)
{
if (std::strlen(rcon_password->GetString()) < 8)
{
if (std::strlen(rcon_password->GetString()) > 0)
{
DevMsg(eDLL_T::CLIENT, "Remote server access requires a password of at least 8 characters\n");
}
m_bInitialized = false;
}
m_bInitialized = true;
}
//-----------------------------------------------------------------------------
// Purpose: NETCON systems shutdown
//-----------------------------------------------------------------------------
void CRConClient::Shutdown(void)
{
if (m_bConnEstablished)
{
this->Disconnect();
}
}
//-----------------------------------------------------------------------------
// Purpose: client rcon main processing loop
//-----------------------------------------------------------------------------
void CRConClient::RunFrame(void)
{
if (m_bInitialized && m_bConnEstablished)
{
this->Recv();
}
}
//-----------------------------------------------------------------------------
// Purpose: connect to address and port stored in 'rcon_address' cvar
// Output : true if connection succeeds, false otherwise
//-----------------------------------------------------------------------------
bool CRConClient::Connect(void)
{
if (strlen(rcon_address->GetString()) > 0)
{
// Default is [127.0.0.1]:37015
m_pNetAdr2->SetIPAndPort(rcon_address->GetString());
}
if (m_pSocket->ConnectSocket(*m_pNetAdr2, true) == SOCKET_ERROR)
{
DevMsg(eDLL_T::CLIENT, "Connection to RCON server failed: (SOCKET_ERROR)\n");
return false;
}
DevMsg(eDLL_T::CLIENT, "Connected to: %s\n", m_pNetAdr2->GetIPAndPort().c_str());
m_bConnEstablished = true;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: connect to specified address and port
// Input : *svInAdr -
// *svInPort -
// Output : true if connection succeeds, false otherwise
//-----------------------------------------------------------------------------
bool CRConClient::Connect(const std::string& svInAdr, const std::string& svInPort)
{
if (svInAdr.size() > 0 && svInPort.size() > 0)
{
// Default is [127.0.0.1]:37015
m_pNetAdr2->SetIPAndPort(svInAdr, svInPort);
}
if (m_pSocket->ConnectSocket(*m_pNetAdr2, true) == SOCKET_ERROR)
{
DevMsg(eDLL_T::CLIENT, "Connection to RCON server failed: (SOCKET_ERROR)\n");
return false;
}
DevMsg(eDLL_T::CLIENT, "Connected to: %s\n", m_pNetAdr2->GetIPAndPort().c_str());
m_bConnEstablished = true;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: disconnect from current session
//-----------------------------------------------------------------------------
void CRConClient::Disconnect(void)
{
::closesocket(m_pSocket->GetAcceptedSocketHandle(0));
m_bConnEstablished = false;
}
//-----------------------------------------------------------------------------
// Purpose: send message
// Input : *svMessage -
//-----------------------------------------------------------------------------
void CRConClient::Send(const std::string& svMessage) const
{
int nSendResult = ::send(m_pSocket->GetAcceptedSocketData(0)->m_hSocket, svMessage.c_str(), svMessage.size(), MSG_NOSIGNAL);
if (nSendResult == SOCKET_ERROR)
{
DevMsg(eDLL_T::CLIENT, "Failed to send RCON message: (SOCKET_ERROR)\n");
}
}
//-----------------------------------------------------------------------------
// Purpose: receive message
//-----------------------------------------------------------------------------
void CRConClient::Recv(void)
{
static char szRecvBuf[MAX_NETCONSOLE_INPUT_LEN]{};
{//////////////////////////////////////////////
int nPendingLen = ::recv(m_pSocket->GetAcceptedSocketData(0)->m_hSocket, szRecvBuf, sizeof(szRecvBuf), MSG_PEEK);
if (nPendingLen == SOCKET_ERROR && m_pSocket->IsSocketBlocking())
{
return;
}
if (nPendingLen <= 0 && m_bConnEstablished) // EOF or error.
{
this->Disconnect();
DevMsg(eDLL_T::CLIENT, "Server closed RCON connection\n");
return;
}
}//////////////////////////////////////////////
u_long nReadLen; // Find out how much we have to read.
::ioctlsocket(m_pSocket->GetAcceptedSocketData(0)->m_hSocket, FIONREAD, &nReadLen);
while (nReadLen > 0)
{
memset(szRecvBuf, '\0', sizeof(szRecvBuf));
int nRecvLen = ::recv(m_pSocket->GetAcceptedSocketData(0)->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
if (nRecvLen == 0 && m_bConnEstablished) // Socket was closed.
{
this->Disconnect();
DevMsg(eDLL_T::CLIENT, "Server closed RCON connection\n");
break;
}
if (nRecvLen < 0 && !m_pSocket->IsSocketBlocking())
{
break;
}
nReadLen -= nRecvLen; // Process what we've got.
this->ProcessBuffer(szRecvBuf, nRecvLen);
}
}
//-----------------------------------------------------------------------------
// Purpose: handles input response buffer
// Input : *pszIn -
// nRecvLen -
//-----------------------------------------------------------------------------
void CRConClient::ProcessBuffer(const char* pszIn, int nRecvLen) const
{
int nCharsInRespondBuffer = 0;
char szInputRespondBuffer[MAX_NETCONSOLE_INPUT_LEN]{};
while (nRecvLen)
{
switch (*pszIn)
{
case '\r':
{
if (nCharsInRespondBuffer)
{
sv_rcon::response sv_response = this->Deserialize(szInputRespondBuffer);
this->ProcessMessage(sv_response);
}
nCharsInRespondBuffer = 0;
break;
}
default:
{
if (nCharsInRespondBuffer < MAX_NETCONSOLE_INPUT_LEN - 1)
{
szInputRespondBuffer[nCharsInRespondBuffer++] = *pszIn;
}
break;
}
}
pszIn++;
nRecvLen--;
}
}
//-----------------------------------------------------------------------------
// Purpose: processes received message
// Input : *sv_response -
//-----------------------------------------------------------------------------
void CRConClient::ProcessMessage(const sv_rcon::response& sv_response) const
{
switch (sv_response.responsetype())
{
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
{
std::string svOut = sv_response.responsebuf();
// TODO: Manipulate string..
DevMsg(eDLL_T::NONE, "%s", svOut.c_str());
break;
}
default:
{
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: serializes input
// Input : *svReqBuf -
// *svReqVal -
// request_t -
// Output : serialized results as string
//-----------------------------------------------------------------------------
std::string CRConClient::Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const
{
cl_rcon::request cl_request;
cl_request.set_requestid(-1);
cl_request.set_requesttype(request_t);
switch (request_t)
{
case cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE:
case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH:
{
cl_request.set_requestbuf(svReqBuf);
cl_request.set_requestval(svReqVal);
break;
}
case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
{
cl_request.set_requestbuf(svReqBuf);
break;
}
}
return cl_request.SerializeAsString().append("\r");
}
//-----------------------------------------------------------------------------
// Purpose: de-serializes input
// Input : *svBuf -
// Output : de-serialized object
//-----------------------------------------------------------------------------
sv_rcon::response CRConClient::Deserialize(const std::string& svBuf) const
{
sv_rcon::response sv_response;
sv_response.ParseFromArray(svBuf.c_str(), static_cast<int>(svBuf.size()));
return sv_response;
}
//-----------------------------------------------------------------------------
// Purpose: checks if client rcon is initialized
// Output : true if initialized, false otherwise
//-----------------------------------------------------------------------------
bool CRConClient::IsInitialized(void) const
{
return this->m_bInitialized;
}
//-----------------------------------------------------------------------------
// Purpose: checks if client rcon is connected
// Output : true if connected, false otherwise
//-----------------------------------------------------------------------------
bool CRConClient::IsConnected(void) const
{
return this->m_bConnEstablished;
}
CRConClient* g_pRConClient = new CRConClient();

View File

@ -1,10 +1,41 @@
#pragma once
#include "tier1/NetAdr2.h"
#include "tier2/SocketCreator.h"
#include "protoc/sv_rcon.pb.h"
#include "protoc/cl_rcon.pb.h"
class CRConClient
{
public:
CRConClient(void){};
~CRConClient(void){};
void Authenticate(void){};
void ProcessMessage(void){};
};
void Init(void);
void Shutdown(void);
void RunFrame(void);
bool Connect(void);
bool Connect(const std::string& svInAdr, const std::string& svInPort);
void Disconnect(void);
void Send(const std::string& svMessage) const;
void Recv(void);
void ProcessBuffer(const char* pszIn, int nRecvLen) const;
void ProcessMessage(const sv_rcon::response& sv_response) const;
std::string Serialize(const std::string& svReqBuf, const std::string& svReqVal, cl_rcon::request_t request_t) const;
sv_rcon::response Deserialize(const std::string& svBuf) const;
bool IsInitialized(void) const;
bool IsConnected(void) const;
private:
CNetAdr2* m_pNetAdr2 = new CNetAdr2("localhost", "37015");
CSocketCreator* m_pSocket = new CSocketCreator();
bool m_bInitialized = false;
bool m_bConnEstablished = false;
};
extern CRConClient* g_pRConClient;

View File

@ -1,6 +1,6 @@
//=============================================================================//
//
// Purpose: Runs the state machine for the host & server
// Purpose: Runs the state machine for the host & server.
//
//=============================================================================//
@ -19,6 +19,8 @@
#include "engine/sys_engine.h"
#ifdef DEDICATED
#include "engine/sv_rcon.h"
#else //
#include "engine/cl_rcon.h"
#endif // DEDICATED
//-----------------------------------------------------------------------------
@ -138,28 +140,30 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
{
if (!g_pCmdLine->CheckParm("-devsdk"))
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg");
IVEngineClient_CommandExecute(NULL, "exec rcon_server.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_server.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_server.cfg\"");
#ifndef DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg");
IVEngineClient_CommandExecute(NULL, "exec rcon_client.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_client.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_client.cfg\"");
#endif // !DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec.cfg\"");
}
else // Development configs.
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_server_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec rcon_server_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_server_dev.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_server_dev.cfg\"");
#ifndef DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec_client_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec rcon_client_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_client_dev.cfg\"");
IVEngineClient_CommandExecute(NULL, "exec \"rcon_client_dev.cfg\"");
#endif // !DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec \"autoexec_dev.cfg\"");
}
g_pConVar->ClearHostNames();
#ifdef DEDICATED
g_pRConServer->Init();
#else //
g_pRConClient->Init();
#endif // DEDICATED
*(bool*)m_bRestrictServerCommands = true; // Restrict commands.
@ -195,6 +199,8 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
}
#ifdef DEDICATED
g_pRConServer->RunFrame();
#else //
g_pRConClient->RunFrame();
#endif // DEDICATED
HostStates_t oldState{};

View File

@ -19,7 +19,7 @@
#include "common/igameserverdata.h"
//-----------------------------------------------------------------------------
// Purpose: creates listen socket for RCON
// Purpose: NETCON systems init
//-----------------------------------------------------------------------------
void CRConServer::Init(void)
{
@ -29,11 +29,7 @@ void CRConServer::Init(void)
{
DevMsg(eDLL_T::SERVER, "Remote server access requires a password of at least 8 characters\n");
}
if (m_pSocket->IsListening())
{
m_pSocket->CloseListenSocket();
}
m_bInitialized = false;
this->Shutdown();
return;
}
@ -47,6 +43,18 @@ void CRConServer::Init(void)
m_bInitialized = true;
}
//-----------------------------------------------------------------------------
// Purpose: NETCON systems shutdown
//-----------------------------------------------------------------------------
void CRConServer::Shutdown(void)
{
if (m_pSocket->IsListening())
{
m_pSocket->CloseListenSocket();
}
m_bInitialized = false;
}
//-----------------------------------------------------------------------------
// Purpose: run tasks for the RCON server
//-----------------------------------------------------------------------------
@ -65,7 +73,7 @@ void CRConServer::Think(void)
CConnectedNetConsoleData* pData = m_pSocket->GetAcceptedSocketData(m_nConnIndex);
if (!pData->m_bAuthorized)
{
CloseConnection();
this->CloseConnection();
}
}
}
@ -126,7 +134,7 @@ void CRConServer::Recv(void)
{
CConnectedNetConsoleData* pData = m_pSocket->GetAcceptedSocketData(m_nConnIndex);
{//////////////////////////////////////////////
if (CheckForBan(pData))
if (this->CheckForBan(pData))
{
std::string svNoAuth = this->Serialize(s_pszBannedMessage, "", sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH);
::send(pData->m_hSocket, svNoAuth.c_str(), static_cast<int>(svNoAuth.size()), MSG_NOSIGNAL);

View File

@ -12,6 +12,7 @@ class CRConServer
{
public:
void Init(void);
void Shutdown(void);
void Think(void);
void RunFrame(void);

View File

@ -316,12 +316,14 @@ void CNetCon::ProcessBuffer(const char* pszIn, int nRecvLen) const
}
default:
{
if (nCharsInRespondBuffer < MAX_NETCONSOLE_INPUT_LEN - 1)
{
szInputRespondBuffer[nCharsInRespondBuffer++] = *pszIn;
}
break;
}
}
pszIn++;
nRecvLen--;
}

View File

@ -5,6 +5,71 @@
#include "client/client.h"
#include "engine/sys_utils.h"
//-----------------------------------------------------------------------------
// Purpose: returns max command lenght
//-----------------------------------------------------------------------------
int CCommand::MaxCommandLength(void)
{
return COMMAND_MAX_LENGTH - 1;
}
//-----------------------------------------------------------------------------
// Purpose: returns argument count
//-----------------------------------------------------------------------------
std::int64_t CCommand::ArgC(void) const
{
return m_nArgc;
}
//-----------------------------------------------------------------------------
// Purpose: returns argument vector
//-----------------------------------------------------------------------------
const char** CCommand::ArgV(void) const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
//-----------------------------------------------------------------------------
// Purpose: returns all args that occur after the 0th arg, in string form
//-----------------------------------------------------------------------------
const char* CCommand::ArgS(void) const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
//-----------------------------------------------------------------------------
// Purpose: returns the entire command in string form, including the 0th arg
//-----------------------------------------------------------------------------
const char* CCommand::GetCommandString(void) const
{
return m_nArgc ? m_pArgSBuffer : "";
}
//-----------------------------------------------------------------------------
// Purpose: returns argument from index as string
// Input : nIndex -
//-----------------------------------------------------------------------------
const char* CCommand::Arg(int nIndex) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if (nIndex < 0 || nIndex >= m_nArgc)
{
return "";
}
return m_ppArgv[nIndex];
}
//-----------------------------------------------------------------------------
// Purpose: gets at arguments
// Input : nInput -
//-----------------------------------------------------------------------------
const char* CCommand::operator[](int nIndex) const
{
return Arg(nIndex);
}
//-----------------------------------------------------------------------------
// Purpose: construct/allocate
//-----------------------------------------------------------------------------
@ -140,11 +205,11 @@ bool ConCommandBase::IsFlagSet(ConCommandBase* pCommandBase, int nFlags)
return pCommandBase->HasFlags(nFlags) != 0;
}
///////////////////////////////////////////////////////////////////////////////
void ConCommand_Attach()
{
DetourAttach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSet);
}
void ConCommand_Detach()
{
DetourDetach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSet);

View File

@ -1,5 +1,8 @@
#pragma once
//-----------------------------------------------------------------------------
// Purpose: Command tokenizer
//-----------------------------------------------------------------------------
class CCommand
{
private:
@ -12,47 +15,13 @@ private:
public:
CCommand() = delete;
inline int MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline std::int64_t ArgC() const
{
return m_nArgc;
}
inline const char** ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char* ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char* GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char* Arg(int nIndex) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if (nIndex < 0 || nIndex >= m_nArgc)
{
return "";
}
return m_ppArgv[nIndex];
}
inline const char* operator[](int nIndex) const
{
return Arg(nIndex);
}
int MaxCommandLength();
std::int64_t ArgC(void) const;
const char** ArgV(void) const;
const char* ArgS(void) const;
const char* GetCommandString(void) const;
const char* Arg(int nIndex) const;
const char* operator[](int nIndex) const;
private:
std::int64_t m_nArgc;
@ -62,6 +31,9 @@ private:
const char* m_ppArgv[COMMAND_MAX_ARGC];
};
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand
{
friend class CCVar;
@ -72,6 +44,9 @@ public:
// TODO
};
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
public:

View File

@ -1,6 +1,6 @@
//=============================================================================//
//
// Purpose: Completion functions for ConCommand callbacks
// Purpose: Completion functions for ConCommand callbacks.
//
//=============================================================================//
@ -25,17 +25,32 @@
#include "mathlib/crc32.h"
#ifndef DEDICATED
/*
=====================
_CGameConsole_f_CompletionFunc
=====================
*/
void _CGameConsole_f_CompletionFunc(const CCommand& cmd)
{
g_pIConsole->m_bActivate = !g_pIConsole->m_bActivate;
}
/*
=====================
_CCompanion_f_CompletionFunc
=====================
*/
void _CCompanion_f_CompletionFunc(const CCommand& cmd)
{
g_pIBrowser->m_bActivate = !g_pIBrowser->m_bActivate;
}
#endif // !DEDICATED
/*
=====================
_Kick_f_CompletionFunc
=====================
*/
void _Kick_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -77,6 +92,11 @@ void _Kick_f_CompletionFunc(CCommand* cmd)
}
}
/*
=====================
_KickID_f_CompletionFunc
=====================
*/
void _KickID_f_CompletionFunc(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
@ -169,6 +189,11 @@ void _KickID_f_CompletionFunc(CCommand* cmd)
}
}
/*
=====================
_Ban_f_CompletionFunc
=====================
*/
void _Ban_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -225,6 +250,11 @@ void _Ban_f_CompletionFunc(CCommand* cmd)
}
}
/*
=====================
_BanID_f_CompletionFunc
=====================
*/
void _BanID_f_CompletionFunc(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
@ -321,6 +351,11 @@ void _BanID_f_CompletionFunc(CCommand* cmd)
}
}
/*
=====================
_Unban_f_CompletionFunc
=====================
*/
void _Unban_f_CompletionFunc(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
@ -364,11 +399,21 @@ void _Unban_f_CompletionFunc(CCommand* cmd)
}
}
/*
=====================
_ReloadBanList_f_CompletionFunc
=====================
*/
void _ReloadBanList_f_CompletionFunc(CCommand* cmd)
{
g_pBanSystem->Load(); // Reload banlist.
}
/*
=====================
_RTech_StringToGUID_f_CompletionFunc
=====================
*/
void _RTech_StringToGUID_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -387,6 +432,11 @@ void _RTech_StringToGUID_f_CompletionFunc(CCommand* cmd)
DevMsg(eDLL_T::RTECH, "] GUID: '0x%llX'\n", guid);
}
/*
=====================
_RTech_AsyncLoad_f_CompletionFunc
=====================
*/
void _RTech_AsyncLoad_f_CompletionFunc(CCommand* cmd)
{
CCommand& args = *cmd; // Get reference.
@ -395,6 +445,14 @@ void _RTech_AsyncLoad_f_CompletionFunc(CCommand* cmd)
HRtech_AsyncLoad(firstArg);
}
/*
=====================
_RTech_Decompress_f_CompletionFunc
Decompresses input RPak file and
dumps results to 'paks\Win32\*.rpak'
=====================
*/
void _RTech_Decompress_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -519,6 +577,15 @@ void _RTech_Decompress_f_CompletionFunc(CCommand* cmd)
outBlock.close();
}
/*
=====================
_NET_TraceNetChan_f_CompletionFunc
Logs all data transmitted and received
over the UDP socket to a file on the disk.
File: '<mod\logs\net_trace.log>'.
=====================
*/
void _NET_TraceNetChan_f_CompletionFunc(CCommand* cmd)
{
static bool bTraceNetChannel = false;
@ -563,6 +630,14 @@ void _NET_TraceNetChan_f_CompletionFunc(CCommand* cmd)
bTraceNetChannel = !bTraceNetChannel;
}
/*
=====================
_VPK_Decompress_f_CompletionFunc
Decompresses input VPK files and
dumps the output to '<mod>\vpk'.
=====================
*/
void _VPK_Decompress_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -598,6 +673,13 @@ void _VPK_Decompress_f_CompletionFunc(CCommand* cmd)
DevMsg(eDLL_T::FS, "--------------------------------------------------------------\n");
}
/*
=====================
_NET_SetKey_f_CompletionFunc
Sets the input netchannel encryption key
=====================
*/
void _NET_SetKey_f_CompletionFunc(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
@ -613,13 +695,88 @@ void _NET_SetKey_f_CompletionFunc(CCommand* cmd)
HNET_SetKey(firstArg);
}
/*
=====================
_NET_GenerateKey_f_CompletionFunc
Sets a random netchannel encryption key
=====================
*/
void _NET_GenerateKey_f_CompletionFunc(CCommand* cmd)
{
HNET_GenerateKey();
}
#ifndef DEDICATED
/*
=====================
_RCON_CmdQuery_f_CompletionFunc
Issues an RCON command to the
RCON server.
=====================
*/
void _RCON_CmdQuery_f_CompletionFunc(CCommand* cmd)
{
// TODO: CRConClient..
return;
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
switch (argSize)
{
case 0:
case 1:
{
if (g_pRConClient->IsInitialized()
&& !g_pRConClient->IsConnected()
&& strlen(rcon_address->GetString()) > 0)
{
g_pRConClient->Connect();
}
break;
}
case 2:
{
if (!g_pRConClient->IsInitialized())
{
DevMsg(eDLL_T::CLIENT, "Failed to issue command to RCON server: uninitialized.\n");
break;
}
CCommand& args = *cmd; // Get reference.
if (!g_pRConClient->IsConnected())
{
DevMsg(eDLL_T::CLIENT, "Failed to issue command to RCON server: unconnected.\n");
break;
}
std::string svCmdQuery = g_pRConClient->Serialize(args[1], "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
g_pRConClient->Send(svCmdQuery);
break;
}
case 3:
{
if (!g_pRConClient->IsInitialized())
{
DevMsg(eDLL_T::CLIENT, "Failed to issue command to RCON server: uninitialized.\n");
break;
}
CCommand& args = *cmd; // Get reference.
if (!g_pRConClient->IsConnected())
{
DevMsg(eDLL_T::CLIENT, "Failed to issue command to RCON server: unconnected.\n");
break;
}
if (strcmp(args[1], "PASS") == 0)
{
std::string svCmdQuery = g_pRConClient->Serialize(args[1], args[2], cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
g_pRConClient->Send(svCmdQuery);
break;
}
std::string svCmdQuery = g_pRConClient->Serialize(args[1], args[2], cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE);
g_pRConClient->Send(svCmdQuery);
break;
}
}
}
#endif // !DEDICATED

View File

@ -33,7 +33,9 @@ void _VPK_Decompress_f_CompletionFunc(CCommand* cmd);
void _NET_TraceNetChan_f_CompletionFunc(CCommand* cmd);
void _NET_SetKey_f_CompletionFunc(CCommand* cmd);
void _NET_GenerateKey_f_CompletionFunc(CCommand* cmd);
#ifndef DEDICATED
void _RCON_CmdQuery_f_CompletionFunc(CCommand* cmd);
#endif // !DEDICATED
///////////////////////////////////////////////////////////////////////////////
class HCompletion : public IDetour

View File

@ -11,34 +11,12 @@
#endif // !NETCONSOLE
//-----------------------------------------------------------------------------
// Purpose: constructor (use this when string contains <[IP]:PORT> or 'loopback'/'localhost').
// Purpose: constructor (use this when string contains <[IP]:PORT>).
// Input : svInAdr -
//-----------------------------------------------------------------------------
CNetAdr2::CNetAdr2(std::string svInAdr)
{
SetType(netadrtype_t::NA_IP);
if (strcmp(svInAdr.c_str(), "loopback") == 0 || strcmp(svInAdr.c_str(), "::1") == 0)
{
SetType(netadrtype_t::NA_LOOPBACK);
svInAdr = "[127.0.0.1" + GetPort(svInAdr);
}
else if (strcmp(svInAdr.c_str(), "localhost"))
{
svInAdr = "[127.0.0.1" + GetPort(svInAdr);
}
// [IP]:PORT
m_svip = GetBase(svInAdr);
SetVersion();
if (GetVersion() == netadrversion_t::NA_V4)
{
reinterpret_cast<sockaddr_in*>(&m_sadr)->sin_port = htons(stoi(GetPort()));
}
else if (GetVersion() == netadrversion_t::NA_V6)
{
reinterpret_cast<sockaddr_in6*>(&m_sadr)->sin6_port = htons(stoi(GetPort()));
}
SetIPAndPort(svInAdr);
}
//-----------------------------------------------------------------------------
@ -102,15 +80,70 @@ void CNetAdr2::SetPort(const std::string& svInPort)
m_svip += ":" + svInPort;
}
//-----------------------------------------------------------------------------
// Purpose: sets the IP address and port.
// Input : *svInAdr -
//-----------------------------------------------------------------------------
void CNetAdr2::SetIPAndPort(std::string svInAdr)
{
SetType(netadrtype_t::NA_IP);
if (strstr(svInAdr.c_str(), "loopback") || strstr(svInAdr.c_str(), "::1"))
{
SetType(netadrtype_t::NA_LOOPBACK);
svInAdr = "[127.0.0.1]:" + GetPort(svInAdr);
}
else if (strstr(svInAdr.c_str(), "localhost"))
{
svInAdr = "[127.0.0.1]:" + GetPort(svInAdr);
}
// [IP]:PORT
m_svip = svInAdr;
SetVersion();
if (GetVersion() == netadrversion_t::NA_V4)
{
reinterpret_cast<sockaddr_in*>(&m_sadr)->sin_port = htons(stoi(GetPort()));
}
else if (GetVersion() == netadrversion_t::NA_V6)
{
reinterpret_cast<sockaddr_in6*>(&m_sadr)->sin6_port = htons(stoi(GetPort()));
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the IP address and port.
// Input : *svInAdr -
// *svInPort -
//-----------------------------------------------------------------------------
void CNetAdr2::SetIPAndPort(const std::string& svInAdr, const std::string& svInPort)
void CNetAdr2::SetIPAndPort(std::string svInAdr, std::string svInPort)
{
SetType(netadrtype_t::NA_IP);
if (strcmp(svInAdr.c_str(), "loopback") == 0 || strcmp(svInAdr.c_str(), "::1") == 0)
{
SetType(netadrtype_t::NA_LOOPBACK);
}
else if (strcmp(svInAdr.c_str(), "localhost") == 0)
{
svInAdr = "127.0.0.1";
}
if (strstr(svInAdr.c_str(), "["))
{
svInAdr = GetBase(svInAdr);
}
m_svip = "[" + svInAdr + "]:" + svInPort;
SetVersion();
if (m_version == netadrversion_t::NA_V4)
{
reinterpret_cast<sockaddr_in*>(&m_sadr)->sin_port = htons(stoi(GetPort()));
}
else if (m_version == netadrversion_t::NA_V6)
{
reinterpret_cast<sockaddr_in6*>(&m_sadr)->sin6_port = htons(stoi(GetPort()));
}
}
//-----------------------------------------------------------------------------

View File

@ -50,7 +50,8 @@ public:
void SetIP(const std::string& svInAdr);
void SetPort(const std::string& svInPort);
void SetIPAndPort(const std::string& svInAdr, const std::string& svInPort);
void SetIPAndPort(std::string svInAdr);
void SetIPAndPort(std::string svInAdr, std::string svInPort);
void SetType(const netadrtype_t& type);
void SetVersion(void);
void SetFromSocket(const int& hSocket);