Windows NT 4.0 source code leak
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.

614 lines
17 KiB

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