|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
Rtclnt.c
Abstract:
Client side of basic RPC scale performance test.
Author:
Mario Goertzel (mariogo) 31-Mar-1994
Revision History:
18/7/96 [MarioGo] - Cloned from rpcrt test
--*/
#include <rpcperf.h>
#include <rpcrt.h>
#ifdef MAC
extern void _cdecl PrintToConsole(const char *lpszFormat, ...) ; extern unsigned long ulSecurityPackage ; #else
#define PrintToConsole printf
extern unsigned long ulSecurityPackage; #endif
// Usage
const char *USAGE = "-n <threads> -a <authnlevel> -s <server> -t <protseq>\n" "Server controls iterations, test cases, and compiles the results.\n" "AuthnLevel: none, connect, call, pkt, integrity, privacy.\n" "Default threads=1, authnlevel=none\n";
unsigned long gInSize = 500 - IN_ADJUSTMENT; unsigned long gOutSize = 500 - OUT_ADJUSTMENT;
#ifdef STATS
// exported by RPCRT4
void I_RpcGetStats(DWORD *pdwStat1, DWORD *pdwStat2, DWORD *pdwStat3, DWORD *pdwStat4); #endif
// Error stuff
#define CHECK_RET(status, string) if (status)\
{ PrintToConsole("%s failed -- %lu (0x%08X)\n", string,\ (unsigned long)status, (unsigned long)status);\ return (status); }
RPC_STATUS DoRpcBindingSetAuthInfo(handle_t Binding) { if (AuthnLevel != RPC_C_AUTHN_LEVEL_NONE) return RpcBindingSetAuthInfoA(Binding, ServerPrincipalName, AuthnLevel, ulSecurityPackage, NULL, RPC_C_AUTHZ_NONE); else return(RPC_S_OK); }
//
// Test wrappers
//
unsigned long DoNullCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p) { unsigned long status; unsigned long calls = 0;
do { status = NullCall(*pb, c); calls++;
} while (status == 0);
if (status != PERF_TESTS_DONE) { RpcRaiseException(status); }
return(calls); }
unsigned long DoMaybeCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p) { unsigned long calls = 0;
for(calls = 10000; calls; calls--) { MaybeCall(*pb, c); }
return(10000); }
unsigned long DoNICall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p) { unsigned long status; unsigned long calls = 0;
do { status = NICall(*pb, c); calls++;
} while (status == 0);
if (status != PERF_TESTS_DONE) { RpcRaiseException(status); }
return(calls); }
unsigned long DoBufferCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p) { unsigned long status; unsigned long calls = 0;
do { RpcTryExcept { status = BufferCall(*pb, c, gInSize, p, gOutSize, p); } RpcExcept(1) { PrintToConsole("\nException %lu (0x%08lX)\n", (unsigned long)RpcExceptionCode(), (unsigned long)RpcExceptionCode()); } RpcEndExcept calls++;
} while (status != PERF_TESTS_DONE);
if (status != PERF_TESTS_DONE) { RpcRaiseException(status); }
return(calls); }
unsigned long DoBindCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p) { unsigned long status; unsigned long calls = 0;
do { status = RpcBindingFree(pb); if (status) { break; }
status = RpcBindingFromStringBindingA(stringBinding, pb); if (status) { break; }
status = NullCall(*pb, c);
calls++; } while (status == 0);
if (status != PERF_TESTS_DONE) { RpcRaiseException(status); }
return(calls); }
static const unsigned long (*TestTable[TEST_MAX])(handle_t *pb, char *stringBinding, unsigned long, char __RPC_FAR *) = { DoNullCall, DoNICall, DoBufferCall, DoMaybeCall, DoBindCall };
//
// Worker calls the correct tests. Maybe multithreaded on NT
//
unsigned long Worker(unsigned long l) { unsigned long status; unsigned long Test; unsigned long ClientId; unsigned long InSize, OutSize; unsigned long Time, Calls; char __RPC_FAR *pBuffer; char __RPC_FAR *stringBinding; handle_t binding; RPC_STATUS RpcErr; int Retries;
pBuffer = MIDL_user_allocate(128*1024L); if (pBuffer == 0) { PrintToConsole("Out of memory!"); return 1; }
status = RpcStringBindingComposeA(0, Protseq, NetworkAddr, Endpoint, 0, &stringBinding); CHECK_RET(status, "RpcStringBindingCompose");
status = RpcBindingFromStringBindingA(stringBinding, &binding); CHECK_RET(status, "RpcBindingFromStringBinding");
status = DoRpcBindingSetAuthInfo(binding); CHECK_RET(status, "RpcBindingSetAuthInfo");
Retries = 15;
do { status = BeginTest(binding, &ClientId, &Test, &InSize, &OutSize);
if (status == PERF_TOO_MANY_CLIENTS) { PrintToConsole("Too many clients, I'm exiting\n"); goto Cleanup ; }
Retries --; if ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0)) { PrintToConsole("Server too busy - retrying ...\n"); } } while ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
if (status) { RPC_STATUS Status2; RPC_ERROR_ENUM_HANDLE EnumHandle;
Status2 = RpcErrorStartEnumeration(&EnumHandle); if (Status2 == RPC_S_ENTRY_NOT_FOUND) { CHECK_RET(status, "ClientConnect"); } else if (Status2 != RPC_S_OK) { PrintToConsole("Couldn't get EEInfo: %d\n", Status2); CHECK_RET(status, "ClientConnect"); } else { RPC_EXTENDED_ERROR_INFO ErrorInfo; int Records; BOOL Result; BOOL CopyStrings = TRUE; PVOID Blob; size_t BlobSize; BOOL fUseFileTime = TRUE; SYSTEMTIME *SystemTimeToUse; SYSTEMTIME SystemTimeBuffer;
Status2 = RpcErrorGetNumberOfRecords(&EnumHandle, &Records); if (Status2 == RPC_S_OK) { PrintToConsole("Number of records is: %d\n", Records); }
while (Status2 == RPC_S_OK) { ErrorInfo.Version = RPC_EEINFO_VERSION; ErrorInfo.Flags = 0; ErrorInfo.NumberOfParameters = 4; if (fUseFileTime) { ErrorInfo.Flags |= EEInfoUseFileTime; }
Status2 = RpcErrorGetNextRecord(&EnumHandle, CopyStrings, &ErrorInfo); if (Status2 == RPC_S_ENTRY_NOT_FOUND) { RpcErrorResetEnumeration(&EnumHandle); break; } else if (Status2 != RPC_S_OK) { PrintToConsole("Couldn't finish enumeration: %d\n", Status2); break; } else { int i;
if (ErrorInfo.ComputerName) { PrintToConsole("ComputerName is %S\n", ErrorInfo.ComputerName); if (CopyStrings) { Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.ComputerName); ASSERT(Result); } } PrintToConsole("ProcessID is %d\n", ErrorInfo.ProcessID); if (fUseFileTime) { Result = FileTimeToSystemTime(&ErrorInfo.u.FileTime, &SystemTimeBuffer); ASSERT(Result); SystemTimeToUse = &SystemTimeBuffer; } else SystemTimeToUse = &ErrorInfo.u.SystemTime;
PrintToConsole("System Time is: %d/%d/%d %d:%d:%d:%d\n", SystemTimeToUse->wMonth, SystemTimeToUse->wDay, SystemTimeToUse->wYear, SystemTimeToUse->wHour, SystemTimeToUse->wMinute, SystemTimeToUse->wSecond, SystemTimeToUse->wMilliseconds); PrintToConsole("Generating component is %d\n", ErrorInfo.GeneratingComponent); PrintToConsole("Status is %d\n", ErrorInfo.Status); PrintToConsole("Detection location is %d\n", (int)ErrorInfo.DetectionLocation); PrintToConsole("Flags is %d\n", ErrorInfo.Flags); PrintToConsole("NumberOfParameters is %d\n", ErrorInfo.NumberOfParameters); for (i = 0; i < ErrorInfo.NumberOfParameters; i ++) { switch(ErrorInfo.Parameters[i].ParameterType) { case eeptAnsiString: PrintToConsole("Ansi string: %s\n", ErrorInfo.Parameters[i].u.AnsiString); if (CopyStrings) { Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.Parameters[i].u.AnsiString); ASSERT(Result); } break;
case eeptUnicodeString: PrintToConsole("Unicode string: %S\n", ErrorInfo.Parameters[i].u.UnicodeString); if (CopyStrings) { Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.Parameters[i].u.UnicodeString); ASSERT(Result); } break;
case eeptLongVal: PrintToConsole("Long val: %d\n", ErrorInfo.Parameters[i].u.LVal); break;
case eeptShortVal: PrintToConsole("Short val: %d\n", (int)ErrorInfo.Parameters[i].u.SVal); break;
case eeptPointerVal: PrintToConsole("Pointer val: %d\n", ErrorInfo.Parameters[i].u.PVal); break;
case eeptNone: PrintToConsole("Truncated\n"); break;
default: PrintToConsole("Invalid type: %d\n", ErrorInfo.Parameters[i].ParameterType); } } } } Status2 = RpcErrorSaveErrorInfo(&EnumHandle, &Blob, &BlobSize); CHECK_RET(Status2, "RpcErrorSaveErrorInfo"); RpcErrorClearInformation(); RpcErrorEndEnumeration(&EnumHandle); Status2 = RpcErrorLoadErrorInfo(Blob, BlobSize, &EnumHandle); CHECK_RET(Status2, "RpcErrorLoadErrorInfo"); } }
CHECK_RET(status, "ClientConnect");
if (InSize > IN_ADJUSTMENT) { InSize -= IN_ADJUSTMENT; } else { InSize = 0; }
if (OutSize > OUT_ADJUSTMENT) { OutSize -= OUT_ADJUSTMENT; } else { OutSize = 0; }
gInSize = InSize; gOutSize = OutSize;
PrintToConsole("Client %ld connected\n", ClientId);
Retries = 15;
do { RpcTryExcept { RpcErr = RPC_S_OK;
Time = GetTickCount();
Calls = ( (TestTable[Test])(&binding, stringBinding, ClientId, pBuffer) );
Time = GetTickCount() - Time; Dump("Completed %d calls in %d ms\n" "%d T/S or %3d.%03d ms/T\n\n", Calls, Time, (Calls * 1000) / Time, Time / Calls, ((Time % Calls) * 1000) / Calls ); } RpcExcept(1) { RpcErr = (unsigned long)RpcExceptionCode(); PrintToConsole("\nException %lu (0x%08lX)\n", RpcErr, RpcErr); } RpcEndExcept Retries --; if ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0)) { PrintToConsole("Server too busy - retrying ...\n"); } } while ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
Cleanup: RpcBindingFree(&binding); return status; }
//
// The Win32 main starts worker threads, otherwise we just call the worker.
//
#ifdef WIN32
int __cdecl main (int argc, char **argv) { char option; unsigned long status, i; HANDLE *pClientThreads; DWORD dwStat1, dwStat2, dwStat3, dwStat4;
InitAllocator();
ulSecurityPackage = RPC_C_AUTHN_WINNT; ParseArgv(argc, argv);
PrintToConsole("Authentication Level is: %s\n", AuthnLevelStr);
if (Options[0] < 0) Options[0] = 1;
pClientThreads = MIDL_user_allocate(sizeof(HANDLE) * Options[0]);
for(i = 0; i < (unsigned long)Options[0]; i++) { pClientThreads[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Worker, 0, 0, &status); if (pClientThreads[i] == 0) ApiError("CreateThread", GetLastError()); }
status = WaitForMultipleObjects(Options[0], pClientThreads, TRUE, // Wait for all client threads
INFINITE); if (status == WAIT_FAILED) { ApiError("WaitForMultipleObjects", GetLastError()); }
#ifdef STATS
I_RpcGetStats(&dwStat1, &dwStat2, &dwStat3, &dwStat4); printf("Stats are: %ld, %ld, %ld, %ld\n", dwStat1, dwStat2, dwStat3, dwStat4); #endif
PrintToConsole("TEST DONE\n"); return(0); } #else // !WIN32
#ifdef WIN
#define main c_main
// We need the following to force the linker to load WinMain from the
// Windows STDIO library
extern int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int); static int (PASCAL *wm_ptr)(HANDLE, HANDLE, LPSTR, int) = WinMain;
#endif
#ifndef MAC
#ifndef FAR
#define FAR __far
#endif
#else
#define FAR
#define main c_main
#endif
int main (int argc, char FAR * FAR * argv) { #ifndef MAC
ParseArgv(argc, argv); #endif
Worker(0);
PrintToConsole("TEST DONE\n");
return(0); } #endif // NTENV
|