mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-21 04:56:01 +08:00
Update from SDK 2013
This commit is contained in:

committed by
Nicholas Hastings

parent
6d5c024820
commit
94b660e16e
22
utils/vmpi/testapps/MessageWatch/MessageRecvMgr.h
Normal file
22
utils/vmpi/testapps/MessageWatch/MessageRecvMgr.h
Normal file
@ -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
|
77
utils/vmpi/testapps/MessageWatch/MessageWatch.cpp
Normal file
77
utils/vmpi/testapps/MessageWatch/MessageWatch.cpp
Normal file
@ -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;
|
||||
}
|
56
utils/vmpi/testapps/MessageWatch/MessageWatch.h
Normal file
56
utils/vmpi/testapps/MessageWatch/MessageWatch.h
Normal file
@ -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_)
|
194
utils/vmpi/testapps/MessageWatch/MessageWatch.rc
Normal file
194
utils/vmpi/testapps/MessageWatch/MessageWatch.rc
Normal file
@ -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
|
||||
|
324
utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp
Normal file
324
utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp
Normal file
@ -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 );
|
||||
}
|
||||
}
|
100
utils/vmpi/testapps/MessageWatch/MessageWatchDlg.h
Normal file
100
utils/vmpi/testapps/MessageWatch/MessageWatchDlg.h
Normal file
@ -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_)
|
15
utils/vmpi/testapps/MessageWatch/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/MessageWatch/StdAfx.cpp
Normal file
@ -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"
|
||||
|
||||
|
||||
|
33
utils/vmpi/testapps/MessageWatch/StdAfx.h
Normal file
33
utils/vmpi/testapps/MessageWatch/StdAfx.h
Normal file
@ -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_)
|
BIN
utils/vmpi/testapps/MessageWatch/res/MessageWatch.ico
Normal file
BIN
utils/vmpi/testapps/MessageWatch/res/MessageWatch.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 766 B |
13
utils/vmpi/testapps/MessageWatch/res/MessageWatch.rc2
Normal file
13
utils/vmpi/testapps/MessageWatch/res/MessageWatch.rc2
Normal file
@ -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...
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
29
utils/vmpi/testapps/MessageWatch/resource.h
Normal file
29
utils/vmpi/testapps/MessageWatch/resource.h
Normal file
@ -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
|
123
utils/vmpi/testapps/MessageWatch/win_idle.cpp
Normal file
123
utils/vmpi/testapps/MessageWatch/win_idle.cpp
Normal file
@ -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);
|
||||
}
|
78
utils/vmpi/testapps/MessageWatch/win_idle.h
Normal file
78
utils/vmpi/testapps/MessageWatch/win_idle.h
Normal file
@ -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__
|
||||
|
15
utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.cpp
Normal file
@ -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
|
31
utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.h
Normal file
31
utils/vmpi/testapps/ThreadedTCPSocketTest/StdAfx.h
Normal file
@ -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_)
|
@ -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;
|
||||
}
|
||||
|
15
utils/vmpi/testapps/pingpong/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/pingpong/StdAfx.cpp
Normal file
@ -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
|
29
utils/vmpi/testapps/pingpong/StdAfx.h
Normal file
29
utils/vmpi/testapps/pingpong/StdAfx.h
Normal file
@ -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_)
|
308
utils/vmpi/testapps/pingpong/pingpong.cpp
Normal file
308
utils/vmpi/testapps/pingpong/pingpong.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
15
utils/vmpi/testapps/socket_stresstest/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/socket_stresstest/StdAfx.cpp
Normal file
@ -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
|
33
utils/vmpi/testapps/socket_stresstest/StdAfx.h
Normal file
33
utils/vmpi/testapps/socket_stresstest/StdAfx.h
Normal file
@ -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_)
|
274
utils/vmpi/testapps/socket_stresstest/socket_stresstest.cpp
Normal file
274
utils/vmpi/testapps/socket_stresstest/socket_stresstest.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
15
utils/vmpi/testapps/vmpi_launch/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/vmpi_launch/StdAfx.cpp
Normal file
@ -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
|
30
utils/vmpi/testapps/vmpi_launch/StdAfx.h
Normal file
30
utils/vmpi/testapps/vmpi_launch/StdAfx.h
Normal file
@ -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_)
|
256
utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp
Normal file
256
utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
38
utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc
Normal file
38
utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc
Normal file
@ -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"
|
||||
}
|
||||
}
|
15
utils/vmpi/testapps/vmpi_ping/StdAfx.cpp
Normal file
15
utils/vmpi/testapps/vmpi_ping/StdAfx.cpp
Normal file
@ -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
|
30
utils/vmpi/testapps/vmpi_ping/StdAfx.h
Normal file
30
utils/vmpi/testapps/vmpi_ping/StdAfx.h
Normal file
@ -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_)
|
196
utils/vmpi/testapps/vmpi_ping/vmpi_ping.cpp
Normal file
196
utils/vmpi/testapps/vmpi_ping/vmpi_ping.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user