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.
256 lines
8.0 KiB
256 lines
8.0 KiB
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
|
|
#include "RemoteServer.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#include "tier1/utlbuffer.h"
|
|
#include "IGameServerData.h"
|
|
extern IGameServerData *g_pGameServerData;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: singleton accessor
|
|
//-----------------------------------------------------------------------------
|
|
CRemoteServer &RemoteServer()
|
|
{
|
|
static CRemoteServer s_RemoteServer;
|
|
return s_RemoteServer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CRemoteServer::CRemoteServer()
|
|
{
|
|
m_iCurrentRequestID = 0;
|
|
m_ListenerID = INVALID_LISTENER_ID;
|
|
m_bInitialized = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CRemoteServer::~CRemoteServer()
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::Initialize()
|
|
{
|
|
m_bInitialized = true;
|
|
Assert( g_pGameServerData );
|
|
m_ListenerID = g_pGameServerData->GetNextListenerID( false ); // don't require auth on this connection
|
|
g_pGameServerData->RegisterAdminUIID( m_ListenerID );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: connects to a remote game server
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::ConnectRemoteGameServer(unsigned int ip, unsigned short port, const char *password)
|
|
{
|
|
assert(!("CRemoteServer::ConnectRemoteGameServer() not yet implemented"));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: request a cvar/data from the server
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::RequestValue(IServerDataResponse *requester, const char *variable)
|
|
{
|
|
Assert( m_bInitialized );
|
|
// add to the response handling table
|
|
int i = m_ResponseHandlers.AddToTail();
|
|
m_ResponseHandlers[i].requestID = m_iCurrentRequestID;
|
|
m_ResponseHandlers[i].handler = requester;
|
|
|
|
// build the command
|
|
char buf[512];
|
|
CUtlBuffer cmd(buf, sizeof(buf));
|
|
|
|
cmd.PutInt(m_iCurrentRequestID++);
|
|
cmd.PutInt(SERVERDATA_REQUESTVALUE);
|
|
cmd.PutString(variable);
|
|
cmd.PutString("");
|
|
|
|
// send to server
|
|
g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sets a value
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::SetValue(const char *variable, const char *value)
|
|
{
|
|
Assert( m_bInitialized );
|
|
// build the command
|
|
char buf[512];
|
|
CUtlBuffer cmd(buf, sizeof(buf));
|
|
|
|
cmd.PutInt(m_iCurrentRequestID++);
|
|
cmd.PutInt(SERVERDATA_SETVALUE);
|
|
cmd.PutString(variable);
|
|
cmd.PutString(value);
|
|
|
|
// send to server
|
|
g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: sends a custom command
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::SendCommand(const char *commandString)
|
|
{
|
|
Assert( m_bInitialized );
|
|
// build the command
|
|
char buf[512];
|
|
CUtlBuffer cmd(buf, sizeof(buf));
|
|
|
|
cmd.PutInt(m_iCurrentRequestID++);
|
|
cmd.PutInt(SERVERDATA_EXECCOMMAND);
|
|
cmd.PutString(commandString);
|
|
cmd.PutString("");
|
|
|
|
g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: changes the current password on the server
|
|
// responds with "PasswordChange" "true" or "PasswordChange" "false"
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::ChangeAccessPassword(IServerDataResponse *requester, const char *newPassword)
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: process any return values, firing any IServerDataResponse items
|
|
// Output : returns true if any items were fired
|
|
//-----------------------------------------------------------------------------
|
|
bool CRemoteServer::ProcessServerResponse()
|
|
{
|
|
Assert(g_pGameServerData != NULL);
|
|
Assert( m_bInitialized );
|
|
|
|
char charbuf[4096];
|
|
bool bProcessedAnyPackets = false;
|
|
while (1)
|
|
{
|
|
// get packet from networking
|
|
int bytesRead = g_pGameServerData->ReadDataResponse(m_ListenerID, charbuf, sizeof(charbuf));
|
|
if (bytesRead < 1)
|
|
break;
|
|
bProcessedAnyPackets = true;
|
|
|
|
// parse response
|
|
CUtlBuffer buf(charbuf, bytesRead, CUtlBuffer::READ_ONLY);
|
|
int requestID = buf.GetInt();
|
|
int responseType = buf.GetInt();
|
|
char variable[64];
|
|
buf.GetString(variable);
|
|
|
|
switch (responseType)
|
|
{
|
|
case SERVERDATA_RESPONSE_VALUE:
|
|
{
|
|
int valueSize = buf.GetInt();
|
|
Assert(valueSize > 0);
|
|
CUtlBuffer value(0, valueSize);
|
|
if (valueSize > 0)
|
|
{
|
|
value.Put(buf.PeekGet(), valueSize);
|
|
}
|
|
else
|
|
{
|
|
// null terminate
|
|
value.PutChar(0);
|
|
}
|
|
|
|
// find callback (usually will be the first one in the list)
|
|
for (int i = m_ResponseHandlers.Head(); m_ResponseHandlers.IsValidIndex(i); i = m_ResponseHandlers.Next(i))
|
|
{
|
|
if (m_ResponseHandlers[i].requestID == requestID)
|
|
{
|
|
// found, call
|
|
m_ResponseHandlers[i].handler->OnServerDataResponse(variable, (const char *)value.Base());
|
|
|
|
// remove from list
|
|
m_ResponseHandlers.Remove(i);
|
|
|
|
// there is only ever one handler for a message
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SERVERDATA_UPDATE:
|
|
{
|
|
// find all the people watching for this message
|
|
for (int i = m_MessageHandlers.Head(); m_MessageHandlers.IsValidIndex(i); i = m_MessageHandlers.Next(i))
|
|
{
|
|
if (!stricmp(m_MessageHandlers[i].messageName, variable))
|
|
{
|
|
// found, call
|
|
m_MessageHandlers[i].handler->OnServerDataResponse(variable, "");
|
|
|
|
// keep looking, there can be more than one handler for a message
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
Assert(responseType == SERVERDATA_RESPONSE_VALUE || responseType == SERVERDATA_UPDATE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bProcessedAnyPackets;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: adds a constant watches for a particular message
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::AddServerMessageHandler(IServerDataResponse *handler, const char *watch)
|
|
{
|
|
// add to the server message handling table
|
|
int i = m_MessageHandlers.AddToTail();
|
|
strncpy(m_MessageHandlers[i].messageName, watch, sizeof(m_MessageHandlers[i].messageName) - 1);
|
|
m_MessageHandlers[i].messageName[sizeof(m_MessageHandlers[i].messageName) - 1] = 0;
|
|
m_MessageHandlers[i].handler = handler;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: removes a requester from the list to guarantee the pointer won't be used
|
|
//-----------------------------------------------------------------------------
|
|
void CRemoteServer::RemoveServerDataResponseTarget(IServerDataResponse *invalidRequester)
|
|
{
|
|
// iterate the responses
|
|
for (int i = 0; i < m_ResponseHandlers.MaxElementIndex(); i++)
|
|
{
|
|
if (m_ResponseHandlers.IsValidIndex(i))
|
|
{
|
|
if (m_ResponseHandlers[i].handler == invalidRequester)
|
|
{
|
|
// found invalid handler, remove from list
|
|
m_ResponseHandlers.Remove(i);
|
|
}
|
|
}
|
|
}
|
|
// iterate the message handlers
|
|
for (int i = 0; i < m_MessageHandlers.MaxElementIndex(); i++)
|
|
{
|
|
if (m_MessageHandlers.IsValidIndex(i))
|
|
{
|
|
if (m_MessageHandlers[i].handler == invalidRequester)
|
|
{
|
|
// found invalid handler, remove from list
|
|
m_MessageHandlers.Remove(i);
|
|
}
|
|
}
|
|
}
|
|
}
|