mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Initial large refactor of the RCON implementation
* Decoding and encoding is done into a single buffer, from raw buffers to avoid extraneous copies. * Added base class holding all core logic for encoding, decoding, receiving and processing of the RCON protocol. This code was initially identical between all implementations of RCON, deduplicating this avoids bugs. * Added more sophisticated error handling, stop right away when decoding for example fails. * Added ability to have more than one active authenticated net console on the server. Controlled by cvar 'sv_rcon_maxconnections' (default 1). * Max packet size for accepted, but not authenticated sockets is now controled by cvar 'sv_rcon_maxpacketsize' (default 1024).
This commit is contained in:
parent
437a54486d
commit
179bd31ee6
@ -10,6 +10,7 @@
|
|||||||
#include "protoc/sv_rcon.pb.h"
|
#include "protoc/sv_rcon.pb.h"
|
||||||
#include "protoc/cl_rcon.pb.h"
|
#include "protoc/cl_rcon.pb.h"
|
||||||
#include "engine/client/cl_rcon.h"
|
#include "engine/client/cl_rcon.h"
|
||||||
|
#include "engine/shared/shared_rcon.h"
|
||||||
#include "engine/net.h"
|
#include "engine/net.h"
|
||||||
#include "squirrel/sqvm.h"
|
#include "squirrel/sqvm.h"
|
||||||
#include "common/igameserverdata.h"
|
#include "common/igameserverdata.h"
|
||||||
@ -20,7 +21,6 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CRConClient::CRConClient()
|
CRConClient::CRConClient()
|
||||||
: m_bInitialized(false)
|
: m_bInitialized(false)
|
||||||
, m_bConnEstablished(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,10 +44,7 @@ void CRConClient::Init(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConClient::Shutdown(void)
|
void CRConClient::Shutdown(void)
|
||||||
{
|
{
|
||||||
if (m_bConnEstablished)
|
Disconnect();
|
||||||
{
|
|
||||||
this->Disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -55,230 +52,89 @@ void CRConClient::Shutdown(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConClient::RunFrame(void)
|
void CRConClient::RunFrame(void)
|
||||||
{
|
{
|
||||||
if (m_bInitialized && m_bConnEstablished)
|
if (IsInitialized() && IsConnected())
|
||||||
{
|
{
|
||||||
this->Recv();
|
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(0);
|
||||||
|
Recv(pData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
return Connect(rcon_address->GetString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: connect to specified address and port
|
|
||||||
// Input : *szInAdr -
|
|
||||||
// Output : true if connection succeeds, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
bool CRConClient::Connect(const char* szInAdr)
|
|
||||||
{
|
|
||||||
string svLocalHost;
|
|
||||||
if (strcmp(szInAdr, "localhost") == 0)
|
|
||||||
{
|
|
||||||
char szHostName[512];
|
|
||||||
if (!gethostname(szHostName, sizeof(szHostName)))
|
|
||||||
{
|
|
||||||
svLocalHost = Format("[%s]:%i", szHostName, hostport->GetInt());
|
|
||||||
szInAdr = svLocalHost.c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_Address.SetFromString(szInAdr, true))
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::CLIENT, "Failed to set RCON address: %s\n", szInAdr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Socket.ConnectSocket(m_Address, true) == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::CLIENT, "Failed to connect to RCON server: (%s)\n", "SOCKET_ERROR");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DevMsg(eDLL_T::CLIENT, "Connected to: %s\n", m_Address.ToString());
|
|
||||||
|
|
||||||
m_bConnEstablished = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: disconnect from current session
|
// Purpose: disconnect from current session
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConClient::Disconnect(void)
|
void CRConClient::Disconnect(const char* szReason)
|
||||||
{
|
{
|
||||||
m_Socket.CloseAcceptedSocket(0);
|
if (IsConnected())
|
||||||
m_bConnEstablished = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: send message
|
|
||||||
// Input : *svMessage -
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConClient::Send(const string& svMessage) const
|
|
||||||
{
|
|
||||||
ostringstream ssSendBuf;
|
|
||||||
const u_long nLen = htonl(static_cast<u_long>(svMessage.size()));
|
|
||||||
|
|
||||||
ssSendBuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
|
||||||
ssSendBuf.write(svMessage.data(), svMessage.size());
|
|
||||||
|
|
||||||
int nSendResult = ::send(m_Socket.GetAcceptedSocketData(0)->m_hSocket,
|
|
||||||
ssSendBuf.str().data(), static_cast<int>(ssSendBuf.str().size()), MSG_NOSIGNAL);
|
|
||||||
if (nSendResult == SOCKET_ERROR)
|
|
||||||
{
|
{
|
||||||
Warning(eDLL_T::CLIENT, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
if (szReason)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: receive message
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConClient::Recv(void)
|
|
||||||
{
|
|
||||||
static char szRecvBuf[1024];
|
|
||||||
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(0);
|
|
||||||
|
|
||||||
{//////////////////////////////////////////////
|
|
||||||
const int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
|
|
||||||
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
|
|
||||||
{
|
{
|
||||||
return;
|
DevMsg(eDLL_T::CLIENT, "%s", szReason);
|
||||||
}
|
|
||||||
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(pData->m_hSocket, FIONREAD, &nReadLen);
|
|
||||||
|
|
||||||
while (nReadLen > 0)
|
|
||||||
{
|
|
||||||
const int nRecvLen = ::recv(pData->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_Socket.IsSocketBlocking())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::CLIENT, NO_ERROR, "RCON Cmd: recv error (%s)\n", NET_ErrorString(WSAGetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nReadLen -= nRecvLen; // Process what we've got.
|
m_Socket.CloseAcceptedSocket(0);
|
||||||
this->ProcessBuffer(szRecvBuf, nRecvLen, pData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: parses input response buffer using length-prefix framing
|
|
||||||
// Input : *pszIn -
|
|
||||||
// nRecvLen -
|
|
||||||
// *pData -
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConClient::ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData)
|
|
||||||
{
|
|
||||||
while (nRecvLen > 0)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadRead < pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
if (pData->m_nPayloadRead == pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
this->ProcessMessage(this->Deserialize(string(
|
|
||||||
reinterpret_cast<char*>(pData->m_RecvBuffer.data()), pData->m_nPayloadLen)));
|
|
||||||
|
|
||||||
pData->m_nPayloadLen = 0;
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pData->m_nPayloadRead < sizeof(u_long)) // Read size field.
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
else // Build prefix.
|
|
||||||
{
|
|
||||||
pData->m_nPayloadLen = ntohl(*reinterpret_cast<u_long*>(&pData->m_RecvBuffer[0]));
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
|
|
||||||
if (pData->m_nPayloadLen < 0 ||
|
|
||||||
pData->m_nPayloadLen > pData->m_RecvBuffer.max_size())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::CLIENT, NO_ERROR, "RCON Cmd: sync error (%d)\n", pData->m_nPayloadLen);
|
|
||||||
this->Disconnect(); // Out of sync (irrecoverable).
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: processes received message
|
// Purpose: processes received message
|
||||||
// Input : *sv_response -
|
// Input : *pMsgBug -
|
||||||
|
// nMsgLen -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConClient::ProcessMessage(const sv_rcon::response& sv_response) const
|
bool CRConClient::ProcessMessage(const char* pMsgBuf, int nMsgLen)
|
||||||
{
|
{
|
||||||
switch (sv_response.responsetype())
|
sv_rcon::response response;
|
||||||
|
bool bSuccess = Decode(&response, pMsgBuf, nMsgLen);
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to decode RCON buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (response.responsetype())
|
||||||
{
|
{
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
|
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
|
||||||
{
|
{
|
||||||
if (!sv_response.responseval().empty())
|
if (!response.responseval().empty())
|
||||||
{
|
{
|
||||||
bool bLocalHost = (g_pNetAdr->ComparePort(m_Address) && g_pNetAdr->CompareAdr(m_Address));
|
const long i = strtol(response.responseval().c_str(), NULL, NULL);
|
||||||
const long i = strtol(sv_response.responseval().c_str(), NULL, NULL);
|
const bool bLocalHost = (g_pNetAdr->ComparePort(m_Address) && g_pNetAdr->CompareAdr(m_Address));
|
||||||
|
const SocketHandle_t hSocket = GetSocket();
|
||||||
|
|
||||||
if (!i) // sv_rcon_sendlogs is not set.
|
if (!i) // sv_rcon_sendlogs is not set.
|
||||||
{
|
{
|
||||||
if (!bLocalHost && cl_rcon_request_sendlogs->GetBool())
|
if (!bLocalHost && cl_rcon_request_sendlogs->GetBool())
|
||||||
{
|
{
|
||||||
string svLogQuery = this->Serialize("", "1", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
vector<char> vecMsg;
|
||||||
this->Send(svLogQuery);
|
bool ret = Serialize(vecMsg, "", "1", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
||||||
|
|
||||||
|
if (ret && !Send(hSocket, vecMsg.data(), int(vecMsg.size())))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bLocalHost)
|
else if (bLocalHost)
|
||||||
{
|
{
|
||||||
// Don't send logs to local host, it already gets logged to the same console.
|
// Don't send logs to local host, it already gets logged to the same console.
|
||||||
string svLogQuery = this->Serialize("", "0", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
vector<char> vecMsg;
|
||||||
this->Send(svLogQuery);
|
bool ret = Serialize(vecMsg, "", "0", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
||||||
|
|
||||||
|
if (ret && !Send(hSocket, vecMsg.data(), int(vecMsg.size())))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DevMsg(eDLL_T::NETCON, "%s", sv_response.responsemsg().c_str());
|
DevMsg(eDLL_T::NETCON, "%s", response.responsemsg().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
|
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
|
||||||
{
|
{
|
||||||
NetMsg(static_cast<LogType_t>(sv_response.messagetype()),
|
NetMsg(static_cast<LogType_t>(response.messagetype()),
|
||||||
static_cast<eDLL_T>(sv_response.messageid()),
|
static_cast<eDLL_T>(response.messageid()),
|
||||||
sv_response.responseval().c_str(), "%s", sv_response.responsemsg().c_str());
|
response.responseval().c_str(), "%s", response.responsemsg().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -286,6 +142,8 @@ void CRConClient::ProcessMessage(const sv_rcon::response& sv_response) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -295,34 +153,24 @@ void CRConClient::ProcessMessage(const sv_rcon::response& sv_response) const
|
|||||||
// request_t -
|
// request_t -
|
||||||
// Output : serialized results as string
|
// Output : serialized results as string
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
string CRConClient::Serialize(const string& svReqBuf, const string& svReqVal, const cl_rcon::request_t request_t) const
|
bool CRConClient::Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||||
|
const char* szReqVal, const cl_rcon::request_t requestType) const
|
||||||
{
|
{
|
||||||
cl_rcon::request cl_request;
|
return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType);
|
||||||
|
|
||||||
cl_request.set_messageid(-1);
|
|
||||||
cl_request.set_requesttype(request_t);
|
|
||||||
cl_request.set_requestmsg(svReqBuf);
|
|
||||||
cl_request.set_requestval(svReqVal);
|
|
||||||
|
|
||||||
return cl_request.SerializeAsString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: de-serializes input
|
// Purpose: retrieves the remote socket
|
||||||
// Input : *svBuf -
|
// Output : SOCKET_ERROR (-1) on failure
|
||||||
// Output : de-serialized object
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
sv_rcon::response CRConClient::Deserialize(const string& svBuf) const
|
SocketHandle_t CRConClient::GetSocket(void)
|
||||||
{
|
{
|
||||||
sv_rcon::response sv_response;
|
return SH_GetNetConSocketHandle(this, 0);
|
||||||
sv_response.ParseFromArray(svBuf.data(), static_cast<int>(svBuf.size()));
|
|
||||||
|
|
||||||
return sv_response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if client rcon is initialized
|
// Purpose: checks if client rcon is initialized
|
||||||
// Output : true if initialized, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CRConClient::IsInitialized(void) const
|
bool CRConClient::IsInitialized(void) const
|
||||||
{
|
{
|
||||||
@ -330,13 +178,13 @@ bool CRConClient::IsInitialized(void) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if client rcon is connected
|
// Purpose: returns whether the rcon client is connected
|
||||||
// Output : true if connected, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CRConClient::IsConnected(void) const
|
bool CRConClient::IsConnected(void)
|
||||||
{
|
{
|
||||||
return m_bConnEstablished;
|
return (GetSocket() != SOCKET_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
CRConClient g_RCONClient;
|
CRConClient g_RCONClient;
|
||||||
CRConClient* RCONClient() // Singleton RCON Client.
|
CRConClient* RCONClient() // Singleton RCON Client.
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
#include "tier2/socketcreator.h"
|
#include "tier2/socketcreator.h"
|
||||||
#include "protoc/sv_rcon.pb.h"
|
#include "protoc/sv_rcon.pb.h"
|
||||||
#include "protoc/cl_rcon.pb.h"
|
#include "protoc/cl_rcon.pb.h"
|
||||||
|
#include "engine/shared/base_rcon.h"
|
||||||
|
|
||||||
class CRConClient
|
class CRConClient : public CNetConBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRConClient(void);
|
CRConClient(void);
|
||||||
@ -15,28 +16,20 @@ public:
|
|||||||
|
|
||||||
void RunFrame(void);
|
void RunFrame(void);
|
||||||
|
|
||||||
bool Connect(void);
|
virtual void Disconnect(const char* szReason = nullptr) override;
|
||||||
bool Connect(const char* szInAdr);
|
|
||||||
void Disconnect(void);
|
|
||||||
|
|
||||||
void Send(const string& svMessage) const;
|
virtual bool ProcessMessage(const char* pMsgBuf, int nMsgLen) override;
|
||||||
void Recv(void);
|
|
||||||
|
|
||||||
void ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData);
|
bool Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||||
void ProcessMessage(const sv_rcon::response& sv_response) const;
|
const char* szReqVal, const cl_rcon::request_t requestType) const;
|
||||||
|
|
||||||
string Serialize(const string& svReqBuf, const string& svReqVal, const cl_rcon::request_t request_t) const;
|
|
||||||
sv_rcon::response Deserialize(const string& svBuf) const;
|
|
||||||
|
|
||||||
bool IsInitialized(void) const;
|
bool IsInitialized(void) const;
|
||||||
bool IsConnected(void) const;
|
bool IsConnected(void);
|
||||||
|
|
||||||
|
SocketHandle_t GetSocket(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_bInitialized = false;
|
bool m_bInitialized;
|
||||||
bool m_bConnEstablished = false;
|
|
||||||
|
|
||||||
netadr_t m_Address;
|
|
||||||
CSocketCreator m_Socket;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CRConClient* RCONClient();
|
CRConClient* RCONClient();
|
@ -16,13 +16,21 @@
|
|||||||
#include "mathlib/sha256.h"
|
#include "mathlib/sha256.h"
|
||||||
#include "common/igameserverdata.h"
|
#include "common/igameserverdata.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static const char s_NoAuthMessage[] = "This server is password protected for console access; authenticate with 'PASS <password>' command.\n";
|
||||||
|
static const char s_WrongPwMessage[] = "Admin password incorrect.\n";
|
||||||
|
static const char s_AuthMessage[] = "Authentication successful.\n";
|
||||||
|
static const char s_BannedMessage[] = "Go away.\n";
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CRConServer::CRConServer(void)
|
CRConServer::CRConServer(void)
|
||||||
: m_bInitialized(false)
|
: m_nConnIndex(0)
|
||||||
, m_nConnIndex(0)
|
, m_nAuthConnections(0)
|
||||||
|
, m_bInitialized(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +48,7 @@ void CRConServer::Init(void)
|
|||||||
{
|
{
|
||||||
if (!m_bInitialized)
|
if (!m_bInitialized)
|
||||||
{
|
{
|
||||||
if (!this->SetPassword(rcon_password->GetString()))
|
if (!SetPassword(rcon_password->GetString()))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -85,7 +93,7 @@ void CRConServer::Think(void)
|
|||||||
const CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
const CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||||
if (!pData->m_bAuthorized)
|
if (!pData->m_bAuthorized)
|
||||||
{
|
{
|
||||||
this->CloseConnection();
|
Disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +128,7 @@ bool CRConServer::SetPassword(const char* pszPassword)
|
|||||||
RCON_MIN_PASSWORD_LEN);
|
RCON_MIN_PASSWORD_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Shutdown();
|
Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,22 +157,42 @@ void CRConServer::RunFrame(void)
|
|||||||
if (m_bInitialized)
|
if (m_bInitialized)
|
||||||
{
|
{
|
||||||
m_Socket.RunFrame();
|
m_Socket.RunFrame();
|
||||||
this->Think();
|
Think();
|
||||||
this->Recv();
|
|
||||||
|
const int nCount = m_Socket.GetAcceptedSocketCount();
|
||||||
|
for (m_nConnIndex = nCount - 1; m_nConnIndex >= 0; m_nConnIndex--)
|
||||||
|
{
|
||||||
|
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||||
|
|
||||||
|
if (CheckForBan(pData))
|
||||||
|
{
|
||||||
|
SendEncode(pData->m_hSocket, s_BannedMessage, "",
|
||||||
|
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, int(eDLL_T::NETCON));
|
||||||
|
Disconnect();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Recv(pData, sv_rcon_maxpacketsize->GetInt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: send message to all connected sockets
|
// Purpose: send message to all connected sockets
|
||||||
// Input : *svMessage -
|
// Input : *pMsgBuf -
|
||||||
|
// nMsgLen -
|
||||||
|
// Output: true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::Send(const std::string& svMessage) const
|
bool CRConServer::SendToAll(const char* pMsgBuf, int nMsgLen) const
|
||||||
{
|
{
|
||||||
std::ostringstream ssSendBuf;
|
std::ostringstream sendbuf;
|
||||||
const u_long nLen = htonl(static_cast<u_long>(svMessage.size()));
|
const u_long nLen = htonl(u_long(nMsgLen));
|
||||||
|
|
||||||
ssSendBuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
bool bSuccess = true;
|
||||||
ssSendBuf.write(svMessage.data(), svMessage.size());
|
|
||||||
|
sendbuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
||||||
|
sendbuf.write(pMsgBuf, nMsgLen);
|
||||||
|
|
||||||
const int nCount = m_Socket.GetAcceptedSocketCount();
|
const int nCount = m_Socket.GetAcceptedSocketCount();
|
||||||
for (int i = nCount - 1; i >= 0; i--)
|
for (int i = nCount - 1; i >= 0; i--)
|
||||||
@ -173,115 +201,75 @@ void CRConServer::Send(const std::string& svMessage) const
|
|||||||
|
|
||||||
if (pData->m_bAuthorized)
|
if (pData->m_bAuthorized)
|
||||||
{
|
{
|
||||||
::send(pData->m_hSocket, ssSendBuf.str().data(),
|
int ret = ::send(pData->m_hSocket, sendbuf.str().data(),
|
||||||
static_cast<int>(ssSendBuf.str().size()), MSG_NOSIGNAL);
|
int(sendbuf.str().size()), MSG_NOSIGNAL);
|
||||||
|
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
bSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: send message to specific connected socket
|
// Purpose: encode and send message to all connected sockets
|
||||||
// Input : hSocket -
|
// Input : *pResponseMsg -
|
||||||
// *svMessage -
|
// *pResponseVal -
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConServer::Send(const SocketHandle_t hSocket, const std::string& svMessage) const
|
|
||||||
{
|
|
||||||
std::ostringstream ssSendBuf;
|
|
||||||
const u_long nLen = htonl(static_cast<u_long>(svMessage.size()));
|
|
||||||
|
|
||||||
ssSendBuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
|
||||||
ssSendBuf.write(svMessage.data(), svMessage.size());
|
|
||||||
|
|
||||||
::send(hSocket, ssSendBuf.str().data(), static_cast<int>(ssSendBuf.str().size()), MSG_NOSIGNAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: send serialized message to all connected sockets
|
|
||||||
// Input : *responseMsg -
|
|
||||||
// *responseVal -
|
|
||||||
// responseType -
|
// responseType -
|
||||||
// nMessageId -
|
// nMessageId -
|
||||||
// nMessageType -
|
// nMessageType -
|
||||||
|
// Output: true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::Send(const std::string& responseMsg, const std::string& responseVal,
|
bool CRConServer::SendEncode(const char* pResponseMsg, const char* pResponseVal,
|
||||||
const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType)
|
const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const
|
||||||
{
|
{
|
||||||
if (this->ShouldSend(responseType))
|
vector<char> vecMsg;
|
||||||
|
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
|
||||||
|
responseType, nMessageId, nMessageType))
|
||||||
{
|
{
|
||||||
this->Send(this->Serialize(responseMsg, responseVal, responseType, nMessageId, nMessageType));
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!SendToAll(vecMsg.data(), int(vecMsg.size())))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::SERVER, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: send serialized message to specific connected socket
|
// Purpose: encode and send message to specific socket
|
||||||
// Input : hSocket -
|
// Input : hSocket -
|
||||||
// *responseMsg -
|
// *pResponseMsg -
|
||||||
// *responseVal -
|
// *pResponseVal -
|
||||||
// responseType -
|
// responseType -
|
||||||
// nMessageId -
|
// nMessageId -
|
||||||
// nMessageType -
|
// nMessageType -
|
||||||
|
// Output: true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::Send(const SocketHandle_t hSocket, const std::string& responseMsg,
|
bool CRConServer::SendEncode(const SocketHandle_t hSocket, const char* pResponseMsg, const char* pResponseVal,
|
||||||
const std::string& responseVal, const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType)
|
const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const
|
||||||
{
|
{
|
||||||
if (this->ShouldSend(responseType))
|
vector<char> vecMsg;
|
||||||
|
if (!Serialize(vecMsg, pResponseMsg, pResponseVal,
|
||||||
|
responseType, nMessageId, nMessageType))
|
||||||
{
|
{
|
||||||
this->Send(hSocket, this->Serialize(responseMsg, responseVal, responseType, nMessageId, nMessageType));
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if (!Send(hSocket, vecMsg.data(), int(vecMsg.size())))
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: receive message
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConServer::Recv(void)
|
|
||||||
{
|
|
||||||
const int nCount = m_Socket.GetAcceptedSocketCount();
|
|
||||||
static char szRecvBuf[1024];
|
|
||||||
|
|
||||||
for (m_nConnIndex = nCount - 1; m_nConnIndex >= 0; m_nConnIndex--)
|
|
||||||
{
|
{
|
||||||
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
Error(eDLL_T::SERVER, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
{//////////////////////////////////////////////
|
return false;
|
||||||
if (this->CheckForBan(pData))
|
|
||||||
{
|
|
||||||
this->Send(pData->m_hSocket, this->Serialize(s_pszBannedMessage, "", sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON)));
|
|
||||||
this->CloseConnection();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
|
|
||||||
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (nPendingLen <= 0) // EOF or error.
|
|
||||||
{
|
|
||||||
this->CloseConnection();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}//////////////////////////////////////////////
|
|
||||||
|
|
||||||
u_long nReadLen; // Find out how much we have to read.
|
|
||||||
::ioctlsocket(pData->m_hSocket, FIONREAD, &nReadLen);
|
|
||||||
|
|
||||||
while (nReadLen > 0)
|
|
||||||
{
|
|
||||||
const int nRecvLen = ::recv(pData->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
|
|
||||||
if (nRecvLen == 0) // Socket was closed.
|
|
||||||
{
|
|
||||||
this->CloseConnection();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nRecvLen < 0 && !m_Socket.IsSocketBlocking())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::SERVER, NO_ERROR, "RCON Cmd: recv error (%s)\n", NET_ErrorString(WSAGetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nReadLen -= nRecvLen; // Process what we've got.
|
|
||||||
this->ProcessBuffer(szRecvBuf, nRecvLen, pData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -293,43 +281,27 @@ void CRConServer::Recv(void)
|
|||||||
// nMessageType -
|
// nMessageType -
|
||||||
// Output : serialized results as string
|
// Output : serialized results as string
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
std::string CRConServer::Serialize(const std::string& responseMsg, const std::string& responseVal,
|
bool CRConServer::Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal,
|
||||||
const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const
|
const sv_rcon::response_t responseType, const int nMessageId, const int nMessageType) const
|
||||||
{
|
{
|
||||||
sv_rcon::response sv_response;
|
sv_rcon::response response;
|
||||||
|
|
||||||
sv_response.set_messageid(nMessageId);
|
response.set_messageid(nMessageId);
|
||||||
sv_response.set_messagetype(nMessageType);
|
response.set_messagetype(nMessageType);
|
||||||
sv_response.set_responsetype(responseType);
|
response.set_responsetype(responseType);
|
||||||
|
response.set_responsemsg(pResponseMsg);
|
||||||
|
response.set_responseval(pResponseVal);
|
||||||
|
|
||||||
switch (responseType)
|
const size_t msgLen = response.ByteSizeLong();
|
||||||
|
vecBuf.resize(msgLen);
|
||||||
|
|
||||||
|
if (!Encode(&response, &vecBuf[0], msgLen))
|
||||||
{
|
{
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
|
Error(eDLL_T::SERVER, NO_ERROR, "Failed to encode RCON buffer\n");
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
|
return false;
|
||||||
{
|
|
||||||
sv_response.set_responsemsg(responseMsg);
|
|
||||||
sv_response.set_responseval(responseVal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return sv_response.SerializeAsString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
return true;
|
||||||
// Purpose: de-serializes input
|
|
||||||
// Input : *svBuf -
|
|
||||||
// Output : de-serialized object
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
cl_rcon::request CRConServer::Deserialize(const std::string& svBuf) const
|
|
||||||
{
|
|
||||||
cl_rcon::request cl_request;
|
|
||||||
cl_request.ParseFromArray(svBuf.data(), static_cast<int>(svBuf.size()));
|
|
||||||
|
|
||||||
return cl_request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -345,14 +317,17 @@ void CRConServer::Authenticate(const cl_rcon::request& cl_request, CConnectedNet
|
|||||||
}
|
}
|
||||||
else // Authorize.
|
else // Authorize.
|
||||||
{
|
{
|
||||||
if (this->Comparator(cl_request.requestmsg()))
|
if (Comparator(cl_request.requestmsg()))
|
||||||
{
|
{
|
||||||
pData->m_bAuthorized = true;
|
pData->m_bAuthorized = true;
|
||||||
m_Socket.CloseListenSocket();
|
if (++m_nAuthConnections >= sv_rcon_maxconnections->GetInt())
|
||||||
|
{
|
||||||
|
m_Socket.CloseListenSocket();
|
||||||
|
CloseNonAuthConnection();
|
||||||
|
}
|
||||||
|
|
||||||
this->CloseNonAuthConnection();
|
SendEncode(pData->m_hSocket, s_AuthMessage, sv_rcon_sendlogs->GetString(),
|
||||||
this->Send(pData->m_hSocket, this->Serialize(s_pszAuthMessage, sv_rcon_sendlogs->GetString(),
|
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||||
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON)));
|
|
||||||
}
|
}
|
||||||
else // Bad password.
|
else // Bad password.
|
||||||
{
|
{
|
||||||
@ -362,8 +337,8 @@ void CRConServer::Authenticate(const cl_rcon::request& cl_request, CConnectedNet
|
|||||||
DevMsg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
|
DevMsg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Send(pData->m_hSocket, this->Serialize(s_pszWrongPwMessage, "",
|
SendEncode(pData->m_hSocket, s_WrongPwMessage, "",
|
||||||
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON)));
|
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||||
|
|
||||||
pData->m_bAuthorized = false;
|
pData->m_bAuthorized = false;
|
||||||
pData->m_bValidated = false;
|
pData->m_bValidated = false;
|
||||||
@ -394,101 +369,46 @@ bool CRConServer::Comparator(std::string svPassword) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: parses input response buffer using length-prefix framing
|
|
||||||
// Input : *pRecvBuf -
|
|
||||||
// nRecvLen -
|
|
||||||
// *pData -
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CRConServer::ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData)
|
|
||||||
{
|
|
||||||
while (nRecvLen > 0)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadRead < pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
if (pData->m_nPayloadRead == pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
this->ProcessMessage(this->Deserialize(std::string(
|
|
||||||
reinterpret_cast<char*>(pData->m_RecvBuffer.data()), pData->m_nPayloadLen)));
|
|
||||||
|
|
||||||
pData->m_nPayloadLen = 0;
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pData->m_nPayloadRead+1 <= sizeof(int)) // Read size field.
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
else // Build prefix.
|
|
||||||
{
|
|
||||||
pData->m_nPayloadLen = int(ntohl(*reinterpret_cast<u_long*>(&pData->m_RecvBuffer[0])));
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
|
|
||||||
if (!pData->m_bAuthorized)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadLen > MAX_NETCONSOLE_INPUT_LEN)
|
|
||||||
{
|
|
||||||
this->CloseConnection(); // Sending large messages while not authenticated.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pData->m_nPayloadLen < 0 ||
|
|
||||||
pData->m_nPayloadLen > pData->m_RecvBuffer.max_size())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::SERVER, NO_ERROR, "RCON Cmd: sync error (%d)\n", pData->m_nPayloadLen);
|
|
||||||
this->CloseConnection(); // Out of sync (irrecoverable).
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: processes received message
|
// Purpose: processes received message
|
||||||
// Input : *cl_request -
|
// Input : *pMsgBuf -
|
||||||
|
// nMsgLen -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::ProcessMessage(const cl_rcon::request& cl_request)
|
bool CRConServer::ProcessMessage(const char* pMsgBuf, int nMsgLen)
|
||||||
{
|
{
|
||||||
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||||
|
|
||||||
if (!pData->m_bAuthorized
|
cl_rcon::request request;
|
||||||
&& cl_request.requesttype() != cl_rcon::request_t::SERVERDATA_REQUEST_AUTH)
|
if (!Decode(&request, pMsgBuf, nMsgLen))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::SERVER, NO_ERROR, "Failed to decode RCON buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pData->m_bAuthorized &&
|
||||||
|
request.requesttype() != cl_rcon::request_t::SERVERDATA_REQUEST_AUTH)
|
||||||
{
|
{
|
||||||
// Notify net console that authentication is required.
|
// Notify net console that authentication is required.
|
||||||
this->Send(pData->m_hSocket, this->Serialize(s_pszNoAuthMessage, "", sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON)));
|
SendEncode(pData->m_hSocket, s_NoAuthMessage, "",
|
||||||
|
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
|
||||||
|
|
||||||
pData->m_bValidated = false;
|
pData->m_bValidated = false;
|
||||||
pData->m_nIgnoredMessage++;
|
pData->m_nIgnoredMessage++;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
switch (cl_request.requesttype())
|
switch (request.requesttype())
|
||||||
{
|
{
|
||||||
case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH:
|
case cl_rcon::request_t::SERVERDATA_REQUEST_AUTH:
|
||||||
{
|
{
|
||||||
this->Authenticate(cl_request, pData);
|
Authenticate(request, pData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
|
case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
|
||||||
{
|
{
|
||||||
if (pData->m_bAuthorized) // Only execute if auth was successful.
|
if (pData->m_bAuthorized) // Only execute if auth was successful.
|
||||||
{
|
{
|
||||||
this->Execute(cl_request, false);
|
Execute(request, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -496,7 +416,7 @@ void CRConServer::ProcessMessage(const cl_rcon::request& cl_request)
|
|||||||
{
|
{
|
||||||
if (pData->m_bAuthorized)
|
if (pData->m_bAuthorized)
|
||||||
{
|
{
|
||||||
this->Execute(cl_request, true);
|
Execute(request, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -504,7 +424,7 @@ void CRConServer::ProcessMessage(const cl_rcon::request& cl_request)
|
|||||||
{
|
{
|
||||||
if (pData->m_bAuthorized)
|
if (pData->m_bAuthorized)
|
||||||
{
|
{
|
||||||
sv_rcon_sendlogs->SetValue(cl_request.requestval().c_str());
|
sv_rcon_sendlogs->SetValue(request.requestval().c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -513,6 +433,8 @@ void CRConServer::ProcessMessage(const cl_rcon::request& cl_request)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -555,8 +477,8 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData* pData)
|
|||||||
const char* pszWhiteListAddress = sv_rcon_whitelist_address->GetString();
|
const char* pszWhiteListAddress = sv_rcon_whitelist_address->GetString();
|
||||||
if (!pszWhiteListAddress[0])
|
if (!pszWhiteListAddress[0])
|
||||||
{
|
{
|
||||||
DevMsg(eDLL_T::SERVER, "Banned list overflowed; please use a whitelist address. RCON shutting down...\n");
|
Warning(eDLL_T::SERVER, "Banned list overflowed; please use a whitelist address. RCON shutting down...\n");
|
||||||
this->Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -586,24 +508,26 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData* pData)
|
|||||||
|| pData->m_nIgnoredMessage >= sv_rcon_maxignores->GetInt())
|
|| pData->m_nIgnoredMessage >= sv_rcon_maxignores->GetInt())
|
||||||
{
|
{
|
||||||
// Don't add white listed address to banned list.
|
// Don't add white listed address to banned list.
|
||||||
if (szNetAdr == sv_rcon_whitelist_address->GetString())
|
if (m_WhiteListAddress.CompareAdr(netAdr))
|
||||||
{
|
{
|
||||||
pData->m_nFailedAttempts = 0;
|
pData->m_nFailedAttempts = 0;
|
||||||
pData->m_nIgnoredMessage = 0;
|
pData->m_nIgnoredMessage = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DevMsg(eDLL_T::SERVER, "Banned '%s' for RCON hacking attempts\n", szNetAdr);
|
Warning(eDLL_T::SERVER, "Banned '%s' for RCON hacking attempts\n", szNetAdr);
|
||||||
m_BannedList.insert(szNetAdr);
|
m_BannedList.insert(szNetAdr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: close specific connection
|
// Purpose: close specific connection
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::CloseConnection(void) // NETMGR
|
void CRConServer::Disconnect(const char* /*szReason*/) // NETMGR
|
||||||
{
|
{
|
||||||
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(m_nConnIndex);
|
||||||
if (pData->m_bAuthorized)
|
if (pData->m_bAuthorized)
|
||||||
@ -611,7 +535,10 @@ void CRConServer::CloseConnection(void) // NETMGR
|
|||||||
// Inform server owner when authenticated connection has been closed.
|
// Inform server owner when authenticated connection has been closed.
|
||||||
netadr_t netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex);
|
netadr_t netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex);
|
||||||
DevMsg(eDLL_T::SERVER, "Net console '%s' closed RCON connection\n", netAdr.ToString());
|
DevMsg(eDLL_T::SERVER, "Net console '%s' closed RCON connection\n", netAdr.ToString());
|
||||||
|
|
||||||
|
m_nAuthConnections--;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Socket.CloseAcceptedSocket(m_nConnIndex);
|
m_Socket.CloseAcceptedSocket(m_nConnIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,11 +561,12 @@ void CRConServer::CloseNonAuthConnection(void)
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if this message should be send or not
|
// Purpose: checks if this message should be send or not
|
||||||
|
// Input : responseType -
|
||||||
// Output : true if it should send, false otherwise
|
// Output : true if it should send, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CRConServer::ShouldSend(const sv_rcon::response_t responseType) const
|
bool CRConServer::ShouldSend(const sv_rcon::response_t responseType) const
|
||||||
{
|
{
|
||||||
if (!this->IsInitialized() || !m_Socket.GetAcceptedSocketCount())
|
if (!IsInitialized() || !m_Socket.GetAcceptedSocketCount())
|
||||||
{
|
{
|
||||||
// Not initialized or no sockets...
|
// Not initialized or no sockets...
|
||||||
return false;
|
return false;
|
||||||
@ -657,8 +585,7 @@ bool CRConServer::ShouldSend(const sv_rcon::response_t responseType) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if server rcon is initialized
|
// Purpose: returns whether the rcon server is initialized
|
||||||
// Output : true if initialized, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CRConServer::IsInitialized(void) const
|
bool CRConServer::IsInitialized(void) const
|
||||||
{
|
{
|
||||||
|
@ -3,16 +3,12 @@
|
|||||||
#include "tier2/socketcreator.h"
|
#include "tier2/socketcreator.h"
|
||||||
#include "protoc/sv_rcon.pb.h"
|
#include "protoc/sv_rcon.pb.h"
|
||||||
#include "protoc/cl_rcon.pb.h"
|
#include "protoc/cl_rcon.pb.h"
|
||||||
|
#include "engine/shared/base_rcon.h"
|
||||||
constexpr char s_pszNoAuthMessage[] = "This server is password protected for console access; authenticate with 'PASS <password>' command.\n";
|
|
||||||
constexpr char s_pszWrongPwMessage[] = "Admin password incorrect.\n";
|
|
||||||
constexpr char s_pszBannedMessage[] = "Go away.\n";
|
|
||||||
constexpr char s_pszAuthMessage[] = "Authentication successful.\n";
|
|
||||||
|
|
||||||
#define RCON_MIN_PASSWORD_LEN 8
|
#define RCON_MIN_PASSWORD_LEN 8
|
||||||
#define RCON_MAX_BANNEDLIST_SIZE 512
|
#define RCON_MAX_BANNEDLIST_SIZE 512
|
||||||
|
|
||||||
class CRConServer
|
class CRConServer : public CNetConBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRConServer(void);
|
CRConServer(void);
|
||||||
@ -27,42 +23,37 @@ public:
|
|||||||
void Think(void);
|
void Think(void);
|
||||||
void RunFrame(void);
|
void RunFrame(void);
|
||||||
|
|
||||||
void Send(const std::string& responseMsg, const std::string& responseVal, const sv_rcon::response_t responseType,
|
bool SendEncode(const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType,
|
||||||
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET));
|
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET)) const;
|
||||||
void Send(const SocketHandle_t hSocket, const std::string& responseMsg, const std::string& responseVal,
|
bool SendEncode(const SocketHandle_t hSocket, const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType,
|
||||||
const sv_rcon::response_t responseType, const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET));
|
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET)) const;
|
||||||
void Recv(void);
|
|
||||||
|
bool SendToAll(const char* pMsgBuf, int nMsgLen) const;
|
||||||
std::string Serialize(const std::string& responseMsg, const std::string& responseVal, const sv_rcon::response_t responseType,
|
|
||||||
|
bool Serialize(vector<char>& vecBuf, const char* pResponseMsg, const char* pResponseVal, const sv_rcon::response_t responseType,
|
||||||
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET)) const;
|
const int nMessageId = static_cast<int>(eDLL_T::NETCON), const int nMessageType = static_cast<int>(LogType_t::LOG_NET)) const;
|
||||||
cl_rcon::request Deserialize(const std::string& svBuf) const;
|
|
||||||
|
|
||||||
void Authenticate(const cl_rcon::request& cl_request, CConnectedNetConsoleData* pData);
|
void Authenticate(const cl_rcon::request& cl_request, CConnectedNetConsoleData* pData);
|
||||||
bool Comparator(std::string svPassword) const;
|
bool Comparator(std::string svPassword) const;
|
||||||
|
|
||||||
void ProcessBuffer(const char* pszIn, int nRecvLen, CConnectedNetConsoleData* pData);
|
virtual bool ProcessMessage(const char* pMsgBug, int nMsgLen) override;
|
||||||
void ProcessMessage(const cl_rcon::request& cl_request);
|
|
||||||
|
|
||||||
void Execute(const cl_rcon::request& cl_request, const bool bConVar) const;
|
void Execute(const cl_rcon::request& cl_request, const bool bConVar) const;
|
||||||
bool CheckForBan(CConnectedNetConsoleData* pData);
|
bool CheckForBan(CConnectedNetConsoleData* pData);
|
||||||
|
|
||||||
void CloseConnection(void);
|
virtual void Disconnect(const char* szReason = nullptr) override;
|
||||||
void CloseNonAuthConnection(void);
|
void CloseNonAuthConnection(void);
|
||||||
|
|
||||||
bool ShouldSend(const sv_rcon::response_t responseType) const;
|
bool ShouldSend(const sv_rcon::response_t responseType) const;
|
||||||
bool IsInitialized(void) const;
|
bool IsInitialized(void) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Send(const std::string& svMessage) const;
|
|
||||||
void Send(const SocketHandle_t hSocket, const std::string& svMessage) const;
|
|
||||||
|
|
||||||
bool m_bInitialized;
|
|
||||||
int m_nConnIndex;
|
int m_nConnIndex;
|
||||||
|
int m_nAuthConnections;
|
||||||
|
bool m_bInitialized;
|
||||||
std::unordered_set<std::string> m_BannedList;
|
std::unordered_set<std::string> m_BannedList;
|
||||||
std::string m_svPasswordHash;
|
std::string m_svPasswordHash;
|
||||||
netadr_t m_Address;
|
|
||||||
netadr_t m_WhiteListAddress;
|
netadr_t m_WhiteListAddress;
|
||||||
CSocketCreator m_Socket;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CRConServer* RCONServer();
|
CRConServer* RCONServer();
|
||||||
|
180
r5dev/engine/shared/base_rcon.cpp
Normal file
180
r5dev/engine/shared/base_rcon.cpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
//===========================================================================//
|
||||||
|
//
|
||||||
|
// Purpose: Base rcon implementation.
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
#include "core/stdafx.h"
|
||||||
|
#include "base_rcon.h"
|
||||||
|
#include "engine/net.h"
|
||||||
|
#include "shared_rcon.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: encode message to buffer
|
||||||
|
// Input : *pMsg -
|
||||||
|
// *pMsgBuf -
|
||||||
|
// nMsgLen -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetConBase::Encode(google::protobuf::MessageLite* pMsg, char* pMsgBuf, size_t nMsgLen) const
|
||||||
|
{
|
||||||
|
return pMsg->SerializeToArray(pMsgBuf, int(nMsgLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: decode message from buffer
|
||||||
|
// Input : *pMsg -
|
||||||
|
// *pMsgBuf -
|
||||||
|
// nMsgLen -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetConBase::Decode(google::protobuf::MessageLite* pMsg, const char* pMsgBuf, size_t nMsgLen) const
|
||||||
|
{
|
||||||
|
return pMsg->ParseFromArray(pMsgBuf, int(nMsgLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: connect to remote
|
||||||
|
// Input : *pHostName -
|
||||||
|
// nPort -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetConBase::Connect(const char* pHostName, const int nPort)
|
||||||
|
{
|
||||||
|
if (CL_NetConConnect(this, pHostName, nPort))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: send message to specific connected socket
|
||||||
|
// Input : hSocket -
|
||||||
|
// *pMsgBuf -
|
||||||
|
// nMsgLen -
|
||||||
|
// Output: true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetConBase::Send(const SocketHandle_t hSocket, const char* pMsgBuf, int nMsgLen) const
|
||||||
|
{
|
||||||
|
std::ostringstream sendbuf;
|
||||||
|
const u_long nLen = htonl(u_long(nMsgLen));
|
||||||
|
|
||||||
|
sendbuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
||||||
|
sendbuf.write(pMsgBuf, nMsgLen);
|
||||||
|
|
||||||
|
int ret = ::send(hSocket, sendbuf.str().data(), int(sendbuf.str().size()), MSG_NOSIGNAL);
|
||||||
|
return (ret != SOCKET_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: receive message
|
||||||
|
// Input : *pData -
|
||||||
|
// nMaxLen -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CNetConBase::Recv(CConnectedNetConsoleData* pData, const int nMaxLen)
|
||||||
|
{
|
||||||
|
static char szRecvBuf[1024];
|
||||||
|
|
||||||
|
{//////////////////////////////////////////////
|
||||||
|
const int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
|
||||||
|
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nPendingLen <= 0) // EOF or error.
|
||||||
|
{
|
||||||
|
Disconnect("Server closed RCON connection\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}//////////////////////////////////////////////
|
||||||
|
|
||||||
|
int nReadLen = 0; // Find out how much we have to read.
|
||||||
|
::ioctlsocket(pData->m_hSocket, FIONREAD, reinterpret_cast<u_long*>(&nReadLen));
|
||||||
|
|
||||||
|
while (nReadLen > 0)
|
||||||
|
{
|
||||||
|
const int nRecvLen = ::recv(pData->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
|
||||||
|
if (nRecvLen == 0) // Socket was closed.
|
||||||
|
{
|
||||||
|
Disconnect("Server closed RCON connection\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nRecvLen < 0 && !m_Socket.IsSocketBlocking())
|
||||||
|
{
|
||||||
|
Error(eDLL_T::ENGINE, NO_ERROR, "RCON Cmd: recv error (%s)\n", NET_ErrorString(WSAGetLastError()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nReadLen -= nRecvLen; // Process what we've got.
|
||||||
|
ProcessBuffer(pData, szRecvBuf, nRecvLen, nMaxLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: parses input response buffer using length-prefix framing
|
||||||
|
// Input : *pRecvBuf -
|
||||||
|
// nRecvLen -
|
||||||
|
// *pData -
|
||||||
|
// Output: true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetConBase::ProcessBuffer(CConnectedNetConsoleData* pData, const char* pRecvBuf, int nRecvLen, int nMaxLen)
|
||||||
|
{
|
||||||
|
while (nRecvLen > 0)
|
||||||
|
{
|
||||||
|
if (pData->m_nPayloadLen)
|
||||||
|
{
|
||||||
|
if (pData->m_nPayloadRead < pData->m_nPayloadLen)
|
||||||
|
{
|
||||||
|
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
||||||
|
|
||||||
|
pRecvBuf++;
|
||||||
|
nRecvLen--;
|
||||||
|
}
|
||||||
|
if (pData->m_nPayloadRead == pData->m_nPayloadLen)
|
||||||
|
{
|
||||||
|
ProcessMessage(
|
||||||
|
reinterpret_cast<const char*>(pData->m_RecvBuffer.data()), pData->m_nPayloadLen);
|
||||||
|
|
||||||
|
pData->m_nPayloadLen = 0;
|
||||||
|
pData->m_nPayloadRead = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pData->m_nPayloadRead+1 <= sizeof(int)) // Read size field.
|
||||||
|
{
|
||||||
|
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
||||||
|
|
||||||
|
pRecvBuf++;
|
||||||
|
nRecvLen--;
|
||||||
|
}
|
||||||
|
else // Build prefix.
|
||||||
|
{
|
||||||
|
pData->m_nPayloadLen = int(ntohl(*reinterpret_cast<u_long*>(&pData->m_RecvBuffer[0])));
|
||||||
|
pData->m_nPayloadRead = 0;
|
||||||
|
|
||||||
|
if (!pData->m_bAuthorized && nMaxLen > -1)
|
||||||
|
{
|
||||||
|
if (pData->m_nPayloadLen > nMaxLen)
|
||||||
|
{
|
||||||
|
Disconnect(); // Sending large messages while not authenticated.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pData->m_nPayloadLen < 0 ||
|
||||||
|
pData->m_nPayloadLen > pData->m_RecvBuffer.max_size())
|
||||||
|
{
|
||||||
|
Error(eDLL_T::ENGINE, NO_ERROR, "RCON Cmd: sync error (%d)\n", pData->m_nPayloadLen);
|
||||||
|
Disconnect(); // Out of sync (irrecoverable).
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
34
r5dev/engine/shared/base_rcon.h
Normal file
34
r5dev/engine/shared/base_rcon.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef BASE_RCON_H
|
||||||
|
#define BASE_RCON_H
|
||||||
|
|
||||||
|
#include "tier1/NetAdr.h"
|
||||||
|
#include "tier2/socketcreator.h"
|
||||||
|
#include "protobuf/message_lite.h"
|
||||||
|
|
||||||
|
class CNetConBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CNetConBase(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual bool Encode(google::protobuf::MessageLite* pMsg, char* pMsgBuf, size_t nMsgLen) const;
|
||||||
|
virtual bool Decode(google::protobuf::MessageLite* pMsg, const char* pMsgBuf, size_t nMsgLen) const;
|
||||||
|
|
||||||
|
virtual bool Connect(const char* pHostAdr, const int nHostPort = -1);
|
||||||
|
virtual void Disconnect(const char* szReason = nullptr) { NOTE_UNUSED(szReason); };
|
||||||
|
|
||||||
|
virtual bool Send(const SocketHandle_t hSocket, const char* pMsgBuf, int nMsgLen) const;
|
||||||
|
virtual void Recv(CConnectedNetConsoleData* pData, const int nMaxLen = -1);
|
||||||
|
|
||||||
|
virtual bool ProcessBuffer(CConnectedNetConsoleData* pData, const char* pRecvBuf, int nRecvLen, int nMaxLen = -1);
|
||||||
|
virtual bool ProcessMessage(const char* /*pMsgBuf*/, int /*nMsgLen*/) { return true; };
|
||||||
|
|
||||||
|
CSocketCreator* GetSocketCreator(void) { return &m_Socket; }
|
||||||
|
netadr_t* GetNetAddress(void) { return &m_Address; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CSocketCreator m_Socket;
|
||||||
|
netadr_t m_Address;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASE_RCON_H
|
114
r5dev/engine/shared/shared_rcon.cpp
Normal file
114
r5dev/engine/shared/shared_rcon.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
//===========================================================================//
|
||||||
|
//
|
||||||
|
// Purpose: Shared rcon utilities.
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
#include "core/stdafx.h"
|
||||||
|
#include "base_rcon.h"
|
||||||
|
#include "shared_rcon.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: serialize message to vector
|
||||||
|
// Input : *pBase -
|
||||||
|
// &vecBuf -
|
||||||
|
// *szReqBuf -
|
||||||
|
// *szReqVal -
|
||||||
|
// *requestType -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CL_NetConSerialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* szReqBuf,
|
||||||
|
const char* szReqVal, const cl_rcon::request_t requestType)
|
||||||
|
{
|
||||||
|
cl_rcon::request request;
|
||||||
|
|
||||||
|
request.set_messageid(-1);
|
||||||
|
request.set_requesttype(requestType);
|
||||||
|
request.set_requestmsg(szReqBuf);
|
||||||
|
request.set_requestval(szReqVal);
|
||||||
|
|
||||||
|
const size_t msgLen = request.ByteSizeLong();
|
||||||
|
vecBuf.resize(msgLen);
|
||||||
|
|
||||||
|
if (!pBase->Encode(&request, &vecBuf[0], msgLen))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to encode RCON buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: attempt to connect to remote
|
||||||
|
// Input : *pBase -
|
||||||
|
// *pHostAdr -
|
||||||
|
// nHostPort -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CL_NetConConnect(CNetConBase* pBase, const char* pHostAdr, const int nHostPort)
|
||||||
|
{
|
||||||
|
string svLocalHost;
|
||||||
|
if (nHostPort != -1 && strcmp(pHostAdr, "localhost") == 0)
|
||||||
|
{
|
||||||
|
char szHostName[512];
|
||||||
|
if (!gethostname(szHostName, sizeof(szHostName)))
|
||||||
|
{
|
||||||
|
svLocalHost = Format("[%s]:%i", szHostName, nHostPort);
|
||||||
|
pHostAdr = svLocalHost.c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CNetAdr* pNetAdr = pBase->GetNetAddress();
|
||||||
|
if (!pNetAdr->SetFromString(pHostAdr, true))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to set RCON address: %s\n", pHostAdr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNetAdr->SetPort(htons(u_short(nHostPort)));
|
||||||
|
|
||||||
|
CSocketCreator* pCreator = pBase->GetSocketCreator();
|
||||||
|
if (pCreator->ConnectSocket(*pNetAdr, true) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevMsg(eDLL_T::CLIENT, "Connected to: %s\n", pNetAdr->ToString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: gets the netconsole data
|
||||||
|
// Input : *pBase -
|
||||||
|
// iSocket -
|
||||||
|
// Output : nullptr on failure
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
CConnectedNetConsoleData* SH_GetNetConData(CNetConBase* pBase, int iSocket)
|
||||||
|
{
|
||||||
|
const CSocketCreator* pCreator = pBase->GetSocketCreator();
|
||||||
|
Assert(iSocket >= 0 && iSocket < pCreator->GetAcceptedSocketCount());
|
||||||
|
|
||||||
|
if (!pCreator->GetAcceptedSocketCount())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pCreator->GetAcceptedSocketData(iSocket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: gets the netconsole socket
|
||||||
|
// Input : *pBase -
|
||||||
|
// iSocket -
|
||||||
|
// Output : SOCKET_ERROR (-1) on failure
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
SocketHandle_t SH_GetNetConSocketHandle(CNetConBase* pBase, int iSocket)
|
||||||
|
{
|
||||||
|
const CConnectedNetConsoleData* pData = SH_GetNetConData(pBase, iSocket);
|
||||||
|
if (!pData)
|
||||||
|
{
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pData->m_hSocket;
|
||||||
|
}
|
14
r5dev/engine/shared/shared_rcon.h
Normal file
14
r5dev/engine/shared/shared_rcon.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef SHARED_RCON_H
|
||||||
|
#define SHARED_RCON_H
|
||||||
|
#include "base_rcon.h"
|
||||||
|
#include "protoc/sv_rcon.pb.h"
|
||||||
|
#include "protoc/cl_rcon.pb.h"
|
||||||
|
|
||||||
|
bool CL_NetConSerialize(const CNetConBase* pBase, vector<char>& vecBuf, const char* szReqBuf,
|
||||||
|
const char* szReqVal, const cl_rcon::request_t requestType);
|
||||||
|
bool CL_NetConConnect(CNetConBase* pBase, const char* pHostAdr, const int nHostPort);
|
||||||
|
|
||||||
|
CConnectedNetConsoleData* SH_GetNetConData(CNetConBase* pBase, int iSocket);
|
||||||
|
SocketHandle_t SH_GetNetConSocketHandle(CNetConBase* pBase, int iSocket);
|
||||||
|
|
||||||
|
#endif // SHARED_RCON_H
|
@ -14,6 +14,7 @@
|
|||||||
#include "protoc/cl_rcon.pb.h"
|
#include "protoc/cl_rcon.pb.h"
|
||||||
#include "public/utility/utility.h"
|
#include "public/utility/utility.h"
|
||||||
#include "engine/net.h"
|
#include "engine/net.h"
|
||||||
|
#include "engine/shared/shared_rcon.h"
|
||||||
#include "netconsole/netconsole.h"
|
#include "netconsole/netconsole.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -23,7 +24,6 @@ CNetCon::CNetCon(void)
|
|||||||
: m_bInitialized(false)
|
: m_bInitialized(false)
|
||||||
, m_bQuitApplication(false)
|
, m_bQuitApplication(false)
|
||||||
, m_bPromptConnect(true)
|
, m_bPromptConnect(true)
|
||||||
, m_bConnEstablished(false)
|
|
||||||
, m_flTickInterval(0.05f)
|
, m_flTickInterval(0.05f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -46,18 +46,20 @@ bool CNetCon::Init(void)
|
|||||||
|
|
||||||
if (nError != 0)
|
if (nError != 0)
|
||||||
{
|
{
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "%s - Failed to start Winsock: (%s)\n", __FUNCTION__, NET_ErrorString(WSAGetLastError()));
|
Error(eDLL_T::CLIENT, NO_ERROR, "%s - Failed to start Winsock: (%s)\n", __FUNCTION__, NET_ErrorString(WSAGetLastError()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->TermSetup();
|
m_bInitialized = true;
|
||||||
|
|
||||||
|
TermSetup();
|
||||||
DevMsg(eDLL_T::NONE, "R5 TCP net console [Version %s]\n", NETCON_VERSION);
|
DevMsg(eDLL_T::NONE, "R5 TCP net console [Version %s]\n", NETCON_VERSION);
|
||||||
|
|
||||||
static std::thread frame([this]()
|
static std::thread frame([this]()
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
this->RunFrame();
|
RunFrame();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
frame.detach();
|
frame.detach();
|
||||||
@ -74,7 +76,6 @@ bool CNetCon::Shutdown(void)
|
|||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
|
|
||||||
m_Socket.CloseAllAcceptedSockets();
|
m_Socket.CloseAllAcceptedSockets();
|
||||||
m_bConnEstablished = false;
|
|
||||||
|
|
||||||
const int nError = ::WSACleanup();
|
const int nError = ::WSACleanup();
|
||||||
if (nError == 0)
|
if (nError == 0)
|
||||||
@ -83,7 +84,7 @@ bool CNetCon::Shutdown(void)
|
|||||||
}
|
}
|
||||||
else // WSACleanup() failed.
|
else // WSACleanup() failed.
|
||||||
{
|
{
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "%s - Failed to stop Winsock: (%s)\n", __FUNCTION__, NET_ErrorString(WSAGetLastError()));
|
Error(eDLL_T::CLIENT, NO_ERROR, "%s - Failed to stop Winsock: (%s)\n", __FUNCTION__, NET_ErrorString(WSAGetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpdLog_Shutdown();
|
SpdLog_Shutdown();
|
||||||
@ -118,40 +119,52 @@ void CNetCon::UserInput(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> l(m_Mutex);
|
std::lock_guard<std::mutex> l(m_Mutex);
|
||||||
if (m_bConnEstablished)
|
if (IsConnected())
|
||||||
{
|
{
|
||||||
if (m_Input.compare("disconnect") == 0)
|
if (m_Input.compare("disconnect") == 0)
|
||||||
{
|
{
|
||||||
this->Disconnect();
|
Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string> vSubStrings = StringSplit(m_Input, ' ', 2);
|
const std::vector<std::string> vSubStrings = StringSplit(m_Input, ' ', 2);
|
||||||
|
vector<char> vecMsg;
|
||||||
|
|
||||||
|
const SocketHandle_t hSocket = GetSocket();
|
||||||
|
bool bSend = false;
|
||||||
|
|
||||||
if (vSubStrings.size() > 1)
|
if (vSubStrings.size() > 1)
|
||||||
{
|
{
|
||||||
if (vSubStrings[0].compare("PASS") == 0) // Auth with RCON server.
|
if (vSubStrings[0].compare("PASS") == 0) // Auth with RCON server.
|
||||||
{
|
{
|
||||||
std::string svSerialized = this->Serialize(vSubStrings[1], "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
bSend = Serialize(vecMsg, vSubStrings[1].c_str(), "",
|
||||||
this->Send(svSerialized);
|
cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
||||||
}
|
}
|
||||||
else if (vSubStrings[0].compare("SET") == 0) // Set value query.
|
else if (vSubStrings[0].compare("SET") == 0) // Set value query.
|
||||||
{
|
{
|
||||||
if (vSubStrings.size() > 2)
|
if (vSubStrings.size() > 2)
|
||||||
{
|
{
|
||||||
std::string svSerialized = this->Serialize(vSubStrings[1], vSubStrings[2], cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE);
|
bSend = Serialize(vecMsg, vSubStrings[1].c_str(), vSubStrings[2].c_str(),
|
||||||
this->Send(svSerialized);
|
cl_rcon::request_t::SERVERDATA_REQUEST_SETVALUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Execute command query.
|
else // Execute command query.
|
||||||
{
|
{
|
||||||
std::string svSerialized = this->Serialize(m_Input, "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
bSend = Serialize(vecMsg, m_Input.c_str(), "",
|
||||||
this->Send(svSerialized);
|
cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!m_Input.empty()) // Single arg command query.
|
else if (!m_Input.empty()) // Single arg command query.
|
||||||
{
|
{
|
||||||
std::string svSerialized = this->Serialize(m_Input, "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
bSend = Serialize(vecMsg, m_Input.c_str(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
||||||
this->Send(svSerialized);
|
}
|
||||||
|
|
||||||
|
if (bSend) // Only send if serialization process was successful.
|
||||||
|
{
|
||||||
|
if (!Send(hSocket, vecMsg.data(), int(vecMsg.size())))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Setup connection from input.
|
else // Setup connection from input.
|
||||||
@ -167,7 +180,14 @@ void CNetCon::UserInput(void)
|
|||||||
std::string svInPort = m_Input.substr(nPos + 1);
|
std::string svInPort = m_Input.substr(nPos + 1);
|
||||||
std::string svInAdr = m_Input.erase(m_Input.find(' '));
|
std::string svInAdr = m_Input.erase(m_Input.find(' '));
|
||||||
|
|
||||||
if (!this->Connect(svInAdr, svInPort))
|
if (svInPort.empty() || svInAdr.empty())
|
||||||
|
{
|
||||||
|
Warning(eDLL_T::CLIENT, "No IP address or port provided\n");
|
||||||
|
m_bPromptConnect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Connect(svInAdr.c_str(), atoi(svInPort.c_str())))
|
||||||
{
|
{
|
||||||
m_bPromptConnect = true;
|
m_bPromptConnect = true;
|
||||||
return;
|
return;
|
||||||
@ -176,7 +196,7 @@ void CNetCon::UserInput(void)
|
|||||||
}
|
}
|
||||||
else // Initialize as [ip]:port.
|
else // Initialize as [ip]:port.
|
||||||
{
|
{
|
||||||
if (!this->Connect(m_Input, ""))
|
if (m_Input.empty() || !Connect(m_Input.c_str()))
|
||||||
{
|
{
|
||||||
m_bPromptConnect = true;
|
m_bPromptConnect = true;
|
||||||
return;
|
return;
|
||||||
@ -199,10 +219,12 @@ void CNetCon::ClearInput(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CNetCon::RunFrame(void)
|
void CNetCon::RunFrame(void)
|
||||||
{
|
{
|
||||||
if (m_bConnEstablished)
|
if (IsInitialized() && IsConnected())
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_Mutex);
|
std::lock_guard<std::mutex> l(m_Mutex);
|
||||||
this->Recv();
|
|
||||||
|
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(0);
|
||||||
|
Recv(pData);
|
||||||
}
|
}
|
||||||
else if (m_bPromptConnect)
|
else if (m_bPromptConnect)
|
||||||
{
|
{
|
||||||
@ -219,219 +241,69 @@ void CNetCon::RunFrame(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CNetCon::ShouldQuit(void) const
|
bool CNetCon::ShouldQuit(void) const
|
||||||
{
|
{
|
||||||
return this->m_bQuitApplication;
|
return m_bQuitApplication;
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: connect to specified address and port
|
|
||||||
// Input : *svInAdr -
|
|
||||||
// *svInPort -
|
|
||||||
// Output : true if connection succeeds, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
bool CNetCon::Connect(const std::string& svInAdr, const std::string& svInPort)
|
|
||||||
{
|
|
||||||
if (!svInAdr.empty() && !svInPort.empty()) // Construct from ip port
|
|
||||||
{
|
|
||||||
string svLocalHost;
|
|
||||||
if (svInAdr.compare("localhost") == 0)
|
|
||||||
{
|
|
||||||
char szHostName[512];
|
|
||||||
if (!gethostname(szHostName, sizeof(szHostName)))
|
|
||||||
{
|
|
||||||
svLocalHost = szHostName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const string svFull = Format("[%s]:%s", svLocalHost.empty() ? svInAdr.c_str() : svLocalHost.c_str(), svInPort.c_str());
|
|
||||||
if (!m_Address.SetFromString(svFull.c_str(), true))
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::NONE, "Failed to set RCON address: %s\n", svFull.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!svInAdr.empty()) // construct from [ip]:port
|
|
||||||
{
|
|
||||||
if (!m_Address.SetFromString(svInAdr.c_str(), true))
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::NONE, "Failed to set RCON address: %s\n", svInAdr.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::NONE, "No IP address provided\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Socket.ConnectSocket(m_Address, true) == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "Failed to connect: error(%s); verify IP and PORT\n", "SOCKET_ERROR");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DevMsg(eDLL_T::NONE, "Connected to: %s\n", m_Address.ToString());
|
|
||||||
|
|
||||||
m_bConnEstablished = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: disconnect from current session
|
// Purpose: disconnect from current session
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CNetCon::Disconnect(void)
|
void CNetCon::Disconnect(const char* szReason)
|
||||||
{
|
{
|
||||||
m_Socket.CloseAcceptedSocket(0);
|
if (IsConnected())
|
||||||
|
{
|
||||||
|
if (szReason)
|
||||||
|
{
|
||||||
|
DevMsg(eDLL_T::CLIENT, "%s", szReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Socket.CloseAcceptedSocket(0);
|
||||||
|
}
|
||||||
|
|
||||||
m_bPromptConnect = true;
|
m_bPromptConnect = true;
|
||||||
m_bConnEstablished = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: send message
|
|
||||||
// Input : *svMessage -
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CNetCon::Send(const std::string& svMessage) const
|
|
||||||
{
|
|
||||||
std::ostringstream ssSendBuf;
|
|
||||||
const u_long nLen = htonl(u_long(svMessage.size()));
|
|
||||||
|
|
||||||
ssSendBuf.write(reinterpret_cast<const char*>(&nLen), sizeof(u_long));
|
|
||||||
ssSendBuf.write(svMessage.data(), svMessage.size());
|
|
||||||
|
|
||||||
const int nSendResult = ::send(m_Socket.GetAcceptedSocketData(0)->m_hSocket,
|
|
||||||
ssSendBuf.str().data(), static_cast<int>(ssSendBuf.str().size()), MSG_NOSIGNAL);
|
|
||||||
if (nSendResult == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "Failed to send message (%s)\n", "SOCKET_ERROR");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: receive message
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CNetCon::Recv(void)
|
|
||||||
{
|
|
||||||
static char szRecvBuf[1024];
|
|
||||||
CConnectedNetConsoleData* pData = m_Socket.GetAcceptedSocketData(0);
|
|
||||||
|
|
||||||
{//////////////////////////////////////////////
|
|
||||||
const int nPendingLen = ::recv(pData->m_hSocket, szRecvBuf, sizeof(char), MSG_PEEK);
|
|
||||||
if (nPendingLen == SOCKET_ERROR && m_Socket.IsSocketBlocking())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nPendingLen <= 0 && m_bConnEstablished) // EOF or error.
|
|
||||||
{
|
|
||||||
this->Disconnect();
|
|
||||||
DevMsg(eDLL_T::NONE, "Server closed connection\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}//////////////////////////////////////////////
|
|
||||||
|
|
||||||
u_long nReadLen; // Find out how much we have to read.
|
|
||||||
::ioctlsocket(pData->m_hSocket, FIONREAD, &nReadLen);
|
|
||||||
|
|
||||||
while (nReadLen > 0)
|
|
||||||
{
|
|
||||||
const int nRecvLen = ::recv(pData->m_hSocket, szRecvBuf, MIN(sizeof(szRecvBuf), nReadLen), MSG_NOSIGNAL);
|
|
||||||
if (nRecvLen == 0 && m_bConnEstablished) // Socket was closed.
|
|
||||||
{
|
|
||||||
this->Disconnect();
|
|
||||||
DevMsg(eDLL_T::NONE, "Server closed connection\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nRecvLen < 0 && !m_Socket.IsSocketBlocking())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "RCON Cmd: recv error (%s)\n", NET_ErrorString(WSAGetLastError()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nReadLen -= nRecvLen; // Process what we've got.
|
|
||||||
this->ProcessBuffer(szRecvBuf, nRecvLen, pData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: parses input response buffer using length-prefix framing
|
|
||||||
// Input : *pRecvBuf -
|
|
||||||
// nRecvLen -
|
|
||||||
// *pData -
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CNetCon::ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData)
|
|
||||||
{
|
|
||||||
while (nRecvLen > 0)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
if (pData->m_nPayloadRead < pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
if (pData->m_nPayloadRead == pData->m_nPayloadLen)
|
|
||||||
{
|
|
||||||
this->ProcessMessage(this->Deserialize(std::string(
|
|
||||||
reinterpret_cast<char*>(pData->m_RecvBuffer.data()), pData->m_nPayloadLen)));
|
|
||||||
|
|
||||||
pData->m_nPayloadLen = 0;
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pData->m_nPayloadRead < sizeof(int)) // Read size field.
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer[pData->m_nPayloadRead++] = *pRecvBuf;
|
|
||||||
|
|
||||||
pRecvBuf++;
|
|
||||||
nRecvLen--;
|
|
||||||
}
|
|
||||||
else // Build prefix.
|
|
||||||
{
|
|
||||||
pData->m_nPayloadLen = ntohl(*reinterpret_cast<u_long*>(&pData->m_RecvBuffer[0]));
|
|
||||||
pData->m_nPayloadRead = 0;
|
|
||||||
|
|
||||||
if (pData->m_nPayloadLen < 0 ||
|
|
||||||
pData->m_nPayloadLen > pData->m_RecvBuffer.max_size())
|
|
||||||
{
|
|
||||||
Error(eDLL_T::NONE, NO_ERROR, "RCON Cmd: sync error (%zu)\n", pData->m_nPayloadLen);
|
|
||||||
this->Disconnect(); // Out of sync (irrecoverable).
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pData->m_RecvBuffer.resize(pData->m_nPayloadLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: processes received message
|
// Purpose: processes received message
|
||||||
// Input : *sv_response -
|
// Input : *sv_response -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CNetCon::ProcessMessage(const sv_rcon::response& sv_response) const
|
bool CNetCon::ProcessMessage(const char* pMsgBuf, int nMsgLen)
|
||||||
{
|
{
|
||||||
switch (sv_response.responsetype())
|
sv_rcon::response response;
|
||||||
|
bool bSuccess = Decode(&response, pMsgBuf, nMsgLen);
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to decode RCON buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (response.responsetype())
|
||||||
{
|
{
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
|
case sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH:
|
||||||
{
|
{
|
||||||
if (!sv_response.responseval().empty())
|
if (!response.responseval().empty())
|
||||||
{
|
{
|
||||||
const long i = strtol(sv_response.responseval().c_str(), NULL, NULL);
|
const long i = strtol(response.responseval().c_str(), NULL, NULL);
|
||||||
if (!i) // sv_rcon_sendlogs is not set.
|
if (!i) // sv_rcon_sendlogs is not set.
|
||||||
{
|
{
|
||||||
string svLogQuery = this->Serialize("", "1",
|
vector<char> vecMsg;
|
||||||
cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
bool ret = Serialize(vecMsg, "", "1", cl_rcon::request_t::SERVERDATA_REQUEST_SEND_CONSOLE_LOG);
|
||||||
this->Send(svLogQuery);
|
|
||||||
|
if (ret && !Send(GetSocket(), vecMsg.data(), int(vecMsg.size())))
|
||||||
|
{
|
||||||
|
Error(eDLL_T::CLIENT, NO_ERROR, "Failed to send RCON message: (%s)\n", "SOCKET_ERROR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DevMsg(eDLL_T::NETCON, "%s", sv_response.responsemsg().c_str());
|
DevMsg(eDLL_T::NETCON, "%s", response.responsemsg().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
|
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
|
||||||
{
|
{
|
||||||
NetMsg(static_cast<LogType_t>(sv_response.messagetype()),
|
NetMsg(static_cast<LogType_t>(response.messagetype()),
|
||||||
static_cast<eDLL_T>(sv_response.messageid()),
|
static_cast<eDLL_T>(response.messageid()),
|
||||||
sv_response.responseval().c_str(), "%s", sv_response.responsemsg().c_str());
|
response.responseval().c_str(), "%s", response.responsemsg().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -439,51 +311,47 @@ void CNetCon::ProcessMessage(const sv_rcon::response& sv_response) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: serializes input
|
// Purpose: serializes message to vector
|
||||||
// Input : *svReqBuf -
|
// Input : &vecBuf -
|
||||||
|
// *szReqBuf -
|
||||||
// *svReqVal -
|
// *svReqVal -
|
||||||
// request_t -
|
// requestType -
|
||||||
// Output : serialized results as string
|
// Output : true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
std::string CNetCon::Serialize(const std::string& svReqBuf, const std::string& svReqVal, const cl_rcon::request_t request_t) const
|
bool CNetCon::Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||||
|
const char* szReqVal, const cl_rcon::request_t requestType) const
|
||||||
{
|
{
|
||||||
cl_rcon::request cl_request;
|
return CL_NetConSerialize(this, vecBuf, szReqBuf, szReqVal, requestType);
|
||||||
|
|
||||||
cl_request.set_messageid(-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_requestmsg(svReqBuf);
|
|
||||||
cl_request.set_requestval(svReqVal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND:
|
|
||||||
{
|
|
||||||
cl_request.set_requestmsg(svReqBuf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cl_request.SerializeAsString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: de-serializes input
|
// Purpose: retrieves the remote socket
|
||||||
// Input : *svBuf -
|
// Output : SOCKET_ERROR (-1) on failure
|
||||||
// Output : de-serialized object
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
sv_rcon::response CNetCon::Deserialize(const std::string& svBuf) const
|
SocketHandle_t CNetCon::GetSocket(void)
|
||||||
{
|
{
|
||||||
sv_rcon::response sv_response;
|
return SH_GetNetConSocketHandle(this, 0);
|
||||||
sv_response.ParseFromArray(svBuf.data(), static_cast<int>(svBuf.size()));
|
}
|
||||||
|
|
||||||
return sv_response;
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: returns whether the rcon client is initialized
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetCon::IsInitialized(void) const
|
||||||
|
{
|
||||||
|
return m_bInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: returns whether the rcon client is connected
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CNetCon::IsConnected(void)
|
||||||
|
{
|
||||||
|
return (GetSocket() != SOCKET_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -500,7 +368,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (argc >= 3) // Get IP and Port from command line.
|
if (argc >= 3) // Get IP and Port from command line.
|
||||||
{
|
{
|
||||||
if (!NetConsole()->Connect(argv[1], argv[2]))
|
if (!NetConsole()->Connect(argv[1], atoi(argv[2])))
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "protoc/cl_rcon.pb.h"
|
#include "protoc/cl_rcon.pb.h"
|
||||||
#include "protoc/sv_rcon.pb.h"
|
#include "protoc/sv_rcon.pb.h"
|
||||||
|
#include "engine/shared/base_rcon.h"
|
||||||
|
|
||||||
constexpr const char* NETCON_VERSION = "2.0.0.1";
|
constexpr const char* NETCON_VERSION = "2.0.0.1";
|
||||||
|
|
||||||
class CNetCon
|
class CNetCon : public CNetConBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CNetCon(void);
|
CNetCon(void);
|
||||||
@ -25,29 +26,23 @@ public:
|
|||||||
void RunFrame(void);
|
void RunFrame(void);
|
||||||
bool ShouldQuit(void) const;
|
bool ShouldQuit(void) const;
|
||||||
|
|
||||||
bool Connect(const std::string& svInAdr, const std::string& svInPort);
|
virtual void Disconnect(const char* szReason = nullptr);
|
||||||
void Disconnect(void);
|
virtual bool ProcessMessage(const char* pMsgBuf, int nMsgLen) override;
|
||||||
|
|
||||||
void Send(const std::string& svMessage) const;
|
bool Serialize(vector<char>& vecBuf, const char* szReqBuf,
|
||||||
void Recv(void);
|
const char* szReqVal, const cl_rcon::request_t requestType) const;
|
||||||
|
|
||||||
void ProcessBuffer(const char* pRecvBuf, int nRecvLen, CConnectedNetConsoleData* pData);
|
SocketHandle_t GetSocket(void);
|
||||||
void ProcessMessage(const sv_rcon::response& sv_response) const;
|
bool IsInitialized(void) const;
|
||||||
|
bool IsConnected(void);
|
||||||
std::string Serialize(const std::string& svReqBuf, const std::string& svReqVal, const cl_rcon::request_t request_t) const;
|
|
||||||
sv_rcon::response Deserialize(const std::string& svBuf) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_bInitialized;
|
bool m_bInitialized;
|
||||||
bool m_bQuitApplication;
|
bool m_bQuitApplication;
|
||||||
bool m_bPromptConnect;
|
bool m_bPromptConnect;
|
||||||
bool m_bConnEstablished;
|
|
||||||
float m_flTickInterval;
|
float m_flTickInterval;
|
||||||
|
|
||||||
CNetAdr m_Address;
|
|
||||||
CSocketCreator m_Socket;
|
|
||||||
std::string m_Input;
|
std::string m_Input;
|
||||||
|
|
||||||
mutable std::mutex m_Mutex;
|
mutable std::mutex m_Mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,6 +113,8 @@ extern ConVar* sv_rcon_banpenalty;
|
|||||||
extern ConVar* sv_rcon_maxfailures;
|
extern ConVar* sv_rcon_maxfailures;
|
||||||
extern ConVar* sv_rcon_maxignores;
|
extern ConVar* sv_rcon_maxignores;
|
||||||
extern ConVar* sv_rcon_maxsockets;
|
extern ConVar* sv_rcon_maxsockets;
|
||||||
|
extern ConVar* sv_rcon_maxconnections;
|
||||||
|
extern ConVar* sv_rcon_maxpacketsize;
|
||||||
extern ConVar* sv_rcon_whitelist_address;
|
extern ConVar* sv_rcon_whitelist_address;
|
||||||
//#endif // DEDICATED
|
//#endif // DEDICATED
|
||||||
#endif // CLIENT_DLL
|
#endif // CLIENT_DLL
|
||||||
|
@ -14,13 +14,13 @@ public:
|
|||||||
void RunFrame(void);
|
void RunFrame(void);
|
||||||
void ProcessAccept(void);
|
void ProcessAccept(void);
|
||||||
|
|
||||||
bool ConfigureSocket(SocketHandle_t hSocket, bool bDualStack = true);
|
|
||||||
bool CreateListenSocket(const netadr_t& netAdr, bool bDualStack = true);
|
bool CreateListenSocket(const netadr_t& netAdr, bool bDualStack = true);
|
||||||
void CloseListenSocket(void);
|
void CloseListenSocket(void);
|
||||||
|
|
||||||
int ConnectSocket(const netadr_t& netAdr, bool bSingleSocket);
|
int ConnectSocket(const netadr_t& netAdr, bool bSingleSocket);
|
||||||
void DisconnectSocket(void);
|
void DisconnectSocket(void);
|
||||||
|
|
||||||
|
bool ConfigureSocket(SocketHandle_t hSocket, bool bDualStack = true);
|
||||||
int OnSocketAccepted(SocketHandle_t hSocket, const netadr_t& netAdr);
|
int OnSocketAccepted(SocketHandle_t hSocket, const netadr_t& netAdr);
|
||||||
|
|
||||||
void CloseAcceptedSocket(int nIndex);
|
void CloseAcceptedSocket(int nIndex);
|
||||||
|
@ -257,6 +257,8 @@ void CoreMsgV(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
|
|||||||
bool bSquirrel = false;
|
bool bSquirrel = false;
|
||||||
bool bWarning = false;
|
bool bWarning = false;
|
||||||
bool bError = false;
|
bool bError = false;
|
||||||
|
#else
|
||||||
|
NOTE_UNUSED(pszLogger);
|
||||||
#endif // !NETCONSOLE
|
#endif // !NETCONSOLE
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -376,10 +378,10 @@ void CoreMsgV(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
|
|||||||
if (bToConsole)
|
if (bToConsole)
|
||||||
{
|
{
|
||||||
#ifndef CLIENT_DLL
|
#ifndef CLIENT_DLL
|
||||||
if (!LoggedFromClient(context))
|
if (!LoggedFromClient(context) && RCONServer()->ShouldSend(sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG))
|
||||||
{
|
{
|
||||||
RCONServer()->Send(formatted, pszUpTime, sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG,
|
RCONServer()->SendEncode(formatted.c_str(), pszUpTime, sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG,
|
||||||
static_cast<int>(context), static_cast<int>(logType));
|
int(context), int(logType));
|
||||||
}
|
}
|
||||||
#endif // !CLIENT_DLL
|
#endif // !CLIENT_DLL
|
||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
|
@ -108,6 +108,8 @@ ConVar* sv_rcon_banpenalty = nullptr; // TODO
|
|||||||
ConVar* sv_rcon_maxfailures = nullptr;
|
ConVar* sv_rcon_maxfailures = nullptr;
|
||||||
ConVar* sv_rcon_maxignores = nullptr;
|
ConVar* sv_rcon_maxignores = nullptr;
|
||||||
ConVar* sv_rcon_maxsockets = nullptr;
|
ConVar* sv_rcon_maxsockets = nullptr;
|
||||||
|
ConVar* sv_rcon_maxconnections = nullptr;
|
||||||
|
ConVar* sv_rcon_maxpacketsize = nullptr;
|
||||||
ConVar* sv_rcon_whitelist_address = nullptr;
|
ConVar* sv_rcon_whitelist_address = nullptr;
|
||||||
//#endif // DEDICATED
|
//#endif // DEDICATED
|
||||||
#endif // !CLIENT_DLL
|
#endif // !CLIENT_DLL
|
||||||
@ -348,7 +350,9 @@ 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_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_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_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_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'");
|
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_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'");
|
||||||
|
|
||||||
sv_quota_stringCmdsPerSecond = ConVar::StaticCreate("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands.", true, 0.f, false, 0.f, nullptr, nullptr);
|
sv_quota_stringCmdsPerSecond = ConVar::StaticCreate("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands.", true, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
sv_validatePersonaName = ConVar::StaticCreate("sv_validatePersonaName" , "1" , FCVAR_RELEASE, "Validate the client's textual persona name on connect.", true, 0.f, false, 0.f, nullptr, nullptr);
|
sv_validatePersonaName = ConVar::StaticCreate("sv_validatePersonaName" , "1" , FCVAR_RELEASE, "Validate the client's textual persona name on connect.", true, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CSocketCreator::CSocketCreator(void)
|
CSocketCreator::CSocketCreator(void)
|
||||||
{
|
{
|
||||||
m_hListenSocket = -1;
|
m_hListenSocket = SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -68,56 +68,6 @@ void CSocketCreator::ProcessAccept(void)
|
|||||||
OnSocketAccepted(newSocket, netAdr);
|
OnSocketAccepted(newSocket, netAdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Configures a socket for use
|
|
||||||
// Input : iSocket -
|
|
||||||
// bDualStack -
|
|
||||||
// Output : true on success, false otherwise
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
bool CSocketCreator::ConfigureSocket(SocketHandle_t hSocket, bool bDualStack /*= true*/)
|
|
||||||
{
|
|
||||||
// Disable NAGLE as RCON cmds are small in size.
|
|
||||||
int opt = 1;
|
|
||||||
int ret = ::setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&opt), sizeof(opt));
|
|
||||||
if (ret == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "TCP_NODELAY", NET_ErrorString(WSAGetLastError()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark socket as reusable.
|
|
||||||
opt = 1;
|
|
||||||
ret = ::setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt));
|
|
||||||
if (ret == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "SO_REUSEADDR", NET_ErrorString(WSAGetLastError()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bDualStack)
|
|
||||||
{
|
|
||||||
// Disable IPv6 only mode to enable dual stack.
|
|
||||||
opt = 0;
|
|
||||||
ret = ::setsockopt(hSocket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char*>(&opt), sizeof(opt));
|
|
||||||
if (ret == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "IPV6_V6ONLY", NET_ErrorString(WSAGetLastError()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark socket as non-blocking.
|
|
||||||
opt = 1;
|
|
||||||
ret = ::ioctlsocket(hSocket, FIONBIO, reinterpret_cast<u_long*>(&opt));
|
|
||||||
if (ret == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
Warning(eDLL_T::ENGINE, "Socket 'ioctl(%s)' failed (%s)\n", "FIONBIO", NET_ErrorString(WSAGetLastError()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: bind to a TCP port and accept incoming connections
|
// Purpose: bind to a TCP port and accept incoming connections
|
||||||
// Input : *netAdr -
|
// Input : *netAdr -
|
||||||
@ -245,6 +195,56 @@ void CSocketCreator::DisconnectSocket(void)
|
|||||||
CloseAllAcceptedSockets();
|
CloseAllAcceptedSockets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Configures a socket for use
|
||||||
|
// Input : iSocket -
|
||||||
|
// bDualStack -
|
||||||
|
// Output : true on success, false otherwise
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CSocketCreator::ConfigureSocket(SocketHandle_t hSocket, bool bDualStack /*= true*/)
|
||||||
|
{
|
||||||
|
// Disable NAGLE as RCON cmds are small in size.
|
||||||
|
int opt = 1;
|
||||||
|
int ret = ::setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&opt), sizeof(opt));
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "TCP_NODELAY", NET_ErrorString(WSAGetLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark socket as reusable.
|
||||||
|
opt = 1;
|
||||||
|
ret = ::setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt));
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "SO_REUSEADDR", NET_ErrorString(WSAGetLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bDualStack)
|
||||||
|
{
|
||||||
|
// Disable IPv6 only mode to enable dual stack.
|
||||||
|
opt = 0;
|
||||||
|
ret = ::setsockopt(hSocket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char*>(&opt), sizeof(opt));
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "IPV6_V6ONLY", NET_ErrorString(WSAGetLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark socket as non-blocking.
|
||||||
|
opt = 1;
|
||||||
|
ret = ::ioctlsocket(hSocket, FIONBIO, reinterpret_cast<u_long*>(&opt));
|
||||||
|
if (ret == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Warning(eDLL_T::ENGINE, "Socket 'ioctl(%s)' failed (%s)\n", "FIONBIO", NET_ErrorString(WSAGetLastError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: handles new TCP requests and puts them in accepted queue
|
// Purpose: handles new TCP requests and puts them in accepted queue
|
||||||
// Input : hSocket -
|
// Input : hSocket -
|
||||||
@ -305,7 +305,7 @@ void CSocketCreator::CloseAllAcceptedSockets(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CSocketCreator::IsListening(void) const
|
bool CSocketCreator::IsListening(void) const
|
||||||
{
|
{
|
||||||
return m_hListenSocket != -1;
|
return m_hListenSocket != SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
<ClCompile Include="..\engine\networkstringtable.cpp" />
|
<ClCompile Include="..\engine\networkstringtable.cpp" />
|
||||||
<ClCompile Include="..\engine\net_chan.cpp" />
|
<ClCompile Include="..\engine\net_chan.cpp" />
|
||||||
<ClCompile Include="..\engine\sdk_dll.cpp" />
|
<ClCompile Include="..\engine\sdk_dll.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp" />
|
||||||
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll.cpp" />
|
<ClCompile Include="..\engine\sys_dll.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
||||||
@ -232,6 +234,8 @@
|
|||||||
<ClInclude Include="..\engine\net_chan.h" />
|
<ClInclude Include="..\engine\net_chan.h" />
|
||||||
<ClInclude Include="..\engine\packed_entity.h" />
|
<ClInclude Include="..\engine\packed_entity.h" />
|
||||||
<ClInclude Include="..\engine\sdk_dll.h" />
|
<ClInclude Include="..\engine\sdk_dll.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h" />
|
||||||
<ClInclude Include="..\engine\staticpropmgr.h" />
|
<ClInclude Include="..\engine\staticpropmgr.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll.h" />
|
<ClInclude Include="..\engine\sys_dll.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll2.h" />
|
<ClInclude Include="..\engine\sys_dll2.h" />
|
||||||
|
@ -229,6 +229,9 @@
|
|||||||
<Filter Include="sdk\public\tier2">
|
<Filter Include="sdk\public\tier2">
|
||||||
<UniqueIdentifier>{3a764173-162a-449c-952b-2db659cbad95}</UniqueIdentifier>
|
<UniqueIdentifier>{3a764173-162a-449c-952b-2db659cbad95}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="sdk\engine\shared">
|
||||||
|
<UniqueIdentifier>{bef90121-4004-47a7-b338-a41ca8078c12}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\client\cdll_engine_int.cpp">
|
<ClCompile Include="..\client\cdll_engine_int.cpp">
|
||||||
@ -675,6 +678,12 @@
|
|||||||
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\client\cdll_engine_int.h">
|
<ClInclude Include="..\client\cdll_engine_int.h">
|
||||||
@ -1724,6 +1733,12 @@
|
|||||||
<ClInclude Include="..\engine\staticpropmgr.h">
|
<ClInclude Include="..\engine\staticpropmgr.h">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="..\shared\resource\lockedserver.png">
|
<Image Include="..\shared\resource\lockedserver.png">
|
||||||
|
@ -237,6 +237,8 @@
|
|||||||
<ClInclude Include="..\engine\server\sv_main.h" />
|
<ClInclude Include="..\engine\server\sv_main.h" />
|
||||||
<ClInclude Include="..\engine\server\sv_rcon.h" />
|
<ClInclude Include="..\engine\server\sv_rcon.h" />
|
||||||
<ClInclude Include="..\engine\staticpropmgr.h" />
|
<ClInclude Include="..\engine\staticpropmgr.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll.h" />
|
<ClInclude Include="..\engine\sys_dll.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll2.h" />
|
<ClInclude Include="..\engine\sys_dll2.h" />
|
||||||
<ClInclude Include="..\engine\sys_engine.h" />
|
<ClInclude Include="..\engine\sys_engine.h" />
|
||||||
@ -548,6 +550,8 @@
|
|||||||
<ClCompile Include="..\engine\server\sv_main.cpp" />
|
<ClCompile Include="..\engine\server\sv_main.cpp" />
|
||||||
<ClCompile Include="..\engine\server\sv_rcon.cpp" />
|
<ClCompile Include="..\engine\server\sv_rcon.cpp" />
|
||||||
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll.cpp" />
|
<ClCompile Include="..\engine\sys_dll.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_engine.cpp" />
|
<ClCompile Include="..\engine\sys_engine.cpp" />
|
||||||
|
@ -178,6 +178,9 @@
|
|||||||
<Filter Include="sdk\public\tier2">
|
<Filter Include="sdk\public\tier2">
|
||||||
<UniqueIdentifier>{f6e7b39b-4032-4a7a-8a44-3aabcbe46ba5}</UniqueIdentifier>
|
<UniqueIdentifier>{f6e7b39b-4032-4a7a-8a44-3aabcbe46ba5}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="sdk\engine\shared">
|
||||||
|
<UniqueIdentifier>{4bccf09c-4f8b-4d7e-ab72-54fd8c1fb5cf}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\common\opcodes.h">
|
<ClInclude Include="..\common\opcodes.h">
|
||||||
@ -1134,6 +1137,12 @@
|
|||||||
<ClInclude Include="..\engine\staticpropmgr.h">
|
<ClInclude Include="..\engine\staticpropmgr.h">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\common\opcodes.cpp">
|
<ClCompile Include="..\common\opcodes.cpp">
|
||||||
@ -1526,6 +1535,12 @@
|
|||||||
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\Dedicated.def" />
|
<None Include="..\Dedicated.def" />
|
||||||
|
@ -59,6 +59,8 @@
|
|||||||
<ClCompile Include="..\engine\server\sv_main.cpp" />
|
<ClCompile Include="..\engine\server\sv_main.cpp" />
|
||||||
<ClCompile Include="..\engine\server\sv_rcon.cpp" />
|
<ClCompile Include="..\engine\server\sv_rcon.cpp" />
|
||||||
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
<ClCompile Include="..\engine\staticpropmgr.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll.cpp" />
|
<ClCompile Include="..\engine\sys_dll.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
<ClCompile Include="..\engine\sys_dll2.cpp" />
|
||||||
<ClCompile Include="..\engine\sys_engine.cpp" />
|
<ClCompile Include="..\engine\sys_engine.cpp" />
|
||||||
@ -257,6 +259,8 @@
|
|||||||
<ClInclude Include="..\engine\server\sv_main.h" />
|
<ClInclude Include="..\engine\server\sv_main.h" />
|
||||||
<ClInclude Include="..\engine\server\sv_rcon.h" />
|
<ClInclude Include="..\engine\server\sv_rcon.h" />
|
||||||
<ClInclude Include="..\engine\staticpropmgr.h" />
|
<ClInclude Include="..\engine\staticpropmgr.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll.h" />
|
<ClInclude Include="..\engine\sys_dll.h" />
|
||||||
<ClInclude Include="..\engine\sys_dll2.h" />
|
<ClInclude Include="..\engine\sys_dll2.h" />
|
||||||
<ClInclude Include="..\engine\sys_engine.h" />
|
<ClInclude Include="..\engine\sys_engine.h" />
|
||||||
|
@ -238,6 +238,9 @@
|
|||||||
<Filter Include="sdk\public\tier2">
|
<Filter Include="sdk\public\tier2">
|
||||||
<UniqueIdentifier>{42a3745e-8686-4f83-97bd-cec9336b4937}</UniqueIdentifier>
|
<UniqueIdentifier>{42a3745e-8686-4f83-97bd-cec9336b4937}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="sdk\engine\shared">
|
||||||
|
<UniqueIdentifier>{f3335ce8-0956-4d3c-9d12-ca2bd5646d8c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\client\vengineclient_impl.cpp">
|
<ClCompile Include="..\client\vengineclient_impl.cpp">
|
||||||
@ -741,6 +744,12 @@
|
|||||||
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
<ClCompile Include="..\engine\staticpropmgr.cpp">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\client\cdll_engine_int.h">
|
<ClInclude Include="..\client\cdll_engine_int.h">
|
||||||
@ -1895,6 +1904,12 @@
|
|||||||
<ClInclude Include="..\engine\staticpropmgr.h">
|
<ClInclude Include="..\engine\staticpropmgr.h">
|
||||||
<Filter>sdk\engine</Filter>
|
<Filter>sdk\engine</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="..\shared\resource\lockedserver.png">
|
<Image Include="..\shared\resource\lockedserver.png">
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\core\termutil.cpp" />
|
<ClCompile Include="..\core\termutil.cpp" />
|
||||||
<ClCompile Include="..\engine\net.cpp" />
|
<ClCompile Include="..\engine\net.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp" />
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp" />
|
||||||
<ClCompile Include="..\netconsole\netconsole.cpp" />
|
<ClCompile Include="..\netconsole\netconsole.cpp" />
|
||||||
<ClCompile Include="..\netconsole\plat_time.cpp" />
|
<ClCompile Include="..\netconsole\plat_time.cpp" />
|
||||||
<ClCompile Include="..\protoc\cl_rcon.pb.cc">
|
<ClCompile Include="..\protoc\cl_rcon.pb.cc">
|
||||||
@ -67,6 +69,8 @@
|
|||||||
<ClInclude Include="..\core\stdafx.h" />
|
<ClInclude Include="..\core\stdafx.h" />
|
||||||
<ClInclude Include="..\core\termutil.h" />
|
<ClInclude Include="..\core\termutil.h" />
|
||||||
<ClInclude Include="..\engine\net.h" />
|
<ClInclude Include="..\engine\net.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h" />
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h" />
|
||||||
<ClInclude Include="..\netconsole\netconsole.h" />
|
<ClInclude Include="..\netconsole\netconsole.h" />
|
||||||
<ClInclude Include="..\protoc\cl_rcon.pb.h" />
|
<ClInclude Include="..\protoc\cl_rcon.pb.h" />
|
||||||
<ClInclude Include="..\protoc\sv_rcon.pb.h" />
|
<ClInclude Include="..\protoc\sv_rcon.pb.h" />
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
<Filter Include="sdk\public\tier2">
|
<Filter Include="sdk\public\tier2">
|
||||||
<UniqueIdentifier>{3bbe24ed-5dce-4eb6-bb00-ed575b8bffc3}</UniqueIdentifier>
|
<UniqueIdentifier>{3bbe24ed-5dce-4eb6-bb00-ed575b8bffc3}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="sdk\engine\shared">
|
||||||
|
<UniqueIdentifier>{b6e80c43-6b7e-4503-aa64-60981ac963dc}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\core\stdafx.cpp">
|
<ClCompile Include="..\core\stdafx.cpp">
|
||||||
@ -82,6 +85,12 @@
|
|||||||
<ClCompile Include="..\core\logdef.cpp">
|
<ClCompile Include="..\core\logdef.cpp">
|
||||||
<Filter>core</Filter>
|
<Filter>core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\shared_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\engine\shared\base_rcon.cpp">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\core\stdafx.h">
|
<ClInclude Include="..\core\stdafx.h">
|
||||||
@ -120,5 +129,11 @@
|
|||||||
<ClInclude Include="..\public\tier2\socketcreator.h">
|
<ClInclude Include="..\public\tier2\socketcreator.h">
|
||||||
<Filter>sdk\public\tier2</Filter>
|
<Filter>sdk\public\tier2</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\base_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\engine\shared\shared_rcon.h">
|
||||||
|
<Filter>sdk\engine\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -853,11 +853,13 @@ void RCON_CmdQuery_f(const CCommand& args)
|
|||||||
{
|
{
|
||||||
if (args.ArgC() < 2)
|
if (args.ArgC() < 2)
|
||||||
{
|
{
|
||||||
|
const char* pszAddress = rcon_address->GetString();
|
||||||
|
|
||||||
if (RCONClient()->IsInitialized()
|
if (RCONClient()->IsInitialized()
|
||||||
&& !RCONClient()->IsConnected()
|
&& !RCONClient()->IsConnected()
|
||||||
&& strlen(rcon_address->GetString()) > 0)
|
&& pszAddress[0])
|
||||||
{
|
{
|
||||||
RCONClient()->Connect();
|
RCONClient()->Connect(pszAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -869,18 +871,26 @@ void RCON_CmdQuery_f(const CCommand& args)
|
|||||||
}
|
}
|
||||||
else if (RCONClient()->IsConnected())
|
else if (RCONClient()->IsConnected())
|
||||||
{
|
{
|
||||||
|
vector<char> vecMsg;
|
||||||
|
bool bSuccess = false;
|
||||||
|
const SocketHandle_t hSocket = RCONClient()->GetSocket();
|
||||||
|
|
||||||
if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value.
|
if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value.
|
||||||
{
|
{
|
||||||
string svCmdQuery;
|
|
||||||
if (args.ArgC() > 2)
|
if (args.ArgC() > 2)
|
||||||
{
|
{
|
||||||
svCmdQuery = RCONClient()->Serialize(args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
||||||
}
|
}
|
||||||
else // Use 'rcon_password' ConVar as password.
|
else // Use 'rcon_password' ConVar as password.
|
||||||
{
|
{
|
||||||
svCmdQuery = RCONClient()->Serialize(rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
bSuccess = RCONClient()->Serialize(vecMsg, rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
|
||||||
}
|
}
|
||||||
RCONClient()->Send(svCmdQuery);
|
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
RCONClient()->Send(hSocket, vecMsg.data(), vecMsg.size());
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server.
|
else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server.
|
||||||
@ -889,8 +899,11 @@ void RCON_CmdQuery_f(const CCommand& args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string svCmdQuery = RCONClient()->Serialize(args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
bSuccess = RCONClient()->Serialize(vecMsg, args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
|
||||||
RCONClient()->Send(svCmdQuery);
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
RCONClient()->Send(hSocket, vecMsg.data(), vecMsg.size());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -910,9 +923,11 @@ RCON_Disconnect_f
|
|||||||
*/
|
*/
|
||||||
void RCON_Disconnect_f(const CCommand& args)
|
void RCON_Disconnect_f(const CCommand& args)
|
||||||
{
|
{
|
||||||
if (RCONClient()->IsConnected())
|
const bool bIsConnected = RCONClient()->IsConnected();
|
||||||
|
RCONClient()->Disconnect();
|
||||||
|
|
||||||
|
if (bIsConnected) // Log if client was indeed connected.
|
||||||
{
|
{
|
||||||
RCONClient()->Disconnect();
|
|
||||||
DevMsg(eDLL_T::CLIENT, "User closed RCON connection\n");
|
DevMsg(eDLL_T::CLIENT, "User closed RCON connection\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user