You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
9.3 KiB
343 lines
9.3 KiB
//========= 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 |
|
} |
|
|
|
|