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.

460 lines
13 KiB

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