summaryrefslogtreecommitdiff
path: root/tracker/AdminServer/rcon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tracker/AdminServer/rcon.cpp')
-rw-r--r--tracker/AdminServer/rcon.cpp343
1 files changed, 343 insertions, 0 deletions
diff --git a/tracker/AdminServer/rcon.cpp b/tracker/AdminServer/rcon.cpp
new file mode 100644
index 0000000..6cd31e7
--- /dev/null
+++ b/tracker/AdminServer/rcon.cpp
@@ -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
+}
+