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.

234 lines
4.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "service_conn_mgr.h"
  9. #include "vmpi.h"
  10. #include "tier0/dbg.h"
  11. #include "tcpsocket_helpers.h"
  12. #define SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL 1000
  13. // ------------------------------------------------------------------------------------------- //
  14. // CServiceConn.
  15. // ------------------------------------------------------------------------------------------- //
  16. CServiceConn::CServiceConn()
  17. {
  18. m_pSocket = NULL;
  19. }
  20. CServiceConn::~CServiceConn()
  21. {
  22. if ( m_pSocket )
  23. m_pSocket->Release();
  24. }
  25. // ------------------------------------------------------------------------------------------- //
  26. // CServiceConnMgr.
  27. // ------------------------------------------------------------------------------------------- //
  28. CServiceConnMgr::CServiceConnMgr()
  29. {
  30. m_bServer = false;
  31. m_bShuttingDown = false;
  32. m_pListenSocket = NULL;
  33. }
  34. CServiceConnMgr::~CServiceConnMgr()
  35. {
  36. Term();
  37. }
  38. bool CServiceConnMgr::InitServer()
  39. {
  40. Term();
  41. m_bServer = true;
  42. // Create a socket to listen on.
  43. for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
  44. {
  45. m_pListenSocket = CreateTCPListenSocketEmu( iPort, 5 );
  46. if ( m_pListenSocket )
  47. break;
  48. }
  49. if ( !m_pListenSocket )
  50. return false;
  51. return true;
  52. }
  53. bool CServiceConnMgr::InitClient()
  54. {
  55. Term();
  56. m_bServer = false;
  57. AttemptConnect();
  58. return true;
  59. }
  60. void CServiceConnMgr::Term()
  61. {
  62. m_bShuttingDown = true; // This prevents some reentrancy.
  63. // Get rid of our registry key.
  64. if ( m_pListenSocket )
  65. {
  66. m_pListenSocket->Release();
  67. m_pListenSocket = NULL;
  68. }
  69. m_Connections.PurgeAndDeleteElements();
  70. m_bShuttingDown = false;
  71. }
  72. bool CServiceConnMgr::IsConnected()
  73. {
  74. return m_Connections.Count() != 0;
  75. }
  76. void CServiceConnMgr::Update()
  77. {
  78. DWORD curTime = GetTickCount();
  79. // Connect if we're an unconnected client.
  80. if ( m_bServer )
  81. {
  82. if ( m_pListenSocket )
  83. {
  84. // Listen for more connections.
  85. while ( 1 )
  86. {
  87. CIPAddr addr;
  88. ITCPSocket *pSocket = m_pListenSocket->UpdateListen( &addr );
  89. if ( !pSocket )
  90. break;
  91. CServiceConn *pConn = new CServiceConn;
  92. pConn->m_ID = m_Connections.AddToTail( pConn );
  93. pConn->m_LastRecvTime = curTime;
  94. pConn->m_pSocket = pSocket;
  95. OnNewConnection( pConn->m_ID );
  96. }
  97. }
  98. }
  99. else
  100. {
  101. if ( !IsConnected() && curTime - m_LastConnectAttemptTime >= SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL )
  102. {
  103. AttemptConnect();
  104. }
  105. }
  106. // Check for timeouts and send acks.
  107. int iNext;
  108. for ( int iCur=m_Connections.Head(); iCur != m_Connections.InvalidIndex(); iCur=iNext )
  109. {
  110. iNext = m_Connections.Next( iCur );
  111. CServiceConn *pConn = m_Connections[iCur];
  112. if ( pConn->m_pSocket->IsConnected() )
  113. {
  114. DWORD startTime = GetTickCount();
  115. CUtlVector<unsigned char> data;
  116. while ( pConn->m_pSocket->Recv( data ) )
  117. {
  118. HandlePacket( (char*)data.Base(), data.Count() );
  119. // Don't sit in this loop too long.
  120. if ( (GetTickCount() - startTime) > 50 )
  121. break;
  122. }
  123. }
  124. else
  125. {
  126. OnTerminateConnection( iCur );
  127. m_Connections.Remove( iCur );
  128. delete pConn;
  129. }
  130. }
  131. }
  132. void CServiceConnMgr::SendPacket( int id, const void *pData, int len )
  133. {
  134. if ( id == -1 )
  135. {
  136. FOR_EACH_LL( m_Connections, i )
  137. {
  138. m_Connections[i]->m_pSocket->Send( pData, len );
  139. }
  140. }
  141. else
  142. {
  143. m_Connections[id]->m_pSocket->Send( pData, len );
  144. }
  145. }
  146. void CServiceConnMgr::AttemptConnect()
  147. {
  148. m_LastConnectAttemptTime = GetTickCount();
  149. ITCPSocket *pSocket = NULL;
  150. for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
  151. {
  152. pSocket = CreateTCPSocketEmu();
  153. if ( !pSocket || !pSocket->BindToAny( 0 ) )
  154. return;
  155. CIPAddr addr( 127, 0, 0, 1, iPort );
  156. if ( TCPSocket_Connect( pSocket, &addr, 0.1 ) )
  157. break;
  158. pSocket->Release();
  159. pSocket = NULL;
  160. }
  161. if ( pSocket )
  162. {
  163. CServiceConn *pConn = new CServiceConn;
  164. pConn->m_ID = m_Connections.AddToTail( pConn );
  165. pConn->m_LastRecvTime = GetTickCount();
  166. pConn->m_pSocket = pSocket;
  167. OnNewConnection( pConn->m_ID );
  168. }
  169. }
  170. void CServiceConnMgr::OnNewConnection( int id )
  171. {
  172. }
  173. void CServiceConnMgr::OnTerminateConnection( int id )
  174. {
  175. }
  176. void CServiceConnMgr::HandlePacket( const char *pData, int len )
  177. {
  178. }