w32socket-unix.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595
  1. /**
  2. * \file
  3. * Unix specific socket code.
  4. *
  5. * Copyright 2016 Microsoft
  6. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  7. */
  8. #include <config.h>
  9. #include <glib.h>
  10. #include <pthread.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #ifdef HAVE_SYS_IOCTL_H
  16. #include <sys/ioctl.h>
  17. #endif
  18. #include <netinet/in.h>
  19. #include <netinet/tcp.h>
  20. #ifdef HAVE_NETDB_H
  21. #include <netdb.h>
  22. #endif
  23. #ifdef HAVE_NETINET_TCP_H
  24. #include <arpa/inet.h>
  25. #endif
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #ifdef HAVE_SYS_UIO_H
  32. #include <sys/uio.h>
  33. #endif
  34. #ifdef HAVE_SYS_IOCTL_H
  35. #include <sys/ioctl.h>
  36. #endif
  37. #ifdef HAVE_SYS_FILIO_H
  38. #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
  39. #endif
  40. #ifdef HAVE_SYS_SOCKIO_H
  41. #include <sys/sockio.h> /* defines SIOCATMARK */
  42. #endif
  43. #include <signal.h>
  44. #ifdef HAVE_SYS_SENDFILE_H
  45. #include <sys/sendfile.h>
  46. #endif
  47. #include <sys/stat.h>
  48. #include "w32socket.h"
  49. #include "w32socket-internals.h"
  50. #include "w32error.h"
  51. #include "fdhandle.h"
  52. #include "utils/mono-logger-internals.h"
  53. #include "utils/mono-poll.h"
  54. #include "utils/mono-compiler.h"
  55. #include "icall-decl.h"
  56. #include "utils/mono-errno.h"
  57. typedef struct {
  58. MonoFDHandle fdhandle;
  59. gint domain;
  60. gint type;
  61. gint protocol;
  62. gint saved_error;
  63. gint still_readable;
  64. } SocketHandle;
  65. static SocketHandle*
  66. socket_data_create (MonoFDType type, gint fd)
  67. {
  68. SocketHandle *sockethandle;
  69. sockethandle = g_new0 (SocketHandle, 1);
  70. mono_fdhandle_init ((MonoFDHandle*) sockethandle, type, fd);
  71. return sockethandle;
  72. }
  73. static void
  74. socket_data_close (MonoFDHandle *fdhandle)
  75. {
  76. MonoThreadInfo *info;
  77. SocketHandle* sockethandle;
  78. gint ret;
  79. sockethandle = (SocketHandle*) fdhandle;
  80. g_assert (sockethandle);
  81. info = mono_thread_info_current ();
  82. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: closing fd %d", __func__, ((MonoFDHandle*) sockethandle)->fd);
  83. /* Shutdown the socket for reading, to interrupt any potential
  84. * receives that may be blocking for data. See bug 75705. */
  85. MONO_ENTER_GC_SAFE;
  86. shutdown (((MonoFDHandle*) sockethandle)->fd, SHUT_RD);
  87. MONO_EXIT_GC_SAFE;
  88. retry_close:
  89. MONO_ENTER_GC_SAFE;
  90. ret = close (((MonoFDHandle*) sockethandle)->fd);
  91. MONO_EXIT_GC_SAFE;
  92. if (ret == -1) {
  93. if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
  94. goto retry_close;
  95. }
  96. sockethandle->saved_error = 0;
  97. }
  98. static void
  99. socket_data_destroy (MonoFDHandle *fdhandle)
  100. {
  101. SocketHandle *sockethandle;
  102. sockethandle = (SocketHandle*) fdhandle;
  103. g_assert (sockethandle);
  104. g_free (sockethandle);
  105. }
  106. void
  107. mono_w32socket_initialize (void)
  108. {
  109. MonoFDHandleCallback socket_data_callbacks;
  110. memset (&socket_data_callbacks, 0, sizeof (socket_data_callbacks));
  111. socket_data_callbacks.close = socket_data_close;
  112. socket_data_callbacks.destroy = socket_data_destroy;
  113. mono_fdhandle_register (MONO_FDTYPE_SOCKET, &socket_data_callbacks);
  114. }
  115. void
  116. mono_w32socket_cleanup (void)
  117. {
  118. }
  119. SOCKET
  120. mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
  121. {
  122. SocketHandle *sockethandle, *accepted_socket_data;
  123. MonoThreadInfo *info;
  124. gint accepted_fd;
  125. if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
  126. mono_w32socket_set_last_error (WSAEFAULT);
  127. return INVALID_SOCKET;
  128. }
  129. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  130. mono_w32error_set_last (WSAENOTSOCK);
  131. return INVALID_SOCKET;
  132. }
  133. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  134. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  135. mono_w32error_set_last (WSAENOTSOCK);
  136. return INVALID_SOCKET;
  137. }
  138. info = mono_thread_info_current ();
  139. do {
  140. MONO_ENTER_GC_SAFE;
  141. accepted_fd = accept (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
  142. MONO_EXIT_GC_SAFE;
  143. } while (accepted_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  144. if (accepted_fd == -1) {
  145. gint error = mono_w32socket_convert_error (errno);
  146. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: accept error: %s", __func__, g_strerror(errno));
  147. mono_w32socket_set_last_error (error);
  148. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  149. return INVALID_SOCKET;
  150. }
  151. accepted_socket_data = socket_data_create (MONO_FDTYPE_SOCKET, accepted_fd);
  152. accepted_socket_data->domain = sockethandle->domain;
  153. accepted_socket_data->type = sockethandle->type;
  154. accepted_socket_data->protocol = sockethandle->protocol;
  155. accepted_socket_data->still_readable = 1;
  156. mono_fdhandle_insert ((MonoFDHandle*) accepted_socket_data);
  157. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: returning accepted handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) accepted_socket_data)->fd));
  158. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  159. return ((MonoFDHandle*) accepted_socket_data)->fd;
  160. }
  161. int
  162. mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, socklen_t addrlen, gboolean blocking)
  163. {
  164. SocketHandle *sockethandle;
  165. gint ret;
  166. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  167. mono_w32error_set_last (WSAENOTSOCK);
  168. return SOCKET_ERROR;
  169. }
  170. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  171. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  172. mono_w32error_set_last (WSAENOTSOCK);
  173. return SOCKET_ERROR;
  174. }
  175. MONO_ENTER_GC_SAFE;
  176. ret = connect (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
  177. MONO_EXIT_GC_SAFE;
  178. if (ret == -1) {
  179. MonoThreadInfo *info;
  180. mono_pollfd fds;
  181. gint errnum, so_error;
  182. socklen_t len;
  183. errnum = errno;
  184. if (errno != EINTR) {
  185. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: connect error: %s", __func__,
  186. g_strerror (errnum));
  187. errnum = mono_w32socket_convert_error (errnum);
  188. if (errnum == WSAEINPROGRESS)
  189. errnum = WSAEWOULDBLOCK; /* see bug #73053 */
  190. mono_w32socket_set_last_error (errnum);
  191. /*
  192. * On solaris x86 getsockopt (SO_ERROR) is not set after
  193. * connect () fails so we need to save this error.
  194. *
  195. * But don't do this for EWOULDBLOCK (bug 317315)
  196. */
  197. if (errnum != WSAEWOULDBLOCK) {
  198. /* ECONNRESET means the socket was closed by another thread */
  199. /* Async close on mac raises ECONNABORTED. */
  200. sockethandle->saved_error = errnum;
  201. }
  202. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  203. return SOCKET_ERROR;
  204. }
  205. info = mono_thread_info_current ();
  206. fds.fd = ((MonoFDHandle*) sockethandle)->fd;
  207. fds.events = MONO_POLLOUT;
  208. for (;;) {
  209. MONO_ENTER_GC_SAFE;
  210. ret = mono_poll (&fds, 1, -1);
  211. MONO_EXIT_GC_SAFE;
  212. if (ret != -1 || mono_thread_info_is_interrupt_state (info))
  213. break;
  214. if (errno != EINTR) {
  215. gint errnum = errno;
  216. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: connect poll error: %s", __func__, g_strerror (errno));
  217. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  218. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  219. return SOCKET_ERROR;
  220. }
  221. }
  222. len = sizeof(so_error);
  223. MONO_ENTER_GC_SAFE;
  224. ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
  225. MONO_EXIT_GC_SAFE;
  226. if (ret == -1) {
  227. gint errnum = errno;
  228. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
  229. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  230. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  231. return SOCKET_ERROR;
  232. }
  233. if (so_error != 0) {
  234. gint errnum = mono_w32socket_convert_error (so_error);
  235. /* Need to save this socket error */
  236. sockethandle->saved_error = errnum;
  237. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: connect getsockopt returned error: %s",
  238. __func__, g_strerror (so_error));
  239. mono_w32socket_set_last_error (errnum);
  240. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  241. return SOCKET_ERROR;
  242. }
  243. }
  244. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  245. return 0;
  246. }
  247. int
  248. mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
  249. {
  250. return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking);
  251. }
  252. int
  253. mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
  254. {
  255. SocketHandle *sockethandle;
  256. int ret;
  257. MonoThreadInfo *info;
  258. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  259. mono_w32error_set_last (WSAENOTSOCK);
  260. return SOCKET_ERROR;
  261. }
  262. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  263. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  264. mono_w32error_set_last (WSAENOTSOCK);
  265. return SOCKET_ERROR;
  266. }
  267. info = mono_thread_info_current ();
  268. do {
  269. MONO_ENTER_GC_SAFE;
  270. ret = recvfrom (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, from, fromlen);
  271. MONO_EXIT_GC_SAFE;
  272. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  273. if (ret == 0 && len > 0) {
  274. /* According to the Linux man page, recvfrom only
  275. * returns 0 when the socket has been shut down
  276. * cleanly. Turn this into an EINTR to simulate win32
  277. * behaviour of returning EINTR when a socket is
  278. * closed while the recvfrom is blocking (we use a
  279. * shutdown() in socket_close() to trigger this.) See
  280. * bug 75705.
  281. */
  282. /* Distinguish between the socket being shut down at
  283. * the local or remote ends, and reads that request 0
  284. * bytes to be read
  285. */
  286. /* If this returns FALSE, it means the socket has been
  287. * closed locally. If it returns TRUE, but
  288. * still_readable != 1 then shutdown
  289. * (SHUT_RD|SHUT_RDWR) has been called locally.
  290. */
  291. if (sockethandle->still_readable != 1) {
  292. ret = -1;
  293. mono_set_errno (EINTR);
  294. }
  295. }
  296. if (ret == -1) {
  297. gint errnum = errno;
  298. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: recv error: %s", __func__, g_strerror(errno));
  299. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  300. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  301. return SOCKET_ERROR;
  302. }
  303. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  304. return ret;
  305. }
  306. static void
  307. wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr)
  308. {
  309. guint32 i;
  310. memset (hdr, 0, sizeof (struct msghdr));
  311. hdr->msg_iovlen = count;
  312. hdr->msg_iov = g_new0 (struct iovec, count);
  313. for (i = 0; i < count; i++) {
  314. hdr->msg_iov [i].iov_base = buffers [i].buf;
  315. hdr->msg_iov [i].iov_len = buffers [i].len;
  316. }
  317. }
  318. static void
  319. msghdr_iov_free (struct msghdr *hdr)
  320. {
  321. g_free (hdr->msg_iov);
  322. }
  323. int
  324. mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
  325. {
  326. SocketHandle *sockethandle;
  327. MonoThreadInfo *info;
  328. gint ret;
  329. struct msghdr hdr;
  330. g_assert (overlapped == NULL);
  331. g_assert (complete == NULL);
  332. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  333. mono_w32error_set_last (WSAENOTSOCK);
  334. return SOCKET_ERROR;
  335. }
  336. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  337. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  338. mono_w32error_set_last (WSAENOTSOCK);
  339. return SOCKET_ERROR;
  340. }
  341. info = mono_thread_info_current ();
  342. wsabuf_to_msghdr (buffers, count, &hdr);
  343. do {
  344. MONO_ENTER_GC_SAFE;
  345. ret = recvmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, *flags);
  346. MONO_EXIT_GC_SAFE;
  347. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  348. msghdr_iov_free (&hdr);
  349. if (ret == 0) {
  350. /* see mono_w32socket_recvfrom */
  351. if (sockethandle->still_readable != 1) {
  352. ret = -1;
  353. mono_set_errno (EINTR);
  354. }
  355. }
  356. if (ret == -1) {
  357. gint errnum = errno;
  358. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: recvmsg error: %s", __func__, g_strerror(errno));
  359. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  360. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  361. return SOCKET_ERROR;
  362. }
  363. *received = ret;
  364. *flags = hdr.msg_flags;
  365. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  366. return 0;
  367. }
  368. int
  369. mono_w32socket_send (SOCKET sock, void *buf, int len, int flags, gboolean blocking)
  370. {
  371. SocketHandle *sockethandle;
  372. int ret;
  373. MonoThreadInfo *info;
  374. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  375. mono_w32error_set_last (WSAENOTSOCK);
  376. return SOCKET_ERROR;
  377. }
  378. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  379. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  380. mono_w32error_set_last (WSAENOTSOCK);
  381. return SOCKET_ERROR;
  382. }
  383. info = mono_thread_info_current ();
  384. do {
  385. MONO_ENTER_GC_SAFE;
  386. ret = send (((MonoFDHandle*) sockethandle)->fd, buf, len, flags);
  387. MONO_EXIT_GC_SAFE;
  388. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  389. if (ret == -1) {
  390. gint errnum = errno;
  391. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: send error: %s", __func__, g_strerror (errno));
  392. #ifdef O_NONBLOCK
  393. /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
  394. * a blocking socket. See bug #599488 */
  395. if (errnum == EAGAIN) {
  396. MONO_ENTER_GC_SAFE;
  397. ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
  398. MONO_EXIT_GC_SAFE;
  399. if (ret != -1 && (ret & O_NONBLOCK) == 0)
  400. errnum = ETIMEDOUT;
  401. }
  402. #endif /* O_NONBLOCK */
  403. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  404. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  405. return SOCKET_ERROR;
  406. }
  407. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  408. return ret;
  409. }
  410. int
  411. mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
  412. {
  413. SocketHandle *sockethandle;
  414. int ret;
  415. MonoThreadInfo *info;
  416. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  417. mono_w32error_set_last (WSAENOTSOCK);
  418. return SOCKET_ERROR;
  419. }
  420. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  421. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  422. mono_w32error_set_last (WSAENOTSOCK);
  423. return SOCKET_ERROR;
  424. }
  425. info = mono_thread_info_current ();
  426. do {
  427. MONO_ENTER_GC_SAFE;
  428. ret = sendto (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, to, tolen);
  429. MONO_EXIT_GC_SAFE;
  430. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  431. if (ret == -1) {
  432. gint errnum = errno;
  433. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: send error: %s", __func__, g_strerror (errno));
  434. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  435. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  436. return SOCKET_ERROR;
  437. }
  438. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  439. return ret;
  440. }
  441. int
  442. mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
  443. {
  444. struct msghdr hdr;
  445. MonoThreadInfo *info;
  446. SocketHandle *sockethandle;
  447. gint ret;
  448. g_assert (overlapped == NULL);
  449. g_assert (complete == NULL);
  450. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  451. mono_w32error_set_last (WSAENOTSOCK);
  452. return SOCKET_ERROR;
  453. }
  454. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  455. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  456. mono_w32error_set_last (WSAENOTSOCK);
  457. return SOCKET_ERROR;
  458. }
  459. info = mono_thread_info_current ();
  460. wsabuf_to_msghdr (buffers, count, &hdr);
  461. do {
  462. MONO_ENTER_GC_SAFE;
  463. ret = sendmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, flags);
  464. MONO_EXIT_GC_SAFE;
  465. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  466. msghdr_iov_free (&hdr);
  467. if (ret == -1) {
  468. gint errnum = errno;
  469. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: sendmsg error: %s", __func__, g_strerror (errno));
  470. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  471. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  472. return SOCKET_ERROR;
  473. }
  474. *sent = ret;
  475. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  476. return 0;
  477. }
  478. #define SF_BUFFER_SIZE 16384
  479. BOOL
  480. mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, gpointer lpTransmitBuffers, guint32 flags, gboolean blocking)
  481. {
  482. MonoThreadInfo *info;
  483. SocketHandle *sockethandle;
  484. gint file;
  485. gssize ret;
  486. #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
  487. struct stat statbuf;
  488. #else
  489. gpointer buffer;
  490. #endif
  491. TRANSMIT_FILE_BUFFERS *buffers = (TRANSMIT_FILE_BUFFERS *)lpTransmitBuffers;
  492. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  493. mono_w32error_set_last (WSAENOTSOCK);
  494. return FALSE;
  495. }
  496. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  497. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  498. mono_w32error_set_last (WSAENOTSOCK);
  499. return FALSE;
  500. }
  501. /* Write the header */
  502. if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
  503. ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Head, buffers->HeadLength, 0, FALSE);
  504. if (ret == SOCKET_ERROR) {
  505. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  506. return FALSE;
  507. }
  508. }
  509. info = mono_thread_info_current ();
  510. file = GPOINTER_TO_INT (file_handle);
  511. #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
  512. MONO_ENTER_GC_SAFE;
  513. ret = fstat (file, &statbuf);
  514. MONO_EXIT_GC_SAFE;
  515. if (ret == -1) {
  516. gint errnum = errno;
  517. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  518. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  519. return FALSE;
  520. }
  521. do {
  522. MONO_ENTER_GC_SAFE;
  523. #ifdef __linux__
  524. ret = sendfile (((MonoFDHandle*) sockethandle)->fd, file, NULL, statbuf.st_size);
  525. #elif defined(DARWIN)
  526. /* TODO: header/tail could be sent in the 5th argument */
  527. /* TODO: Might not send the entire file for non-blocking sockets */
  528. ret = sendfile (file, ((MonoFDHandle*) sockethandle)->fd, 0, &statbuf.st_size, NULL, 0);
  529. #endif
  530. MONO_EXIT_GC_SAFE;
  531. } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  532. #else
  533. buffer = g_malloc (SF_BUFFER_SIZE);
  534. do {
  535. do {
  536. MONO_ENTER_GC_SAFE;
  537. ret = read (file, buffer, SF_BUFFER_SIZE);
  538. MONO_EXIT_GC_SAFE;
  539. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  540. if (ret == -1 || ret == 0)
  541. break;
  542. do {
  543. MONO_ENTER_GC_SAFE;
  544. ret = send (((MonoFDHandle*) sockethandle)->fd, buffer, ret, 0); /* short sends? enclose this in a loop? */
  545. MONO_EXIT_GC_SAFE;
  546. } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  547. } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
  548. g_free (buffer);
  549. #endif
  550. if (ret == -1) {
  551. gint errnum = errno;
  552. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  553. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  554. return FALSE;
  555. }
  556. /* Write the tail */
  557. if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
  558. ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Tail, buffers->TailLength, 0, FALSE);
  559. if (ret == SOCKET_ERROR) {
  560. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  561. return FALSE;
  562. }
  563. }
  564. if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
  565. mono_w32socket_close (((MonoFDHandle*) sockethandle)->fd);
  566. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  567. return TRUE;
  568. }
  569. SOCKET
  570. mono_w32socket_socket (int domain, int type, int protocol)
  571. {
  572. SocketHandle *sockethandle;
  573. gint fd;
  574. retry_socket:
  575. MONO_ENTER_GC_SAFE;
  576. fd = socket (domain, type, protocol);
  577. MONO_EXIT_GC_SAFE;
  578. if (fd == -1) {
  579. if (domain == AF_INET && type == SOCK_RAW && protocol == 0) {
  580. /* Retry with protocol == 4 (see bug #54565) */
  581. // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
  582. protocol = 4;
  583. goto retry_socket;
  584. }
  585. gint errnum = errno;
  586. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: socket error: %s", __func__, g_strerror (errno));
  587. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  588. return INVALID_SOCKET;
  589. }
  590. sockethandle = socket_data_create(MONO_FDTYPE_SOCKET, fd);
  591. sockethandle->domain = domain;
  592. sockethandle->type = type;
  593. sockethandle->protocol = protocol;
  594. sockethandle->still_readable = 1;
  595. /* .net seems to set this by default for SOCK_STREAM, not for
  596. * SOCK_DGRAM (see bug #36322)
  597. * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
  598. *
  599. * It seems winsock has a rather different idea of what
  600. * SO_REUSEADDR means. If it's set, then a new socket can be
  601. * bound over an existing listening socket. There's a new
  602. * windows-specific option called SO_EXCLUSIVEADDRUSE but
  603. * using that means the socket MUST be closed properly, or a
  604. * denial of service can occur. Luckily for us, winsock
  605. * behaves as though any other system would when SO_REUSEADDR
  606. * is true, so we don't need to do anything else here. See
  607. * bug 53992.
  608. * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
  609. */
  610. {
  611. int ret;
  612. const int true_ = 1;
  613. MONO_ENTER_GC_SAFE;
  614. ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
  615. MONO_EXIT_GC_SAFE;
  616. if (ret == -1) {
  617. gint errnum = errno;
  618. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: Error setting SO_REUSEADDR", __func__);
  619. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  620. MONO_ENTER_GC_SAFE;
  621. close (((MonoFDHandle*) sockethandle)->fd);
  622. MONO_EXIT_GC_SAFE;
  623. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  624. return INVALID_SOCKET;
  625. }
  626. }
  627. mono_fdhandle_insert ((MonoFDHandle*) sockethandle);
  628. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: returning socket handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) sockethandle)->fd));
  629. return ((MonoFDHandle*) sockethandle)->fd;
  630. }
  631. gint
  632. mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
  633. {
  634. SocketHandle *sockethandle;
  635. int ret;
  636. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  637. mono_w32error_set_last (WSAENOTSOCK);
  638. return SOCKET_ERROR;
  639. }
  640. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  641. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  642. mono_w32error_set_last (WSAENOTSOCK);
  643. return SOCKET_ERROR;
  644. }
  645. MONO_ENTER_GC_SAFE;
  646. ret = bind (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
  647. MONO_EXIT_GC_SAFE;
  648. if (ret == -1) {
  649. gint errnum = errno;
  650. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: bind error: %s", __func__, g_strerror(errno));
  651. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  652. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  653. return SOCKET_ERROR;
  654. }
  655. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  656. return 0;
  657. }
  658. gint
  659. mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
  660. {
  661. SocketHandle *sockethandle;
  662. gint ret;
  663. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  664. mono_w32error_set_last (WSAENOTSOCK);
  665. return SOCKET_ERROR;
  666. }
  667. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  668. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  669. mono_w32error_set_last (WSAENOTSOCK);
  670. return SOCKET_ERROR;
  671. }
  672. #ifdef HAVE_GETPEERNAME
  673. MONO_ENTER_GC_SAFE;
  674. ret = getpeername (((MonoFDHandle*) sockethandle)->fd, name, namelen);
  675. MONO_EXIT_GC_SAFE;
  676. #else
  677. ret = -1;
  678. #endif
  679. if (ret == -1) {
  680. gint errnum = errno;
  681. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: getpeername error: %s", __func__, g_strerror (errno));
  682. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  683. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  684. return SOCKET_ERROR;
  685. }
  686. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  687. return 0;
  688. }
  689. gint
  690. mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
  691. {
  692. SocketHandle *sockethandle;
  693. gint ret;
  694. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  695. mono_w32error_set_last (WSAENOTSOCK);
  696. return SOCKET_ERROR;
  697. }
  698. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  699. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  700. mono_w32error_set_last (WSAENOTSOCK);
  701. return SOCKET_ERROR;
  702. }
  703. MONO_ENTER_GC_SAFE;
  704. ret = getsockname (((MonoFDHandle*) sockethandle)->fd, name, namelen);
  705. MONO_EXIT_GC_SAFE;
  706. if (ret == -1) {
  707. gint errnum = errno;
  708. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: getsockname error: %s", __func__, g_strerror (errno));
  709. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  710. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  711. return SOCKET_ERROR;
  712. }
  713. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  714. return 0;
  715. }
  716. gint
  717. mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
  718. {
  719. SocketHandle *sockethandle;
  720. gint ret;
  721. struct timeval tv;
  722. gpointer tmp_val;
  723. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  724. mono_w32error_set_last (WSAENOTSOCK);
  725. return SOCKET_ERROR;
  726. }
  727. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  728. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  729. mono_w32error_set_last (WSAENOTSOCK);
  730. return SOCKET_ERROR;
  731. }
  732. tmp_val = optval;
  733. if (level == SOL_SOCKET &&
  734. (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
  735. tmp_val = &tv;
  736. *optlen = sizeof (tv);
  737. }
  738. MONO_ENTER_GC_SAFE;
  739. ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
  740. MONO_EXIT_GC_SAFE;
  741. if (ret == -1) {
  742. gint errnum = errno;
  743. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: getsockopt error: %s", __func__, g_strerror (errno));
  744. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  745. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  746. return SOCKET_ERROR;
  747. }
  748. if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
  749. *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
  750. *optlen = sizeof (int);
  751. }
  752. if (optname == SO_ERROR) {
  753. if (*((int *)optval) != 0) {
  754. *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
  755. sockethandle->saved_error = *((int *)optval);
  756. } else {
  757. *((int *)optval) = sockethandle->saved_error;
  758. }
  759. }
  760. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  761. return 0;
  762. }
  763. gint
  764. mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, gconstpointer optval, socklen_t optlen)
  765. {
  766. SocketHandle *sockethandle;
  767. gint ret;
  768. gconstpointer tmp_val;
  769. #if defined (__linux__)
  770. /* This has its address taken so it cannot be moved to the if block which uses it */
  771. gint bufsize = 0;
  772. #endif
  773. struct timeval tv;
  774. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  775. mono_w32error_set_last (WSAENOTSOCK);
  776. return SOCKET_ERROR;
  777. }
  778. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  779. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  780. mono_w32error_set_last (WSAENOTSOCK);
  781. return SOCKET_ERROR;
  782. }
  783. tmp_val = optval;
  784. if (level == SOL_SOCKET &&
  785. (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
  786. int ms = *((int *) optval);
  787. tv.tv_sec = ms / 1000;
  788. tv.tv_usec = (ms % 1000) * 1000; // micro from milli
  789. tmp_val = &tv;
  790. optlen = sizeof (tv);
  791. }
  792. #if defined (__linux__)
  793. else if (level == SOL_SOCKET &&
  794. (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
  795. /* According to socket(7) the Linux kernel doubles the
  796. * buffer sizes "to allow space for bookkeeping
  797. * overhead."
  798. */
  799. bufsize = *((int *) optval);
  800. bufsize /= 2;
  801. tmp_val = &bufsize;
  802. }
  803. #endif
  804. MONO_ENTER_GC_SAFE;
  805. ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
  806. MONO_EXIT_GC_SAFE;
  807. if (ret == -1) {
  808. gint errnum = errno;
  809. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: setsockopt error: %s", __func__, g_strerror (errno));
  810. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  811. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  812. return SOCKET_ERROR;
  813. }
  814. #if defined (SO_REUSEPORT)
  815. /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
  816. if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
  817. int type;
  818. socklen_t type_len = sizeof (type);
  819. MONO_ENTER_GC_SAFE;
  820. ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_TYPE, &type, &type_len);
  821. MONO_EXIT_GC_SAFE;
  822. if (!ret) {
  823. if (type == SOCK_DGRAM || type == SOCK_STREAM) {
  824. MONO_ENTER_GC_SAFE;
  825. setsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_REUSEPORT, tmp_val, optlen);
  826. MONO_EXIT_GC_SAFE;
  827. }
  828. }
  829. }
  830. #endif
  831. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  832. return ret;
  833. }
  834. gint
  835. mono_w32socket_listen (SOCKET sock, gint backlog)
  836. {
  837. SocketHandle *sockethandle;
  838. gint ret;
  839. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  840. mono_w32error_set_last (WSAENOTSOCK);
  841. return SOCKET_ERROR;
  842. }
  843. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  844. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  845. mono_w32error_set_last (WSAENOTSOCK);
  846. return SOCKET_ERROR;
  847. }
  848. MONO_ENTER_GC_SAFE;
  849. ret = listen (((MonoFDHandle*) sockethandle)->fd, backlog);
  850. MONO_EXIT_GC_SAFE;
  851. if (ret == -1) {
  852. gint errnum = errno;
  853. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: listen error: %s", __func__, g_strerror (errno));
  854. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  855. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  856. return SOCKET_ERROR;
  857. }
  858. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  859. return 0;
  860. }
  861. gint
  862. mono_w32socket_shutdown (SOCKET sock, gint how)
  863. {
  864. SocketHandle *sockethandle;
  865. gint ret;
  866. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  867. mono_w32error_set_last (WSAENOTSOCK);
  868. return SOCKET_ERROR;
  869. }
  870. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  871. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  872. mono_w32error_set_last (WSAENOTSOCK);
  873. return SOCKET_ERROR;
  874. }
  875. if (how == SHUT_RD || how == SHUT_RDWR)
  876. sockethandle->still_readable = 0;
  877. MONO_ENTER_GC_SAFE;
  878. ret = shutdown (((MonoFDHandle*) sockethandle)->fd, how);
  879. MONO_EXIT_GC_SAFE;
  880. if (ret == -1) {
  881. gint errnum = errno;
  882. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: shutdown error: %s", __func__, g_strerror (errno));
  883. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  884. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  885. return SOCKET_ERROR;
  886. }
  887. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  888. return ret;
  889. }
  890. gint
  891. mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
  892. {
  893. SocketHandle *sockethandle;
  894. SOCKET newsock;
  895. gint ret;
  896. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: called on socket %d!", __func__, sock);
  897. /* We could check the socket type here and fail unless its
  898. * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
  899. * if we really wanted to */
  900. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  901. mono_w32error_set_last (WSAENOTSOCK);
  902. return SOCKET_ERROR;
  903. }
  904. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  905. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  906. mono_w32error_set_last (WSAENOTSOCK);
  907. return SOCKET_ERROR;
  908. }
  909. MONO_ENTER_GC_SAFE;
  910. newsock = socket (sockethandle->domain, sockethandle->type, sockethandle->protocol);
  911. MONO_EXIT_GC_SAFE;
  912. if (newsock == -1) {
  913. gint errnum = errno;
  914. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: socket error: %s", __func__, g_strerror (errnum));
  915. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  916. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  917. return SOCKET_ERROR;
  918. }
  919. /* According to Stevens "Advanced Programming in the UNIX
  920. * Environment: UNIX File I/O" dup2() is atomic so there
  921. * should not be a race condition between the old fd being
  922. * closed and the new socket fd being copied over */
  923. do {
  924. MONO_ENTER_GC_SAFE;
  925. ret = dup2 (newsock, ((MonoFDHandle*) sockethandle)->fd);
  926. MONO_EXIT_GC_SAFE;
  927. } while (ret == -1 && errno == EAGAIN);
  928. if (ret == -1) {
  929. gint errnum = errno;
  930. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: dup2 error: %s", __func__, g_strerror (errnum));
  931. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  932. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  933. return SOCKET_ERROR;
  934. }
  935. MONO_ENTER_GC_SAFE;
  936. close (newsock);
  937. MONO_EXIT_GC_SAFE;
  938. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  939. return 0;
  940. }
  941. static gboolean
  942. extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
  943. {
  944. gboolean ret;
  945. MONO_ENTER_GC_UNSAFE;
  946. ret = mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
  947. MONO_EXIT_GC_UNSAFE;
  948. return ret;
  949. }
  950. static gboolean
  951. extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
  952. OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
  953. {
  954. gboolean ret;
  955. MONO_ENTER_GC_UNSAFE;
  956. ret = mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
  957. MONO_EXIT_GC_UNSAFE;
  958. return ret;
  959. }
  960. const
  961. static struct {
  962. GUID guid;
  963. gpointer func;
  964. } extension_functions[] = {
  965. { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, (gpointer)extension_disconect },
  966. { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, (gpointer)extension_transmit_file },
  967. { {0} , NULL },
  968. };
  969. gint
  970. mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
  971. {
  972. SocketHandle *sockethandle;
  973. gint ret;
  974. gpointer buffer;
  975. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  976. mono_w32error_set_last (WSAENOTSOCK);
  977. return SOCKET_ERROR;
  978. }
  979. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  980. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  981. mono_w32error_set_last (WSAENOTSOCK);
  982. return SOCKET_ERROR;
  983. }
  984. if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
  985. gint i;
  986. GUID *guid;
  987. if (inputlen < sizeof(GUID)) {
  988. /* As far as I can tell, windows doesn't
  989. * actually set an error here...
  990. */
  991. mono_w32socket_set_last_error (WSAEINVAL);
  992. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  993. return SOCKET_ERROR;
  994. }
  995. if (outputlen < sizeof(gpointer)) {
  996. /* Or here... */
  997. mono_w32socket_set_last_error (WSAEINVAL);
  998. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  999. return SOCKET_ERROR;
  1000. }
  1001. if (output == NULL) {
  1002. /* Or here */
  1003. mono_w32socket_set_last_error (WSAEINVAL);
  1004. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1005. return SOCKET_ERROR;
  1006. }
  1007. guid = (GUID*) input;
  1008. for (i = 0; extension_functions[i].func; i++) {
  1009. if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
  1010. memcpy (output, &extension_functions[i].func, sizeof(gpointer));
  1011. *written = sizeof(gpointer);
  1012. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1013. return 0;
  1014. }
  1015. }
  1016. mono_w32socket_set_last_error (WSAEINVAL);
  1017. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1018. return SOCKET_ERROR;
  1019. }
  1020. if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
  1021. guint32 onoff;
  1022. if (inputlen < 3 * sizeof (guint32)) {
  1023. mono_w32socket_set_last_error (WSAEINVAL);
  1024. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1025. return SOCKET_ERROR;
  1026. }
  1027. onoff = *((guint32*) input);
  1028. MONO_ENTER_GC_SAFE;
  1029. ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
  1030. MONO_EXIT_GC_SAFE;
  1031. if (ret < 0) {
  1032. mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
  1033. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1034. return SOCKET_ERROR;
  1035. }
  1036. #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
  1037. if (onoff != 0) {
  1038. /* Values are in ms, but we need s */
  1039. guint32 keepalivetime, keepaliveinterval, rem;
  1040. keepalivetime = *(((guint32*) input) + 1);
  1041. keepaliveinterval = *(((guint32*) input) + 2);
  1042. /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
  1043. rem = keepalivetime % 1000;
  1044. keepalivetime /= 1000;
  1045. if (keepalivetime == 0 || rem >= 500)
  1046. keepalivetime++;
  1047. MONO_ENTER_GC_SAFE;
  1048. ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
  1049. MONO_EXIT_GC_SAFE;
  1050. if (ret == 0) {
  1051. rem = keepaliveinterval % 1000;
  1052. keepaliveinterval /= 1000;
  1053. if (keepaliveinterval == 0 || rem >= 500)
  1054. keepaliveinterval++;
  1055. MONO_ENTER_GC_SAFE;
  1056. ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
  1057. MONO_EXIT_GC_SAFE;
  1058. }
  1059. if (ret != 0) {
  1060. mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
  1061. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1062. return SOCKET_ERROR;
  1063. }
  1064. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1065. return 0;
  1066. }
  1067. #endif
  1068. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1069. return 0;
  1070. }
  1071. buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
  1072. MONO_ENTER_GC_SAFE;
  1073. ret = ioctl (((MonoFDHandle*) sockethandle)->fd, command, buffer);
  1074. MONO_EXIT_GC_SAFE;
  1075. if (ret == -1) {
  1076. g_free (buffer);
  1077. gint errnum = errno;
  1078. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
  1079. mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
  1080. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1081. return SOCKET_ERROR;
  1082. }
  1083. if (!buffer) {
  1084. *written = 0;
  1085. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1086. return 0;
  1087. }
  1088. /* We just copy the buffer to the output. Some ioctls
  1089. * don't even output any data, but, well...
  1090. *
  1091. * NB windows returns WSAEFAULT if outputlen is too small */
  1092. inputlen = (inputlen > outputlen) ? outputlen : inputlen;
  1093. if (inputlen > 0 && output != NULL)
  1094. memcpy (output, buffer, inputlen);
  1095. g_free (buffer);
  1096. *written = inputlen;
  1097. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1098. return 0;
  1099. }
  1100. gboolean
  1101. mono_w32socket_close (SOCKET sock)
  1102. {
  1103. if (!mono_fdhandle_close (sock)) {
  1104. mono_w32error_set_last (ERROR_INVALID_HANDLE);
  1105. return FALSE;
  1106. }
  1107. return TRUE;
  1108. }
  1109. gint
  1110. mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
  1111. {
  1112. #ifdef O_NONBLOCK
  1113. SocketHandle *sockethandle;
  1114. gint ret;
  1115. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  1116. mono_w32error_set_last (WSAENOTSOCK);
  1117. return SOCKET_ERROR;
  1118. }
  1119. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  1120. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1121. mono_w32error_set_last (WSAENOTSOCK);
  1122. return SOCKET_ERROR;
  1123. }
  1124. /* This works better than ioctl(...FIONBIO...)
  1125. * on Linux (it causes connect to return
  1126. * EINPROGRESS, but the ioctl doesn't seem to) */
  1127. MONO_ENTER_GC_SAFE;
  1128. ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
  1129. MONO_EXIT_GC_SAFE;
  1130. if (ret == -1) {
  1131. gint errnum = mono_w32socket_convert_error (errno);
  1132. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: fcntl(F_GETFL) error: %s", __func__, g_strerror (errno));
  1133. mono_w32socket_set_last_error (errnum);
  1134. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1135. return SOCKET_ERROR;
  1136. }
  1137. MONO_ENTER_GC_SAFE;
  1138. ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
  1139. MONO_EXIT_GC_SAFE;
  1140. if (ret == -1) {
  1141. gint errnum = mono_w32socket_convert_error (errno);
  1142. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: fcntl(F_SETFL) error: %s", __func__, g_strerror (errno));
  1143. mono_w32socket_set_last_error (errnum);
  1144. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1145. return SOCKET_ERROR;
  1146. }
  1147. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1148. return 0;
  1149. #else
  1150. mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
  1151. return SOCKET_ERROR;
  1152. #endif /* O_NONBLOCK */
  1153. }
  1154. gint
  1155. mono_w32socket_get_available (SOCKET sock, guint64 *amount)
  1156. {
  1157. SocketHandle *sockethandle;
  1158. gint ret;
  1159. if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
  1160. mono_w32error_set_last (WSAENOTSOCK);
  1161. return SOCKET_ERROR;
  1162. }
  1163. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  1164. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1165. mono_w32error_set_last (WSAENOTSOCK);
  1166. return SOCKET_ERROR;
  1167. }
  1168. #if defined (HOST_DARWIN)
  1169. // ioctl (socket, FIONREAD, XXX) returns the size of
  1170. // the UDP header as well on Darwin.
  1171. //
  1172. // Use getsockopt SO_NREAD instead to get the
  1173. // right values for TCP and UDP.
  1174. //
  1175. // ai_canonname can be null in some cases on darwin,
  1176. // where the runtime assumes it will be the value of
  1177. // the ip buffer.
  1178. socklen_t optlen = sizeof (int);
  1179. MONO_ENTER_GC_SAFE;
  1180. ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
  1181. MONO_EXIT_GC_SAFE;
  1182. if (ret == -1) {
  1183. gint errnum = mono_w32socket_convert_error (errno);
  1184. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: getsockopt error: %s", __func__, g_strerror (errno));
  1185. mono_w32socket_set_last_error (errnum);
  1186. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1187. return SOCKET_ERROR;
  1188. }
  1189. #else
  1190. MONO_ENTER_GC_SAFE;
  1191. ret = ioctl (((MonoFDHandle*) sockethandle)->fd, FIONREAD, (gulong*) amount);
  1192. MONO_EXIT_GC_SAFE;
  1193. if (ret == -1) {
  1194. gint errnum = mono_w32socket_convert_error (errno);
  1195. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_SOCKET, "%s: ioctl error: %s", __func__, g_strerror (errno));
  1196. mono_w32socket_set_last_error (errnum);
  1197. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1198. return SOCKET_ERROR;
  1199. }
  1200. #endif
  1201. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1202. return 0;
  1203. }
  1204. void
  1205. mono_w32socket_set_last_error (gint32 error)
  1206. {
  1207. mono_w32error_set_last (error);
  1208. }
  1209. gint32
  1210. mono_w32socket_get_last_error (void)
  1211. {
  1212. return mono_w32error_get_last ();
  1213. }
  1214. gint32
  1215. mono_w32socket_convert_error (gint error)
  1216. {
  1217. switch (error) {
  1218. case 0: return ERROR_SUCCESS;
  1219. case EACCES: return WSAEACCES;
  1220. #ifdef EADDRINUSE
  1221. case EADDRINUSE: return WSAEADDRINUSE;
  1222. #endif
  1223. #ifdef EAFNOSUPPORT
  1224. case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
  1225. #endif
  1226. #if EAGAIN != EWOULDBLOCK
  1227. case EAGAIN: return WSAEWOULDBLOCK;
  1228. #endif
  1229. #ifdef EALREADY
  1230. case EALREADY: return WSAEALREADY;
  1231. #endif
  1232. case EBADF: return WSAENOTSOCK;
  1233. #ifdef ECONNABORTED
  1234. case ECONNABORTED: return WSAENETDOWN;
  1235. #endif
  1236. #ifdef ECONNREFUSED
  1237. case ECONNREFUSED: return WSAECONNREFUSED;
  1238. #endif
  1239. #ifdef ECONNRESET
  1240. case ECONNRESET: return WSAECONNRESET;
  1241. #endif
  1242. case EDOM: return WSAEINVAL; /* not a precise match, best wecan do. */
  1243. case EFAULT: return WSAEFAULT;
  1244. #ifdef EHOSTUNREACH
  1245. case EHOSTUNREACH: return WSAEHOSTUNREACH;
  1246. #endif
  1247. #ifdef EINPROGRESS
  1248. case EINPROGRESS: return WSAEINPROGRESS;
  1249. #endif
  1250. case EINTR: return WSAEINTR;
  1251. case EINVAL: return WSAEINVAL;
  1252. case EIO: return WSA_INVALID_HANDLE; /* not a precise match, best we can do. */
  1253. #ifdef EISCONN
  1254. case EISCONN: return WSAEISCONN;
  1255. #endif
  1256. case ELOOP: return WSAELOOP;
  1257. case ENFILE: return WSAEMFILE; /* not a precise match, best we can do. */
  1258. case EMFILE: return WSAEMFILE;
  1259. #ifdef EMSGSIZE
  1260. case EMSGSIZE: return WSAEMSGSIZE;
  1261. #endif
  1262. case ENAMETOOLONG: return WSAENAMETOOLONG;
  1263. #ifdef ENETUNREACH
  1264. case ENETUNREACH: return WSAENETUNREACH;
  1265. #endif
  1266. #ifdef ENOBUFS
  1267. case ENOBUFS: return WSAENOBUFS; /* not documented */
  1268. #endif
  1269. case ENOMEM: return WSAENOBUFS;
  1270. #ifdef ENOPROTOOPT
  1271. case ENOPROTOOPT: return WSAENOPROTOOPT;
  1272. #endif
  1273. #ifdef ENOSR
  1274. case ENOSR: return WSAENETDOWN;
  1275. #endif
  1276. #ifdef ENOTCONN
  1277. case ENOTCONN: return WSAENOTCONN;
  1278. #endif
  1279. case ENOTDIR: return WSA_INVALID_PARAMETER; /* not a precise match, best we can do. */
  1280. #ifdef ENOTSOCK
  1281. case ENOTSOCK: return WSAENOTSOCK;
  1282. #endif
  1283. case ENOTTY: return WSAENOTSOCK;
  1284. #ifdef EOPNOTSUPP
  1285. case EOPNOTSUPP: return WSAEOPNOTSUPP;
  1286. #endif
  1287. case EPERM: return WSAEACCES;
  1288. case EPIPE: return WSAESHUTDOWN;
  1289. #ifdef EPROTONOSUPPORT
  1290. case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
  1291. #endif
  1292. #if ERESTARTSYS
  1293. case ERESTARTSYS: return WSAENETDOWN;
  1294. #endif
  1295. /*FIXME: case EROFS: return WSAE????; */
  1296. #ifdef ESOCKTNOSUPPORT
  1297. case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
  1298. #endif
  1299. #ifdef ETIMEDOUT
  1300. case ETIMEDOUT: return WSAETIMEDOUT;
  1301. #endif
  1302. #ifdef EWOULDBLOCK
  1303. case EWOULDBLOCK: return WSAEWOULDBLOCK;
  1304. #endif
  1305. #ifdef EADDRNOTAVAIL
  1306. case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
  1307. #endif
  1308. /* This might happen with unix sockets */
  1309. case ENOENT: return WSAECONNREFUSED;
  1310. #ifdef EDESTADDRREQ
  1311. case EDESTADDRREQ: return WSAEDESTADDRREQ;
  1312. #endif
  1313. #ifdef EHOSTDOWN
  1314. case EHOSTDOWN: return WSAEHOSTDOWN;
  1315. #endif
  1316. #ifdef ENETDOWN
  1317. case ENETDOWN: return WSAENETDOWN;
  1318. #endif
  1319. case ENODEV: return WSAENETDOWN;
  1320. #ifdef EPROTOTYPE
  1321. case EPROTOTYPE: return WSAEPROTOTYPE;
  1322. #endif
  1323. #ifdef ENXIO
  1324. case ENXIO: return WSAENXIO;
  1325. #endif
  1326. #ifdef ENONET
  1327. case ENONET: return WSAENETUNREACH;
  1328. #endif
  1329. #ifdef ENOKEY
  1330. case ENOKEY: return WSAENETUNREACH;
  1331. #endif
  1332. default:
  1333. g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
  1334. }
  1335. }
  1336. #ifndef ENABLE_NETCORE
  1337. MonoBoolean
  1338. ves_icall_System_Net_Sockets_Socket_SupportPortReuse_icall (MonoProtocolType proto)
  1339. {
  1340. #if defined (SO_REUSEPORT)
  1341. return TRUE;
  1342. #else
  1343. #ifdef __linux__
  1344. /* Linux always supports double binding for UDP, even on older kernels. */
  1345. if (proto == ProtocolType_Udp)
  1346. return TRUE;
  1347. #endif
  1348. return FALSE;
  1349. #endif
  1350. }
  1351. #endif
  1352. gboolean
  1353. mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
  1354. {
  1355. SocketHandle *sockethandle;
  1356. if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle), (MonoFDHandle**) &sockethandle)) {
  1357. mono_w32error_set_last (ERROR_INVALID_HANDLE);
  1358. return FALSE;
  1359. }
  1360. if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
  1361. mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
  1362. mono_w32error_set_last (ERROR_INVALID_HANDLE);
  1363. return FALSE;
  1364. }
  1365. *duplicate_handle = handle;
  1366. return TRUE;
  1367. }