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.

624 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1994 - 1999
  6. //
  7. // File: sct.c
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////////
  11. //
  12. // Filename: sct.c
  13. //
  14. // Description: This file contains common routines for socket I/O
  15. // routines for use with IPC raw network performance
  16. // tests.
  17. // This module is written using win32 API calls.
  18. //
  19. // Authors: Scott Holden (Translator from NT API to win32 API)
  20. // Mahesh Keni (Mahesh wrote this application using mostly
  21. // NT native API calls)
  22. //
  23. /////////////////////////////////////////////////////////////////////////
  24. #include "rawcom.h"
  25. #include "sct.h"
  26. /************************************************************************/
  27. // Socket specific functions
  28. /************************************************************************/
  29. INTEGER
  30. TCPSocket_Connect(
  31. IN int AddrFly,
  32. IN USHORT CIndex,
  33. IN PCHAR srvaddr)
  34. {
  35. INTEGER RetCode;
  36. SOCKADDR csockaddr; // socket address for connecting
  37. PSOCKADDR_IN paddr_in = (PSOCKADDR_IN)&csockaddr;
  38. paddr_in->sin_family = (short)AddrFly;
  39. // use port number based on either client number or machine number
  40. // i.e. if NClients > MachineNumber then use CIndex otherwise use
  41. // machine number. We can run one client each from different machines
  42. // or run multiple clients from same machine.
  43. paddr_in->sin_port = htons((USHORT)(SERV_TCP_PORT + CIndex));
  44. paddr_in->sin_addr.s_addr = inet_addr(srvaddr);
  45. RetCode=connect(Clients[CIndex].c_Sock.c_Sockid,
  46. &csockaddr,
  47. sizeof(SOCKADDR));
  48. if (RetCode == SOCKET_ERROR) {
  49. //DbgPrint("Error: Connect:%ld\n",WSAGetLastError());
  50. }
  51. //MyDbgPrint("Successfully connected \n");
  52. return(RetCode);
  53. }
  54. /************************************************************************/
  55. /*++
  56. This routine just initializes for socket programming
  57. --*/
  58. NTSTATUS
  59. SCTCP_Initialize(
  60. IN USHORT NClients, // Number of clients
  61. IN PCHAR ServerName, // Server IP address
  62. IN USHORT SrvCli) // server or client
  63. {
  64. INTEGER RetCode = 0;
  65. WSADATA WsaData; // got from RCP prog
  66. RetCode = WSAStartup(0x0101, &WsaData);
  67. if (RetCode == SOCKET_ERROR) {
  68. //DbgPrint("Error: WSAStartup : %ld \n",WSAGetLastError());
  69. return(STATUS_UNSUCCESSFUL);
  70. }
  71. return(STATUS_SUCCESS);
  72. }
  73. /************************************************************************/
  74. /*++
  75. This routine is responsible Creating a Socket instance and doing bind for
  76. for a thread.
  77. --*/
  78. NTSTATUS
  79. SCTCP_PerClientInit(
  80. IN USHORT CIndex, // client index
  81. IN USHORT SrvCli )
  82. {
  83. //NTSTATUS pstatus;
  84. INTEGER RetCode;
  85. SOCKADDR saddr; // socket address
  86. //INTEGER saddrlen;
  87. SOCKET isockid;
  88. // We can combine this with SPX routines later
  89. PSOCKADDR_IN paddr_in = (PSOCKADDR_IN)&saddr;
  90. int protocol = IPPROTO_TCP;
  91. // First create a socket for this client
  92. if ((isockid = socket(AddrFly, SOCK_STREAM, protocol)) == INVALID_SOCKET) {
  93. //DbgPrint("Error: Invalid Socket: %ld \n",WSAGetLastError());
  94. return(STATUS_UNSUCCESSFUL);
  95. }
  96. Clients[CIndex].c_Sock.c_Sockid = isockid;
  97. // now do the address binding part
  98. // should get ip address from Name
  99. ClearSocket(&saddr); // cleanup the structure
  100. paddr_in->sin_family = (short)AddrFly;
  101. if (SrvCli) { // if it's a server only then do the binding
  102. paddr_in->sin_port = htons((USHORT)(SERV_TCP_PORT + CIndex));
  103. paddr_in->sin_addr.s_addr = inet_addr(HostName); // use htonl
  104. }
  105. else { // for client assign socket id.
  106. paddr_in->sin_port = 0;
  107. paddr_in->sin_addr.s_addr = 0;
  108. }
  109. RetCode = bind(isockid, &saddr, sizeof(saddr));
  110. if (RetCode == SOCKET_ERROR) {
  111. //DbgPrint("Error: Bind: %ld\n",WSAGetLastError());;
  112. closesocket(isockid);
  113. return (STATUS_UNSUCCESSFUL);
  114. }
  115. else {
  116. if (SrvCli) { Clients[CIndex].c_Sock.c_Listenid = isockid; }
  117. else { Clients[CIndex].c_Sock.c_Sockid = isockid; }
  118. }
  119. // post a listen if it's a server
  120. if (SrvCli) {
  121. if (RetCode = Socket_Listen(CIndex) == SOCKET_ERROR) {
  122. //DbgPrint("Sock: Error in Listen %d\n", RetCode);
  123. return (STATUS_UNSUCCESSFUL);
  124. }
  125. // Listen posted Successfully
  126. }
  127. return (STATUS_SUCCESS);
  128. }
  129. /************************************************************************/
  130. /*++
  131. This routine is responsible for issueing Listen and waiting till a
  132. client is connected. When this routine returns successfully we can
  133. assume that a connection is established.
  134. --*/
  135. NTSTATUS
  136. SCTCP_Wait_For_Client(
  137. IN USHORT CIndex) // client index and namedpipe instance number
  138. {
  139. //NTSTATUS wstatus;
  140. INTEGER RetCode;
  141. /*
  142. // post a listen
  143. if (RetCode = Socket_Listen(CIndex) == SOCKET_ERROR) {
  144. DbgPrint("Sock: Error in Listen %d\n", RetCode);
  145. return (STATUS_UNSUCCESSFUL);
  146. }
  147. // If listen was completed successfully then accept the connection
  148. */
  149. if (RetCode = Socket_Accept(CIndex) == SOCKET_ERROR) {
  150. //DbgPrint("Sock: Error in Accept %d\n", RetCode);
  151. return (STATUS_UNSUCCESSFUL);
  152. }
  153. return (STATUS_SUCCESS);
  154. }
  155. /************************************************************************/
  156. /*++
  157. This routine is responsible for issueing Disconnect to close the
  158. connection with a client.
  159. --*/
  160. NTSTATUS
  161. SCTCP_Disconnect_Client(
  162. IN USHORT CIndex) // client index and namedpipe instance number
  163. {
  164. INTEGER RetCode;
  165. //Close the socket so that it can disconnect
  166. if ( (RetCode = Socket_Close(CIndex)) == SOCKET_ERROR) {
  167. //DbgPrint("Sock: Error in Close Sockid %d\n", RetCode);
  168. // return (STATUS_UNSUCCESSFUL);
  169. }
  170. return (STATUS_SUCCESS);
  171. }
  172. /************************************************************************/
  173. /*++
  174. This routine is responsible for establishing a connection to the
  175. server side. When this routine returns successfully we can assume that
  176. a connection is established.
  177. --*/
  178. NTSTATUS
  179. SCTCP_Connect_To_Server(
  180. IN USHORT CIndex) // client index and namedpipe instance number
  181. {
  182. INTEGER RetCode;
  183. RetCode = TCPSocket_Connect(AddrFly, CIndex, ServerName);
  184. if (RetCode == SOCKET_ERROR) {
  185. //DbgPrint("Sock: Error in Connect %d\n", RetCode);
  186. return (STATUS_UNSUCCESSFUL);
  187. }
  188. return (STATUS_SUCCESS);
  189. }
  190. /************************************************************************/
  191. /*++
  192. This routine allocates memory required for all the buffers for a client.
  193. --*/
  194. NTSTATUS
  195. SCTCP_Allocate_Memory(
  196. IN USHORT CIndex) // client index and namedpipe instance number
  197. {
  198. //NTSTATUS astatus;
  199. ULONG AllocSize;
  200. // AllocSize = Clients[CIndex].c_reqbuf.SendSize;
  201. AllocSize = MAXBUFSIZE;
  202. // Allocate memory for Send Buffer
  203. //MyDbgPrint("Alloc Send Buf: %ld \n", Clients[CIndex].c_reqbuf.SendSize);
  204. /*
  205. astatus = NtAllocateVirtualMemory(
  206. NtCurrentProcess(),
  207. (PVOID *) (&(Clients[CIndex].c_pSendBuf)),
  208. 0L,
  209. &(AllocSize),
  210. MEM_COMMIT,
  211. PAGE_READWRITE);
  212. if (!NT_SUCCESS(astatus)) {
  213. DbgPrint("Nmp SendBuf: Allocate memory failed: err: %lx \n", astatus);
  214. return astatus;
  215. }
  216. */
  217. (LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
  218. (LPVOID) Clients[CIndex].c_pSendBuf,
  219. (DWORD)AllocSize,
  220. (DWORD)MEM_COMMIT,
  221. (DWORD)PAGE_READWRITE);
  222. sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data", CIndex+1);
  223. // AllocSize = Clients[CIndex].c_reqbuf.RecvSize;
  224. AllocSize = MAXBUFSIZE;
  225. //MyDbgPrint("Alloc: Recv Buf: %ld \n", Clients[CIndex].c_reqbuf.RecvSize);
  226. // Allocate memory for Receive Buffer
  227. /*
  228. astatus = NtAllocateVirtualMemory(
  229. NtCurrentProcess(),
  230. (PVOID *) (&(Clients[CIndex].c_pRecvBuf)),
  231. 0L,
  232. &(AllocSize),
  233. MEM_COMMIT,
  234. PAGE_READWRITE);
  235. if (!NT_SUCCESS(astatus)) {
  236. DbgPrint("Nmp RecvBuf :Allocate memory failed: err: %lx \n", astatus);
  237. return astatus;
  238. }
  239. */
  240. (LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
  241. (LPVOID) Clients[CIndex].c_pRecvBuf,
  242. (DWORD)AllocSize,
  243. (DWORD)MEM_COMMIT,
  244. (DWORD)PAGE_READWRITE);
  245. sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data", CIndex+1);
  246. //return astatus;
  247. return STATUS_SUCCESS;
  248. }
  249. /************************************************************************/
  250. /*++
  251. This routine deallocates memory for a client.
  252. --*/
  253. NTSTATUS
  254. SCTCP_Deallocate_Memory(
  255. IN USHORT CIndex) // client index and namedpipe instance number
  256. {
  257. NTSTATUS dstatus;
  258. ULONG DeallocSize;
  259. // Deallocate memory for Send Buffer
  260. // DeallocSize = Clients[CIndex].c_reqbuf.SendSize;
  261. DeallocSize = MAXBUFSIZE;
  262. /*
  263. dstatus = NtFreeVirtualMemory(
  264. NtCurrentProcess(),
  265. (PVOID *) (&(Clients[CIndex].c_pSendBuf)),
  266. &(DeallocSize),
  267. MEM_DECOMMIT);
  268. */
  269. dstatus = VirtualFree(
  270. (LPVOID) Clients[CIndex].c_pSendBuf,
  271. DeallocSize,
  272. MEM_DECOMMIT);
  273. if (!NT_SUCCESS(dstatus)) {
  274. //DbgPrint("Nmp SendBuf: Deallocate memory failed: err: %lx \n", dstatus);
  275. return dstatus;
  276. }
  277. // DeallocSize = Clients[CIndex].c_reqbuf.RecvSize;
  278. DeallocSize = MAXBUFSIZE;
  279. // Deallocate memory for Receive Buffer
  280. /*
  281. dstatus = NtFreeVirtualMemory(
  282. NtCurrentProcess(),
  283. (PVOID *) (&(Clients[CIndex].c_pRecvBuf)),
  284. &(DeallocSize),
  285. MEM_DECOMMIT);
  286. */
  287. dstatus = VirtualFree(
  288. (LPVOID) Clients[CIndex].c_pRecvBuf,
  289. DeallocSize,
  290. MEM_DECOMMIT);
  291. if (!NT_SUCCESS(dstatus)) {
  292. //DbgPrint("Nmp RecvBuf :Deallocate memory failed: err: %lx \n", dstatus);
  293. }
  294. return dstatus;
  295. }
  296. /************************************************************************/
  297. /*++
  298. This routine is responsible for disconnecting a session.
  299. --*/
  300. NTSTATUS
  301. SCTCP_Disconnect_From_Server(
  302. IN USHORT CIndex) // client index and namedpipe instance number
  303. {
  304. INTEGER RetCode;
  305. //Close the socket so that it can disconnect
  306. if ( (RetCode = Socket_Close(CIndex)) == SOCKET_ERROR) {
  307. //DbgPrint("Sock: Error in Close Sockid %d\n", RetCode);
  308. return (STATUS_UNSUCCESSFUL);
  309. }
  310. return (STATUS_SUCCESS);
  311. }
  312. /************************************************************************/
  313. /*++
  314. This routine does handshake with it's peer. For Server this means
  315. receiving request message from a client. For Client it means just the
  316. opposite.
  317. --*/
  318. NTSTATUS
  319. SCTCP_DoHandshake(
  320. IN USHORT CIndex, // client index
  321. IN USHORT SrvCli // if it's a server or client
  322. )
  323. {
  324. ULONG RWreqLen;
  325. INTEGER RetCode = 0;
  326. RWreqLen = sizeof(struct reqbuf);
  327. // for server do receive for a request buffer
  328. if (SrvCli) {
  329. RetCode = Socket_Recv(
  330. CIndex,
  331. (PVOID) &(Clients[CIndex].c_reqbuf),
  332. (PULONG) &RWreqLen);
  333. if (RetCode == SOCKET_ERROR) {
  334. //DbgPrint("Sock: Error in Recv %d\n", RetCode);
  335. return (STATUS_UNSUCCESSFUL);
  336. }
  337. }
  338. else { // for Client do send of reqbuf size
  339. // Based on TestCmd make changes i.e. 'U'->'P'
  340. RetCode = Socket_Send(
  341. CIndex,
  342. (PVOID) &(Clients[CIndex].c_reqbuf),
  343. (PULONG) &RWreqLen);
  344. if (RetCode == SOCKET_ERROR) {
  345. //DbgPrint("Sock: Error in Send %d\n", RetCode);
  346. return (STATUS_UNSUCCESSFUL);
  347. }
  348. }
  349. // check if read/write length is ok
  350. if (RWreqLen != sizeof(struct reqbuf)) {
  351. //DbgPrint("Sock:Read/Write Len mismatch: read %ld \n", RWreqLen);
  352. }
  353. /*
  354. MyDbgPrint("handshake: Sendl:%ld Recvl:%ld \n",
  355. Clients[CIndex].c_reqbuf.SendSize,
  356. Clients[CIndex].c_reqbuf.RecvSize);
  357. */
  358. return (STATUS_SUCCESS);
  359. }
  360. /************************************************************************/
  361. /*++
  362. This routine Reads data from IPC. For server it means reading data
  363. NumSends times in SendBuffers and for a client NumRecvs times into
  364. RecvBuffer.
  365. --*/
  366. NTSTATUS
  367. SCTCP_ReadFromIPC(
  368. IN USHORT CIndex, // client index and namedpipe instance number
  369. IN OUT PULONG pReadDone,
  370. IN USHORT SrvCli // if it's a server or client
  371. )
  372. {
  373. ULONG NumReads;
  374. ULONG ReadLen;
  375. PCHAR ReadBuf;
  376. INTEGER RetCode;
  377. if (SrvCli) { // set proper iterations and buffer for Server
  378. NumReads = Clients[CIndex].c_reqbuf.NumSends;
  379. ReadBuf = Clients[CIndex].c_pSendBuf;
  380. ReadLen = Clients[CIndex].c_reqbuf.SendSize;
  381. }
  382. else { // for client do proper settings
  383. NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
  384. ReadBuf = Clients[CIndex].c_pRecvBuf;
  385. ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
  386. }
  387. while (NumReads--) {
  388. RetCode = Socket_Recv(
  389. CIndex,
  390. (PVOID) ReadBuf,
  391. (PULONG)&ReadLen);
  392. if (RetCode == SOCKET_ERROR) {
  393. //DbgPrint("Sock: Error in Recv %d\n", RetCode);
  394. return (STATUS_UNSUCCESSFUL);
  395. }
  396. // Assign the read length
  397. *pReadDone = ReadLen;
  398. }
  399. return (STATUS_SUCCESS);
  400. }
  401. /************************************************************************/
  402. /*++
  403. This routine Writes data to IPC. For server it means writing data
  404. NumRecvs times in RecvBuffers and for a client NumSends times into
  405. SendBuffer.
  406. --*/
  407. NTSTATUS
  408. SCTCP_WriteToIPC(
  409. IN USHORT CIndex, // client index and namedpipe instance number
  410. IN OUT PULONG pWriteDone,
  411. IN USHORT SrvCli // if it's a server or client
  412. )
  413. {
  414. ULONG NumWrites;
  415. ULONG WriteLen;
  416. PCHAR WriteBuf;
  417. INTEGER RetCode;
  418. if (SrvCli) { // set proper iterations and buffer for Server
  419. NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
  420. WriteBuf = Clients[CIndex].c_pRecvBuf;
  421. WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
  422. }
  423. else { // for client do proper settings
  424. NumWrites = Clients[CIndex].c_reqbuf.NumSends;
  425. WriteBuf = Clients[CIndex].c_pSendBuf;
  426. WriteLen = Clients[CIndex].c_reqbuf.SendSize;
  427. }
  428. while (NumWrites--) {
  429. RetCode = Socket_Send(
  430. CIndex,
  431. (PVOID) WriteBuf,
  432. (PULONG) &WriteLen);
  433. if (RetCode == SOCKET_ERROR) {
  434. //DbgPrint("Sock: Error in Send %d\n", RetCode);
  435. return (STATUS_UNSUCCESSFUL);
  436. }
  437. *pWriteDone = WriteLen;
  438. }
  439. return (STATUS_SUCCESS);
  440. }
  441. /************************************************************************/
  442. /*++
  443. This routine does transaction type IO to IPC. This just assumes that
  444. both Number of reads and writes are equal and will use Number of reads
  445. as it's basis.
  446. --*/
  447. NTSTATUS
  448. SCTCP_XactIO(
  449. IN USHORT CIndex, // client index and namedpipe instance number
  450. IN OUT PULONG pReadDone,
  451. IN OUT PULONG pWriteDone,
  452. IN USHORT SrvCli, // if it's a server or client
  453. IN BOOLEAN FirstIter
  454. )
  455. {
  456. ULONG NumReads;
  457. ULONG ReadLen;
  458. PCHAR ReadBuf;
  459. ULONG WriteLen;
  460. PCHAR WriteBuf;
  461. //INTEGER RetCode;
  462. NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
  463. if (SrvCli) { // set proper iterations and buffer for Server
  464. ReadBuf = Clients[CIndex].c_pSendBuf;
  465. ReadLen = Clients[CIndex].c_reqbuf.SendSize;
  466. WriteBuf = Clients[CIndex].c_pRecvBuf;
  467. WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
  468. }
  469. else { // for client do proper settings
  470. ReadBuf = Clients[CIndex].c_pRecvBuf;
  471. ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
  472. WriteBuf = Clients[CIndex].c_pSendBuf;
  473. WriteLen = Clients[CIndex].c_reqbuf.SendSize;
  474. }
  475. /*
  476. while (NumReads--) {
  477. *pReadDone = ReadLen;
  478. *pWriteDone = WriteLen;
  479. }
  480. */
  481. return (STATUS_SUCCESS);
  482. }
  483. /************************************************************************/
  484. NTSTATUS
  485. SCTCP_Cleanup(VOID)
  486. {
  487. USHORT Cindex = 0; // client index
  488. //NTSTATUS cstatus;
  489. NTSTATUS exitstatus = 0;
  490. /*
  491. for (Cindex = 0; Cindex < NClients; Cindex++) {
  492. // if the client was used then close the NamedPipe handle
  493. cstatus = NtClose (Clients[Cindex].c_Nmp.c_PipeHandle);
  494. if (!NT_SUCCESS(cstatus)) {
  495. printf("Failed to close NMPhandle thno:%d err=%lx\n",
  496. Cindex,cstatus);
  497. }
  498. // terminate the thread
  499. cstatus = NtTerminateThread(
  500. Clients[Cindex].c_hThHandle,
  501. exitstatus);
  502. if (!NT_SUCCESS(cstatus)) {
  503. printf("Failed to terminate thread no:%d err=%lx\n",
  504. Cindex,cstatus);
  505. }
  506. }
  507. */
  508. return (STATUS_SUCCESS);
  509. }
  510. /************************************************************************/
  511. /*++
  512. This routine does a client specific cleanup work.
  513. --*/
  514. NTSTATUS
  515. SCTCP_ThreadCleanUp(
  516. IN USHORT CIndex
  517. )
  518. {
  519. //NTSTATUS tstatus;
  520. // For Server Close the ListenId
  521. return STATUS_SUCCESS;
  522. }
  523. /************************************************************************/