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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "RemoteServer.h"
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include "tier1/utlbuffer.h"
  11. #include "IGameServerData.h"
  12. extern IGameServerData *g_pGameServerData;
  13. //-----------------------------------------------------------------------------
  14. // Purpose: singleton accessor
  15. //-----------------------------------------------------------------------------
  16. CRemoteServer &RemoteServer()
  17. {
  18. static CRemoteServer s_RemoteServer;
  19. return s_RemoteServer;
  20. }
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Constructor
  23. //-----------------------------------------------------------------------------
  24. CRemoteServer::CRemoteServer()
  25. {
  26. m_iCurrentRequestID = 0;
  27. m_ListenerID = INVALID_LISTENER_ID;
  28. m_bInitialized = false;
  29. }
  30. //-----------------------------------------------------------------------------
  31. // Purpose: Destructor
  32. //-----------------------------------------------------------------------------
  33. CRemoteServer::~CRemoteServer()
  34. {
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Destructor
  38. //-----------------------------------------------------------------------------
  39. void CRemoteServer::Initialize()
  40. {
  41. m_bInitialized = true;
  42. Assert( g_pGameServerData );
  43. m_ListenerID = g_pGameServerData->GetNextListenerID( false ); // don't require auth on this connection
  44. g_pGameServerData->RegisterAdminUIID( m_ListenerID );
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Purpose: connects to a remote game server
  48. //-----------------------------------------------------------------------------
  49. void CRemoteServer::ConnectRemoteGameServer(unsigned int ip, unsigned short port, const char *password)
  50. {
  51. assert(!("CRemoteServer::ConnectRemoteGameServer() not yet implemented"));
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Purpose: request a cvar/data from the server
  55. //-----------------------------------------------------------------------------
  56. void CRemoteServer::RequestValue(IServerDataResponse *requester, const char *variable)
  57. {
  58. Assert( m_bInitialized );
  59. // add to the response handling table
  60. int i = m_ResponseHandlers.AddToTail();
  61. m_ResponseHandlers[i].requestID = m_iCurrentRequestID;
  62. m_ResponseHandlers[i].handler = requester;
  63. // build the command
  64. char buf[512];
  65. CUtlBuffer cmd(buf, sizeof(buf));
  66. cmd.PutInt(m_iCurrentRequestID++);
  67. cmd.PutInt(SERVERDATA_REQUESTVALUE);
  68. cmd.PutString(variable);
  69. cmd.PutString("");
  70. // send to server
  71. g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: sets a value
  75. //-----------------------------------------------------------------------------
  76. void CRemoteServer::SetValue(const char *variable, const char *value)
  77. {
  78. Assert( m_bInitialized );
  79. // build the command
  80. char buf[512];
  81. CUtlBuffer cmd(buf, sizeof(buf));
  82. cmd.PutInt(m_iCurrentRequestID++);
  83. cmd.PutInt(SERVERDATA_SETVALUE);
  84. cmd.PutString(variable);
  85. cmd.PutString(value);
  86. // send to server
  87. g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose: sends a custom command
  91. //-----------------------------------------------------------------------------
  92. void CRemoteServer::SendCommand(const char *commandString)
  93. {
  94. Assert( m_bInitialized );
  95. // build the command
  96. char buf[512];
  97. CUtlBuffer cmd(buf, sizeof(buf));
  98. cmd.PutInt(m_iCurrentRequestID++);
  99. cmd.PutInt(SERVERDATA_EXECCOMMAND);
  100. cmd.PutString(commandString);
  101. cmd.PutString("");
  102. g_pGameServerData->WriteDataRequest(m_ListenerID, cmd.Base(), cmd.TellPut());
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: changes the current password on the server
  106. // responds with "PasswordChange" "true" or "PasswordChange" "false"
  107. //-----------------------------------------------------------------------------
  108. void CRemoteServer::ChangeAccessPassword(IServerDataResponse *requester, const char *newPassword)
  109. {
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Purpose: process any return values, firing any IServerDataResponse items
  113. // Output : returns true if any items were fired
  114. //-----------------------------------------------------------------------------
  115. bool CRemoteServer::ProcessServerResponse()
  116. {
  117. Assert(g_pGameServerData != NULL);
  118. Assert( m_bInitialized );
  119. char charbuf[4096];
  120. bool bProcessedAnyPackets = false;
  121. while (1)
  122. {
  123. // get packet from networking
  124. int bytesRead = g_pGameServerData->ReadDataResponse(m_ListenerID, charbuf, sizeof(charbuf));
  125. if (bytesRead < 1)
  126. break;
  127. bProcessedAnyPackets = true;
  128. // parse response
  129. CUtlBuffer buf(charbuf, bytesRead, CUtlBuffer::READ_ONLY);
  130. int requestID = buf.GetInt();
  131. int responseType = buf.GetInt();
  132. char variable[64];
  133. buf.GetString(variable);
  134. switch (responseType)
  135. {
  136. case SERVERDATA_RESPONSE_VALUE:
  137. {
  138. int valueSize = buf.GetInt();
  139. Assert(valueSize > 0);
  140. CUtlBuffer value(0, valueSize);
  141. if (valueSize > 0)
  142. {
  143. value.Put(buf.PeekGet(), valueSize);
  144. }
  145. else
  146. {
  147. // null terminate
  148. value.PutChar(0);
  149. }
  150. // find callback (usually will be the first one in the list)
  151. for (int i = m_ResponseHandlers.Head(); m_ResponseHandlers.IsValidIndex(i); i = m_ResponseHandlers.Next(i))
  152. {
  153. if (m_ResponseHandlers[i].requestID == requestID)
  154. {
  155. // found, call
  156. m_ResponseHandlers[i].handler->OnServerDataResponse(variable, (const char *)value.Base());
  157. // remove from list
  158. m_ResponseHandlers.Remove(i);
  159. // there is only ever one handler for a message
  160. break;
  161. }
  162. }
  163. }
  164. break;
  165. case SERVERDATA_UPDATE:
  166. {
  167. // find all the people watching for this message
  168. for (int i = m_MessageHandlers.Head(); m_MessageHandlers.IsValidIndex(i); i = m_MessageHandlers.Next(i))
  169. {
  170. if (!stricmp(m_MessageHandlers[i].messageName, variable))
  171. {
  172. // found, call
  173. m_MessageHandlers[i].handler->OnServerDataResponse(variable, "");
  174. // keep looking, there can be more than one handler for a message
  175. }
  176. }
  177. }
  178. break;
  179. default:
  180. Assert(responseType == SERVERDATA_RESPONSE_VALUE || responseType == SERVERDATA_UPDATE);
  181. break;
  182. }
  183. }
  184. return bProcessedAnyPackets;
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Purpose: adds a constant watches for a particular message
  188. //-----------------------------------------------------------------------------
  189. void CRemoteServer::AddServerMessageHandler(IServerDataResponse *handler, const char *watch)
  190. {
  191. // add to the server message handling table
  192. int i = m_MessageHandlers.AddToTail();
  193. strncpy(m_MessageHandlers[i].messageName, watch, sizeof(m_MessageHandlers[i].messageName) - 1);
  194. m_MessageHandlers[i].messageName[sizeof(m_MessageHandlers[i].messageName) - 1] = 0;
  195. m_MessageHandlers[i].handler = handler;
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose: removes a requester from the list to guarantee the pointer won't be used
  199. //-----------------------------------------------------------------------------
  200. void CRemoteServer::RemoveServerDataResponseTarget(IServerDataResponse *invalidRequester)
  201. {
  202. // iterate the responses
  203. for (int i = 0; i < m_ResponseHandlers.MaxElementIndex(); i++)
  204. {
  205. if (m_ResponseHandlers.IsValidIndex(i))
  206. {
  207. if (m_ResponseHandlers[i].handler == invalidRequester)
  208. {
  209. // found invalid handler, remove from list
  210. m_ResponseHandlers.Remove(i);
  211. }
  212. }
  213. }
  214. // iterate the message handlers
  215. for (int i = 0; i < m_MessageHandlers.MaxElementIndex(); i++)
  216. {
  217. if (m_MessageHandlers.IsValidIndex(i))
  218. {
  219. if (m_MessageHandlers[i].handler == invalidRequester)
  220. {
  221. // found invalid handler, remove from list
  222. m_MessageHandlers.Remove(i);
  223. }
  224. }
  225. }
  226. }