Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

562 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. Rtclnt.c
  5. Abstract:
  6. Client side of basic RPC scale performance test.
  7. Author:
  8. Mario Goertzel (mariogo) 31-Mar-1994
  9. Revision History:
  10. 18/7/96 [MarioGo] - Cloned from rpcrt test
  11. --*/
  12. #include <rpcperf.h>
  13. #include <rpcrt.h>
  14. #ifdef MAC
  15. extern void _cdecl PrintToConsole(const char *lpszFormat, ...) ;
  16. extern unsigned long ulSecurityPackage ;
  17. #else
  18. #define PrintToConsole printf
  19. extern unsigned long ulSecurityPackage;
  20. #endif
  21. // Usage
  22. const char *USAGE = "-n <threads> -a <authnlevel> -s <server> -t <protseq>\n"
  23. "Server controls iterations, test cases, and compiles the results.\n"
  24. "AuthnLevel: none, connect, call, pkt, integrity, privacy.\n"
  25. "Default threads=1, authnlevel=none\n";
  26. unsigned long gInSize = 500 - IN_ADJUSTMENT;
  27. unsigned long gOutSize = 500 - OUT_ADJUSTMENT;
  28. #ifdef STATS
  29. // exported by RPCRT4
  30. void I_RpcGetStats(DWORD *pdwStat1, DWORD *pdwStat2, DWORD *pdwStat3, DWORD *pdwStat4);
  31. #endif
  32. // Error stuff
  33. #define CHECK_RET(status, string) if (status)\
  34. { PrintToConsole("%s failed -- %lu (0x%08X)\n", string,\
  35. (unsigned long)status, (unsigned long)status);\
  36. return (status); }
  37. RPC_STATUS DoRpcBindingSetAuthInfo(handle_t Binding)
  38. {
  39. if (AuthnLevel != RPC_C_AUTHN_LEVEL_NONE)
  40. return RpcBindingSetAuthInfoA(Binding,
  41. ServerPrincipalName,
  42. AuthnLevel,
  43. ulSecurityPackage,
  44. NULL,
  45. RPC_C_AUTHZ_NONE);
  46. else
  47. return(RPC_S_OK);
  48. }
  49. //
  50. // Test wrappers
  51. //
  52. unsigned long DoNullCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p)
  53. {
  54. unsigned long status;
  55. unsigned long calls = 0;
  56. do
  57. {
  58. status = NullCall(*pb, c);
  59. calls++;
  60. }
  61. while (status == 0);
  62. if (status != PERF_TESTS_DONE)
  63. {
  64. RpcRaiseException(status);
  65. }
  66. return(calls);
  67. }
  68. unsigned long DoMaybeCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p)
  69. {
  70. unsigned long calls = 0;
  71. for(calls = 10000; calls; calls--)
  72. {
  73. MaybeCall(*pb, c);
  74. }
  75. return(10000);
  76. }
  77. unsigned long DoNICall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p)
  78. {
  79. unsigned long status;
  80. unsigned long calls = 0;
  81. do
  82. {
  83. status = NICall(*pb, c);
  84. calls++;
  85. }
  86. while (status == 0);
  87. if (status != PERF_TESTS_DONE)
  88. {
  89. RpcRaiseException(status);
  90. }
  91. return(calls);
  92. }
  93. unsigned long DoBufferCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p)
  94. {
  95. unsigned long status;
  96. unsigned long calls = 0;
  97. do
  98. {
  99. RpcTryExcept
  100. {
  101. status = BufferCall(*pb, c, gInSize, p, gOutSize, p);
  102. }
  103. RpcExcept(1)
  104. {
  105. PrintToConsole("\nException %lu (0x%08lX)\n",
  106. (unsigned long)RpcExceptionCode(),
  107. (unsigned long)RpcExceptionCode());
  108. }
  109. RpcEndExcept
  110. calls++;
  111. }
  112. while (status != PERF_TESTS_DONE);
  113. if (status != PERF_TESTS_DONE)
  114. {
  115. RpcRaiseException(status);
  116. }
  117. return(calls);
  118. }
  119. unsigned long DoBindCall(handle_t *pb, char *stringBinding, unsigned long c, char __RPC_FAR *p)
  120. {
  121. unsigned long status;
  122. unsigned long calls = 0;
  123. do
  124. {
  125. status = RpcBindingFree(pb);
  126. if (status)
  127. {
  128. break;
  129. }
  130. status = RpcBindingFromStringBindingA(stringBinding, pb);
  131. if (status)
  132. {
  133. break;
  134. }
  135. status = NullCall(*pb, c);
  136. calls++;
  137. }
  138. while (status == 0);
  139. if (status != PERF_TESTS_DONE)
  140. {
  141. RpcRaiseException(status);
  142. }
  143. return(calls);
  144. }
  145. static const unsigned long (*TestTable[TEST_MAX])(handle_t *pb, char *stringBinding, unsigned long, char __RPC_FAR *) =
  146. {
  147. DoNullCall,
  148. DoNICall,
  149. DoBufferCall,
  150. DoMaybeCall,
  151. DoBindCall
  152. };
  153. //
  154. // Worker calls the correct tests. Maybe multithreaded on NT
  155. //
  156. unsigned long Worker(unsigned long l)
  157. {
  158. unsigned long status;
  159. unsigned long Test;
  160. unsigned long ClientId;
  161. unsigned long InSize, OutSize;
  162. unsigned long Time, Calls;
  163. char __RPC_FAR *pBuffer;
  164. char __RPC_FAR *stringBinding;
  165. handle_t binding;
  166. RPC_STATUS RpcErr;
  167. int Retries;
  168. pBuffer = MIDL_user_allocate(128*1024L);
  169. if (pBuffer == 0)
  170. {
  171. PrintToConsole("Out of memory!");
  172. return 1;
  173. }
  174. status =
  175. RpcStringBindingComposeA(0,
  176. Protseq,
  177. NetworkAddr,
  178. Endpoint,
  179. 0,
  180. &stringBinding);
  181. CHECK_RET(status, "RpcStringBindingCompose");
  182. status =
  183. RpcBindingFromStringBindingA(stringBinding, &binding);
  184. CHECK_RET(status, "RpcBindingFromStringBinding");
  185. status =
  186. DoRpcBindingSetAuthInfo(binding);
  187. CHECK_RET(status, "RpcBindingSetAuthInfo");
  188. Retries = 15;
  189. do
  190. {
  191. status = BeginTest(binding, &ClientId, &Test, &InSize, &OutSize);
  192. if (status == PERF_TOO_MANY_CLIENTS)
  193. {
  194. PrintToConsole("Too many clients, I'm exiting\n");
  195. goto Cleanup ;
  196. }
  197. Retries --;
  198. if ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0))
  199. {
  200. PrintToConsole("Server too busy - retrying ...\n");
  201. }
  202. }
  203. while ((status == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
  204. if (status)
  205. {
  206. RPC_STATUS Status2;
  207. RPC_ERROR_ENUM_HANDLE EnumHandle;
  208. Status2 = RpcErrorStartEnumeration(&EnumHandle);
  209. if (Status2 == RPC_S_ENTRY_NOT_FOUND)
  210. {
  211. CHECK_RET(status, "ClientConnect");
  212. }
  213. else if (Status2 != RPC_S_OK)
  214. {
  215. PrintToConsole("Couldn't get EEInfo: %d\n", Status2);
  216. CHECK_RET(status, "ClientConnect");
  217. }
  218. else
  219. {
  220. RPC_EXTENDED_ERROR_INFO ErrorInfo;
  221. int Records;
  222. BOOL Result;
  223. BOOL CopyStrings = TRUE;
  224. PVOID Blob;
  225. size_t BlobSize;
  226. BOOL fUseFileTime = TRUE;
  227. SYSTEMTIME *SystemTimeToUse;
  228. SYSTEMTIME SystemTimeBuffer;
  229. Status2 = RpcErrorGetNumberOfRecords(&EnumHandle, &Records);
  230. if (Status2 == RPC_S_OK)
  231. {
  232. PrintToConsole("Number of records is: %d\n", Records);
  233. }
  234. while (Status2 == RPC_S_OK)
  235. {
  236. ErrorInfo.Version = RPC_EEINFO_VERSION;
  237. ErrorInfo.Flags = 0;
  238. ErrorInfo.NumberOfParameters = 4;
  239. if (fUseFileTime)
  240. {
  241. ErrorInfo.Flags |= EEInfoUseFileTime;
  242. }
  243. Status2 = RpcErrorGetNextRecord(&EnumHandle, CopyStrings, &ErrorInfo);
  244. if (Status2 == RPC_S_ENTRY_NOT_FOUND)
  245. {
  246. RpcErrorResetEnumeration(&EnumHandle);
  247. break;
  248. }
  249. else if (Status2 != RPC_S_OK)
  250. {
  251. PrintToConsole("Couldn't finish enumeration: %d\n", Status2);
  252. break;
  253. }
  254. else
  255. {
  256. int i;
  257. if (ErrorInfo.ComputerName)
  258. {
  259. PrintToConsole("ComputerName is %S\n", ErrorInfo.ComputerName);
  260. if (CopyStrings)
  261. {
  262. Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.ComputerName);
  263. ASSERT(Result);
  264. }
  265. }
  266. PrintToConsole("ProcessID is %d\n", ErrorInfo.ProcessID);
  267. if (fUseFileTime)
  268. {
  269. Result = FileTimeToSystemTime(&ErrorInfo.u.FileTime, &SystemTimeBuffer);
  270. ASSERT(Result);
  271. SystemTimeToUse = &SystemTimeBuffer;
  272. }
  273. else
  274. SystemTimeToUse = &ErrorInfo.u.SystemTime;
  275. PrintToConsole("System Time is: %d/%d/%d %d:%d:%d:%d\n",
  276. SystemTimeToUse->wMonth,
  277. SystemTimeToUse->wDay,
  278. SystemTimeToUse->wYear,
  279. SystemTimeToUse->wHour,
  280. SystemTimeToUse->wMinute,
  281. SystemTimeToUse->wSecond,
  282. SystemTimeToUse->wMilliseconds);
  283. PrintToConsole("Generating component is %d\n", ErrorInfo.GeneratingComponent);
  284. PrintToConsole("Status is %d\n", ErrorInfo.Status);
  285. PrintToConsole("Detection location is %d\n", (int)ErrorInfo.DetectionLocation);
  286. PrintToConsole("Flags is %d\n", ErrorInfo.Flags);
  287. PrintToConsole("NumberOfParameters is %d\n", ErrorInfo.NumberOfParameters);
  288. for (i = 0; i < ErrorInfo.NumberOfParameters; i ++)
  289. {
  290. switch(ErrorInfo.Parameters[i].ParameterType)
  291. {
  292. case eeptAnsiString:
  293. PrintToConsole("Ansi string: %s\n", ErrorInfo.Parameters[i].u.AnsiString);
  294. if (CopyStrings)
  295. {
  296. Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.Parameters[i].u.AnsiString);
  297. ASSERT(Result);
  298. }
  299. break;
  300. case eeptUnicodeString:
  301. PrintToConsole("Unicode string: %S\n", ErrorInfo.Parameters[i].u.UnicodeString);
  302. if (CopyStrings)
  303. {
  304. Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.Parameters[i].u.UnicodeString);
  305. ASSERT(Result);
  306. }
  307. break;
  308. case eeptLongVal:
  309. PrintToConsole("Long val: %d\n", ErrorInfo.Parameters[i].u.LVal);
  310. break;
  311. case eeptShortVal:
  312. PrintToConsole("Short val: %d\n", (int)ErrorInfo.Parameters[i].u.SVal);
  313. break;
  314. case eeptPointerVal:
  315. PrintToConsole("Pointer val: %d\n", ErrorInfo.Parameters[i].u.PVal);
  316. break;
  317. case eeptNone:
  318. PrintToConsole("Truncated\n");
  319. break;
  320. default:
  321. PrintToConsole("Invalid type: %d\n", ErrorInfo.Parameters[i].ParameterType);
  322. }
  323. }
  324. }
  325. }
  326. Status2 = RpcErrorSaveErrorInfo(&EnumHandle, &Blob, &BlobSize);
  327. CHECK_RET(Status2, "RpcErrorSaveErrorInfo");
  328. RpcErrorClearInformation();
  329. RpcErrorEndEnumeration(&EnumHandle);
  330. Status2 = RpcErrorLoadErrorInfo(Blob, BlobSize, &EnumHandle);
  331. CHECK_RET(Status2, "RpcErrorLoadErrorInfo");
  332. }
  333. }
  334. CHECK_RET(status, "ClientConnect");
  335. if (InSize > IN_ADJUSTMENT)
  336. {
  337. InSize -= IN_ADJUSTMENT;
  338. }
  339. else
  340. {
  341. InSize = 0;
  342. }
  343. if (OutSize > OUT_ADJUSTMENT)
  344. {
  345. OutSize -= OUT_ADJUSTMENT;
  346. }
  347. else
  348. {
  349. OutSize = 0;
  350. }
  351. gInSize = InSize;
  352. gOutSize = OutSize;
  353. PrintToConsole("Client %ld connected\n", ClientId);
  354. Retries = 15;
  355. do
  356. {
  357. RpcTryExcept
  358. {
  359. RpcErr = RPC_S_OK;
  360. Time = GetTickCount();
  361. Calls = ( (TestTable[Test])(&binding, stringBinding, ClientId, pBuffer) );
  362. Time = GetTickCount() - Time;
  363. Dump("Completed %d calls in %d ms\n"
  364. "%d T/S or %3d.%03d ms/T\n\n",
  365. Calls,
  366. Time,
  367. (Calls * 1000) / Time,
  368. Time / Calls,
  369. ((Time % Calls) * 1000) / Calls
  370. );
  371. }
  372. RpcExcept(1)
  373. {
  374. RpcErr = (unsigned long)RpcExceptionCode();
  375. PrintToConsole("\nException %lu (0x%08lX)\n",
  376. RpcErr, RpcErr);
  377. }
  378. RpcEndExcept
  379. Retries --;
  380. if ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0))
  381. {
  382. PrintToConsole("Server too busy - retrying ...\n");
  383. }
  384. }
  385. while ((RpcErr == RPC_S_SERVER_UNAVAILABLE) && (Retries > 0));
  386. Cleanup:
  387. RpcBindingFree(&binding);
  388. return status;
  389. }
  390. //
  391. // The Win32 main starts worker threads, otherwise we just call the worker.
  392. //
  393. #ifdef WIN32
  394. int __cdecl
  395. main (int argc, char **argv)
  396. {
  397. char option;
  398. unsigned long status, i;
  399. HANDLE *pClientThreads;
  400. DWORD dwStat1, dwStat2, dwStat3, dwStat4;
  401. InitAllocator();
  402. ulSecurityPackage = RPC_C_AUTHN_WINNT;
  403. ParseArgv(argc, argv);
  404. PrintToConsole("Authentication Level is: %s\n", AuthnLevelStr);
  405. if (Options[0] < 0)
  406. Options[0] = 1;
  407. pClientThreads = MIDL_user_allocate(sizeof(HANDLE) * Options[0]);
  408. for(i = 0; i < (unsigned long)Options[0]; i++)
  409. {
  410. pClientThreads[i] = CreateThread(0,
  411. 0,
  412. (LPTHREAD_START_ROUTINE)Worker,
  413. 0,
  414. 0,
  415. &status);
  416. if (pClientThreads[i] == 0)
  417. ApiError("CreateThread", GetLastError());
  418. }
  419. status = WaitForMultipleObjects(Options[0],
  420. pClientThreads,
  421. TRUE, // Wait for all client threads
  422. INFINITE);
  423. if (status == WAIT_FAILED)
  424. {
  425. ApiError("WaitForMultipleObjects", GetLastError());
  426. }
  427. #ifdef STATS
  428. I_RpcGetStats(&dwStat1, &dwStat2, &dwStat3, &dwStat4);
  429. printf("Stats are: %ld, %ld, %ld, %ld\n", dwStat1, dwStat2, dwStat3, dwStat4);
  430. #endif
  431. PrintToConsole("TEST DONE\n");
  432. return(0);
  433. }
  434. #else // !WIN32
  435. #ifdef WIN
  436. #define main c_main
  437. // We need the following to force the linker to load WinMain from the
  438. // Windows STDIO library
  439. extern int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
  440. static int (PASCAL *wm_ptr)(HANDLE, HANDLE, LPSTR, int) = WinMain;
  441. #endif
  442. #ifndef MAC
  443. #ifndef FAR
  444. #define FAR __far
  445. #endif
  446. #else
  447. #define FAR
  448. #define main c_main
  449. #endif
  450. int main (int argc, char FAR * FAR * argv)
  451. {
  452. #ifndef MAC
  453. ParseArgv(argc, argv);
  454. #endif
  455. Worker(0);
  456. PrintToConsole("TEST DONE\n");
  457. return(0);
  458. }
  459. #endif // NTENV