This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// stdafx.cpp : source file that includes just the standard includes
// vmpi_service.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
+35
View File
@@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_)
#define AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <winsock2.h>
#include <shellapi.h>
#include <winuser.h>
#include "basetypes.h"
#include <stdio.h>
#include "iphelpers.h"
// TODO: reference additional headers your program requires here
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_)
+500
View File
@@ -0,0 +1,500 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "stdafx.h"
#include "tier1/utldict.h"
#include <pdh.h>
#include <pdhmsg.h>
#include "perf_counters.h"
#if 1
class CPerfTracker : public IPerfTracker
{
public:
CPerfTracker()
{
m_hProcessorTimeCounter = NULL;
m_dwProcessID = 0;
if ( PdhOpenQuery( NULL, 0, &m_hQuery ) != ERROR_SUCCESS )
m_hQuery = NULL;
SYSTEM_INFO info;
GetSystemInfo( &info );
m_nProcessors = (int)info.dwNumberOfProcessors;
}
~CPerfTracker()
{
if ( m_hQuery )
PdhCloseQuery( m_hQuery );
}
virtual void Init( unsigned long dwProcessID )
{
Term();
m_dwProcessID = dwProcessID;
char instanceName[512];
if ( GetInstanceNameFromProcessID( m_dwProcessID, instanceName, sizeof( instanceName ) ) )
{
// Create a counter to watch this process' time.
char str[512];
V_snprintf( str, sizeof( str ), "\\Process(%s)\\%% Processor Time", instanceName );
if ( PdhAddCounter( m_hQuery, str, 0, &m_hProcessorTimeCounter ) != ERROR_SUCCESS )
{
m_hProcessorTimeCounter = NULL;
}
V_snprintf( str, sizeof( str ), "\\Process(%s)\\Private Bytes", instanceName );
if ( PdhAddCounter( m_hQuery, str, 0, &m_hPrivateBytesCounter ) != ERROR_SUCCESS )
{
m_hPrivateBytesCounter = NULL;
}
}
}
void Term()
{
if ( m_hProcessorTimeCounter )
PdhRemoveCounter( m_hProcessorTimeCounter );
if ( m_hPrivateBytesCounter )
PdhRemoveCounter( m_hPrivateBytesCounter );
m_hProcessorTimeCounter = NULL;
m_hPrivateBytesCounter = NULL;
}
virtual void Release()
{
delete this;
}
virtual unsigned long GetProcessID()
{
return m_dwProcessID;
}
virtual void GetPerfData( int &processorPercentage, int &memoryUsageMegabytes )
{
processorPercentage = 101;
memoryUsageMegabytes = 0;
// Collect query data..
PDH_STATUS ret = PdhCollectQueryData( m_hQuery );
if ( ret != ERROR_SUCCESS )
return;
// Check processor usage.
DWORD dwType;
PDH_FMT_COUNTERVALUE counterValue;
if ( PdhGetFormattedCounterValue( m_hProcessorTimeCounter, PDH_FMT_LONG | PDH_FMT_NOCAP100, &dwType, &counterValue ) == ERROR_SUCCESS )
processorPercentage = counterValue.longValue / m_nProcessors;
else
processorPercentage = 101;
// Check memory usage.
if ( PdhGetFormattedCounterValue( m_hPrivateBytesCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &dwType, &counterValue ) == ERROR_SUCCESS )
memoryUsageMegabytes = (int)(counterValue.doubleValue / (1024.0 * 1024.0));
else
memoryUsageMegabytes = 0;
}
private:
bool GetInstanceNameFromProcessID( DWORD processID, char *instanceName, int instanceNameLen )
{
instanceName[0] = 0;
bool bRet = false;
// This refreshes the object list. If we don't do this, it won't get new process IDs correctly.
DWORD dummy = 0;
PdhEnumObjects( NULL, NULL, NULL, &dummy, PERF_DETAIL_NOVICE, true );
// Find out how much data we need.
DWORD counterListLen=2, instanceListLen=2;
char *counterList = new char[counterListLen];
char *instanceList = new char[instanceListLen];
PDH_STATUS stat = PdhEnumObjectItems( NULL, NULL, "Process", counterList, &counterListLen, instanceList, &instanceListLen, PERF_DETAIL_NOVICE, 0 );
if ( stat == PDH_MORE_DATA )
{
delete [] counterList;
delete [] instanceList;
char *counterList = new char[counterListLen];
char *instanceList = new char[instanceListLen];
stat = PdhEnumObjectItems( NULL, NULL, "Process", counterList, &counterListLen, instanceList, &instanceListLen, PERF_DETAIL_NOVICE, 0 );
if ( stat == ERROR_SUCCESS )
{
// We need the # of each one..
CUtlDict<int,int> counts;
// The instance name list is a bunch of strings terminated with nulls. The final one has two nulls after it.
// Walk through the list and get the process ID associated with each instance name.
const char *pCur = instanceList;
while ( *pCur )
{
int index = counts.Find( pCur );
if ( index == counts.InvalidIndex() )
counts.Insert( pCur, 1 );
else
counts[index]++;
pCur += strlen( pCur ) + 1;
}
// Each instance (like "vrad") might have multiple versions, like if you're running multiple vrad processes at the same time.
for ( int i=counts.First(); i != counts.InvalidIndex(); i=counts.Next( i ) )
{
const char *pInstanceName = counts.GetElementName( i );
int nInstances = counts[i];
for ( int iInstance=0; iInstance < nInstances; iInstance++ )
{
char testInstanceName[256], fullObjectName[256];
V_snprintf( testInstanceName, sizeof( testInstanceName ), "%s#%d", pInstanceName, iInstance );
V_snprintf( fullObjectName, sizeof( fullObjectName ), "\\Process(%s)\\ID Process", testInstanceName );
HCOUNTER hCounter = NULL;
stat = PdhAddCounter( m_hQuery, fullObjectName, 0, &hCounter );
if ( stat == ERROR_SUCCESS )
{
stat = PdhCollectQueryData( m_hQuery );
if ( stat == ERROR_SUCCESS )
{
DWORD dwType;
PDH_FMT_COUNTERVALUE counterValue;
stat = PdhGetFormattedCounterValue( hCounter, PDH_FMT_LONG, &dwType, &counterValue );
if ( stat == 0 && counterValue.longValue == (long)processID )
{
// Finall! We found it.
V_strncpy( instanceName, testInstanceName, instanceNameLen );
bRet = true;
PdhRemoveCounter( hCounter );
break;
}
}
PdhRemoveCounter( hCounter );
}
}
if ( bRet )
break;
}
}
delete [] counterList;
delete [] instanceList;
}
return bRet;
}
private:
DWORD m_dwProcessID;
PDH_HQUERY m_hQuery;
HCOUNTER m_hProcessorTimeCounter;
HCOUNTER m_hPrivateBytesCounter;
int m_nProcessors;
};
IPerfTracker* CreatePerfTracker()
{
return new CPerfTracker;
}
#else
#include <winperf.h>
// --------------------------------------------------------------------------------------------------------------------- //
// NOTE: THIS IS THE OLD, UGLY WAY TO DO IT.
// --------------------------------------------------------------------------------------------------------------------- //
class CPerfTracker
{
public:
CPerfTracker();
void Init( unsigned long dwProcessID );
unsigned long GetProcessID();
// Get the percentage of CPU time that the process is using.
int GetCPUPercentage();
private:
DWORD m_dwProcessID;
LONGLONG m_lnOldValue;
LARGE_INTEGER m_OldPerfTime100nSec;
int m_nProcessors;
};
#define TOTALBYTES 100*1024
#define BYTEINCREMENT 10*1024
#define SYSTEM_OBJECT_INDEX 2 // 'System' object
#define PROCESS_OBJECT_INDEX 230 // 'Process' object
#define PROCESSOR_OBJECT_INDEX 238 // 'Processor' object
#define TOTAL_PROCESSOR_TIME_COUNTER_INDEX 240 // '% Total processor time' counter (valid in WinNT under 'System' object)
#define PROCESSOR_TIME_COUNTER_INDEX 6 // '% processor time' counter (for Win2K/XP)
//
// The performance data is accessed through the registry key
// HKEY_PEFORMANCE_DATA.
// However, although we use the registry to collect performance data,
// the data is not stored in the registry database.
// Instead, calling the registry functions with the HKEY_PEFORMANCE_DATA key
// causes the system to collect the data from the appropriate system
// object managers.
//
// QueryPerformanceData allocates memory block for getting the
// performance data.
//
//
void QueryPerformanceData(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex)
{
//
// Since i want to use the same allocated area for each query,
// i declare CBuffer as static.
// The allocated is changed only when RegQueryValueEx return ERROR_MORE_DATA
//
static CUtlVector<char> Buffer;
if ( Buffer.Count() == 0 )
Buffer.SetSize( TOTALBYTES );
DWORD BufferSize = Buffer.Count();
LONG lRes;
char keyName[32];
V_snprintf(keyName, sizeof(keyName), "%d",dwObjectIndex);
memset( Buffer.Base(), 0, Buffer.Count() );
while( (lRes = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
keyName,
NULL,
NULL,
(LPBYTE)Buffer.Base(),
&BufferSize )) == ERROR_MORE_DATA )
{
// Get a buffer that is big enough.
BufferSize += BYTEINCREMENT;
Buffer.SetSize( BufferSize );
}
*pPerfData = (PPERF_DATA_BLOCK)Buffer.Base();
}
/*****************************************************************
* *
* Functions used to navigate through the performance data. *
* *
*****************************************************************/
inline PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK PerfData )
{
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength) );
}
inline PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength) );
}
inline PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj + PerfObj->HeaderLength) );
}
inline PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION PerfCntr )
{
return( (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + PerfCntr->ByteLength) );
}
inline PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + PerfObj->DefinitionLength) );
}
inline PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION PerfInst )
{
PPERF_COUNTER_BLOCK PerfCntrBlk;
PerfCntrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + PerfInst->ByteLength);
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength) );
}
template<class T>
T GetCounterValueForProcessID(PPERF_OBJECT_TYPE pPerfObj, DWORD dwCounterIndex, DWORD dwProcessID)
{
unsigned long PROC_ID_COUNTER = 784;
BOOL bProcessIDExist = FALSE;
PPERF_COUNTER_DEFINITION pPerfCntr = NULL;
PPERF_COUNTER_DEFINITION pTheRequestedPerfCntr = NULL;
PPERF_COUNTER_DEFINITION pProcIDPerfCntr = NULL;
PPERF_INSTANCE_DEFINITION pPerfInst = NULL;
PPERF_COUNTER_BLOCK pCounterBlock = NULL;
// Get the first counter.
pPerfCntr = FirstCounter( pPerfObj );
for( DWORD j=0; j < pPerfObj->NumCounters; j++ )
{
if (pPerfCntr->CounterNameTitleIndex == PROC_ID_COUNTER)
{
pProcIDPerfCntr = pPerfCntr;
if (pTheRequestedPerfCntr)
break;
}
if (pPerfCntr->CounterNameTitleIndex == dwCounterIndex)
{
pTheRequestedPerfCntr = pPerfCntr;
if (pProcIDPerfCntr)
break;
}
// Get the next counter.
pPerfCntr = NextCounter( pPerfCntr );
}
if( pPerfObj->NumInstances == PERF_NO_INSTANCES )
{
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfObj + pPerfObj->DefinitionLength);
}
else
{
pPerfInst = FirstInstance( pPerfObj );
for( int k=0; k < pPerfObj->NumInstances; k++ )
{
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfInst + pPerfInst->ByteLength);
if (pCounterBlock)
{
DWORD processID = *(DWORD*)((LPBYTE) pCounterBlock + pProcIDPerfCntr->CounterOffset);
if (processID == dwProcessID)
{
bProcessIDExist = TRUE;
break;
}
}
// Get the next instance.
pPerfInst = NextInstance( pPerfInst );
}
}
if (bProcessIDExist && pCounterBlock)
{
T *lnValue = NULL;
lnValue = (T*)((LPBYTE) pCounterBlock + pTheRequestedPerfCntr->CounterOffset);
return *lnValue;
}
return -1;
}
template<class T>
T GetCounterValueForProcessID(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex, DWORD dwProcessID)
{
QueryPerformanceData(pPerfData, dwObjectIndex, dwCounterIndex);
PPERF_OBJECT_TYPE pPerfObj = NULL;
T lnValue = {0};
// Get the first object type.
pPerfObj = FirstObject( *pPerfData );
// Look for the given object index
for( DWORD i=0; i < (*pPerfData)->NumObjectTypes; i++ )
{
if (pPerfObj->ObjectNameTitleIndex == dwObjectIndex)
{
lnValue = GetCounterValueForProcessID<T>(pPerfObj, dwCounterIndex, dwProcessID);
break;
}
pPerfObj = NextObject( pPerfObj );
}
return lnValue;
}
// ------------------------------------------------------------------------------------------- //
// CPerfTracker implementation.
// ------------------------------------------------------------------------------------------- //
CPerfTracker::CPerfTracker()
{
Init( 0 );
SYSTEM_INFO info;
GetSystemInfo( &info );
m_nProcessors = (int)info.dwNumberOfProcessors;
}
void CPerfTracker::Init( unsigned long dwProcessID )
{
m_dwProcessID = dwProcessID;
m_lnOldValue = 0;
}
unsigned long CPerfTracker::GetProcessID()
{
return m_dwProcessID;
}
int CPerfTracker::GetCPUPercentage()
{
DWORD dwObjectIndex = PROCESS_OBJECT_INDEX;
DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX;
PPERF_DATA_BLOCK pPerfData = NULL;
LONGLONG lnNewValue = GetCounterValueForProcessID<LONGLONG>( &pPerfData, dwObjectIndex, dwCpuUsageIndex, m_dwProcessID );
LARGE_INTEGER NewPerfTime100nSec = pPerfData->PerfTime100nSec;
if ( m_lnOldValue == 0 )
{
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
return 0;
}
LONGLONG lnValueDelta = lnNewValue - m_lnOldValue;
double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart;
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
double a = (double)lnValueDelta / DeltaPerfTime100nSec;
int CpuUsage = (int) (a*100);
if (CpuUsage < 0)
return 0;
return CpuUsage / m_nProcessors;
}
#endif
+28
View File
@@ -0,0 +1,28 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef PERF_COUNTERS_H
#define PERF_COUNTERS_H
#ifdef _WIN32
#pragma once
#endif
class IPerfTracker
{
public:
virtual void Init( unsigned long dwProcessID ) = 0;
virtual void Release() = 0;
virtual unsigned long GetProcessID() = 0;
virtual void GetPerfData( int &processorPercentage, int &memoryUsageMegabytes ) = 0;
};
IPerfTracker* CreatePerfTracker();
#endif // PERF_COUNTERS_H
+18
View File
@@ -0,0 +1,18 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Vmpi_service.rc
//
#define IDS_STRING102 102
#define IDS_VERSION_STRING 102 // *** If this changes, change the matching value in vmpi_defs.h!
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
@@ -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 )
{
}
@@ -0,0 +1,92 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SERVICE_CONN_MGR_H
#define SERVICE_CONN_MGR_H
#ifdef _WIN32
#pragma once
#endif
#include "utllinkedlist.h"
#include "utlvector.h"
#include "tcpsocket.h"
#include "ThreadedTCPSocketEmu.h"
class CServiceConn
{
public:
CServiceConn();
~CServiceConn();
int m_ID;
ITCPSocket *m_pSocket;
DWORD m_LastRecvTime;
};
// ------------------------------------------------------------------------------------------ //
// CServiceConnMgr. This class manages connections to all the UIs (there should only be one UI at
// any given time, but it's conceivable that multiple people can be logged into NT servers
// simultaneously).
// ------------------------------------------------------------------------------------------ //
class CServiceConnMgr
{
public:
CServiceConnMgr();
~CServiceConnMgr();
bool InitServer(); // Registers as a systemwide server.
bool InitClient(); // Connects to the server.
void Term();
// Returns true if there are any connections. If you used InitClient() and there are
// no connections, it will continuously try to connect with a server.
bool IsConnected();
// This should be called as often as possible. It checks for dead connections and it
// handles incoming packets from UIs.
void Update();
// This sends out a message. If id is -1, then it sends to all connections.
void SendPacket( int id, const void *pData, int len );
// Overridables.
public:
virtual void OnNewConnection( int id );
virtual void OnTerminateConnection( int id );
virtual void HandlePacket( const char *pData, int len );
private:
void AttemptConnect();
private:
CUtlLinkedList<CServiceConn*, int> m_Connections;
bool m_bShuttingDown;
// This tells if we're running as a client or server.
bool m_bServer;
// If we're a client, this is the last time we tried to connect.
DWORD m_LastConnectAttemptTime;
// If we're the server, this is the socket we listen on.
ITCPListenSocket *m_pListenSocket;
};
#endif // SERVICE_CONN_MGR_H
+181
View File
@@ -0,0 +1,181 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "stdafx.h"
#include "service_helpers.h"
static CRITICAL_SECTION g_CtrlHandlerMutex;
static void (*g_pInternalServiceFn)( void *pParam ) = NULL;
static void *g_pInternalServiceParam = NULL;
static volatile bool g_bShouldExit = false;
SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle = NULL;
void WINAPI MyServiceCtrlHandler( DWORD Opcode )
{
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here.
ServiceHelpers_ExitEarly();
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus) )
{
status = GetLastError();
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
}
Msg( "[MY_SERVICE] Leaving MyService \n" );
return;
case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;
default:
Msg("[MY_SERVICE] Unrecognized opcode %ld\n", Opcode );
}
// Send current status.
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
{
status = GetLastError();
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
}
}
void WINAPI MyServiceStart( DWORD argc, LPTSTR *argv )
{
DWORD status;
MyServiceStatus.dwServiceType = SERVICE_WIN32;
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatusHandle = RegisterServiceCtrlHandler( "MyService", MyServiceCtrlHandler );
if ( MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
{
Msg("[MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError() );
return;
}
// Initialization complete - report running status.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
{
status = GetLastError();
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
}
// Run the app's main in-thread loop.
g_pInternalServiceFn( g_pInternalServiceParam );
// Tell the SCM that we're stopped.
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwWin32ExitCode = NO_ERROR;
MyServiceStatus.dwServiceSpecificExitCode = 0;
SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus );
// This is where the service does its work.
Msg( "[MY_SERVICE] Returning the Main Thread \n" );
}
void ServiceHelpers_Init()
{
InitializeCriticalSection( &g_CtrlHandlerMutex );
}
bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam )
{
// Ok, just run the service.
const SERVICE_TABLE_ENTRY DispatchTable[2] =
{
{ (char*)pServiceName, MyServiceStart },
{ NULL, NULL }
};
g_pInternalServiceFn = pFn;
g_pInternalServiceParam = pParam;
if ( StartServiceCtrlDispatcher( DispatchTable ) )
{
return true;
}
else
{
Msg( "StartServiceCtrlDispatcher error = '%s'\n", GetLastErrorString() );
return false;
}
}
void ServiceHelpers_ExitEarly()
{
EnterCriticalSection( &g_CtrlHandlerMutex );
g_bShouldExit = true;
LeaveCriticalSection( &g_CtrlHandlerMutex );
}
bool ServiceHelpers_ShouldExit()
{
EnterCriticalSection( &g_CtrlHandlerMutex );
bool bRet = g_bShouldExit;
LeaveCriticalSection( &g_CtrlHandlerMutex );
return bRet;
}
char* GetLastErrorString()
{
static char err[2048];
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
LocalFree( lpMsgBuf );
err[ sizeof( err ) - 1 ] = 0;
return err;
}
+43
View File
@@ -0,0 +1,43 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SERVICE_HELPERS_H
#define SERVICE_HELPERS_H
#ifdef _WIN32
#pragma once
#endif
// Call this if you want to use the ExitEarly() and ShouldExit() helpers.
void ServiceHelpers_Init();
// Start this app in the service control manager.
//
// The service will run in a thread. If the service starts successfully, then
// it will call pFn and pass in pParam. Inside there, you should loop until
// ShouldServiceExit() returns true.
bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam );
// Call this to exit the service early. This will make ShouldServiceExit() return true,
// and your main thread function should pick it up and exit.
//
// NOTE: this can be used even if the service isn't running as long as you call ServiceHelpers_Init().
void ServiceHelpers_ExitEarly();
// Your thread loop should call this each time around. If this function returns true,
// then your thread function should return, causing the service to exit.
//
// NOTE: this can be used even if the service isn't running as long as you call ServiceHelpers_Init().
bool ServiceHelpers_ShouldExit();
// This function wants a better home.
char* GetLastErrorString();
#endif // SERVICE_HELPERS_H
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined(AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_)
#define AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h"
#endif // !defined(AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_)
+74
View File
@@ -0,0 +1,74 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_VERSION_STRING "3.3"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+60
View File
@@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
// VMPI_SERVICE.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,..\..\common,..\"
$PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE"
}
$Linker
{
$AdditionalDependencies "$BASE pdh.lib ws2_32.lib odbc32.lib odbccp32.lib"
}
}
$Project "Vmpi_service"
{
$Folder "Source Files"
{
$File "..\iphelpers.cpp"
$File "service_conn_mgr.cpp"
$File "service_helpers.cpp"
$File "perf_counters.cpp"
$File "vmpi_service.rc"
$File "StdAfx.cpp"
$File "..\tcpsocket_helpers.cpp"
$File "..\ThreadedTCPSocket.cpp"
$File "..\ThreadedTCPSocketEmu.cpp"
$File "..\threadhelpers.cpp"
$File "vmpi_service.cpp"
}
$Folder "Header Files"
{
$File "service_conn_mgr.h"
$File "service_helpers.h"
$File "perf_counters.h"
$File "StdAfx.h"
$File "resource.h"
$File "vmpi_service.h"
}
$Folder "Resource Files"
{
$File "..\vmpi_service_ui\idi_busy_icon.ico"
$File "..\vmpi_service_ui\idi_disabled_icon.ico"
$File "..\vmpi_service_ui\idi_waiting_icon.ico"
$File "..\vmpi_service_ui\vmpi_service.ico"
}
}