mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-10 18:59:36 +00:00
1
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user