diff options
Diffstat (limited to 'utils/vmpi/testapps')
34 files changed, 3801 insertions, 0 deletions
diff --git a/utils/vmpi/testapps/MessageWatch/MessageRecvMgr.h b/utils/vmpi/testapps/MessageWatch/MessageRecvMgr.h new file mode 100644 index 0000000..f570ddc --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageRecvMgr.h @@ -0,0 +1,22 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MESSAGERECVMGR_H +#define MESSAGERECVMGR_H +#ifdef _WIN32 +#pragma once +#endif + + +class IMessageRecvMgr +{ +public: + +}; + + +#endif // MESSAGERECVMGR_H diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatch.cpp b/utils/vmpi/testapps/MessageWatch/MessageWatch.cpp new file mode 100644 index 0000000..4e8dab0 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatch.cpp @@ -0,0 +1,77 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// MessageWatch.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "MessageWatch.h" +#include "MessageWatchDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchApp + +BEGIN_MESSAGE_MAP(CMessageWatchApp, CWinApp) + //{{AFX_MSG_MAP(CMessageWatchApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchApp construction + +CMessageWatchApp::CMessageWatchApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CMessageWatchApp object + +CMessageWatchApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchApp initialization + +BOOL CMessageWatchApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CMessageWatchDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + return FALSE; +} diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatch.h b/utils/vmpi/testapps/MessageWatch/MessageWatch.h new file mode 100644 index 0000000..3ad65ab --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatch.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// MessageWatch.h : main header file for the MESSAGEWATCH application +// + +#if !defined(AFX_MESSAGEWATCH_H__72A09EC9_2B19_4AC5_A281_5FAD41F6DFCA__INCLUDED_) +#define AFX_MESSAGEWATCH_H__72A09EC9_2B19_4AC5_A281_5FAD41F6DFCA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchApp: +// See MessageWatch.cpp for the implementation of this class +// + +class CMessageWatchApp : public CWinApp +{ +public: + CMessageWatchApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMessageWatchApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CMessageWatchApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MESSAGEWATCH_H__72A09EC9_2B19_4AC5_A281_5FAD41F6DFCA__INCLUDED_) diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatch.rc b/utils/vmpi/testapps/MessageWatch/MessageWatch.rc new file mode 100644 index 0000000..bfbbbd5 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatch.rc @@ -0,0 +1,194 @@ +//Microsoft Developer Studio 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 DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\MessageWatch.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "res\\MessageWatch.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MESSAGEWATCH_DIALOG DIALOGEX 0, 0, 232, 147 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "MessageWatch" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Quit",IDCANCEL,175,126,50,14 + LISTBOX IDC_MACHINES,7,7,218,114,LBS_SORT | LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Show All",IDSHOWALL,7,126,50,14 + PUSHBUTTON "&Hide All",IDHIDEALL,91,126,50,14 +END + +IDD_OUTPUT DIALOG DISCARDABLE 0, 0, 320, 225 +STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Output" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DEBUG_OUTPUT,7,7,306,211,ES_MULTILINE | ES_READONLY | + WS_VSCROLL +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "MessageWatch MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "MessageWatch\0" + VALUE "LegalCopyright", "Copyright (C) 2002\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "MessageWatch.EXE\0" + VALUE "ProductName", "MessageWatch Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_MESSAGEWATCH_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 225 + TOPMARGIN, 7 + BOTTOMMARGIN, 140 + END + + IDD_OUTPUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 218 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\MessageWatch.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatch.vcproj b/utils/vmpi/testapps/MessageWatch/MessageWatch.vcproj new file mode 100644 index 0000000..1fd1804 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatch.vcproj @@ -0,0 +1,282 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="MessageWatch" + ProjectGUID="{52DE0F9C-D5D8-4C31-A6EB-6841285BF1CB}" + SccProjectName="" + SccAuxPath="" + SccLocalPath="" + SccProvider="" + Keyword="MFCProj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + UseOfMFC="2" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\common,..\..\..\public,..\..\..\public\tier1,..\..\..\common,.." + PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;PROTECTED_THINGS_DISABLE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Debug/MessageWatch.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="copy "$(TargetPath)" ..\..\..\..\game\bin +" + Outputs="..\..\..\..\game\bin\messagewatch.exe"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib" + OutputFile=".\Debug/MessageWatch.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Debug/MessageWatch.pdb" + SubSystem="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\Debug/MessageWatch.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + UseOfMFC="2" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + AdditionalIncludeDirectories="..\..\common,..\..\..\public,..\..\..\public\tier1,..\..\..\common,.." + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;PROTECTED_THINGS_DISABLE" + StringPooling="TRUE" + RuntimeLibrary="2" + EnableFunctionLevelLinking="TRUE" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Release/MessageWatch.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="copy "$(TargetPath)" ..\..\..\..\game\bin +" + Outputs="..\..\..\..\game\bin\messagewatch.exe"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib" + OutputFile=".\Release/MessageWatch.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + ProgramDatabaseFile=".\Release/MessageWatch.pdb" + SubSystem="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\Release/MessageWatch.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="..\..\common\consolewnd.cpp"> + </File> + <File + RelativePath="MessageWatch.cpp"> + </File> + <File + RelativePath="MessageWatch.rc"> + </File> + <File + RelativePath="MessageWatchDlg.cpp"> + </File> + <File + RelativePath="StdAfx.cpp"> + </File> + <File + RelativePath="win_idle.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="..\..\common\consolewnd.h"> + </File> + <File + RelativePath="..\..\common\iphelpers.h"> + </File> + <File + RelativePath="..\..\common\messagemgr.h"> + </File> + <File + RelativePath="MessageWatch.h"> + </File> + <File + RelativePath="MessageWatchDlg.h"> + </File> + <File + RelativePath="Resource.h"> + </File> + <File + RelativePath="StdAfx.h"> + </File> + <File + RelativePath="..\..\common\tcpsocket.h"> + </File> + <File + RelativePath="..\..\common\threadhelpers.h"> + </File> + <File + RelativePath="win_idle.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + <File + RelativePath="res\MessageWatch.ico"> + </File> + <File + RelativePath="res\MessageWatch.rc2"> + </File> + </Filter> + <File + RelativePath="ReadMe.txt"> + </File> + <File + RelativePath="..\..\..\lib\public\tier0.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\vmpi.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\vstdlib.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp b/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp new file mode 100644 index 0000000..9098caa --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp @@ -0,0 +1,324 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// MessageWatchDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "MessageWatch.h" +#include "MessageWatchDlg.h" +#include "messagemgr.h" +#include "tier1/strtools.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +#define WM_STARTIDLE (WM_USER + 565) + + +// --------------------------------------------------------------------------- // +// CSender. +// --------------------------------------------------------------------------- // + +CSender::CSender() +{ + m_pSocket = NULL; + m_pConsoleWnd = NULL; +} + +CSender::~CSender() +{ + if ( m_pSocket ) + m_pSocket->Release(); + + if ( m_pConsoleWnd ) + m_pConsoleWnd->Release(); +} + + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchDlg dialog + +CMessageWatchDlg::CMessageWatchDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMessageWatchDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMessageWatchDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + + m_pListenSocket = NULL; +} + +CMessageWatchDlg::~CMessageWatchDlg() +{ + // destroy the sender objects. + + if ( m_pListenSocket ) + m_pListenSocket->Release(); +} + +void CMessageWatchDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMessageWatchDlg) + DDX_Control(pDX, IDC_MACHINES, m_Machines); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CMessageWatchDlg, CDialog) + //{{AFX_MSG_MAP(CMessageWatchDlg) + ON_MESSAGE(WM_STARTIDLE, OnStartIdle) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_LBN_DBLCLK(IDC_MACHINES, OnDblclkMachines) + ON_BN_CLICKED(IDSHOWALL, OnShowall) + ON_BN_CLICKED(IDHIDEALL, OnHideall) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchDlg message handlers + +BOOL CMessageWatchDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // Setup our listen socket and thread. + m_pListenSocket = CreateIPSocket(); + m_pListenSocket->BindToAny( MSGMGR_BROADCAST_PORT ); + + m_cWinIdle.StartIdle( GetSafeHwnd(), WM_STARTIDLE, 0, 0, 100 ); + m_cWinIdle.NextIdle(); + + return TRUE; // return TRUE unless you set the focus to a control +} + + +LONG CMessageWatchDlg::OnStartIdle( UINT, LONG ) +{ + MSG msg; + if (!PeekMessage(&msg, GetSafeHwnd(), 0,0, PM_NOREMOVE)) + OnIdle(); + m_cWinIdle.NextIdle(); + return 0; +} + + +void CMessageWatchDlg::OnIdle() +{ + // Kill dead connections. + int iNext; + for ( int iSender=m_Senders.Head(); iSender != m_Senders.InvalidIndex(); iSender = iNext ) + { + iNext = m_Senders.Next( iSender ); + + CSender *pSender = m_Senders[iSender]; + if ( pSender->m_pSocket && !pSender->m_pSocket->IsConnected() ) + { + // Just release the socket so the text stays there. + pSender->m_pSocket->Release(); + pSender->m_pSocket = NULL; + } + } + + // Look for new connections. + while ( 1 ) + { + CIPAddr ipFrom; + char data[16]; + int len = m_pListenSocket->RecvFrom( data, sizeof( data ), &ipFrom ); + if ( len == -1 ) + break; + + if ( data[0] == MSGMGR_PACKETID_ANNOUNCE_PRESENCE && + *((int*)&data[1]) == MSGMGR_VERSION ) + { + int iPort = *((int*)&data[5]); + + // See if we have a machine with this info yet. + CIPAddr connectAddr = ipFrom; + connectAddr.port = iPort; + + // NOTE: we'll accept connections from machines we were connected to earlier but + // lost the connection to. + CSender *pSender = FindSenderByAddr( ipFrom.ip ); + if ( !pSender || !pSender->m_pSocket ) + { + // 'nitiate the connection. + ITCPSocket *pNew = CreateTCPSocket(); + if ( pNew->BindToAny( 0 ) && TCPSocket_Connect( pNew, &connectAddr, 1000 ) ) + { + char nameStr[256]; + char title[512]; + if ( !ConvertIPAddrToString( &ipFrom, nameStr, sizeof( nameStr ) ) ) + Q_snprintf( nameStr, sizeof( nameStr ), "%d.%d.%d.%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3] ); + + Q_snprintf( title, sizeof( title ), "%s:%d", nameStr, iPort ); + + // If the sender didn't exist yet, add a new one. + if ( !pSender ) + { + pSender = new CSender; + + IConsoleWnd *pWnd = CreateConsoleWnd( + AfxGetInstanceHandle(), + IDD_OUTPUT, + IDC_DEBUG_OUTPUT, + false + ); + + pSender->m_pConsoleWnd = pWnd; + pWnd->SetTitle( title ); + + Q_strncpy( pSender->m_Name, title, sizeof( pSender->m_Name ) ); + m_Senders.AddToTail( pSender ); + m_Machines.AddString( pSender->m_Name ); + } + + pSender->m_Addr = connectAddr; + pSender->m_pSocket = pNew; + } + else + { + pNew->Release(); + } + } + } + } + + + // Read input from our current connections. + FOR_EACH_LL( m_Senders, i ) + { + CSender *pSender = m_Senders[i]; + + while ( 1 ) + { + if ( !pSender->m_pSocket ) + break; + + CUtlVector<unsigned char> data; + if ( !pSender->m_pSocket->Recv( data ) ) + break; + + if ( data[0] == MSGMGR_PACKETID_MSG ) + { + char *pMsg = (char*)&data[1]; + pSender->m_pConsoleWnd->PrintToConsole( pMsg ); + OutputDebugString( pMsg ); + } + } + } +} + + +void CMessageWatchDlg::OnDestroy() +{ + // Stop the idling thread + m_cWinIdle.EndIdle(); + CDialog::OnDestroy(); +} + + +CSender* CMessageWatchDlg::FindSenderByAddr( const unsigned char ip[4] ) +{ + FOR_EACH_LL( m_Senders, i ) + { + if ( memcmp( m_Senders[i]->m_Addr.ip, ip, 4 ) == 0 ) + return m_Senders[i]; + } + return NULL; +} + + +CSender* CMessageWatchDlg::FindSenderByName( const char *pName ) +{ + FOR_EACH_LL( m_Senders, i ) + { + if ( stricmp( pName, m_Senders[i]->m_Name ) == 0 ) + return m_Senders[i]; + } + return NULL; +} + + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CMessageWatchDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CMessageWatchDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CMessageWatchDlg::OnDblclkMachines() +{ + int index = m_Machines.GetCurSel(); + if ( index != LB_ERR ) + { + CString str; + m_Machines.GetText( index, str ); + + CSender *pSender = FindSenderByName( str ); + if ( pSender ) + pSender->m_pConsoleWnd->SetVisible( true ); + } +} + +void CMessageWatchDlg::OnShowall() +{ + FOR_EACH_LL( m_Senders, i ) + { + m_Senders[i]->m_pConsoleWnd->SetVisible( true ); + } +} + +void CMessageWatchDlg::OnHideall() +{ + FOR_EACH_LL( m_Senders, i ) + { + m_Senders[i]->m_pConsoleWnd->SetVisible( false ); + } +} diff --git a/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.h b/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.h new file mode 100644 index 0000000..e495a54 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.h @@ -0,0 +1,100 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// MessageWatchDlg.h : header file +// + +#if !defined(AFX_MESSAGEWATCHDLG_H__AB9CEAF4_0166_4CCA_9DEC_77C0918F78C4__INCLUDED_) +#define AFX_MESSAGEWATCHDLG_H__AB9CEAF4_0166_4CCA_9DEC_77C0918F78C4__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#include "iphelpers.h" +#include "tcpsocket.h" +#include "threadhelpers.h" +#include "consolewnd.h" +#include "win_idle.h" + + +///////////////////////////////////////////////////////////////////////////// +// CMessageWatchDlg dialog + +class CSender +{ +public: + CSender(); + ~CSender(); + +public: + + CIPAddr m_Addr; + ITCPSocket *m_pSocket; + IConsoleWnd *m_pConsoleWnd; + char m_Name[128]; +}; + +class CMessageWatchDlg : public CDialog +{ +// Construction +public: + CMessageWatchDlg(CWnd* pParent = NULL); // standard constructor + ~CMessageWatchDlg(); + + + // Listen for broadcasts on this socket. + ISocket *m_pListenSocket; + + // Connections we've made. + CUtlLinkedList<CSender*,int> m_Senders; + + CCriticalSection m_SocketsCS; + CWinIdle m_cWinIdle; + + + CSender* FindSenderByAddr( const unsigned char ip[4] ); + CSender* FindSenderByName( const char *pName ); + + +// Dialog Data + //{{AFX_DATA(CMessageWatchDlg) + enum { IDD = IDD_MESSAGEWATCH_DIALOG }; + CListBox m_Machines; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMessageWatchDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + void OnIdle(); + + // Generated message map functions + //{{AFX_MSG(CMessageWatchDlg) + afx_msg void OnDestroy(); + afx_msg LONG OnStartIdle(UINT, LONG); + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnDblclkMachines(); + afx_msg void OnShowall(); + afx_msg void OnHideall(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MESSAGEWATCHDLG_H__AB9CEAF4_0166_4CCA_9DEC_77C0918F78C4__INCLUDED_) diff --git a/utils/vmpi/testapps/MessageWatch/StdAfx.cpp b/utils/vmpi/testapps/MessageWatch/StdAfx.cpp new file mode 100644 index 0000000..43fa619 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// MessageWatch.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/utils/vmpi/testapps/MessageWatch/StdAfx.h b/utils/vmpi/testapps/MessageWatch/StdAfx.h new file mode 100644 index 0000000..adf866a --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/StdAfx.h @@ -0,0 +1,33 @@ +//========= 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__70653A1B_FB34_4AD9_861C_580071240D6F__INCLUDED_) +#define AFX_STDAFX_H__70653A1B_FB34_4AD9_861C_580071240D6F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include <afxwin.h> // MFC core and standard components +#include <afxext.h> // MFC extensions +#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include <afxcmn.h> // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__70653A1B_FB34_4AD9_861C_580071240D6F__INCLUDED_) diff --git a/utils/vmpi/testapps/MessageWatch/res/MessageWatch.ico b/utils/vmpi/testapps/MessageWatch/res/MessageWatch.ico Binary files differnew file mode 100644 index 0000000..dc0d87d --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/res/MessageWatch.ico diff --git a/utils/vmpi/testapps/MessageWatch/res/MessageWatch.rc2 b/utils/vmpi/testapps/MessageWatch/res/MessageWatch.rc2 new file mode 100644 index 0000000..cf543e7 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/res/MessageWatch.rc2 @@ -0,0 +1,13 @@ +// +// MESSAGEWATCH.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/utils/vmpi/testapps/MessageWatch/resource.h b/utils/vmpi/testapps/MessageWatch/resource.h new file mode 100644 index 0000000..05f2c75 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/resource.h @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by MessageWatch.rc +// +#define IDSHOWALL 3 +#define IDHIDEALL 4 +#define IDD_MESSAGEWATCH_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDD_OUTPUT 129 +#define IDC_MACHINES 1000 +#define IDC_DEBUG_OUTPUT 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/utils/vmpi/testapps/MessageWatch/win_idle.cpp b/utils/vmpi/testapps/MessageWatch/win_idle.cpp new file mode 100644 index 0000000..69ac9da --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/win_idle.cpp @@ -0,0 +1,123 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// Class for sending idle messages to a window + +#include "stdafx.h" +#include "win_idle.h" + +// Stub function to get into the object's main thread loop +DWORD WINAPI CWinIdle::ThreadStub(LPVOID pIdle) +{ + return ((CWinIdle *)pIdle)->RunIdle(); +} + +CWinIdle::CWinIdle() : + m_hIdleThread(NULL), + m_hIdleEvent(NULL), + m_hStopEvent(NULL), + m_hWnd(0), + m_uMsg(0), + m_dwDelay(0) +{ +} + +CWinIdle::~CWinIdle() +{ + if (m_hIdleThread) + OutputDebugString("!!CWinIdle Warning!! Idle thread not shut down!\n"); +} + +DWORD CWinIdle::RunIdle() +{ + // Set up an event list + HANDLE aEvents[2]; + + aEvents[0] = m_hStopEvent; + aEvents[1] = m_hIdleEvent; + + // Wait for a stop or idle event + while (WaitForMultipleObjects(2, aEvents, FALSE, INFINITE) != WAIT_OBJECT_0) + { + // Send an idle message + PostMessage(m_hWnd, m_uMsg, m_wParam, m_lParam); + // Wait for a bit... + Sleep(m_dwDelay); + } + + return 0; +} + +BOOL CWinIdle::StartIdle(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam, DWORD dwDelay) +{ + // Make sure it's not already running + if (m_hIdleThread) + return FALSE; + + // Make sure they send in a valid handle.. + if (!hWnd) + return FALSE; + + // Create the events + m_hIdleEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + m_hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + // Make sure the events got created + if ((!m_hIdleEvent) || (!m_hStopEvent)) + return FALSE; + + // Create the thread + DWORD dwThreadID; + m_hIdleThread = CreateThread(NULL, 0, CWinIdle::ThreadStub, (void *)this, 0, &dwThreadID); + + if (m_hIdleThread) + { + SetThreadPriority(m_hIdleThread, THREAD_PRIORITY_IDLE); + + m_hWnd = hWnd; + m_uMsg = uMessage; + m_wParam = wParam; + m_lParam = lParam; + + m_dwDelay = dwDelay; + } + + return m_hIdleThread != 0; +} + +BOOL CWinIdle::EndIdle() +{ + // Make sure it's running + if (!m_hIdleThread) + return FALSE; + + // Stop the idle thread + SetEvent(m_hStopEvent); + WaitForSingleObject(m_hIdleThread, INFINITE); + CloseHandle(m_hIdleThread); + + // Get rid of the event objects + CloseHandle(m_hIdleEvent); + CloseHandle(m_hStopEvent); + + // Set everything back to 0 + m_hIdleEvent = 0; + m_hStopEvent = 0; + m_hIdleThread = 0; + + return TRUE; +} + +void CWinIdle::NextIdle() +{ + // Make sure the thread's running + if (!m_hIdleThread) + return; + + // Signal an idle message + SetEvent(m_hIdleEvent); +} diff --git a/utils/vmpi/testapps/MessageWatch/win_idle.h b/utils/vmpi/testapps/MessageWatch/win_idle.h new file mode 100644 index 0000000..6e2e3f3 --- /dev/null +++ b/utils/vmpi/testapps/MessageWatch/win_idle.h @@ -0,0 +1,78 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// WinIdle.h - Defines a class for sending idle messages to a window from a secondary thread + +#ifndef __WINIDLE_H__ +#define __WINIDLE_H__ + + +class CWinIdle +{ +protected: + HANDLE m_hIdleEvent, m_hStopEvent; + + HWND m_hWnd; + UINT m_uMsg; + WPARAM m_wParam; + LPARAM m_lParam; + + DWORD m_dwDelay; + + HANDLE m_hIdleThread; + + // The thread calling stub + static DWORD WINAPI ThreadStub(LPVOID pIdle); + // The actual idle loop + virtual DWORD RunIdle(); + +public: + CWinIdle(); + virtual ~CWinIdle(); + + inline DWORD GetDelay() {return m_dwDelay;} + inline void SetDelay(DWORD delay) {m_dwDelay = delay;} + + // Member access + virtual HANDLE GetThreadHandle() const { return m_hIdleThread; }; + + // Start idling, and define the message and window to use + // Returns TRUE on success + virtual BOOL StartIdle(HWND hWnd, UINT uMessage, WPARAM wParam = 0, LPARAM lParam = 0, DWORD dwDelay = 0); + // Stop idling + // Returns TRUE on success + virtual BOOL EndIdle(); + // Notify the idle process that the message was received. + // Note : If this function is not called, the idle thread will not send any messages + virtual void NextIdle(); +}; + + +// Used to slow down the idle thread while dialogs are up. +class IdleChanger +{ +public: + IdleChanger(CWinIdle *pIdle, DWORD msDelay) + { + m_pIdle = pIdle; + m_OldDelay = pIdle->GetDelay(); + pIdle->SetDelay(msDelay); + } + + ~IdleChanger() + { + m_pIdle->SetDelay(m_OldDelay); + } + + CWinIdle *m_pIdle; + DWORD m_OldDelay; +}; + + + +#endif //__WINIDLE_H__ + diff --git a/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.cpp b/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.cpp new file mode 100644 index 0000000..538b0e0 --- /dev/null +++ b/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// ThreadedTCPSocketTest.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 diff --git a/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.h b/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.h new file mode 100644 index 0000000..e29801c --- /dev/null +++ b/utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.h @@ -0,0 +1,31 @@ +//========= 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__AA10D99C_786F_4324_86C6_4D7CDE546561__INCLUDED_) +#define AFX_STDAFX_H__AA10D99C_786F_4324_86C6_4D7CDE546561__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include <stdio.h> +#include <windows.h> +#include <conio.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__AA10D99C_786F_4324_86C6_4D7CDE546561__INCLUDED_) diff --git a/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.cpp b/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.cpp new file mode 100644 index 0000000..0b82c56 --- /dev/null +++ b/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.cpp @@ -0,0 +1,198 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// ThreadedTCPSocketTest.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "IThreadedTCPSocket.h" +#include "threadhelpers.h" +#include "vstdlib/random.h" + + +CCriticalSection g_MsgCS; + + +IThreadedTCPSocket *g_pClientSocket = NULL; +IThreadedTCPSocket *g_pServerSocket = NULL; + +CEvent g_ClientPacketEvent; +CUtlVector<char> g_ClientPacket; + + + +SpewRetval_t MySpewFunc( SpewType_t type, char const *pMsg ) +{ + CCriticalSectionLock csLock( &g_MsgCS ); + csLock.Lock(); + + printf( "%s", pMsg ); + OutputDebugString( pMsg ); + + csLock.Unlock(); + + if( type == SPEW_ASSERT ) + return SPEW_DEBUGGER; + else if( type == SPEW_ERROR ) + return SPEW_ABORT; + else + return SPEW_CONTINUE; +} + + +class CHandler_Server : public ITCPSocketHandler +{ +public: + virtual void Init( IThreadedTCPSocket *pSocket ) + { + } + + virtual void OnPacketReceived( CTCPPacket *pPacket ) + { + // Echo the data back. + g_pServerSocket->Send( pPacket->GetData(), pPacket->GetLen() ); + pPacket->Release(); + } + + virtual void OnError( int errorCode, const char *pErrorString ) + { + Msg( "Server error: %s\n", pErrorString ); + } +}; + + + +class CHandler_Client : public ITCPSocketHandler +{ +public: + virtual void Init( IThreadedTCPSocket *pSocket ) + { + } + + virtual void OnPacketReceived( CTCPPacket *pPacket ) + { + if ( g_ClientPacket.Count() < pPacket->GetLen() ) + g_ClientPacket.SetSize( pPacket->GetLen() ); + + memcpy( g_ClientPacket.Base(), pPacket->GetData(), pPacket->GetLen() ); + g_ClientPacketEvent.SetEvent(); + pPacket->Release(); + } + + virtual void OnError( int errorCode, const char *pErrorString ) + { + Msg( "Client error: %s\n", pErrorString ); + } +}; + + + +class CHandlerCreator_Server : public IHandlerCreator +{ +public: + virtual ITCPSocketHandler* CreateNewHandler() + { + return new CHandler_Server; + } +}; + +class CHandlerCreator_Client : public IHandlerCreator +{ +public: + virtual ITCPSocketHandler* CreateNewHandler() + { + return new CHandler_Client; + } +}; + + + +int main(int argc, char* argv[]) +{ + SpewOutputFunc( MySpewFunc ); + + // Figure out a random port to use. + CCycleCount cnt; + cnt.Sample(); + CUniformRandomStream randomStream; + randomStream.SetSeed( cnt.GetMicroseconds() ); + int iPort = randomStream.RandomInt( 20000, 30000 ); + + + g_ClientPacketEvent.Init( false, false ); + + + // Setup the "server". + CHandlerCreator_Server serverHandler; + CIPAddr addr( 127, 0, 0, 1, iPort ); + + ITCPConnectSocket *pListener = ThreadedTCP_CreateListener( + &serverHandler, + (unsigned short)iPort ); + + + // Setup the "client". + CHandlerCreator_Client clientCreator; + ITCPConnectSocket *pConnector = ThreadedTCP_CreateConnector( + CIPAddr( 127, 0, 0, 1, iPort ), + CIPAddr(), + &clientCreator ); + + + // Wait for them to connect. + while ( !g_pClientSocket ) + { + if ( !pConnector->Update( &g_pClientSocket ) ) + { + Error( "Error in client connector!\n" ); + } + } + pConnector->Release(); + + + while ( !g_pServerSocket ) + { + if ( !pListener->Update( &g_pServerSocket ) ) + Error( "Error in server connector!\n" ); + } + pListener->Release(); + + + // Send some data. + __int64 totalBytes = 0; + CCycleCount startTime; + int iPacket = 1; + + startTime.Sample(); + CUtlVector<char> buf; + + while ( (GetAsyncKeyState( VK_SHIFT ) & 0x8000) == 0 ) + { + int size = randomStream.RandomInt( 1024*0, 1024*320 ); + if ( buf.Count() < size ) + buf.SetSize( size ); + + if ( g_pClientSocket->Send( buf.Base(), size ) ) + { + // Server receives the data and echoes it back. Verify that the data is good. + WaitForSingleObject( g_ClientPacketEvent.GetEventHandle(), INFINITE ); + Assert( memcmp( g_ClientPacket.Base(), buf.Base(), size ) == 0 ); + + totalBytes += size; + CCycleCount curTime, elapsed; + curTime.Sample(); + CCycleCount::Sub( curTime, startTime, elapsed ); + double flSeconds = elapsed.GetSeconds(); + Msg( "Packet %d, %d bytes, %dk/sec\n", iPacket++, size, (int)(((totalBytes+511)/1024) / flSeconds) ); + } + } + + g_pClientSocket->Release(); + g_pServerSocket->Release(); + return 0; +} + diff --git a/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.vcproj b/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.vcproj new file mode 100644 index 0000000..60c80d4 --- /dev/null +++ b/utils/vmpi/testapps/ThreadedTCPSocketTest/ThreadedTCPSocketTest.vcproj @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="ThreadedTCPSocketTest" + ProjectGUID="{6973F221-D381-4569-901F-6D5311FB4CD5}" + SccProjectName="" + SccAuxPath="" + SccLocalPath="" + SccProvider=""> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..,..\..\..\public,..\..\..\public\tier1" + PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Debug/ThreadedTCPSocketTest.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Debug/ThreadedTCPSocketTest.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Debug/ThreadedTCPSocketTest.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Debug/ThreadedTCPSocketTest.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + AdditionalIncludeDirectories="..,..\..\..\public,..\..\..\public\tier1" + PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + StringPooling="TRUE" + RuntimeLibrary="0" + EnableFunctionLevelLinking="TRUE" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Release/ThreadedTCPSocketTest.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="3" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Release/ThreadedTCPSocketTest.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Release/ThreadedTCPSocketTest.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Release/ThreadedTCPSocketTest.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="StdAfx.cpp"> + </File> + <File + RelativePath="..\ThreadedTCPSocket.cpp"> + </File> + <File + RelativePath="..\ThreadedTCPSocketEmu.cpp"> + </File> + <File + RelativePath="ThreadedTCPSocketTest.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="..\IThreadedTCPSocket.h"> + </File> + <File + RelativePath="StdAfx.h"> + </File> + <File + RelativePath="..\ThreadedTCPSocketEmu.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + </Filter> + <File + RelativePath="..\..\..\lib\public\dbg.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\platform.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="ReadMe.txt"> + </File> + <File + RelativePath="..\..\..\lib\public\vmpi.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\vstdlib.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/utils/vmpi/testapps/pingpong/StdAfx.cpp b/utils/vmpi/testapps/pingpong/StdAfx.cpp new file mode 100644 index 0000000..31353c4 --- /dev/null +++ b/utils/vmpi/testapps/pingpong/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// pingpong.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 diff --git a/utils/vmpi/testapps/pingpong/StdAfx.h b/utils/vmpi/testapps/pingpong/StdAfx.h new file mode 100644 index 0000000..59dfc17 --- /dev/null +++ b/utils/vmpi/testapps/pingpong/StdAfx.h @@ -0,0 +1,29 @@ +//========= 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__13A3CFA6_6BF8_45A8_A2CD_91444DCFF7C0__INCLUDED_) +#define AFX_STDAFX_H__13A3CFA6_6BF8_45A8_A2CD_91444DCFF7C0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include <stdio.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__13A3CFA6_6BF8_45A8_A2CD_91444DCFF7C0__INCLUDED_) diff --git a/utils/vmpi/testapps/pingpong/pingpong.cpp b/utils/vmpi/testapps/pingpong/pingpong.cpp new file mode 100644 index 0000000..e589197 --- /dev/null +++ b/utils/vmpi/testapps/pingpong/pingpong.cpp @@ -0,0 +1,308 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// pingpong.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include <assert.h> +#include <stdlib.h> +#include "tcpsocket.h" +#include "tier0/fasttimer.h" +#include "vmpi.h" +#include "tcpsocket_helpers.h" + +//#define USE_MPI + + +#if defined( USE_MPI ) + #include "mpi/mpi.h" + #include "vmpi.h" + #include "tier1/bitbuf.h" + + int myProcId = -1; +#else + IChannel *g_pSocket = NULL; + int g_iPortNum = 27141; +#endif + + +int PrintUsage() +{ + printf( "pingpong <-server or -client ip>\n" ); + return 1; +} + + +void DoClientConnect( const char *pIP ) +{ +#if defined( USE_MPI ) + int argc = 1; + char *testargv[1] = { "-nounc" }; + char **argv = testargv; + if ( MPI_Init( &argc, &argv ) ) + { + assert( false ); + } + MPI_Comm_rank( MPI_COMM_WORLD, &myProcId ); + + int nProcs; + MPI_Comm_size( MPI_COMM_WORLD, &nProcs ); + if ( nProcs != 2 ) + { + assert( false ); + } +#else + // Try to connect, or listen. + ITCPSocket *pTCPSocket = CreateTCPSocket(); + if ( !pTCPSocket->BindToAny( 0 ) ) + { + assert( false ); + } + + CIPAddr addr; + if ( !ConvertStringToIPAddr( pIP, &addr ) ) + { + assert( false ); + } + + addr.port = g_iPortNum; + printf( "Client connecting to %d.%d.%d.%d:%d\n", addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], addr.port ); + if ( !TCPSocket_Connect( pTCPSocket, &addr, 50000 ) ) + { + assert( false ); + } + + printf( "Client connected...\n "); + g_pSocket = pTCPSocket; +#endif +} + + +void DoServerConnect() +{ +#if defined( USE_MPI ) + ISocket *pSocket = CreateIPSocket(); + if ( !pSocket ) + { + printf( "Error creating a socket.\n" ); + assert( false ); + return; + } + else if ( !pSocket->BindToAny( VMPI_SERVICE_PORT ) ) + { + printf( "Error binding a socket to port %d.\n", VMPI_SERVICE_PORT ); + assert( false ); + return; + } + + printf( "Waiting for jobs...\n" ); + while ( 1 ) + { + // Any incoming packets? + char data[2048]; + CIPAddr ipFrom; + int len = pSocket->RecvFrom( data, sizeof( data ), &ipFrom ); + if ( len > 3 ) + { + bf_read buf( data, len ); + if ( buf.ReadByte() == VMPI_PROTOCOL_VERSION ) + { + if ( buf.ReadByte() == VMPI_LOOKING_FOR_WORKERS ) + { + // Read the listen port. + int iListenPort = buf.ReadLong(); + + static char ipString[128]; + _snprintf( ipString, sizeof( ipString ), "%d.%d.%d.%d:%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3], iListenPort ); + + int argc = 3; + char *testargv[3]; + testargv[0] = "<supposedly the executable name!>"; + testargv[1] = "-mpi_worker"; + testargv[2] = ipString; + + char **argv = testargv; + if ( MPI_Init( &argc, &argv ) ) + { + assert( false ); + } + MPI_Comm_rank( MPI_COMM_WORLD, &myProcId ); + + int nProcs; + MPI_Comm_size( MPI_COMM_WORLD, &nProcs ); + if ( nProcs != 2 ) + { + assert( false ); + } + break; + } + } + } + + Sleep( 100 ); + } + + pSocket->Release(); +#else + // Try to connect, or listen. + ITCPListenSocket *pListen = CreateTCPListenSocket( g_iPortNum ); + if ( !pListen ) + { + assert( false ); + } + + printf( "Server listening...\n" ); + + CIPAddr addr; + ITCPSocket *pTCPSocket = TCPSocket_ListenForOneConnection( pListen, &addr, 50000 ); + if ( !pTCPSocket ) + { + assert( false ); + } + pListen->Release(); + + printf( "Server connected...\n "); + g_pSocket = pTCPSocket; +#endif +} + + +void SendData( const void *pBuf, int size ) +{ +#if defined( USE_MPI ) + MPI_Send( (void*)pBuf, size, MPI_BYTE, !myProcId, 0, MPI_COMM_WORLD ); +#else + g_pSocket->Send( pBuf, size ); +#endif +} + + +void RecvData( CUtlVector<unsigned char> &recvBuf ) +{ +#if defined( USE_MPI ) + MPI_Status stat; + MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat); + + recvBuf.SetCount( stat.count ); + MPI_Recv( recvBuf.Base(), stat.count, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat); +#else + if ( !g_pSocket->Recv( recvBuf, 50000 ) ) + { + g_pSocket->Release(); + g_pSocket = NULL; + } +#endif +} + + +int main( int argc, char* argv[] ) +{ + if ( argc < 2 ) + { + return PrintUsage(); + } + + const char *pClientOrServer = argv[1]; + const char *pIP = NULL; + + bool bClient = false; + if ( stricmp( pClientOrServer, "-client" ) == 0 ) + { + if ( argc < 3 ) + { + return PrintUsage(); + } + + bClient = true; + pIP = argv[2]; + } + + CUtlVector<unsigned char> recvBuf; + if ( bClient ) + { + DoClientConnect( pIP ); + + // Ok, now start blasting packets of different sizes and measure how long it takes to get an ack back. + int nIterations = 30; + + for ( int size=350; size <= 350000; size += 512 ) + { + CUtlVector<unsigned char> buf; + buf.SetCount( size ); + + double flTotalRoundTripTime = 0; + + CFastTimer throughputTimer; + throughputTimer.Start(); + + for ( int i=0; i < nIterations; i++ ) + { + for ( int z=0; z < size; z++ ) + buf[z] = (char)rand(); + + SendData( buf.Base(), buf.Count() ); + + CFastTimer timer; + timer.Start(); + RecvData( recvBuf ); + timer.End(); + + + // Make sure we got the same data back. + assert( recvBuf.Count() == buf.Count() ); + for ( z=0; z < size; z++ ) + { + assert( recvBuf[z] == buf[z] ); + } + + + //if ( i % 100 == 0 ) + // printf( "%05d\n", i ); +printf( "%d\n", i ); + flTotalRoundTripTime += timer.GetDuration().GetMillisecondsF(); + } + throughputTimer.End(); + double flTotalSeconds = throughputTimer.GetDuration().GetSeconds(); + + double flAvgRoundTripTime = flTotalRoundTripTime / nIterations; + printf( "%d: %.2f ms per roundtrip (%d bytes/sec) sec: %.2f megs: %.2f\n", + size, + flAvgRoundTripTime, + (int)((size*nIterations)/flTotalSeconds), + flTotalSeconds, + (double)(size*nIterations) / (1024*1024) ); + } + + // Send an 'end' message to the server. + int val = -1; + SendData( &val, sizeof( val ) ); + } + else + { + // Wait for a connection. + DoServerConnect(); + + // Wait for packets and ack them. + while ( 1 ) + { + RecvData( recvBuf ); + if ( !g_pSocket ) + break; + + if ( recvBuf.Count() < 4 ) + { + assert( false ); + } + + SendData( recvBuf.Base(), recvBuf.Count() ); + } + } + + return 0; +} + diff --git a/utils/vmpi/testapps/pingpong/pingpong.vcproj b/utils/vmpi/testapps/pingpong/pingpong.vcproj new file mode 100644 index 0000000..e162afb --- /dev/null +++ b/utils/vmpi/testapps/pingpong/pingpong.vcproj @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="pingpong" + ProjectGUID="{5E114A75-BC7C-4E3A-895D-47C097AFF02B}" + SccProjectName="" + SccAuxPath="" + SccLocalPath="" + SccProvider=""> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + AdditionalIncludeDirectories="..\..\..\public,..\..\common,..\..\vmpi" + PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + StringPooling="TRUE" + RuntimeLibrary="0" + EnableFunctionLevelLinking="TRUE" + PrecompiledHeaderFile=".\Release/pingpong.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="4" + SuppressStartupBanner="TRUE" + DebugInformationFormat="3" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Release/pingpong.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + IgnoreAllDefaultLibraries="FALSE" + IgnoreDefaultLibraryNames="libcmtd.lib" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Release/pingpong.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Release/pingpong.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\..\public,..\..\common,..\..\vmpi" + PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + PrecompiledHeaderFile=".\Debug/pingpong.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="4" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Debug/pingpong.exe" + LinkIncremental="2" + SuppressStartupBanner="TRUE" + IgnoreDefaultLibraryNames="libcmt.lib" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Debug/pingpong.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Debug/pingpong.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="..\..\..\public\tier0\memoverride.cpp"> + </File> + <File + RelativePath="pingpong.cpp"> + </File> + <File + RelativePath="StdAfx.cpp"> + </File> + <File + RelativePath="..\tcpsocket.cpp"> + </File> + <File + RelativePath="..\tcpsocket_helpers.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="..\..\..\public\tier1\bitbuf.h"> + </File> + <File + RelativePath="..\..\..\public\platform\fasttimer.h"> + </File> + <File + RelativePath="..\..\common\ichannel.h"> + </File> + <File + RelativePath="..\..\common\iphelpers.h"> + </File> + <File + RelativePath="..\..\common\loopback_channel.h"> + </File> + <File + RelativePath="StdAfx.h"> + </File> + <File + RelativePath="..\..\common\tcpsocket.h"> + </File> + <File + RelativePath="..\..\..\public\tier1\utlvector.h"> + </File> + <File + RelativePath="..\..\common\vmpi.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + </Filter> + <File + RelativePath="ReadMe.txt"> + </File> + <File + RelativePath="..\..\..\lib\public\tier0.lib"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\tier1.lib"> + </File> + <File + RelativePath="..\..\..\lib\public\vmpi.lib"> + </File> + <File + RelativePath="..\..\..\lib\public\vstdlib.lib"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/utils/vmpi/testapps/socket_stresstest/StdAfx.cpp b/utils/vmpi/testapps/socket_stresstest/StdAfx.cpp new file mode 100644 index 0000000..2b565b0 --- /dev/null +++ b/utils/vmpi/testapps/socket_stresstest/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// socket_stresstest.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 diff --git a/utils/vmpi/testapps/socket_stresstest/StdAfx.h b/utils/vmpi/testapps/socket_stresstest/StdAfx.h new file mode 100644 index 0000000..3c554be --- /dev/null +++ b/utils/vmpi/testapps/socket_stresstest/StdAfx.h @@ -0,0 +1,33 @@ +//========= 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__7E382B26_1CB4_461A_8087_762358153941__INCLUDED_) +#define AFX_STDAFX_H__7E382B26_1CB4_461A_8087_762358153941__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 <stdio.h> +#include "tcpsocket.h" +#include <conio.h> +#include <stdlib.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__7E382B26_1CB4_461A_8087_762358153941__INCLUDED_) diff --git a/utils/vmpi/testapps/socket_stresstest/socket_stresstest.cpp b/utils/vmpi/testapps/socket_stresstest/socket_stresstest.cpp new file mode 100644 index 0000000..55ab97d --- /dev/null +++ b/utils/vmpi/testapps/socket_stresstest/socket_stresstest.cpp @@ -0,0 +1,274 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// socket_stresstest.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "utllinkedlist.h" + + +class CSocketInfo +{ +public: + + bool IsValid() + { + return m_pSocket != 0; + } + + void Term(); + + void ThreadFn(); + + + +public: + ITCPSocket *m_pSocket; + int m_iListenPort; + + DWORD m_CreateTime; // When this socket was created. + DWORD m_ExpireTime; +}; + + + +CSocketInfo g_Infos[132]; +CRITICAL_SECTION g_CS, g_PrintCS; +HANDLE g_hThreads[ ARRAYSIZE( g_Infos ) ]; +bool g_bShouldExit = false; +CUtlLinkedList<int,int> g_ListenPorts; + + +SpewRetval_t StressTestSpew( SpewType_t type, char const *pMsg ) +{ + EnterCriticalSection( &g_PrintCS ); + printf( "%s", pMsg ); + LeaveCriticalSection( &g_PrintCS ); + + if( type == SPEW_ASSERT ) + return SPEW_DEBUGGER; + else if( type == SPEW_ERROR ) + return SPEW_ABORT; + else + return SPEW_CONTINUE; +} + + +void CSocketInfo::Term() +{ + if ( m_pSocket ) + { + m_pSocket->Release(); + m_pSocket = 0; + } +} + + +CSocketInfo* FindOldestSocketInfo( CSocketInfo *pInfos, int nInfos ) +{ + int iOldest = 0; + DWORD oldestTime = 0xFFFFFFFF; + for ( int i=0; i < nInfos; i++ ) + { + if ( !pInfos[i].IsValid() ) + return &pInfos[i]; + + if ( pInfos[i].m_CreateTime < oldestTime ) + { + oldestTime = pInfos[i].m_CreateTime; + iOldest = i; + } + } + return &pInfos[iOldest]; +} + + +int g_iNextExpire = -1; + +void CSocketInfo::ThreadFn() +{ + int iInfo = this - g_Infos; + + while ( !g_bShouldExit ) + { + DWORD curTime = GetTickCount(); + + // Break the connection after a certain amount of time. + if ( m_pSocket && curTime >= m_ExpireTime ) + { + Term(); + Msg( "%02d: expire.\n", iInfo, m_iListenPort ); + } + + if ( m_pSocket ) + { + EnterCriticalSection( &g_CS ); + if ( g_iNextExpire == -1 ) + { + g_iNextExpire = iInfo; + LeaveCriticalSection( &g_CS ); + + Msg( "%02d: forcing an expire.\n", iInfo, m_iListenPort ); + Sleep( 16000 ); + + EnterCriticalSection( &g_CS ); + g_iNextExpire = -1; + } + LeaveCriticalSection( &g_CS ); + + if ( m_pSocket->IsConnected() ) + { + // Receive whatever data it has waiting for it. + CUtlVector<unsigned char> data; + while ( m_pSocket->Recv( data ) ) + { + Msg( "%02d: recv %d.\n", iInfo, data.Count() ); + } + + // Send some data. + int size = rand() % 8192; + data.SetSize( size ); + m_pSocket->Send( data.Base(), data.Count() ); + //Msg( "%02d: send %d.\n", iInfo, data.Count() ); + } + else + { + Term(); + } + } + else + { + // Not initialized.. either listen or connect. + int iConnectPort = -1; + if ( rand() > VALVE_RAND_MAX/2 ) + { + if ( rand() % 100 < 50 ) + Sleep( 500 ); + + EnterCriticalSection( &g_CS ); + int iHead = g_ListenPorts.Head(); + if ( iHead != g_ListenPorts.InvalidIndex() ) + iConnectPort = g_ListenPorts[iHead]; + LeaveCriticalSection( &g_CS ); + } + + if ( iConnectPort != -1 ) + { + CIPAddr addr( 127, 0, 0, 1, iConnectPort ); + + m_pSocket = CreateTCPSocket(); + m_pSocket->BindToAny( 0 ); + m_CreateTime = curTime; + m_ExpireTime = curTime + rand() % 5000; + if ( !TCPSocket_Connect( m_pSocket, &addr, 3.0f ) ) + { + Term(); + } + } + else + { + for ( int iTry=0; iTry < 32; iTry++ ) + { + m_iListenPort = 100 + rand() % (VALVE_RAND_MAX/2); + ITCPListenSocket *pListenSocket = CreateTCPListenSocket( m_iListenPort ); + if ( pListenSocket ) + { + Msg( "%02d: listen on %d.\n", iInfo, m_iListenPort ); + + // Add us to the list of ports to connect to. + EnterCriticalSection( &g_CS ); + g_ListenPorts.AddToTail( m_iListenPort ); + LeaveCriticalSection( &g_CS ); + + // Listen for a connection. + CIPAddr connectedAddr; + m_pSocket = TCPSocket_ListenForOneConnection( pListenSocket, &connectedAddr, 4.0 ); + + // Remove us from the list of ports to connect to. + EnterCriticalSection( &g_CS ); + g_ListenPorts.Remove( g_ListenPorts.Find( m_iListenPort ) ); + LeaveCriticalSection( &g_CS ); + + pListenSocket->Release(); + + if ( m_pSocket ) + { + Msg( "%02d: listen found connection.\n", iInfo ); + m_CreateTime = curTime; + m_ExpireTime = curTime + rand() % 5000; + } + break; + } + } + } + } + + Sleep( 1 ); + } + + g_hThreads[iInfo] = 0; +} + + +DWORD WINAPI ThreadFn( LPVOID lpParameter ) +{ + CSocketInfo *pInfo = (CSocketInfo*)lpParameter; + pInfo->ThreadFn(); + return 0; +} + + +void AllocError( unsigned long size ) +{ + Assert( false ); +} + + +int main(int argc, char* argv[]) +{ + memset( g_Infos, 0, sizeof( g_Infos ) ); + memset( g_hThreads, 0, sizeof( g_hThreads ) ); + + InitializeCriticalSection( &g_CS ); + InitializeCriticalSection( &g_PrintCS ); + + SpewOutputFunc( StressTestSpew ); + Plat_SetAllocErrorFn( AllocError ); + + SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS ); + + for ( int i=0; i < ARRAYSIZE( g_Infos ); i++ ) + { + DWORD dwThreadID = 0; + g_hThreads[i] = CreateThread( + NULL, + 0, + ThreadFn, + &g_Infos[i], + 0, + &dwThreadID ); + } + + + while ( !kbhit() ) + { + } + + g_bShouldExit = true; + + HANDLE hZeroArray[ ARRAYSIZE( g_Infos ) ]; + memset( hZeroArray, 0, sizeof( hZeroArray ) ); + + while ( memcmp( hZeroArray, g_hThreads, sizeof( hZeroArray ) ) != 0 ) + { + Sleep( 10 ); + } + + return 0; +} + diff --git a/utils/vmpi/testapps/socket_stresstest/socket_stresstest.vcproj b/utils/vmpi/testapps/socket_stresstest/socket_stresstest.vcproj new file mode 100644 index 0000000..89b144e --- /dev/null +++ b/utils/vmpi/testapps/socket_stresstest/socket_stresstest.vcproj @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="socket_stresstest" + ProjectGUID="{46DE8944-1A71-4A43-98FE-7A96CB8E5596}" + SccProjectName="" + SccAuxPath="" + SccLocalPath="" + SccProvider=""> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..,..\..\common,..\..\..\public,..\..\..\public\tier1" + PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + PrecompiledHeaderFile=".\Debug/socket_stresstest.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Debug/socket_stresstest.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Debug/socket_stresstest.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Debug/socket_stresstest.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + AdditionalIncludeDirectories="..,..\..\common,..\..\..\public,..\..\..\public\tier1" + PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + StringPooling="TRUE" + RuntimeLibrary="0" + EnableFunctionLevelLinking="TRUE" + PrecompiledHeaderFile=".\Release/socket_stresstest.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Release/socket_stresstest.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + ProgramDatabaseFile=".\Release/socket_stresstest.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Release/socket_stresstest.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="..\iphelpers.cpp"> + </File> + <File + RelativePath="socket_stresstest.cpp"> + </File> + <File + RelativePath="StdAfx.cpp"> + </File> + <File + RelativePath="..\tcpsocket.cpp"> + </File> + <File + RelativePath="..\threadhelpers.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="StdAfx.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + </Filter> + <File + RelativePath="ReadMe.txt"> + </File> + <File + RelativePath="..\..\..\lib\public\tier0.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\vstdlib.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/utils/vmpi/testapps/vmpi_launch/StdAfx.cpp b/utils/vmpi/testapps/vmpi_launch/StdAfx.cpp new file mode 100644 index 0000000..7d621ea --- /dev/null +++ b/utils/vmpi/testapps/vmpi_launch/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// vmpi_launch.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 diff --git a/utils/vmpi/testapps/vmpi_launch/StdAfx.h b/utils/vmpi/testapps/vmpi_launch/StdAfx.h new file mode 100644 index 0000000..a673b65 --- /dev/null +++ b/utils/vmpi/testapps/vmpi_launch/StdAfx.h @@ -0,0 +1,30 @@ +//========= 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__00616BF6_B7E2_4D94_8DC8_3F85BEBD1834__INCLUDED_) +#define AFX_STDAFX_H__00616BF6_B7E2_4D94_8DC8_3F85BEBD1834__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include <stdio.h> +#include <windows.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__00616BF6_B7E2_4D94_8DC8_3F85BEBD1834__INCLUDED_) diff --git a/utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp b/utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp new file mode 100644 index 0000000..7ecb47b --- /dev/null +++ b/utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp @@ -0,0 +1,256 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_launch.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "iphelpers.h" +#include "bitbuf.h" +#include "vmpi.h" + +bool g_bBroadcast = false; + +int PrintUsage() +{ + printf( "vmpi_launch -machine <remote machine> -priority <priority> [-mpi_pw <password>] -command \"command line...\"\n" ); + printf( "-command must be the last switch..\n" ); + return 1; +} + + +int GetCurMicrosecondsAndSleep( int sleepLen ) +{ + Sleep( sleepLen ); + + int retVal; + __asm + { + rdtsc + mov retVal, eax + } + return retVal; +} + + +const char* FindArg( int argc, char **argv, const char *pName, const char *pDefault ) +{ + for ( int i=0; i < argc; i++ ) + { + if ( stricmp( argv[i], pName ) == 0 ) + { + if ( (i+1) < argc ) + return argv[i+1]; + else + return pDefault; + } + } + return NULL; +} + + +int ParseArgs( int argc, char **argv, CIPAddr &remoteIP, int &iPriority, int &iFirstArg ) +{ + if ( FindArg( argc, argv, "-broadcast", "1" ) ) + g_bBroadcast = true; + + if ( g_bBroadcast == false ) + { + const char *pRemoteIPStr = FindArg( argc, argv, "-machine", NULL ); + if ( !pRemoteIPStr || !ConvertStringToIPAddr( pRemoteIPStr, &remoteIP ) ) + { + printf( "%s is not a valid machine name or IP address.\n", pRemoteIPStr ); + return PrintUsage(); + } + } + + iPriority = 0; + const char *pPriorityStr = FindArg( argc, argv, "-priority", NULL ); + if ( pPriorityStr ) + iPriority = atoi( pPriorityStr ); + + if ( iPriority < 0 || iPriority > 1000 ) + { + printf( "%s is not a valid priority.\n", pPriorityStr ); + return PrintUsage(); + } + + const char *pCommand = FindArg( argc, argv, "-command", NULL ); + if ( !pCommand ) + { + return PrintUsage(); + } + for ( iFirstArg=1; iFirstArg < argc; iFirstArg++ ) + { + if ( argv[iFirstArg] == pCommand ) + break; + } + + return 0; +} + + +void SendJobRequest( + ISocket *pSocket, + int argc, + char **argv, + CIPAddr &remoteIP, + int &iPriority, + int &iFirstArg, + int jobID[4] ) +{ + // Build the packet to send out the job. + char packetData[4096]; + bf_write packetBuf; + + // Come up with a unique job ID. + jobID[0] = GetCurMicrosecondsAndSleep( 1 ); + jobID[1] = GetCurMicrosecondsAndSleep( 1 ); + jobID[2] = GetCurMicrosecondsAndSleep( 1 ); + jobID[3] = GetCurMicrosecondsAndSleep( 1 ); + + + // Broadcast out to tell all the machines we want workers. + packetBuf.StartWriting( packetData, sizeof( packetData ) ); + packetBuf.WriteByte( VMPI_PROTOCOL_VERSION ); + + const char *pPassword = FindArg( argc, argv, "-mpi_pw", "" ); + packetBuf.WriteString( pPassword ); + + packetBuf.WriteByte( VMPI_LOOKING_FOR_WORKERS ); + + packetBuf.WriteShort( 0 ); // Tell the port that we're listening on. + // In this case, there is no VMPI master waiting for the app to connect, so + // this parameter doesn't matter. + packetBuf.WriteShort( iPriority ); + + packetBuf.WriteLong( jobID[0] ); + packetBuf.WriteLong( jobID[1] ); + packetBuf.WriteLong( jobID[2] ); + packetBuf.WriteLong( jobID[3] ); + packetBuf.WriteWord( argc-iFirstArg ); // 1 command line argument.. + + // Write the alternate exe name. + for ( int iArg=iFirstArg; iArg < argc; iArg++ ) + packetBuf.WriteString( argv[iArg] ); + + for ( int iBroadcastPort=VMPI_SERVICE_PORT; iBroadcastPort <= VMPI_LAST_SERVICE_PORT; iBroadcastPort++ ) + { + remoteIP.port = iBroadcastPort; + + if ( g_bBroadcast == false ) + pSocket->SendTo( &remoteIP, packetBuf.GetBasePointer(), packetBuf.GetNumBytesWritten() ); + else + pSocket->Broadcast( packetBuf.GetBasePointer(), packetBuf.GetNumBytesWritten(), iBroadcastPort ); + } + + if ( g_bBroadcast == false ) + printf( "Sent command, waiting for reply...\n" ); + else + printf( "Sent command\n" ); +} + + +bool WaitForJobStart( ISocket *pSocket, const CIPAddr &remoteIP, const int jobID[4] ) +{ + while ( 1 ) + { + CIPAddr senderAddr; + char data[4096]; + int len = -1; + + if ( g_bBroadcast == false ) + pSocket->RecvFrom( data, sizeof( data ), &senderAddr ); + else + pSocket->RecvFrom( data, sizeof( data ), NULL ); + + if ( len == 19 && + memcmp( senderAddr.ip, remoteIP.ip, sizeof( senderAddr.ip ) ) == 0 && + data[1] == VMPI_NOTIFY_START_STATUS && + memcmp( &data[2], jobID, 16 ) == 0 ) + { + if ( data[18] == 0 ) + { + // Wasn't able to run. + printf( "Wasn't able to run on target machine.\n" ); + return false; + } + else + { + // Ok, the process is running now. + printf( "Process running, waiting for completion...\n" ); + return true; + } + } + + Sleep( 100 ); + } +} + + +void WaitForJobEnd( ISocket *pSocket, const CIPAddr &remoteIP, const int jobID[4] ) +{ + while ( 1 ) + { + CIPAddr senderAddr; + char data[4096]; + int len = pSocket->RecvFrom( data, sizeof( data ), &senderAddr ); + if ( len == 18 && + memcmp( senderAddr.ip, remoteIP.ip, sizeof( senderAddr.ip ) ) == 0 && + data[1] == VMPI_NOTIFY_END_STATUS && + memcmp( &data[2], jobID, 16 ) == 0 ) + { + int ret = *((int*)&data[2]); + printf( "Finished [%d].\n", ret ); + break; + } + + Sleep( 100 ); + } +} + + +int main(int argc, char* argv[]) +{ + if ( argc < 4 ) + { + return PrintUsage(); + } + + + // Parse the command line. + CIPAddr remoteIP; + int iFirstArg, iPriority; + int jobID[4]; + + int ret = ParseArgs( argc, argv, remoteIP, iPriority, iFirstArg ); + if ( ret != 0 ) + return ret; + + // Now send the command to the vmpi service on that machine. + ISocket *pSocket = CreateIPSocket(); + if ( !pSocket->BindToAny( 0 ) ) + { + printf( "Error binding a socket.\n" ); + return 1; + } + + SendJobRequest( pSocket, argc, argv, remoteIP, iPriority, iFirstArg, jobID ); + + // Wait for a reply, positive or negative. + if ( g_bBroadcast == false ) + { + if ( !WaitForJobStart( pSocket, remoteIP, jobID ) ) + return 2; + + WaitForJobEnd( pSocket, remoteIP, jobID ); + } + + pSocket->Release(); + return 0; +} + diff --git a/utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc b/utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc new file mode 100644 index 0000000..99b642a --- /dev/null +++ b/utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// VMPI_LAUNCH.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\..\..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_exe_con_win32_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,.\,..\.." + } + + $Linker + { + $AdditionalDependencies "ws2_32.lib odbc32.lib odbccp32.lib" + } +} + +$Project "Vmpi_launch" +{ + $Folder "Source Files" + { + $File "..\..\iphelpers.cpp" + $File "StdAfx.cpp" + $File "vmpi_launch.cpp" + } + + $Folder "Header Files" + { + $File "StdAfx.h" + } +} diff --git a/utils/vmpi/testapps/vmpi_ping/StdAfx.cpp b/utils/vmpi/testapps/vmpi_ping/StdAfx.cpp new file mode 100644 index 0000000..94441ca --- /dev/null +++ b/utils/vmpi/testapps/vmpi_ping/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// vmpi_ping.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 diff --git a/utils/vmpi/testapps/vmpi_ping/StdAfx.h b/utils/vmpi/testapps/vmpi_ping/StdAfx.h new file mode 100644 index 0000000..1339f3d --- /dev/null +++ b/utils/vmpi/testapps/vmpi_ping/StdAfx.h @@ -0,0 +1,30 @@ +//========= 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__04B9E767_FE9B_4F2A_84A3_D6B85737214E__INCLUDED_) +#define AFX_STDAFX_H__04B9E767_FE9B_4F2A_84A3_D6B85737214E__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 <stdio.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__04B9E767_FE9B_4F2A_84A3_D6B85737214E__INCLUDED_) diff --git a/utils/vmpi/testapps/vmpi_ping/vmpi_ping.cpp b/utils/vmpi/testapps/vmpi_ping/vmpi_ping.cpp new file mode 100644 index 0000000..17ddd8e --- /dev/null +++ b/utils/vmpi/testapps/vmpi_ping/vmpi_ping.cpp @@ -0,0 +1,196 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_ping.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "iphelpers.h" +#include "vmpi.h" +#include "tier0/platform.h" +#include "bitbuf.h" +#include <conio.h> +#include <stdlib.h> + + +const char* FindArg( int argc, char **argv, const char *pName, const char *pDefault = "" ) +{ + for ( int i=0; i < argc; i++ ) + { + if ( stricmp( argv[i], pName ) == 0 ) + { + if ( (i+1) < argc ) + return argv[i+1]; + else + return pDefault; + } + } + return NULL; +} + + +int main(int argc, char* argv[]) +{ + CUtlVector<CIPAddr> addrs; + + printf( "\n" ); + printf( "vmpi_ping <option>\n" ); + printf( "option can be:\n" ); + printf( " -stop .. stop any VMPI services\n" ); + printf( " -kill .. kill any processes being run by VMPI\n" ); + printf( " -patch <timeout> .. stops VMPI services for <timeout> seconds\n" ); + printf( " -mpi_pw <password> .. only talk to services with the specified password\n" ); + printf( " -dns .. enable DNS lookups (slows the listing down)\n" ); + printf( " -ShowConsole .. show the console window\n" ); + printf( " -HideConsole .. hide the console window\n" ); + + //Scary to show these to users... + //printf( " -ShowCache .. show the cache directory and its capacity\n" ); + //printf( " -FlushCache .. flush the cache of ALL VMPI services\n" ); + + printf( "\n" ); + + + ISocket *pSocket = CreateIPSocket(); + if ( !pSocket->BindToAny( 0 ) ) + { + printf( "Error binding to a port!\n" ); + return 1; + } + + const char *pPassword = FindArg( argc, argv, "-mpi_pw" ); + + + // Figure out which action they want to take. + int timeout = 0; + char cRequest = VMPI_PING_REQUEST; + if ( FindArg( argc, argv, "-Stop" ) ) + { + cRequest = VMPI_STOP_SERVICE; + } + else if ( FindArg( argc, argv, "-Kill" ) ) + { + cRequest = VMPI_KILL_PROCESS; + } +/* + else if ( FindArg( argc, argv, "-ShowConsole" ) ) + { + cRequest = VMPI_SHOW_CONSOLE_WINDOW; + } + else if ( FindArg( argc, argv, "-HideConsole" ) ) + { + cRequest = VMPI_HIDE_CONSOLE_WINDOW; + } +*/ + else if ( FindArg( argc, argv, "-ShowCache" ) ) + { + cRequest = VMPI_GET_CACHE_INFO; + } + else if ( FindArg( argc, argv, "-FlushCache" ) ) + { + cRequest = VMPI_FLUSH_CACHE; + } + else + { + const char *pTimeout = FindArg( argc, argv, "-patch", "60" ); + if ( pTimeout ) + { + if ( isdigit( pTimeout[0] ) ) + { + cRequest = VMPI_SERVICE_PATCH; + timeout = atoi( pTimeout ); + printf( "Patching with timeout of %d seconds.\n", timeout ); + } + else + { + printf( "-patch requires a timeout parameter.\n" ); + return 1; + } + } + } + + + int nMachines = 0; + printf( "Pinging VMPI Services... press a key to stop.\n\n" ); + while ( !kbhit() ) + { + for ( int i=VMPI_SERVICE_PORT; i <= VMPI_LAST_SERVICE_PORT; i++ ) + { + unsigned char data[256]; + bf_write buf( data, sizeof( data ) ); + buf.WriteByte( VMPI_PROTOCOL_VERSION ); + buf.WriteString( pPassword ); + buf.WriteByte( cRequest ); + + if ( cRequest == VMPI_SERVICE_PATCH ) + buf.WriteLong( timeout ); + + pSocket->Broadcast( data, buf.GetNumBytesWritten(), i ); + } + + while ( 1 ) + { + CIPAddr ipFrom; + char in[256]; + int len = pSocket->RecvFrom( in, sizeof( in ), &ipFrom ); + if ( len == -1 ) + break; + + if ( len >= 2 && + in[0] == VMPI_PROTOCOL_VERSION && + in[1] == VMPI_PING_RESPONSE && + addrs.Find( ipFrom ) == -1 ) + { + char *pStateString = "(unknown)"; + if ( len >= 3 ) + { + if ( in[2] ) + pStateString = "(running)"; + else + pStateString = "(idle) "; + } + + ++nMachines; + char nameStr[256]; + + if ( FindArg( argc, argv, "-dns" ) && ConvertIPAddrToString( &ipFrom, nameStr, sizeof( nameStr ) ) ) + { + printf( "%02d. %s - %s:%d (%d.%d.%d.%d)", + nMachines, pStateString, nameStr, ipFrom.port, + ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3] ); + } + else + { + printf( "%02d. %s - %d.%d.%d.%d:%d", + nMachines, pStateString, ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3], ipFrom.port ); + } + + if ( cRequest == VMPI_GET_CACHE_INFO ) + { + // Next var is a 64-bit int with the size of the cache. + char *pCur = &in[3]; + __int64 cacheSize = *((__int64*)pCur); + pCur += sizeof( __int64 ); + + char *pCacheDir = pCur; + + __int64 nMegs = cacheSize / (1024*1024); + printf( "\n\tCache dir: %s, size: %d megs", pCur, nMegs ); + } + + printf( "\n" ); + + addrs.AddToTail( ipFrom ); + } + } + + Sleep( 1000 ); + } + + return 0; +} + diff --git a/utils/vmpi/testapps/vmpi_ping/vmpi_ping.vcproj b/utils/vmpi/testapps/vmpi_ping/vmpi_ping.vcproj new file mode 100644 index 0000000..a2a6dc7 --- /dev/null +++ b/utils/vmpi/testapps/vmpi_ping/vmpi_ping.vcproj @@ -0,0 +1,249 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="vmpi_ping" + ProjectGUID="{D6F83A58-89A2-4F57-9761-32208BD95E83}" + SccProjectName="" + SccAuxPath="" + SccLocalPath="" + SccProvider=""> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\common,..\..\..\common,..\..\..\public,..\..\..\public\tier1,.." + PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + BasicRuntimeChecks="3" + RuntimeLibrary="5" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Debug/vmpi_ping.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="if exist ..\..\..\..\game\bin\vmpi_ping.exe attrib -r ..\..\..\..\game\bin\vmpi_ping.exe +copy "$(TargetPath)" ..\..\..\..\game\bin +" + Outputs="..\..\..\..\game\bin\vmpi_ping.exe"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Debug/vmpi_ping.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile=".\Debug/vmpi_ping.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Debug/vmpi_ping.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + AdditionalIncludeDirectories="..\..\common,..\..\..\common,..\..\..\public,..\..\..\public\tier1,.." + PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;PROTECTED_THINGS_DISABLE" + StringPooling="TRUE" + RuntimeLibrary="4" + EnableFunctionLevelLinking="TRUE" + UsePrecompiledHeader="3" + PrecompiledHeaderThrough="stdafx.h" + PrecompiledHeaderFile=".\Release/vmpi_ping.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + CompileAs="0"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="if exist ..\..\..\..\game\bin\vmpi_ping.exe attrib -r ..\..\..\..\game\bin\vmpi_ping.exe +copy "$(TargetPath)" ..\..\..\..\game\bin +" + Outputs="..\..\..\..\game\bin\vmpi_ping.exe"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib" + OutputFile=".\Release/vmpi_ping.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + ProgramDatabaseFile=".\Release/vmpi_ping.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Release/vmpi_ping.tlb" + HeaderFileName=""/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="..\iphelpers.cpp"> + </File> + <File + RelativePath="..\..\..\public\tier0\memoverride.cpp"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0"/> + </FileConfiguration> + </File> + <File + RelativePath="StdAfx.cpp"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1"/> + </FileConfiguration> + </File> + <File + RelativePath="vmpi_ping.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="..\..\common\iphelpers.h"> + </File> + <File + RelativePath="StdAfx.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"> + </Filter> + <File + RelativePath="ReadMe.txt"> + </File> + <File + RelativePath="..\..\..\lib\public\tier0.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\lib\public\tier1.lib"> + </File> + <File + RelativePath="..\..\..\lib\public\vstdlib.lib"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine=""/> + </FileConfiguration> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> |