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
234 lines
4.3 KiB
//========= 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 ) |
|
{ |
|
} |
|
|
|
|