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