1
0

ntsock.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. ntsock.c
  9. Abstract:
  10. This module contains socket support for Win32 platforms.
  11. Author:
  12. Evan Green 27-Aug-2014
  13. Environment:
  14. Win32
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <stdio.h>
  20. #include <windows.h>
  21. #include <winsock2.h>
  22. #include <ws2tcpip.h>
  23. #include "sock.h"
  24. //
  25. // ---------------------------------------------------------------- Definitions
  26. //
  27. //
  28. // ------------------------------------------------------ Data Type Definitions
  29. //
  30. //
  31. // ----------------------------------------------- Internal Function Prototypes
  32. //
  33. //
  34. // -------------------------------------------------------------------- Globals
  35. //
  36. BOOL DbgrSocketsInitialized = FALSE;
  37. //
  38. // ------------------------------------------------------------------ Functions
  39. //
  40. int
  41. DbgrSocketInitializeLibrary (
  42. void
  43. )
  44. /*++
  45. Routine Description:
  46. This routine initializes socket support in the application.
  47. Arguments:
  48. None.
  49. Return Value:
  50. 0 on success.
  51. Non-zero on failure.
  52. --*/
  53. {
  54. int Result;
  55. WSADATA WsaData;
  56. if (DbgrSocketsInitialized != FALSE) {
  57. return 0;
  58. }
  59. Result = WSAStartup(MAKEWORD(2, 2), &WsaData);
  60. if (Result != 0) {
  61. return Result;
  62. }
  63. DbgrSocketsInitialized = TRUE;
  64. return 0;
  65. }
  66. void
  67. DbgrSocketDestroyLibrary (
  68. void
  69. )
  70. /*++
  71. Routine Description:
  72. This routine tears down socket support in the application.
  73. Arguments:
  74. None.
  75. Return Value:
  76. None.
  77. --*/
  78. {
  79. if (DbgrSocketsInitialized == FALSE) {
  80. return;
  81. }
  82. WSACleanup();
  83. DbgrSocketsInitialized = FALSE;
  84. return;
  85. }
  86. int
  87. DbgrSocketCreateStreamSocket (
  88. void
  89. )
  90. /*++
  91. Routine Description:
  92. This routine creates an IPv4 TCP socket.
  93. Arguments:
  94. None.
  95. Return Value:
  96. Returns the socket on success.
  97. Returns a value less than zero on failure.
  98. --*/
  99. {
  100. return socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  101. }
  102. int
  103. DbgrSocketBind (
  104. int Socket,
  105. char *Host,
  106. int Port
  107. )
  108. /*++
  109. Routine Description:
  110. This routine binds the given socket to the given address and port.
  111. Arguments:
  112. Socket - Supplies the socket to bind.
  113. Host - Supplies a pointer to the host string. Supply NULL to use any
  114. address.
  115. Port - Supplies the port to bind on.
  116. Return Value:
  117. 0 on success.
  118. Non-zero on failure.
  119. --*/
  120. {
  121. struct sockaddr_in Address;
  122. int Result;
  123. Address.sin_family = AF_INET;
  124. Address.sin_port = htons(Port);
  125. Address.sin_addr.s_addr = INADDR_ANY;
  126. if ((Host != NULL) && (*Host != '\0')) {
  127. Address.sin_addr.s_addr = inet_addr(Host);
  128. if (Address.sin_addr.s_addr == INADDR_NONE) {
  129. return 1;
  130. }
  131. }
  132. Result = bind(Socket,
  133. (struct sockaddr *)&Address,
  134. sizeof(struct sockaddr_in));
  135. return Result;
  136. }
  137. int
  138. DbgrSocketConnect (
  139. int Socket,
  140. char *Host,
  141. int Port
  142. )
  143. /*++
  144. Routine Description:
  145. This routine connects to a remote server.
  146. Arguments:
  147. Socket - Supplies the socket to connect.
  148. Host - Supplies a pointer to the host string to connect to.
  149. Port - Supplies the port to bind on.
  150. Return Value:
  151. 0 on success.
  152. Non-zero on failure.
  153. --*/
  154. {
  155. struct sockaddr_in Address;
  156. int Result;
  157. Address.sin_family = AF_INET;
  158. Address.sin_port = htons(Port);
  159. Address.sin_addr.s_addr = inet_addr(Host);
  160. if (Address.sin_addr.s_addr == INADDR_NONE) {
  161. return 1;
  162. }
  163. Result = connect(Socket,
  164. (struct sockaddr *)&Address,
  165. sizeof(struct sockaddr_in));
  166. return Result;
  167. }
  168. int
  169. DbgrSocketListen (
  170. int Socket
  171. )
  172. /*++
  173. Routine Description:
  174. This routine starts a server socket listening for connections.
  175. Arguments:
  176. Socket - Supplies the socket to listen on.
  177. Return Value:
  178. 0 on success.
  179. Non-zero on failure.
  180. --*/
  181. {
  182. return listen(Socket, SOMAXCONN);
  183. }
  184. int
  185. DbgrSocketAccept (
  186. int Socket,
  187. char **Host,
  188. int *Port
  189. )
  190. /*++
  191. Routine Description:
  192. This routine accepts a new incoming connection from the given listening
  193. socket.
  194. Arguments:
  195. Socket - Supplies the socket to accept an incoming connection from.
  196. Host - Supplies an optional pointer where a string describing the host will
  197. be returned on success. The caller is responsible for freeing this
  198. string.
  199. Port - Supplies an optional pointer where the port number will be returned
  200. on success.
  201. Return Value:
  202. Returns the newly connected client socket on success.
  203. Returns a negative value on failure.
  204. --*/
  205. {
  206. struct sockaddr_in Address;
  207. int Result;
  208. socklen_t Size;
  209. if (Host != NULL) {
  210. *Host = NULL;
  211. }
  212. if (Port != NULL) {
  213. *Port = 0;
  214. }
  215. Size = sizeof(struct sockaddr_in);
  216. Result = accept(Socket, (struct sockaddr *)&Address, &Size);
  217. if (Result < 0) {
  218. return Result;
  219. }
  220. if (Host != NULL) {
  221. *Host = strdup(inet_ntoa(Address.sin_addr));
  222. }
  223. if (Port != NULL) {
  224. *Port = ntohs(Address.sin_port);
  225. }
  226. return Result;
  227. }
  228. int
  229. DbgrSocketGetName (
  230. int Socket,
  231. char **Host,
  232. int *Port
  233. )
  234. /*++
  235. Routine Description:
  236. This routine gets the current local host and port for the given socket.
  237. Arguments:
  238. Socket - Supplies the socket to query.
  239. Host - Supplies an optional pointer where a string describing the host will
  240. be returned on success. The caller is responsible for freeing this
  241. string.
  242. Port - Supplies an optional pointer where the port number will be returned
  243. on success.
  244. Return Value:
  245. 0 on success.
  246. Returns a non-zero value on failure.
  247. --*/
  248. {
  249. struct sockaddr_in Address;
  250. int Result;
  251. int Size;
  252. if (Host != NULL) {
  253. *Host = NULL;
  254. }
  255. if (Port != NULL) {
  256. *Port = 0;
  257. }
  258. Size = sizeof(Address);
  259. Result = getsockname(Socket, (struct sockaddr *)&Address, &Size);
  260. if (Result != 0) {
  261. return Result;
  262. }
  263. if (Host != NULL) {
  264. *Host = strdup(inet_ntoa(Address.sin_addr));
  265. }
  266. if (Port != NULL) {
  267. *Port = ntohs(Address.sin_port);
  268. }
  269. return 0;
  270. }
  271. int
  272. DbgrSocketShutdown (
  273. int Socket
  274. )
  275. /*++
  276. Routine Description:
  277. This routine shuts down a socket. It shuts down both the read and write
  278. sides of the connection.
  279. Arguments:
  280. Socket - Supplies the socket to shut down.
  281. Return Value:
  282. 0 on success.
  283. Non-zero on failure.
  284. --*/
  285. {
  286. //
  287. // Unfortunately, Windows doesn't unblock threads blocked in send or
  288. // recv when a socket is shut down. The only solution is to close it,
  289. // which is not ideal as the file descriptor might get reused.
  290. //
  291. return closesocket(Socket);
  292. }
  293. void
  294. DbgrSocketClose (
  295. int Socket
  296. )
  297. /*++
  298. Routine Description:
  299. This routine closes a socket.
  300. Arguments:
  301. Socket - Supplies the socket to destroy.
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. closesocket(Socket);
  307. return;
  308. }
  309. int
  310. DbgrSocketSend (
  311. int Socket,
  312. const void *Data,
  313. int Length
  314. )
  315. /*++
  316. Routine Description:
  317. This routine sends data out of a connected socket.
  318. Arguments:
  319. Socket - Supplies the file descriptor of the socket to send data out of.
  320. Data - Supplies the buffer of data to send.
  321. Length - Supplies the length of the data buffer, in bytes.
  322. Return Value:
  323. Returns the number of bytes sent on success.
  324. -1 on error, and the errno variable will be set to contain more information.
  325. --*/
  326. {
  327. return send(Socket, Data, Length, 0);
  328. }
  329. int
  330. DbgrSocketReceive (
  331. int Socket,
  332. void *Buffer,
  333. int Length
  334. )
  335. /*++
  336. Routine Description:
  337. This routine receives data from a connected socket.
  338. Arguments:
  339. Socket - Supplies the file descriptor of the socket to receive data from.
  340. Buffer - Supplies a pointer to a buffer where the received data will be
  341. returned.
  342. Length - Supplies the length of the data buffer, in bytes.
  343. Return Value:
  344. Returns the number of bytes received on success.
  345. -1 on error, and the errno variable will be set to contain more information.
  346. --*/
  347. {
  348. return recv(Socket, Buffer, Length, 0);
  349. }
  350. int
  351. DbgrSocketPeek (
  352. int Socket,
  353. void *Buffer,
  354. int Length
  355. )
  356. /*++
  357. Routine Description:
  358. This routine peeks at data from a received socket, but does not remove it
  359. from the queue.
  360. Arguments:
  361. Socket - Supplies the file descriptor of the socket to receive data from.
  362. Buffer - Supplies a pointer to a buffer where the peeked data will be
  363. returned.
  364. Length - Supplies the length of the data buffer, in bytes.
  365. Return Value:
  366. Returns the number of bytes received on success.
  367. -1 on error, and the errno variable will be set to contain more information.
  368. --*/
  369. {
  370. return recvfrom(Socket, Buffer, Length, MSG_PEEK, NULL, NULL);
  371. }
  372. //
  373. // --------------------------------------------------------- Internal Functions
  374. //