1
This commit is contained in:
343
tracker/AdminServer/rcon.cpp
Normal file
343
tracker/AdminServer/rcon.cpp
Normal file
@ -0,0 +1,343 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: defines a RCon class used to send rcon commands to remote servers
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "rcon.h"
|
||||
#include "Iresponse.h"
|
||||
|
||||
#include "RconMsgHandler.h"
|
||||
#include "Socket.h"
|
||||
#include "proto_oob.h"
|
||||
#include "DialogGameInfo.h"
|
||||
#include "inetapi.h"
|
||||
#include "dialogkickplayer.h"
|
||||
|
||||
extern void v_strncpy(char *dest, const char *src, int bufsize);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NONE = 0,
|
||||
INFO_REQUESTED,
|
||||
INFO_RECEIVED
|
||||
} RCONSTATUS;
|
||||
|
||||
|
||||
CRcon::CRcon(IResponse *target,serveritem_t &server,const char *password) {
|
||||
|
||||
memcpy(&m_Server, &server,sizeof(serveritem_t));
|
||||
m_pResponseTarget=target;
|
||||
|
||||
m_bIsRefreshing = false;
|
||||
m_bChallenge = false;
|
||||
m_bNewRcon = false;
|
||||
m_bPasswordFail = false;
|
||||
m_bDisable = false;
|
||||
m_bGotChallenge = false;
|
||||
m_iChallenge = 0;
|
||||
m_fQuerySendTime= 0;
|
||||
|
||||
v_strncpy(m_sPassword,password,100);
|
||||
|
||||
int bytecode = S2A_INFO_DETAILED;
|
||||
m_pQuery = new CSocket("internet rcon query", -1);
|
||||
m_pQuery->AddMessageHandler(new CRconMsgHandlerDetails(this, CMsgHandler::MSGHANDLER_ALL, &bytecode));
|
||||
}
|
||||
|
||||
CRcon::~CRcon() {
|
||||
delete m_pQuery;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: resets the state of the rcon object back to startup conditions (i.e get challenge again)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::Reset()
|
||||
{
|
||||
m_bIsRefreshing = false;
|
||||
m_bChallenge = false;
|
||||
m_bNewRcon = false;
|
||||
m_bPasswordFail = false;
|
||||
m_bDisable = false;
|
||||
m_bGotChallenge = false;
|
||||
m_iChallenge = 0;
|
||||
m_fQuerySendTime= 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sends a challenge request to the server if we have yet to get one,
|
||||
// else it sends the rcon itself
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::SendRcon(const char *command)
|
||||
{
|
||||
|
||||
if(m_bDisable==true) // rcon is disabled because it has failed.
|
||||
{
|
||||
m_pResponseTarget->ServerFailedToRespond();
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_bIsRefreshing)
|
||||
{ // we are already processing a request, lets queue this
|
||||
queue_requests_t queue;
|
||||
strncpy(queue.queued,command,1024);
|
||||
|
||||
if(requests.Count()>10) // to many request already...
|
||||
return;
|
||||
|
||||
requests.AddToTail(queue);
|
||||
return;
|
||||
}
|
||||
|
||||
m_bIsRefreshing=true;
|
||||
m_bPasswordFail=false;
|
||||
|
||||
if(m_bGotChallenge==false) // haven't got the challenge id yet
|
||||
{
|
||||
GetChallenge();
|
||||
v_strncpy(m_sCmd,command,1024); // store away the command for later :)
|
||||
m_bChallenge=true; // note that we are requesting a challenge and need to still run this command
|
||||
}
|
||||
else
|
||||
{
|
||||
RconRequest(command,m_iChallenge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: runs a frame of the net handler
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::RunFrame()
|
||||
{
|
||||
// only the "ping" command has a timeout
|
||||
/* float curtime = CSocket::GetClock();
|
||||
if(m_fQuerySendTime!=0 && (curtime-m_fQuerySendTime)> 10.0f) // 10 seconds
|
||||
{
|
||||
m_fQuerySendTime= 0;
|
||||
m_pResponseTarget->ServerFailedToRespond();
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_pQuery)
|
||||
{
|
||||
m_pQuery->Frame();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: emits a challenge request
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::GetChallenge()
|
||||
{
|
||||
CMsgBuffer *buffer = m_pQuery->GetSendBuffer();
|
||||
assert( buffer );
|
||||
|
||||
if ( !buffer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
netadr_t adr;
|
||||
adr.ip[0] = m_Server.ip[0];
|
||||
adr.ip[1] = m_Server.ip[1];
|
||||
adr.ip[2] = m_Server.ip[2];
|
||||
adr.ip[3] = m_Server.ip[3];
|
||||
adr.port = (m_Server.port & 0xff) << 8 | (m_Server.port & 0xff00) >> 8;
|
||||
adr.type = NA_IP;
|
||||
// Set state
|
||||
m_Server.received = (int)INFO_REQUESTED;
|
||||
// Create query message
|
||||
buffer->Clear();
|
||||
// Write control sequence
|
||||
buffer->WriteLong(0xffffffff);
|
||||
// Write query string
|
||||
buffer->WriteString("challenge rcon");
|
||||
// Sendmessage
|
||||
m_pQuery->SendMessage( &adr );
|
||||
|
||||
// set the clock for this send
|
||||
m_fQuerySendTime = CSocket::GetClock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: emits a valid rcon request, the challenge id has already been found
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::RconRequest(const char *command, int challenge)
|
||||
{
|
||||
CMsgBuffer *buffer = m_pQuery->GetSendBuffer();
|
||||
assert( buffer );
|
||||
|
||||
if ( !buffer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
netadr_t adr;
|
||||
adr.ip[0] = m_Server.ip[0];
|
||||
adr.ip[1] = m_Server.ip[1];
|
||||
adr.ip[2] = m_Server.ip[2];
|
||||
adr.ip[3] = m_Server.ip[3];
|
||||
adr.port = (m_Server.port & 0xff) << 8 | (m_Server.port & 0xff00) >> 8;
|
||||
adr.type = NA_IP;
|
||||
|
||||
// Set state
|
||||
m_Server.received = (int)INFO_REQUESTED;
|
||||
// Create query message
|
||||
buffer->Clear();
|
||||
// Write control sequence
|
||||
buffer->WriteLong(0xffffffff);
|
||||
|
||||
// Write query string
|
||||
char rcon_cmd[600];
|
||||
_snprintf(rcon_cmd,600,"rcon %u \"%s\" %s",challenge,m_sPassword,command);
|
||||
|
||||
buffer->WriteString(rcon_cmd);
|
||||
// Sendmessage
|
||||
m_pQuery->SendMessage( &adr );
|
||||
// set the clock for this send
|
||||
m_fQuerySendTime = CSocket::GetClock();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called when an rcon responds
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::UpdateServer(netadr_t *adr, int challenge, const char *resp)
|
||||
{
|
||||
|
||||
m_fQuerySendTime= 0;
|
||||
if(m_bChallenge==true) // now send the RCON request itself
|
||||
{
|
||||
m_bChallenge=false; // m_bChallenge is set to say we just requested the challenge value
|
||||
m_iChallenge=challenge;
|
||||
m_bGotChallenge=true;
|
||||
RconRequest(m_sCmd,m_iChallenge);
|
||||
}
|
||||
else // this is the result of the RCON request
|
||||
{
|
||||
m_bNewRcon=true;
|
||||
v_strncpy(m_sRconResponse,resp,2048);
|
||||
m_bIsRefreshing=false;
|
||||
|
||||
// this must be before the SeverResponded() :)
|
||||
if(requests.Count()>0)
|
||||
{ // we have queued requests
|
||||
SendRcon(requests[0].queued);
|
||||
requests.Remove(0); // now delete this element
|
||||
}
|
||||
|
||||
|
||||
// notify the UI of the new server info
|
||||
m_pResponseTarget->ServerResponded();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: run when a refresh is asked for
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::Refresh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns if a rcon is currently being performed
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRcon::IsRefreshing()
|
||||
{
|
||||
|
||||
return m_bIsRefreshing;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: the server to which this rcon class is bound
|
||||
//-----------------------------------------------------------------------------
|
||||
serveritem_t &CRcon::GetServer()
|
||||
{
|
||||
return m_Server;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: the challenge id used in rcons
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRcon::Challenge()
|
||||
{
|
||||
return m_bChallenge;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns if a new rcon result is available
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRcon::NewRcon()
|
||||
{
|
||||
bool val = m_bNewRcon;
|
||||
m_bNewRcon=false;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the response of the last rcon
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CRcon::RconResponse()
|
||||
{
|
||||
return (const char *)m_sRconResponse;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called when the wrong password is used, when a ServerFailed is called
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRcon::PasswordFail()
|
||||
{
|
||||
bool val=m_bPasswordFail;
|
||||
m_bPasswordFail=false;
|
||||
return val;
|
||||
//m_pResponseTarget->ServerFailedToRespond();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called by the rcon message handler to denote a bad password
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::BadPassword(const char *info)
|
||||
{
|
||||
strncpy(m_sRconResponse,info,100);
|
||||
m_bPasswordFail=true;
|
||||
m_bDisable=true;
|
||||
m_fQuerySendTime= 0;
|
||||
|
||||
m_bIsRefreshing=false;
|
||||
|
||||
/* // this must be before the ServerFailedToRespond() :)
|
||||
if(requests.Count()>0)
|
||||
{ // we have queued requests
|
||||
SendRcon(requests[0].queued);
|
||||
requests.Remove(0); // now delete this element
|
||||
}
|
||||
*/
|
||||
|
||||
m_pResponseTarget->ServerFailedToRespond();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: return whether rcon has been disabled (due to bad passwords)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CRcon::Disabled()
|
||||
{
|
||||
return m_bDisable;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the password to use for rcons
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRcon::SetPassword(const char *newPass)
|
||||
{
|
||||
strncpy(m_sPassword,newPass,100);
|
||||
m_bDisable=false; // new password, so we can try again
|
||||
}
|
||||
|
Reference in New Issue
Block a user