summaryrefslogtreecommitdiff
path: root/utils/vmpi/vmpi_service/service_conn_mgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/vmpi/vmpi_service/service_conn_mgr.cpp')
-rw-r--r--utils/vmpi/vmpi_service/service_conn_mgr.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/utils/vmpi/vmpi_service/service_conn_mgr.cpp b/utils/vmpi/vmpi_service/service_conn_mgr.cpp
new file mode 100644
index 0000000..c8b48ca
--- /dev/null
+++ b/utils/vmpi/vmpi_service/service_conn_mgr.cpp
@@ -0,0 +1,234 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "stdafx.h"
+#include "service_conn_mgr.h"
+#include "vmpi.h"
+#include "tier0/dbg.h"
+#include "tcpsocket_helpers.h"
+
+
+#define SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL 1000
+
+
+
+// ------------------------------------------------------------------------------------------- //
+// CServiceConn.
+// ------------------------------------------------------------------------------------------- //
+
+CServiceConn::CServiceConn()
+{
+ m_pSocket = NULL;
+}
+
+
+CServiceConn::~CServiceConn()
+{
+ if ( m_pSocket )
+ m_pSocket->Release();
+}
+
+
+// ------------------------------------------------------------------------------------------- //
+// CServiceConnMgr.
+// ------------------------------------------------------------------------------------------- //
+
+
+CServiceConnMgr::CServiceConnMgr()
+{
+ m_bServer = false;
+ m_bShuttingDown = false;
+ m_pListenSocket = NULL;
+}
+
+
+CServiceConnMgr::~CServiceConnMgr()
+{
+ Term();
+}
+
+
+bool CServiceConnMgr::InitServer()
+{
+ Term();
+
+ m_bServer = true;
+
+ // Create a socket to listen on.
+ for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
+ {
+ m_pListenSocket = CreateTCPListenSocketEmu( iPort, 5 );
+ if ( m_pListenSocket )
+ break;
+ }
+ if ( !m_pListenSocket )
+ return false;
+
+ return true;
+}
+
+
+bool CServiceConnMgr::InitClient()
+{
+ Term();
+
+ m_bServer = false;
+
+ AttemptConnect();
+ return true;
+}
+
+
+void CServiceConnMgr::Term()
+{
+ m_bShuttingDown = true; // This prevents some reentrancy.
+
+ // Get rid of our registry key.
+ if ( m_pListenSocket )
+ {
+ m_pListenSocket->Release();
+ m_pListenSocket = NULL;
+ }
+
+ m_Connections.PurgeAndDeleteElements();
+
+ m_bShuttingDown = false;
+}
+
+
+bool CServiceConnMgr::IsConnected()
+{
+ return m_Connections.Count() != 0;
+}
+
+
+void CServiceConnMgr::Update()
+{
+ DWORD curTime = GetTickCount();
+
+ // Connect if we're an unconnected client.
+ if ( m_bServer )
+ {
+ if ( m_pListenSocket )
+ {
+ // Listen for more connections.
+ while ( 1 )
+ {
+ CIPAddr addr;
+ ITCPSocket *pSocket = m_pListenSocket->UpdateListen( &addr );
+ if ( !pSocket )
+ break;
+
+ CServiceConn *pConn = new CServiceConn;
+ pConn->m_ID = m_Connections.AddToTail( pConn );
+ pConn->m_LastRecvTime = curTime;
+ pConn->m_pSocket = pSocket;
+
+ OnNewConnection( pConn->m_ID );
+ }
+ }
+ }
+ else
+ {
+ if ( !IsConnected() && curTime - m_LastConnectAttemptTime >= SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL )
+ {
+ AttemptConnect();
+ }
+ }
+
+ // Check for timeouts and send acks.
+ int iNext;
+ for ( int iCur=m_Connections.Head(); iCur != m_Connections.InvalidIndex(); iCur=iNext )
+ {
+ iNext = m_Connections.Next( iCur );
+ CServiceConn *pConn = m_Connections[iCur];
+
+ if ( pConn->m_pSocket->IsConnected() )
+ {
+ DWORD startTime = GetTickCount();
+ CUtlVector<unsigned char> data;
+ while ( pConn->m_pSocket->Recv( data ) )
+ {
+ HandlePacket( (char*)data.Base(), data.Count() );
+
+ // Don't sit in this loop too long.
+ if ( (GetTickCount() - startTime) > 50 )
+ break;
+ }
+ }
+ else
+ {
+ OnTerminateConnection( iCur );
+ m_Connections.Remove( iCur );
+ delete pConn;
+ }
+ }
+}
+
+
+void CServiceConnMgr::SendPacket( int id, const void *pData, int len )
+{
+ if ( id == -1 )
+ {
+ FOR_EACH_LL( m_Connections, i )
+ {
+ m_Connections[i]->m_pSocket->Send( pData, len );
+ }
+ }
+ else
+ {
+ m_Connections[id]->m_pSocket->Send( pData, len );
+ }
+}
+
+
+void CServiceConnMgr::AttemptConnect()
+{
+ m_LastConnectAttemptTime = GetTickCount();
+
+
+ ITCPSocket *pSocket = NULL;
+ for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
+ {
+ pSocket = CreateTCPSocketEmu();
+ if ( !pSocket || !pSocket->BindToAny( 0 ) )
+ return;
+
+ CIPAddr addr( 127, 0, 0, 1, iPort );
+ if ( TCPSocket_Connect( pSocket, &addr, 0.1 ) )
+ break;
+
+ pSocket->Release();
+ pSocket = NULL;
+ }
+
+ if ( pSocket )
+ {
+ CServiceConn *pConn = new CServiceConn;
+ pConn->m_ID = m_Connections.AddToTail( pConn );
+ pConn->m_LastRecvTime = GetTickCount();
+ pConn->m_pSocket = pSocket;
+
+ OnNewConnection( pConn->m_ID );
+ }
+}
+
+
+void CServiceConnMgr::OnNewConnection( int id )
+{
+}
+
+
+void CServiceConnMgr::OnTerminateConnection( int id )
+{
+}
+
+
+void CServiceConnMgr::HandlePacket( const char *pData, int len )
+{
+}
+