summaryrefslogtreecommitdiff
path: root/utils/vmpi/testapps/vmpi_launch
diff options
context:
space:
mode:
Diffstat (limited to 'utils/vmpi/testapps/vmpi_launch')
-rw-r--r--utils/vmpi/testapps/vmpi_launch/StdAfx.cpp15
-rw-r--r--utils/vmpi/testapps/vmpi_launch/StdAfx.h30
-rw-r--r--utils/vmpi/testapps/vmpi_launch/vmpi_launch.cpp256
-rw-r--r--utils/vmpi/testapps/vmpi_launch/vmpi_launch.vpc38
4 files changed, 339 insertions, 0 deletions
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"
+ }
+}