Team Fortress 2 Source Code as on 22/4/2020
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

//========= 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);
}
}
}
}