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.

456 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1994 - 1999
  6. //
  7. // File: scipx.c
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////////
  11. //
  12. // Filename: scipx.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 "scipx.h"
  26. /************************************************************************/
  27. NTSTATUS
  28. SCIPX_Initialize(
  29. IN USHORT NClients, // Number of clients
  30. IN PCHAR ServerName, // Server IP address
  31. IN USHORT SrvCli) // server or client
  32. {
  33. INTEGER RetCode = 0;
  34. WSADATA WsaData; // got from RCP prog
  35. RetCode = WSAStartup(0x0101, &WsaData);
  36. if (RetCode == SOCKET_ERROR) {
  37. //DbgPrint("Error: WSAStartup : %ld \n",WSAGetLastError());
  38. return(STATUS_UNSUCCESSFUL);
  39. }
  40. return(STATUS_SUCCESS);
  41. }
  42. /************************************************************************/
  43. /*++
  44. This routine is responsible Creating a Socket instance and doing bind for
  45. for a thread.
  46. --*/
  47. NTSTATUS
  48. SCIPX_PerClientInit(
  49. IN USHORT CIndex, // client index
  50. IN USHORT SrvCli )
  51. {
  52. NTSTATUS pstatus;
  53. INTEGER RetCode;
  54. SOCKADDR saddr; // socket address
  55. INTEGER saddrlen;
  56. SOCKET isockid;
  57. // We can combine this with SPX routines later
  58. PSOCKADDR_NS paddr_ns = (PSOCKADDR_NS)&saddr;
  59. int protocol = NSPROTO_IPX;
  60. // First create a socket for this client
  61. if ((isockid = socket(AddrFly, SOCK_DGRAM, protocol)) == INVALID_SOCKET) {
  62. //DbgPrint("Error: Invalid Socket: %ld \n",WSAGetLastError());
  63. return(STATUS_UNSUCCESSFUL);
  64. }
  65. Clients[CIndex].c_Sock.c_Sockid = isockid;
  66. // now do the address binding part
  67. // should get ip address from Name
  68. ClearSocket(&saddr); // cleanup the structure
  69. paddr_ns->sa_family = (short)AddrFly;
  70. if (SrvCli) { //
  71. paddr_ns->sa_socket = htons((USHORT)(SERV_IPX_PORT + CIndex));
  72. }
  73. else { // for client assign socket id.
  74. paddr_ns->sa_socket = 0;
  75. }
  76. RetCode = bind(isockid, &saddr, sizeof(saddr));
  77. if (RetCode == SOCKET_ERROR) {
  78. //DbgPrint("Error: Bind: %ld\n",WSAGetLastError());;
  79. closesocket(isockid);
  80. return (STATUS_UNSUCCESSFUL);
  81. }
  82. else {
  83. Clients[CIndex].c_Sock.c_Sockid = isockid;
  84. }
  85. return (STATUS_SUCCESS);
  86. }
  87. /************************************************************************/
  88. /*++
  89. This routine is responsible for Connecting a server address to a
  90. socket if Connected flag is true.
  91. --*/
  92. NTSTATUS
  93. SCIPX_Connect_To_Server(
  94. IN USHORT CIndex) // client index and namedpipe instance number
  95. {
  96. INTEGER RetCode;
  97. SOCKADDR_NS saddr; // socket address
  98. saddr.sa_family = (short)AddrFly; // Address family
  99. saddr.sa_socket = htons((USHORT)(SERV_IPX_PORT + CIndex));
  100. RtlCopyMemory((saddr.sa_nodenum), ServerName,6);
  101. RtlCopyMemory((saddr.sa_netnum), ServerName+6,4);
  102. RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&saddr);
  103. if (RetCode == SOCKET_ERROR) {
  104. //DbgPrint("Sock: Error in Connect %d\n", RetCode);
  105. return (STATUS_UNSUCCESSFUL);
  106. }
  107. return (STATUS_SUCCESS);
  108. }
  109. /************************************************************************/
  110. /*++
  111. This routine allocates memory required for all the buffers for a client.
  112. --*/
  113. NTSTATUS
  114. SCIPX_Allocate_Memory(
  115. IN USHORT CIndex) // client index and namedpipe instance number
  116. {
  117. NTSTATUS astatus;
  118. ULONG AllocSize;
  119. // AllocSize = Clients[CIndex].c_reqbuf.SendSize;
  120. AllocSize = MAXBUFSIZE;
  121. (LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
  122. (LPVOID) Clients[CIndex].c_pSendBuf,
  123. (DWORD)AllocSize,
  124. (DWORD)MEM_COMMIT,
  125. (DWORD)PAGE_READWRITE);
  126. sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data",CIndex+1);
  127. if (Clients[CIndex].c_pSendBuf == NULL) {
  128. astatus = GetLastError();
  129. printf("\nVirtual Alloc error\n");
  130. }
  131. // AllocSize = Clients[CIndex].c_reqbuf.RecvSize;
  132. AllocSize = MAXBUFSIZE;
  133. (LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
  134. (LPVOID) Clients[CIndex].c_pRecvBuf,
  135. (DWORD)AllocSize,
  136. (DWORD)MEM_COMMIT,
  137. (DWORD)PAGE_READWRITE);
  138. sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data",CIndex+1);
  139. if (Clients[CIndex].c_pRecvBuf == NULL) {
  140. astatus = GetLastError();
  141. printf("\nVirtual Alloc error\n");
  142. }
  143. return astatus;
  144. }
  145. /************************************************************************/
  146. /*++
  147. This routine deallocates memory for a client.
  148. --*/
  149. NTSTATUS
  150. SCIPX_Deallocate_Memory(
  151. IN USHORT CIndex) // client index and namedpipe instance number
  152. {
  153. NTSTATUS dstatus;
  154. ULONG DeallocSize;
  155. // Deallocate memory for Send Buffer
  156. // DeallocSize = Clients[CIndex].c_reqbuf.SendSize;
  157. DeallocSize = MAXBUFSIZE;
  158. /*
  159. dstatus = NtFreeVirtualMemory(
  160. NtCurrentProcess(),
  161. (PVOID *) (&(Clients[CIndex].c_pSendBuf)),
  162. &(DeallocSize),
  163. MEM_DECOMMIT);
  164. */
  165. dstatus = VirtualFree(
  166. (LPVOID) Clients[CIndex].c_pSendBuf,
  167. DeallocSize,
  168. MEM_DECOMMIT);
  169. if (!NT_SUCCESS(dstatus)) {
  170. //DbgPrint("Nmp SendBuf: Deallocate memory failed: err: %lx \n", dstatus);
  171. return dstatus;
  172. }
  173. // DeallocSize = Clients[CIndex].c_reqbuf.RecvSize;
  174. DeallocSize = MAXBUFSIZE;
  175. // Deallocate memory for Receive Buffer
  176. /*
  177. dstatus = NtFreeVirtualMemory(
  178. NtCurrentProcess(),
  179. (PVOID *) (&(Clients[CIndex].c_pRecvBuf)),
  180. &(DeallocSize),
  181. MEM_DECOMMIT);
  182. */
  183. dstatus = VirtualFree(
  184. (LPVOID) Clients[CIndex].c_pRecvBuf,
  185. DeallocSize,
  186. MEM_DECOMMIT);
  187. if (!NT_SUCCESS(dstatus)) {
  188. //DbgPrint("Nmp RecvBuf :Deallocate memory failed: err: %lx \n", dstatus);
  189. }
  190. return dstatus;
  191. }
  192. /************************************************************************/
  193. /*++
  194. This routine is responsible for disconnecting a session.
  195. --*/
  196. NTSTATUS
  197. SCIPX_Disconnect_From_Server(
  198. IN USHORT CIndex) // client index and namedpipe instance number
  199. {
  200. INTEGER RetCode;
  201. //Close the socket so that it can disconnect
  202. if ( (RetCode = DGSocket_Close(CIndex)) == SOCKET_ERROR) {
  203. //DbgPrint("Sock: Error in Close Sockid %d\n", RetCode);
  204. return (STATUS_UNSUCCESSFUL);
  205. }
  206. return (STATUS_SUCCESS);
  207. }
  208. /************************************************************************/
  209. /*++
  210. This routine does handshake with it's peer. For Server this means
  211. receiving request message from a client. For Client it means just the
  212. opposite.
  213. --*/
  214. NTSTATUS
  215. SCIPX_DoHandshake(
  216. IN USHORT CIndex, // client index
  217. IN USHORT SrvCli) // if it's a server or client
  218. {
  219. ULONG RWreqLen;
  220. INTEGER RetCode = 0;
  221. SOCKADDR_NS daddr;
  222. USHORT daddrlen = 16;
  223. RWreqLen = sizeof(struct reqbuf);
  224. // for server do receivefrom for a request buffer
  225. if (SrvCli) {
  226. RetCode = DGSocket_RecvFrom(
  227. CIndex,
  228. (PVOID) &(Clients[CIndex].c_reqbuf),
  229. (PULONG) &RWreqLen,
  230. (PSOCKADDR)&daddr,
  231. &daddrlen);
  232. if (RetCode == SOCKET_ERROR) {
  233. //DbgPrint("Sock: Error in Recv %d\n", RetCode);
  234. return (STATUS_UNSUCCESSFUL);
  235. }
  236. // Now connect this address to client's Socket
  237. RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&daddr);
  238. if (RetCode == SOCKET_ERROR) {
  239. //DbgPrint("Sock: Error in Connect %d\n", RetCode);
  240. return (STATUS_UNSUCCESSFUL);
  241. }
  242. }
  243. else { // for Client do send of reqbuf size
  244. // Client always does Send
  245. RetCode = DGSocket_Send(
  246. CIndex,
  247. (PVOID) &(Clients[CIndex].c_reqbuf),
  248. (PULONG) &RWreqLen);
  249. if (RetCode == SOCKET_ERROR) {
  250. //DbgPrint("Sock: Error in Send %d\n", RetCode);
  251. return (STATUS_UNSUCCESSFUL);
  252. }
  253. }
  254. // check if read/write length is ok
  255. if (RWreqLen != sizeof(struct reqbuf)) {
  256. //DbgPrint("Sock:Read/Write Len mismatch: read %ld \n", RWreqLen);
  257. }
  258. /*
  259. MyDbgPrint("handshake: Sendl:%ld Recvl:%ld \n",
  260. Clients[CIndex].c_reqbuf.SendSize,
  261. Clients[CIndex].c_reqbuf.RecvSize);
  262. */
  263. return (STATUS_SUCCESS);
  264. }
  265. /************************************************************************/
  266. /*++
  267. This routine Reads data from IPC. For server it means reading data
  268. NumSends times in SendBuffers and for a client NumRecvs times into
  269. RecvBuffer.
  270. --*/
  271. NTSTATUS
  272. SCIPX_ReadFromIPC(
  273. IN USHORT CIndex, // client index and namedpipe instance number
  274. IN OUT PULONG pReadDone,
  275. IN USHORT SrvCli) // if it's a server or client
  276. {
  277. ULONG NumReads;
  278. ULONG ReadLen;
  279. PCHAR ReadBuf;
  280. INTEGER RetCode;
  281. // SOCKADDR_NS raddr;
  282. // INTEGER raddrlen;
  283. if (SrvCli) { // set proper iterations and buffer for Server
  284. NumReads = Clients[CIndex].c_reqbuf.NumSends;
  285. ReadBuf = Clients[CIndex].c_pSendBuf;
  286. ReadLen = Clients[CIndex].c_reqbuf.SendSize;
  287. }
  288. else { // for client do proper settings
  289. NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
  290. ReadBuf = Clients[CIndex].c_pRecvBuf;
  291. ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
  292. }
  293. while (NumReads--) {
  294. RetCode = DGSocket_Recv(
  295. CIndex,
  296. (PVOID) ReadBuf,
  297. (PULONG)&ReadLen);
  298. if (RetCode == SOCKET_ERROR) {
  299. //DbgPrint("DGSock: Error in Recv %d\n", RetCode);
  300. return (STATUS_UNSUCCESSFUL);
  301. }
  302. // Assign the read length
  303. *pReadDone = ReadLen;
  304. }
  305. return (STATUS_SUCCESS);
  306. }
  307. /************************************************************************/
  308. /*++
  309. This routine Writes data to IPC. For server it means writing data
  310. NumRecvs times in RecvBuffers and for a client NumSends times into
  311. SendBuffer.
  312. --*/
  313. NTSTATUS
  314. SCIPX_WriteToIPC(
  315. IN USHORT CIndex, // client index and namedpipe instance number
  316. IN OUT PULONG pWriteDone,
  317. IN USHORT SrvCli) // if it's a server or client
  318. {
  319. ULONG NumWrites;
  320. ULONG WriteLen;
  321. PCHAR WriteBuf;
  322. INTEGER RetCode;
  323. if (SrvCli) { // set proper iterations and buffer for Server
  324. NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
  325. WriteBuf = Clients[CIndex].c_pRecvBuf;
  326. WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
  327. }
  328. else { // for client do proper settings
  329. NumWrites = Clients[CIndex].c_reqbuf.NumSends;
  330. WriteBuf = Clients[CIndex].c_pSendBuf;
  331. WriteLen = Clients[CIndex].c_reqbuf.SendSize;
  332. }
  333. while (NumWrites--) {
  334. RetCode = DGSocket_Send(
  335. CIndex,
  336. (PVOID) WriteBuf,
  337. (PULONG) &WriteLen);
  338. if (RetCode == SOCKET_ERROR) {
  339. //DbgPrint("Sock: Error in Send %d\n", RetCode);
  340. return (STATUS_UNSUCCESSFUL);
  341. }
  342. *pWriteDone = WriteLen;
  343. }
  344. return (STATUS_SUCCESS);
  345. }
  346. /************************************************************************/
  347. NTSTATUS
  348. SCIPX_Cleanup(VOID)
  349. {
  350. USHORT Cindex = 0; // client index
  351. NTSTATUS cstatus;
  352. NTSTATUS exitstatus = 0;
  353. return (STATUS_SUCCESS);
  354. }
  355. /************************************************************************/
  356. /*++
  357. This routine does a client specific cleanup work.
  358. --*/
  359. NTSTATUS
  360. SCIPX_ThreadCleanUp(
  361. IN USHORT CIndex)
  362. {
  363. // For Server Close the ListenId
  364. return STATUS_SUCCESS;
  365. }
  366. /************************************************************************/
  367. /*++
  368. For IPX do nothing.
  369. --*/
  370. NTSTATUS
  371. SCIPX_Wait_For_Client(
  372. IN USHORT CIndex) // client index
  373. {
  374. return (STATUS_SUCCESS);
  375. }
  376. /************************************************************************/
  377. /*++
  378. This routine is responsible for issueing Disconnect to close the
  379. connection with a client.
  380. --*/
  381. NTSTATUS
  382. SCIPX_Disconnect_Client(
  383. IN USHORT CIndex) // client index
  384. {
  385. INTEGER RetCode;
  386. SOCKADDR_NS daddr; // socket address
  387. ClearSocket(&daddr);
  388. RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&daddr);
  389. if (RetCode == SOCKET_ERROR) {
  390. //DbgPrint("Sock: in Disconnect Client: Sock_Connect %d\n", RetCode);
  391. return (STATUS_UNSUCCESSFUL);
  392. }
  393. return (STATUS_SUCCESS);
  394. }
  395. /************************************************************************/