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.

610 lines
16 KiB

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