3 * Unix specific socket code.
5 * Copyright 2016 Microsoft
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #ifdef HAVE_SYS_IOCTL_H
18 #include <sys/ioctl.h>
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
37 #ifdef HAVE_SYS_FILIO_H
38 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
40 #ifdef HAVE_SYS_SOCKIO_H
41 #include <sys/sockio.h> /* defines SIOCATMARK */
43 #ifndef HAVE_MSG_NOSIGNAL
46 #ifdef HAVE_SYS_SENDFILE_H
47 #include <sys/sendfile.h>
51 #include "w32socket.h"
52 #include "w32socket-internals.h"
55 #include "utils/mono-logger-internals.h"
56 #include "utils/mono-poll.h"
59 MonoFDHandle fdhandle;
68 socket_data_create (MonoFDType type, gint fd)
70 SocketHandle *sockethandle;
72 sockethandle = g_new0 (SocketHandle, 1);
73 mono_fdhandle_init ((MonoFDHandle*) sockethandle, type, fd);
79 socket_data_close (MonoFDHandle *fdhandle)
82 SocketHandle* sockethandle;
85 sockethandle = (SocketHandle*) fdhandle;
86 g_assert (sockethandle);
88 info = mono_thread_info_current ();
90 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) sockethandle)->fd);
92 /* Shutdown the socket for reading, to interrupt any potential
93 * receives that may be blocking for data. See bug 75705. */
95 shutdown (((MonoFDHandle*) sockethandle)->fd, SHUT_RD);
100 ret = close (((MonoFDHandle*) sockethandle)->fd);
103 if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
107 sockethandle->saved_error = 0;
111 socket_data_destroy (MonoFDHandle *fdhandle)
113 SocketHandle *sockethandle;
115 sockethandle = (SocketHandle*) fdhandle;
116 g_assert (sockethandle);
118 g_free (sockethandle);
122 mono_w32socket_initialize (void)
124 MonoFDHandleCallback socket_data_callbacks = {
125 .close = socket_data_close,
126 .destroy = socket_data_destroy
129 mono_fdhandle_register (MONO_FDTYPE_SOCKET, &socket_data_callbacks);
133 mono_w32socket_cleanup (void)
138 mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
140 SocketHandle *sockethandle, *accepted_socket_data;
141 MonoThreadInfo *info;
144 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
145 mono_w32socket_set_last_error (WSAEFAULT);
146 return INVALID_SOCKET;
149 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
150 mono_w32error_set_last (WSAENOTSOCK);
151 return INVALID_SOCKET;
154 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
155 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
156 mono_w32error_set_last (WSAENOTSOCK);
157 return INVALID_SOCKET;
160 info = mono_thread_info_current ();
164 accepted_fd = accept (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
166 } while (accepted_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
168 if (accepted_fd == -1) {
169 gint error = mono_w32socket_convert_error (errno);
170 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno));
171 mono_w32socket_set_last_error (error);
172 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
173 return INVALID_SOCKET;
176 accepted_socket_data = socket_data_create (MONO_FDTYPE_SOCKET, accepted_fd);
177 accepted_socket_data->domain = sockethandle->domain;
178 accepted_socket_data->type = sockethandle->type;
179 accepted_socket_data->protocol = sockethandle->protocol;
180 accepted_socket_data->still_readable = 1;
182 mono_fdhandle_insert ((MonoFDHandle*) accepted_socket_data);
184 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning accepted handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) accepted_socket_data)->fd));
186 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
187 return ((MonoFDHandle*) accepted_socket_data)->fd;
191 mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
193 SocketHandle *sockethandle;
196 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
197 mono_w32error_set_last (WSAENOTSOCK);
201 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
202 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
203 mono_w32error_set_last (WSAENOTSOCK);
208 ret = connect (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
211 MonoThreadInfo *info;
213 gint errnum, so_error;
218 if (errno != EINTR) {
219 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
220 g_strerror (errnum));
222 errnum = mono_w32socket_convert_error (errnum);
223 if (errnum == WSAEINPROGRESS)
224 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
226 mono_w32socket_set_last_error (errnum);
229 * On solaris x86 getsockopt (SO_ERROR) is not set after
230 * connect () fails so we need to save this error.
232 * But don't do this for EWOULDBLOCK (bug 317315)
234 if (errnum != WSAEWOULDBLOCK) {
235 /* ECONNRESET means the socket was closed by another thread */
236 /* Async close on mac raises ECONNABORTED. */
237 sockethandle->saved_error = errnum;
239 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
243 info = mono_thread_info_current ();
245 fds.fd = ((MonoFDHandle*) sockethandle)->fd;
246 fds.events = MONO_POLLOUT;
249 ret = mono_poll (&fds, 1, -1);
251 if (ret != -1 || mono_thread_info_is_interrupt_state (info))
254 if (errno != EINTR) {
256 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno));
257 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
258 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
263 len = sizeof(so_error);
265 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
269 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
270 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
271 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
276 gint errnum = mono_w32socket_convert_error (so_error);
278 /* Need to save this socket error */
279 sockethandle->saved_error = errnum;
281 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
282 __func__, g_strerror (so_error));
284 mono_w32socket_set_last_error (errnum);
285 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
290 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
295 mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
297 return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking);
301 mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
303 SocketHandle *sockethandle;
305 MonoThreadInfo *info;
307 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
308 mono_w32error_set_last (WSAENOTSOCK);
312 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
313 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
314 mono_w32error_set_last (WSAENOTSOCK);
318 info = mono_thread_info_current ();
322 ret = recvfrom (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, from, fromlen);
324 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
326 if (ret == 0 && len > 0) {
327 /* According to the Linux man page, recvfrom only
328 * returns 0 when the socket has been shut down
329 * cleanly. Turn this into an EINTR to simulate win32
330 * behaviour of returning EINTR when a socket is
331 * closed while the recvfrom is blocking (we use a
332 * shutdown() in socket_close() to trigger this.) See
335 /* Distinguish between the socket being shut down at
336 * the local or remote ends, and reads that request 0
340 /* If this returns FALSE, it means the socket has been
341 * closed locally. If it returns TRUE, but
342 * still_readable != 1 then shutdown
343 * (SHUT_RD|SHUT_RDWR) has been called locally.
345 if (sockethandle->still_readable != 1) {
353 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno));
354 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
355 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
358 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
363 wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr)
367 memset (hdr, 0, sizeof (struct msghdr));
368 hdr->msg_iovlen = count;
369 hdr->msg_iov = g_new0 (struct iovec, count);
370 for (i = 0; i < count; i++) {
371 hdr->msg_iov [i].iov_base = buffers [i].buf;
372 hdr->msg_iov [i].iov_len = buffers [i].len;
377 msghdr_iov_free (struct msghdr *hdr)
379 g_free (hdr->msg_iov);
383 mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
385 SocketHandle *sockethandle;
386 MonoThreadInfo *info;
390 g_assert (overlapped == NULL);
391 g_assert (complete == NULL);
393 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
394 mono_w32error_set_last (WSAENOTSOCK);
398 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
399 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
400 mono_w32error_set_last (WSAENOTSOCK);
404 info = mono_thread_info_current ();
406 wsabuf_to_msghdr (buffers, count, &hdr);
410 ret = recvmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, *flags);
412 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
414 msghdr_iov_free (&hdr);
417 /* see mono_w32socket_recvfrom */
418 if (sockethandle->still_readable != 1) {
426 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno));
427 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
428 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
433 *flags = hdr.msg_flags;
435 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
440 mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
442 SocketHandle *sockethandle;
444 MonoThreadInfo *info;
446 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
447 mono_w32error_set_last (WSAENOTSOCK);
451 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
452 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
453 mono_w32error_set_last (WSAENOTSOCK);
457 info = mono_thread_info_current ();
461 ret = send (((MonoFDHandle*) sockethandle)->fd, buf, len, flags);
463 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
467 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
470 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
471 * a blocking socket. See bug #599488 */
472 if (errnum == EAGAIN) {
474 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
476 if (ret != -1 && (ret & O_NONBLOCK) == 0)
479 #endif /* O_NONBLOCK */
480 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
481 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
484 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
489 mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
491 SocketHandle *sockethandle;
493 MonoThreadInfo *info;
495 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
496 mono_w32error_set_last (WSAENOTSOCK);
500 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
501 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
502 mono_w32error_set_last (WSAENOTSOCK);
506 info = mono_thread_info_current ();
510 ret = sendto (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, to, tolen);
512 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
516 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
517 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
518 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
521 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
526 mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
529 MonoThreadInfo *info;
530 SocketHandle *sockethandle;
533 g_assert (overlapped == NULL);
534 g_assert (complete == NULL);
536 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
537 mono_w32error_set_last (WSAENOTSOCK);
541 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
542 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
543 mono_w32error_set_last (WSAENOTSOCK);
547 info = mono_thread_info_current ();
549 wsabuf_to_msghdr (buffers, count, &hdr);
553 ret = sendmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, flags);
555 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
557 msghdr_iov_free (&hdr);
561 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
562 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
563 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
568 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
572 #define SF_BUFFER_SIZE 16384
575 mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
577 MonoThreadInfo *info;
578 SocketHandle *sockethandle;
581 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
587 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
588 mono_w32error_set_last (WSAENOTSOCK);
592 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
593 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
594 mono_w32error_set_last (WSAENOTSOCK);
598 /* Write the header */
599 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
600 ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Head, buffers->HeadLength, 0, FALSE);
601 if (ret == SOCKET_ERROR) {
602 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
607 info = mono_thread_info_current ();
609 file = GPOINTER_TO_INT (file_handle);
611 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
613 ret = fstat (file, &statbuf);
617 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
618 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
625 ret = sendfile (((MonoFDHandle*) sockethandle)->fd, file, NULL, statbuf.st_size);
626 #elif defined(DARWIN)
627 /* TODO: header/tail could be sent in the 5th argument */
628 /* TODO: Might not send the entire file for non-blocking sockets */
629 ret = sendfile (file, ((MonoFDHandle*) sockethandle)->fd, 0, &statbuf.st_size, NULL, 0);
632 } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
634 buffer = g_malloc (SF_BUFFER_SIZE);
639 ret = read (file, buffer, SF_BUFFER_SIZE);
641 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
643 if (ret == -1 || ret == 0)
648 ret = send (((MonoFDHandle*) sockethandle)->fd, buffer, ret, 0); /* short sends? enclose this in a loop? */
650 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
651 } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
658 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
659 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
664 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
665 ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Tail, buffers->TailLength, 0, FALSE);
666 if (ret == SOCKET_ERROR) {
667 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
672 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
673 mono_w32socket_close (((MonoFDHandle*) sockethandle)->fd);
675 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
680 mono_w32socket_socket (int domain, int type, int protocol)
682 SocketHandle *sockethandle;
687 fd = socket (domain, type, protocol);
690 if (domain == AF_INET && type == SOCK_RAW && protocol == 0) {
691 /* Retry with protocol == 4 (see bug #54565) */
692 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
698 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno));
699 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
700 return INVALID_SOCKET;
703 sockethandle = socket_data_create(MONO_FDTYPE_SOCKET, fd);
704 sockethandle->domain = domain;
705 sockethandle->type = type;
706 sockethandle->protocol = protocol;
707 sockethandle->still_readable = 1;
709 /* .net seems to set this by default for SOCK_STREAM, not for
710 * SOCK_DGRAM (see bug #36322)
711 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
713 * It seems winsock has a rather different idea of what
714 * SO_REUSEADDR means. If it's set, then a new socket can be
715 * bound over an existing listening socket. There's a new
716 * windows-specific option called SO_EXCLUSIVEADDRUSE but
717 * using that means the socket MUST be closed properly, or a
718 * denial of service can occur. Luckily for us, winsock
719 * behaves as though any other system would when SO_REUSEADDR
720 * is true, so we don't need to do anything else here. See
722 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
728 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
732 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
733 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
736 close (((MonoFDHandle*) sockethandle)->fd);
739 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
740 return INVALID_SOCKET;
744 mono_fdhandle_insert ((MonoFDHandle*) sockethandle);
746 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) sockethandle)->fd));
748 return ((MonoFDHandle*) sockethandle)->fd;
752 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
754 SocketHandle *sockethandle;
757 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
758 mono_w32error_set_last (WSAENOTSOCK);
762 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
763 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
764 mono_w32error_set_last (WSAENOTSOCK);
769 ret = bind (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
773 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno));
774 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
775 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
779 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
784 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
786 SocketHandle *sockethandle;
789 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
790 mono_w32error_set_last (WSAENOTSOCK);
794 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
795 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
796 mono_w32error_set_last (WSAENOTSOCK);
801 ret = getpeername (((MonoFDHandle*) sockethandle)->fd, name, namelen);
805 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno));
806 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
807 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
811 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
816 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
818 SocketHandle *sockethandle;
821 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
822 mono_w32error_set_last (WSAENOTSOCK);
826 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
827 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
828 mono_w32error_set_last (WSAENOTSOCK);
833 ret = getsockname (((MonoFDHandle*) sockethandle)->fd, name, namelen);
837 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
838 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
839 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
843 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
848 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
850 SocketHandle *sockethandle;
855 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
856 mono_w32error_set_last (WSAENOTSOCK);
860 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
861 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
862 mono_w32error_set_last (WSAENOTSOCK);
867 if (level == SOL_SOCKET &&
868 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
870 *optlen = sizeof (tv);
874 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
878 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
879 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
880 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
884 if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
885 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
886 *optlen = sizeof (int);
889 if (optname == SO_ERROR) {
890 if (*((int *)optval) != 0) {
891 *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
892 sockethandle->saved_error = *((int *)optval);
894 *((int *)optval) = sockethandle->saved_error;
898 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
903 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
905 SocketHandle *sockethandle;
908 #if defined (__linux__)
909 /* This has its address taken so it cannot be moved to the if block which uses it */
914 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
915 mono_w32error_set_last (WSAENOTSOCK);
919 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
920 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
921 mono_w32error_set_last (WSAENOTSOCK);
926 if (level == SOL_SOCKET &&
927 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
928 int ms = *((int *) optval);
929 tv.tv_sec = ms / 1000;
930 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
932 optlen = sizeof (tv);
934 #if defined (__linux__)
935 else if (level == SOL_SOCKET &&
936 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
937 /* According to socket(7) the Linux kernel doubles the
938 * buffer sizes "to allow space for bookkeeping
941 bufsize = *((int *) optval);
949 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
953 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
954 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
955 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
959 #if defined (SO_REUSEPORT)
960 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
961 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
963 socklen_t type_len = sizeof (type);
966 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_TYPE, &type, &type_len);
969 if (type == SOCK_DGRAM || type == SOCK_STREAM) {
971 setsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_REUSEPORT, tmp_val, optlen);
978 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
983 mono_w32socket_listen (SOCKET sock, gint backlog)
985 SocketHandle *sockethandle;
988 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
989 mono_w32error_set_last (WSAENOTSOCK);
993 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
994 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
995 mono_w32error_set_last (WSAENOTSOCK);
1000 ret = listen (((MonoFDHandle*) sockethandle)->fd, backlog);
1003 gint errnum = errno;
1004 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
1005 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1006 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1007 return SOCKET_ERROR;
1010 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1015 mono_w32socket_shutdown (SOCKET sock, gint how)
1017 SocketHandle *sockethandle;
1020 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1021 mono_w32error_set_last (WSAENOTSOCK);
1022 return SOCKET_ERROR;
1025 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1026 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1027 mono_w32error_set_last (WSAENOTSOCK);
1028 return SOCKET_ERROR;
1031 if (how == SHUT_RD || how == SHUT_RDWR)
1032 sockethandle->still_readable = 0;
1035 ret = shutdown (((MonoFDHandle*) sockethandle)->fd, how);
1038 gint errnum = errno;
1039 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno));
1040 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1041 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1042 return SOCKET_ERROR;
1045 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1050 mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
1052 SocketHandle *sockethandle;
1056 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock);
1058 /* We could check the socket type here and fail unless its
1059 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1060 * if we really wanted to */
1062 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1063 mono_w32error_set_last (WSAENOTSOCK);
1064 return SOCKET_ERROR;
1067 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1068 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1069 mono_w32error_set_last (WSAENOTSOCK);
1070 return SOCKET_ERROR;
1074 newsock = socket (sockethandle->domain, sockethandle->type, sockethandle->protocol);
1076 if (newsock == -1) {
1077 gint errnum = errno;
1078 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum));
1079 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1080 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1081 return SOCKET_ERROR;
1084 /* According to Stevens "Advanced Programming in the UNIX
1085 * Environment: UNIX File I/O" dup2() is atomic so there
1086 * should not be a race condition between the old fd being
1087 * closed and the new socket fd being copied over */
1090 ret = dup2 (newsock, ((MonoFDHandle*) sockethandle)->fd);
1092 } while (ret == -1 && errno == EAGAIN);
1095 gint errnum = errno;
1096 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum));
1097 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1098 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1099 return SOCKET_ERROR;
1106 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1111 extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
1114 MONO_ENTER_GC_UNSAFE;
1115 ret = mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
1116 MONO_EXIT_GC_UNSAFE;
1121 extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
1122 OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
1125 MONO_ENTER_GC_UNSAFE;
1126 ret = mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
1127 MONO_EXIT_GC_UNSAFE;
1134 } extension_functions[] = {
1135 { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, extension_disconect },
1136 { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, extension_transmit_file },
1141 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
1143 SocketHandle *sockethandle;
1147 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1148 mono_w32error_set_last (WSAENOTSOCK);
1149 return SOCKET_ERROR;
1152 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1153 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1154 mono_w32error_set_last (WSAENOTSOCK);
1155 return SOCKET_ERROR;
1158 if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1162 if (inputlen < sizeof(GUID)) {
1163 /* As far as I can tell, windows doesn't
1164 * actually set an error here...
1166 mono_w32socket_set_last_error (WSAEINVAL);
1167 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1168 return SOCKET_ERROR;
1171 if (outputlen < sizeof(gpointer)) {
1173 mono_w32socket_set_last_error (WSAEINVAL);
1174 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1175 return SOCKET_ERROR;
1178 if (output == NULL) {
1180 mono_w32socket_set_last_error (WSAEINVAL);
1181 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1182 return SOCKET_ERROR;
1185 guid = (GUID*) input;
1186 for (i = 0; extension_functions[i].func; i++) {
1187 if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
1188 memcpy (output, &extension_functions[i].func, sizeof(gpointer));
1189 *written = sizeof(gpointer);
1190 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1195 mono_w32socket_set_last_error (WSAEINVAL);
1196 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1197 return SOCKET_ERROR;
1200 if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1203 if (inputlen < 3 * sizeof (guint32)) {
1204 mono_w32socket_set_last_error (WSAEINVAL);
1205 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1206 return SOCKET_ERROR;
1209 onoff = *((guint32*) input);
1212 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
1215 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1216 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1217 return SOCKET_ERROR;
1220 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1222 /* Values are in ms, but we need s */
1223 guint32 keepalivetime, keepaliveinterval, rem;
1225 keepalivetime = *(((guint32*) input) + 1);
1226 keepaliveinterval = *(((guint32*) input) + 2);
1228 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1229 rem = keepalivetime % 1000;
1230 keepalivetime /= 1000;
1231 if (keepalivetime == 0 || rem >= 500)
1234 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
1237 rem = keepaliveinterval % 1000;
1238 keepaliveinterval /= 1000;
1239 if (keepaliveinterval == 0 || rem >= 500)
1240 keepaliveinterval++;
1242 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
1246 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1247 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1248 return SOCKET_ERROR;
1251 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1256 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1260 buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
1263 ret = ioctl (((MonoFDHandle*) sockethandle)->fd, command, buffer);
1268 gint errnum = errno;
1269 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
1270 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1271 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1272 return SOCKET_ERROR;
1277 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1281 /* We just copy the buffer to the output. Some ioctls
1282 * don't even output any data, but, well...
1284 * NB windows returns WSAEFAULT if outputlen is too small */
1285 inputlen = (inputlen > outputlen) ? outputlen : inputlen;
1287 if (inputlen > 0 && output != NULL)
1288 memcpy (output, buffer, inputlen);
1291 *written = inputlen;
1293 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1298 mono_w32socket_close (SOCKET sock)
1300 if (!mono_fdhandle_close (sock)) {
1301 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1309 mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
1312 SocketHandle *sockethandle;
1315 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1316 mono_w32error_set_last (WSAENOTSOCK);
1317 return SOCKET_ERROR;
1320 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1321 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1322 mono_w32error_set_last (WSAENOTSOCK);
1323 return SOCKET_ERROR;
1326 /* This works better than ioctl(...FIONBIO...)
1327 * on Linux (it causes connect to return
1328 * EINPROGRESS, but the ioctl doesn't seem to) */
1330 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
1333 gint errnum = mono_w32socket_convert_error (errno);
1334 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_GETFL) error: %s", __func__, g_strerror (errno));
1335 mono_w32socket_set_last_error (errnum);
1336 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1337 return SOCKET_ERROR;
1341 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
1344 gint errnum = mono_w32socket_convert_error (errno);
1345 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_SETFL) error: %s", __func__, g_strerror (errno));
1346 mono_w32socket_set_last_error (errnum);
1347 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1348 return SOCKET_ERROR;
1351 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1354 mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
1355 return SOCKET_ERROR;
1356 #endif /* O_NONBLOCK */
1360 mono_w32socket_get_available (SOCKET sock, guint64 *amount)
1362 SocketHandle *sockethandle;
1365 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1366 mono_w32error_set_last (WSAENOTSOCK);
1367 return SOCKET_ERROR;
1370 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1371 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1372 mono_w32error_set_last (WSAENOTSOCK);
1373 return SOCKET_ERROR;
1376 #if defined (PLATFORM_MACOSX)
1377 // ioctl (socket, FIONREAD, XXX) returns the size of
1378 // the UDP header as well on Darwin.
1380 // Use getsockopt SO_NREAD instead to get the
1381 // right values for TCP and UDP.
1383 // ai_canonname can be null in some cases on darwin,
1384 // where the runtime assumes it will be the value of
1387 socklen_t optlen = sizeof (int);
1389 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
1392 gint errnum = mono_w32socket_convert_error (errno);
1393 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
1394 mono_w32socket_set_last_error (errnum);
1395 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1396 return SOCKET_ERROR;
1400 ret = ioctl (((MonoFDHandle*) sockethandle)->fd, FIONREAD, (gulong*) amount);
1403 gint errnum = mono_w32socket_convert_error (errno);
1404 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1405 mono_w32socket_set_last_error (errnum);
1406 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1407 return SOCKET_ERROR;
1411 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1416 mono_w32socket_set_last_error (gint32 error)
1418 mono_w32error_set_last (error);
1422 mono_w32socket_get_last_error (void)
1424 return mono_w32error_get_last ();
1428 mono_w32socket_convert_error (gint error)
1431 case 0: return ERROR_SUCCESS;
1432 case EACCES: return WSAEACCES;
1434 case EADDRINUSE: return WSAEADDRINUSE;
1437 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1439 #if EAGAIN != EWOULDBLOCK
1440 case EAGAIN: return WSAEWOULDBLOCK;
1443 case EALREADY: return WSAEALREADY;
1445 case EBADF: return WSAENOTSOCK;
1447 case ECONNABORTED: return WSAENETDOWN;
1450 case ECONNREFUSED: return WSAECONNREFUSED;
1453 case ECONNRESET: return WSAECONNRESET;
1455 case EFAULT: return WSAEFAULT;
1457 case EHOSTUNREACH: return WSAEHOSTUNREACH;
1460 case EINPROGRESS: return WSAEINPROGRESS;
1462 case EINTR: return WSAEINTR;
1463 case EINVAL: return WSAEINVAL;
1464 /*FIXME: case EIO: return WSAE????; */
1466 case EISCONN: return WSAEISCONN;
1468 /* FIXME: case ELOOP: return WSA????; */
1469 case EMFILE: return WSAEMFILE;
1471 case EMSGSIZE: return WSAEMSGSIZE;
1473 /* FIXME: case ENAMETOOLONG: return WSAEACCES; */
1475 case ENETUNREACH: return WSAENETUNREACH;
1478 case ENOBUFS: return WSAENOBUFS; /* not documented */
1480 /* case ENOENT: return WSAE????; */
1481 case ENOMEM: return WSAENOBUFS;
1483 case ENOPROTOOPT: return WSAENOPROTOOPT;
1486 case ENOSR: return WSAENETDOWN;
1489 case ENOTCONN: return WSAENOTCONN;
1491 /*FIXME: case ENOTDIR: return WSAE????; */
1493 case ENOTSOCK: return WSAENOTSOCK;
1495 case ENOTTY: return WSAENOTSOCK;
1497 case EOPNOTSUPP: return WSAEOPNOTSUPP;
1499 case EPERM: return WSAEACCES;
1500 case EPIPE: return WSAESHUTDOWN;
1501 #ifdef EPROTONOSUPPORT
1502 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1505 case ERESTARTSYS: return WSAENETDOWN;
1507 /*FIXME: case EROFS: return WSAE????; */
1508 #ifdef ESOCKTNOSUPPORT
1509 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1512 case ETIMEDOUT: return WSAETIMEDOUT;
1515 case EWOULDBLOCK: return WSAEWOULDBLOCK;
1517 #ifdef EADDRNOTAVAIL
1518 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1520 /* This might happen with unix sockets */
1521 case ENOENT: return WSAECONNREFUSED;
1523 case EDESTADDRREQ: return WSAEDESTADDRREQ;
1526 case EHOSTDOWN: return WSAEHOSTDOWN;
1529 case ENETDOWN: return WSAENETDOWN;
1531 case ENODEV: return WSAENETDOWN;
1533 case EPROTOTYPE: return WSAEPROTOTYPE;
1536 case ENXIO: return WSAENXIO;
1539 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
1544 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error)
1547 #if defined (SO_REUSEPORT)
1551 /* Linux always supports double binding for UDP, even on older kernels. */
1552 if (proto == ProtocolType_Udp)
1560 mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
1562 SocketHandle *sockethandle;
1564 if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle), (MonoFDHandle**) &sockethandle)) {
1565 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1569 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1570 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1571 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1575 *duplicate_handle = handle;