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"
57 #include "utils/mono-compiler.h"
60 MonoFDHandle fdhandle;
69 socket_data_create (MonoFDType type, gint fd)
71 SocketHandle *sockethandle;
73 sockethandle = g_new0 (SocketHandle, 1);
74 mono_fdhandle_init ((MonoFDHandle*) sockethandle, type, fd);
80 socket_data_close (MonoFDHandle *fdhandle)
83 SocketHandle* sockethandle;
86 sockethandle = (SocketHandle*) fdhandle;
87 g_assert (sockethandle);
89 info = mono_thread_info_current ();
91 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) sockethandle)->fd);
93 /* Shutdown the socket for reading, to interrupt any potential
94 * receives that may be blocking for data. See bug 75705. */
96 shutdown (((MonoFDHandle*) sockethandle)->fd, SHUT_RD);
101 ret = close (((MonoFDHandle*) sockethandle)->fd);
104 if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
108 sockethandle->saved_error = 0;
112 socket_data_destroy (MonoFDHandle *fdhandle)
114 SocketHandle *sockethandle;
116 sockethandle = (SocketHandle*) fdhandle;
117 g_assert (sockethandle);
119 g_free (sockethandle);
123 mono_w32socket_initialize (void)
125 MonoFDHandleCallback socket_data_callbacks = {
126 .close = socket_data_close,
127 .destroy = socket_data_destroy
130 mono_fdhandle_register (MONO_FDTYPE_SOCKET, &socket_data_callbacks);
134 mono_w32socket_cleanup (void)
139 mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
141 SocketHandle *sockethandle, *accepted_socket_data;
142 MonoThreadInfo *info;
145 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
146 mono_w32socket_set_last_error (WSAEFAULT);
147 return INVALID_SOCKET;
150 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
151 mono_w32error_set_last (WSAENOTSOCK);
152 return INVALID_SOCKET;
155 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
156 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
157 mono_w32error_set_last (WSAENOTSOCK);
158 return INVALID_SOCKET;
161 info = mono_thread_info_current ();
165 accepted_fd = accept (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
167 } while (accepted_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
169 if (accepted_fd == -1) {
170 gint error = mono_w32socket_convert_error (errno);
171 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno));
172 mono_w32socket_set_last_error (error);
173 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
174 return INVALID_SOCKET;
177 accepted_socket_data = socket_data_create (MONO_FDTYPE_SOCKET, accepted_fd);
178 accepted_socket_data->domain = sockethandle->domain;
179 accepted_socket_data->type = sockethandle->type;
180 accepted_socket_data->protocol = sockethandle->protocol;
181 accepted_socket_data->still_readable = 1;
183 mono_fdhandle_insert ((MonoFDHandle*) accepted_socket_data);
185 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning accepted handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) accepted_socket_data)->fd));
187 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
188 return ((MonoFDHandle*) accepted_socket_data)->fd;
192 mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
194 SocketHandle *sockethandle;
197 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
198 mono_w32error_set_last (WSAENOTSOCK);
202 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
203 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
204 mono_w32error_set_last (WSAENOTSOCK);
209 ret = connect (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
212 MonoThreadInfo *info;
214 gint errnum, so_error;
219 if (errno != EINTR) {
220 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
221 g_strerror (errnum));
223 errnum = mono_w32socket_convert_error (errnum);
224 if (errnum == WSAEINPROGRESS)
225 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
227 mono_w32socket_set_last_error (errnum);
230 * On solaris x86 getsockopt (SO_ERROR) is not set after
231 * connect () fails so we need to save this error.
233 * But don't do this for EWOULDBLOCK (bug 317315)
235 if (errnum != WSAEWOULDBLOCK) {
236 /* ECONNRESET means the socket was closed by another thread */
237 /* Async close on mac raises ECONNABORTED. */
238 sockethandle->saved_error = errnum;
240 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
244 info = mono_thread_info_current ();
246 fds.fd = ((MonoFDHandle*) sockethandle)->fd;
247 fds.events = MONO_POLLOUT;
250 ret = mono_poll (&fds, 1, -1);
252 if (ret != -1 || mono_thread_info_is_interrupt_state (info))
255 if (errno != EINTR) {
257 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno));
258 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
259 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
264 len = sizeof(so_error);
266 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
270 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
271 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
272 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
277 gint errnum = mono_w32socket_convert_error (so_error);
279 /* Need to save this socket error */
280 sockethandle->saved_error = errnum;
282 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
283 __func__, g_strerror (so_error));
285 mono_w32socket_set_last_error (errnum);
286 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
291 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
296 mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
298 return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking);
302 mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
304 SocketHandle *sockethandle;
306 MonoThreadInfo *info;
308 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
309 mono_w32error_set_last (WSAENOTSOCK);
313 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
314 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
315 mono_w32error_set_last (WSAENOTSOCK);
319 info = mono_thread_info_current ();
323 ret = recvfrom (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, from, fromlen);
325 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
327 if (ret == 0 && len > 0) {
328 /* According to the Linux man page, recvfrom only
329 * returns 0 when the socket has been shut down
330 * cleanly. Turn this into an EINTR to simulate win32
331 * behaviour of returning EINTR when a socket is
332 * closed while the recvfrom is blocking (we use a
333 * shutdown() in socket_close() to trigger this.) See
336 /* Distinguish between the socket being shut down at
337 * the local or remote ends, and reads that request 0
341 /* If this returns FALSE, it means the socket has been
342 * closed locally. If it returns TRUE, but
343 * still_readable != 1 then shutdown
344 * (SHUT_RD|SHUT_RDWR) has been called locally.
346 if (sockethandle->still_readable != 1) {
354 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno));
355 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
356 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
359 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
364 wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr)
368 memset (hdr, 0, sizeof (struct msghdr));
369 hdr->msg_iovlen = count;
370 hdr->msg_iov = g_new0 (struct iovec, count);
371 for (i = 0; i < count; i++) {
372 hdr->msg_iov [i].iov_base = buffers [i].buf;
373 hdr->msg_iov [i].iov_len = buffers [i].len;
378 msghdr_iov_free (struct msghdr *hdr)
380 g_free (hdr->msg_iov);
384 mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
386 SocketHandle *sockethandle;
387 MonoThreadInfo *info;
391 g_assert (overlapped == NULL);
392 g_assert (complete == NULL);
394 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
395 mono_w32error_set_last (WSAENOTSOCK);
399 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
400 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
401 mono_w32error_set_last (WSAENOTSOCK);
405 info = mono_thread_info_current ();
407 wsabuf_to_msghdr (buffers, count, &hdr);
411 ret = recvmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, *flags);
413 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
415 msghdr_iov_free (&hdr);
418 /* see mono_w32socket_recvfrom */
419 if (sockethandle->still_readable != 1) {
427 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno));
428 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
429 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
434 *flags = hdr.msg_flags;
436 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
441 mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
443 SocketHandle *sockethandle;
445 MonoThreadInfo *info;
447 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
448 mono_w32error_set_last (WSAENOTSOCK);
452 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
453 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
454 mono_w32error_set_last (WSAENOTSOCK);
458 info = mono_thread_info_current ();
462 ret = send (((MonoFDHandle*) sockethandle)->fd, buf, len, flags);
464 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
468 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
471 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
472 * a blocking socket. See bug #599488 */
473 if (errnum == EAGAIN) {
475 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
477 if (ret != -1 && (ret & O_NONBLOCK) == 0)
480 #endif /* O_NONBLOCK */
481 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
482 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
485 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
490 mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
492 SocketHandle *sockethandle;
494 MonoThreadInfo *info;
496 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
497 mono_w32error_set_last (WSAENOTSOCK);
501 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
502 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
503 mono_w32error_set_last (WSAENOTSOCK);
507 info = mono_thread_info_current ();
511 ret = sendto (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, to, tolen);
513 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
517 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
518 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
519 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
522 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
527 mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
530 MonoThreadInfo *info;
531 SocketHandle *sockethandle;
534 g_assert (overlapped == NULL);
535 g_assert (complete == NULL);
537 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
538 mono_w32error_set_last (WSAENOTSOCK);
542 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
543 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
544 mono_w32error_set_last (WSAENOTSOCK);
548 info = mono_thread_info_current ();
550 wsabuf_to_msghdr (buffers, count, &hdr);
554 ret = sendmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, flags);
556 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
558 msghdr_iov_free (&hdr);
562 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
563 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
564 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
569 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
573 #define SF_BUFFER_SIZE 16384
576 mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
578 MonoThreadInfo *info;
579 SocketHandle *sockethandle;
582 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
588 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
589 mono_w32error_set_last (WSAENOTSOCK);
593 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
594 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
595 mono_w32error_set_last (WSAENOTSOCK);
599 /* Write the header */
600 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
601 ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Head, buffers->HeadLength, 0, FALSE);
602 if (ret == SOCKET_ERROR) {
603 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
608 info = mono_thread_info_current ();
610 file = GPOINTER_TO_INT (file_handle);
612 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
614 ret = fstat (file, &statbuf);
618 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
619 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
626 ret = sendfile (((MonoFDHandle*) sockethandle)->fd, file, NULL, statbuf.st_size);
627 #elif defined(DARWIN)
628 /* TODO: header/tail could be sent in the 5th argument */
629 /* TODO: Might not send the entire file for non-blocking sockets */
630 ret = sendfile (file, ((MonoFDHandle*) sockethandle)->fd, 0, &statbuf.st_size, NULL, 0);
633 } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
635 buffer = g_malloc (SF_BUFFER_SIZE);
640 ret = read (file, buffer, SF_BUFFER_SIZE);
642 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
644 if (ret == -1 || ret == 0)
649 ret = send (((MonoFDHandle*) sockethandle)->fd, buffer, ret, 0); /* short sends? enclose this in a loop? */
651 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
652 } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
659 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
660 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
665 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
666 ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Tail, buffers->TailLength, 0, FALSE);
667 if (ret == SOCKET_ERROR) {
668 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
673 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
674 mono_w32socket_close (((MonoFDHandle*) sockethandle)->fd);
676 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
681 mono_w32socket_socket (int domain, int type, int protocol)
683 SocketHandle *sockethandle;
688 fd = socket (domain, type, protocol);
691 if (domain == AF_INET && type == SOCK_RAW && protocol == 0) {
692 /* Retry with protocol == 4 (see bug #54565) */
693 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
699 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno));
700 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
701 return INVALID_SOCKET;
704 sockethandle = socket_data_create(MONO_FDTYPE_SOCKET, fd);
705 sockethandle->domain = domain;
706 sockethandle->type = type;
707 sockethandle->protocol = protocol;
708 sockethandle->still_readable = 1;
710 /* .net seems to set this by default for SOCK_STREAM, not for
711 * SOCK_DGRAM (see bug #36322)
712 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
714 * It seems winsock has a rather different idea of what
715 * SO_REUSEADDR means. If it's set, then a new socket can be
716 * bound over an existing listening socket. There's a new
717 * windows-specific option called SO_EXCLUSIVEADDRUSE but
718 * using that means the socket MUST be closed properly, or a
719 * denial of service can occur. Luckily for us, winsock
720 * behaves as though any other system would when SO_REUSEADDR
721 * is true, so we don't need to do anything else here. See
723 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
729 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
733 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
734 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
737 close (((MonoFDHandle*) sockethandle)->fd);
740 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
741 return INVALID_SOCKET;
745 mono_fdhandle_insert ((MonoFDHandle*) sockethandle);
747 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) sockethandle)->fd));
749 return ((MonoFDHandle*) sockethandle)->fd;
753 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
755 SocketHandle *sockethandle;
758 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
759 mono_w32error_set_last (WSAENOTSOCK);
763 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
764 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
765 mono_w32error_set_last (WSAENOTSOCK);
770 ret = bind (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
774 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno));
775 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
776 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
780 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
785 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
787 SocketHandle *sockethandle;
790 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
791 mono_w32error_set_last (WSAENOTSOCK);
795 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
796 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
797 mono_w32error_set_last (WSAENOTSOCK);
802 ret = getpeername (((MonoFDHandle*) sockethandle)->fd, name, namelen);
806 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno));
807 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
808 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
812 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
817 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
819 SocketHandle *sockethandle;
822 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
823 mono_w32error_set_last (WSAENOTSOCK);
827 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
828 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
829 mono_w32error_set_last (WSAENOTSOCK);
834 ret = getsockname (((MonoFDHandle*) sockethandle)->fd, name, namelen);
838 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
839 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
840 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
844 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
849 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
851 SocketHandle *sockethandle;
856 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
857 mono_w32error_set_last (WSAENOTSOCK);
861 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
862 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
863 mono_w32error_set_last (WSAENOTSOCK);
868 if (level == SOL_SOCKET &&
869 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
871 *optlen = sizeof (tv);
875 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
879 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
880 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
881 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
885 if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
886 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
887 *optlen = sizeof (int);
890 if (optname == SO_ERROR) {
891 if (*((int *)optval) != 0) {
892 *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
893 sockethandle->saved_error = *((int *)optval);
895 *((int *)optval) = sockethandle->saved_error;
899 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
904 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
906 SocketHandle *sockethandle;
909 #if defined (__linux__)
910 /* This has its address taken so it cannot be moved to the if block which uses it */
915 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
916 mono_w32error_set_last (WSAENOTSOCK);
920 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
921 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
922 mono_w32error_set_last (WSAENOTSOCK);
927 if (level == SOL_SOCKET &&
928 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
929 int ms = *((int *) optval);
930 tv.tv_sec = ms / 1000;
931 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
933 optlen = sizeof (tv);
935 #if defined (__linux__)
936 else if (level == SOL_SOCKET &&
937 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
938 /* According to socket(7) the Linux kernel doubles the
939 * buffer sizes "to allow space for bookkeeping
942 bufsize = *((int *) optval);
950 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
954 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
955 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
956 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
960 #if defined (SO_REUSEPORT)
961 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
962 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
964 socklen_t type_len = sizeof (type);
967 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_TYPE, &type, &type_len);
970 if (type == SOCK_DGRAM || type == SOCK_STREAM) {
972 setsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_REUSEPORT, tmp_val, optlen);
979 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
984 mono_w32socket_listen (SOCKET sock, gint backlog)
986 SocketHandle *sockethandle;
989 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
990 mono_w32error_set_last (WSAENOTSOCK);
994 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
995 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
996 mono_w32error_set_last (WSAENOTSOCK);
1001 ret = listen (((MonoFDHandle*) sockethandle)->fd, backlog);
1004 gint errnum = errno;
1005 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
1006 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1007 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1008 return SOCKET_ERROR;
1011 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1016 mono_w32socket_shutdown (SOCKET sock, gint how)
1018 SocketHandle *sockethandle;
1021 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1022 mono_w32error_set_last (WSAENOTSOCK);
1023 return SOCKET_ERROR;
1026 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1027 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1028 mono_w32error_set_last (WSAENOTSOCK);
1029 return SOCKET_ERROR;
1032 if (how == SHUT_RD || how == SHUT_RDWR)
1033 sockethandle->still_readable = 0;
1036 ret = shutdown (((MonoFDHandle*) sockethandle)->fd, how);
1039 gint errnum = errno;
1040 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno));
1041 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1042 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1043 return SOCKET_ERROR;
1046 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1051 mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
1053 SocketHandle *sockethandle;
1057 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock);
1059 /* We could check the socket type here and fail unless its
1060 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1061 * if we really wanted to */
1063 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1064 mono_w32error_set_last (WSAENOTSOCK);
1065 return SOCKET_ERROR;
1068 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1069 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1070 mono_w32error_set_last (WSAENOTSOCK);
1071 return SOCKET_ERROR;
1075 newsock = socket (sockethandle->domain, sockethandle->type, sockethandle->protocol);
1077 if (newsock == -1) {
1078 gint errnum = errno;
1079 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum));
1080 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1081 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1082 return SOCKET_ERROR;
1085 /* According to Stevens "Advanced Programming in the UNIX
1086 * Environment: UNIX File I/O" dup2() is atomic so there
1087 * should not be a race condition between the old fd being
1088 * closed and the new socket fd being copied over */
1091 ret = dup2 (newsock, ((MonoFDHandle*) sockethandle)->fd);
1093 } while (ret == -1 && errno == EAGAIN);
1096 gint errnum = errno;
1097 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum));
1098 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1099 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1100 return SOCKET_ERROR;
1107 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1112 extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
1115 MONO_ENTER_GC_UNSAFE;
1116 ret = mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
1117 MONO_EXIT_GC_UNSAFE;
1122 extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
1123 OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
1126 MONO_ENTER_GC_UNSAFE;
1127 ret = mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
1128 MONO_EXIT_GC_UNSAFE;
1135 } extension_functions[] = {
1136 { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, extension_disconect },
1137 { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, extension_transmit_file },
1142 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
1144 SocketHandle *sockethandle;
1148 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1149 mono_w32error_set_last (WSAENOTSOCK);
1150 return SOCKET_ERROR;
1153 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1154 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1155 mono_w32error_set_last (WSAENOTSOCK);
1156 return SOCKET_ERROR;
1159 if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1163 if (inputlen < sizeof(GUID)) {
1164 /* As far as I can tell, windows doesn't
1165 * actually set an error here...
1167 mono_w32socket_set_last_error (WSAEINVAL);
1168 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1169 return SOCKET_ERROR;
1172 if (outputlen < sizeof(gpointer)) {
1174 mono_w32socket_set_last_error (WSAEINVAL);
1175 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1176 return SOCKET_ERROR;
1179 if (output == NULL) {
1181 mono_w32socket_set_last_error (WSAEINVAL);
1182 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1183 return SOCKET_ERROR;
1186 guid = (GUID*) input;
1187 for (i = 0; extension_functions[i].func; i++) {
1188 if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
1189 memcpy (output, &extension_functions[i].func, sizeof(gpointer));
1190 *written = sizeof(gpointer);
1191 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1196 mono_w32socket_set_last_error (WSAEINVAL);
1197 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1198 return SOCKET_ERROR;
1201 if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1204 if (inputlen < 3 * sizeof (guint32)) {
1205 mono_w32socket_set_last_error (WSAEINVAL);
1206 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1207 return SOCKET_ERROR;
1210 onoff = *((guint32*) input);
1213 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
1216 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1217 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1218 return SOCKET_ERROR;
1221 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1223 /* Values are in ms, but we need s */
1224 guint32 keepalivetime, keepaliveinterval, rem;
1226 keepalivetime = *(((guint32*) input) + 1);
1227 keepaliveinterval = *(((guint32*) input) + 2);
1229 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1230 rem = keepalivetime % 1000;
1231 keepalivetime /= 1000;
1232 if (keepalivetime == 0 || rem >= 500)
1235 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
1238 rem = keepaliveinterval % 1000;
1239 keepaliveinterval /= 1000;
1240 if (keepaliveinterval == 0 || rem >= 500)
1241 keepaliveinterval++;
1243 ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
1247 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1248 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1249 return SOCKET_ERROR;
1252 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1257 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1261 buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
1264 ret = ioctl (((MonoFDHandle*) sockethandle)->fd, command, buffer);
1269 gint errnum = errno;
1270 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
1271 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1272 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1273 return SOCKET_ERROR;
1278 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1282 /* We just copy the buffer to the output. Some ioctls
1283 * don't even output any data, but, well...
1285 * NB windows returns WSAEFAULT if outputlen is too small */
1286 inputlen = (inputlen > outputlen) ? outputlen : inputlen;
1288 if (inputlen > 0 && output != NULL)
1289 memcpy (output, buffer, inputlen);
1292 *written = inputlen;
1294 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1299 mono_w32socket_close (SOCKET sock)
1301 if (!mono_fdhandle_close (sock)) {
1302 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1310 mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
1313 SocketHandle *sockethandle;
1316 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1317 mono_w32error_set_last (WSAENOTSOCK);
1318 return SOCKET_ERROR;
1321 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1322 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1323 mono_w32error_set_last (WSAENOTSOCK);
1324 return SOCKET_ERROR;
1327 /* This works better than ioctl(...FIONBIO...)
1328 * on Linux (it causes connect to return
1329 * EINPROGRESS, but the ioctl doesn't seem to) */
1331 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
1334 gint errnum = mono_w32socket_convert_error (errno);
1335 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_GETFL) error: %s", __func__, g_strerror (errno));
1336 mono_w32socket_set_last_error (errnum);
1337 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1338 return SOCKET_ERROR;
1342 ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
1345 gint errnum = mono_w32socket_convert_error (errno);
1346 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_SETFL) error: %s", __func__, g_strerror (errno));
1347 mono_w32socket_set_last_error (errnum);
1348 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1349 return SOCKET_ERROR;
1352 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1355 mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
1356 return SOCKET_ERROR;
1357 #endif /* O_NONBLOCK */
1361 mono_w32socket_get_available (SOCKET sock, guint64 *amount)
1363 SocketHandle *sockethandle;
1366 if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
1367 mono_w32error_set_last (WSAENOTSOCK);
1368 return SOCKET_ERROR;
1371 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1372 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1373 mono_w32error_set_last (WSAENOTSOCK);
1374 return SOCKET_ERROR;
1377 #if defined (HOST_DARWIN)
1378 // ioctl (socket, FIONREAD, XXX) returns the size of
1379 // the UDP header as well on Darwin.
1381 // Use getsockopt SO_NREAD instead to get the
1382 // right values for TCP and UDP.
1384 // ai_canonname can be null in some cases on darwin,
1385 // where the runtime assumes it will be the value of
1388 socklen_t optlen = sizeof (int);
1390 ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
1393 gint errnum = mono_w32socket_convert_error (errno);
1394 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
1395 mono_w32socket_set_last_error (errnum);
1396 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1397 return SOCKET_ERROR;
1401 ret = ioctl (((MonoFDHandle*) sockethandle)->fd, FIONREAD, (gulong*) amount);
1404 gint errnum = mono_w32socket_convert_error (errno);
1405 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1406 mono_w32socket_set_last_error (errnum);
1407 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1408 return SOCKET_ERROR;
1412 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1417 mono_w32socket_set_last_error (gint32 error)
1419 mono_w32error_set_last (error);
1423 mono_w32socket_get_last_error (void)
1425 return mono_w32error_get_last ();
1429 mono_w32socket_convert_error (gint error)
1432 case 0: return ERROR_SUCCESS;
1433 case EACCES: return WSAEACCES;
1435 case EADDRINUSE: return WSAEADDRINUSE;
1438 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1440 #if EAGAIN != EWOULDBLOCK
1441 case EAGAIN: return WSAEWOULDBLOCK;
1444 case EALREADY: return WSAEALREADY;
1446 case EBADF: return WSAENOTSOCK;
1448 case ECONNABORTED: return WSAENETDOWN;
1451 case ECONNREFUSED: return WSAECONNREFUSED;
1454 case ECONNRESET: return WSAECONNRESET;
1456 case EFAULT: return WSAEFAULT;
1458 case EHOSTUNREACH: return WSAEHOSTUNREACH;
1461 case EINPROGRESS: return WSAEINPROGRESS;
1463 case EINTR: return WSAEINTR;
1464 case EINVAL: return WSAEINVAL;
1465 /*FIXME: case EIO: return WSAE????; */
1467 case EISCONN: return WSAEISCONN;
1469 /* FIXME: case ELOOP: return WSA????; */
1470 case EMFILE: return WSAEMFILE;
1472 case EMSGSIZE: return WSAEMSGSIZE;
1474 /* FIXME: case ENAMETOOLONG: return WSAEACCES; */
1476 case ENETUNREACH: return WSAENETUNREACH;
1479 case ENOBUFS: return WSAENOBUFS; /* not documented */
1481 /* case ENOENT: return WSAE????; */
1482 case ENOMEM: return WSAENOBUFS;
1484 case ENOPROTOOPT: return WSAENOPROTOOPT;
1487 case ENOSR: return WSAENETDOWN;
1490 case ENOTCONN: return WSAENOTCONN;
1492 /*FIXME: case ENOTDIR: return WSAE????; */
1494 case ENOTSOCK: return WSAENOTSOCK;
1496 case ENOTTY: return WSAENOTSOCK;
1498 case EOPNOTSUPP: return WSAEOPNOTSUPP;
1500 case EPERM: return WSAEACCES;
1501 case EPIPE: return WSAESHUTDOWN;
1502 #ifdef EPROTONOSUPPORT
1503 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1506 case ERESTARTSYS: return WSAENETDOWN;
1508 /*FIXME: case EROFS: return WSAE????; */
1509 #ifdef ESOCKTNOSUPPORT
1510 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1513 case ETIMEDOUT: return WSAETIMEDOUT;
1516 case EWOULDBLOCK: return WSAEWOULDBLOCK;
1518 #ifdef EADDRNOTAVAIL
1519 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1521 /* This might happen with unix sockets */
1522 case ENOENT: return WSAECONNREFUSED;
1524 case EDESTADDRREQ: return WSAEDESTADDRREQ;
1527 case EHOSTDOWN: return WSAEHOSTDOWN;
1530 case ENETDOWN: return WSAENETDOWN;
1532 case ENODEV: return WSAENETDOWN;
1534 case EPROTOTYPE: return WSAEPROTOTYPE;
1537 case ENXIO: return WSAENXIO;
1540 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
1545 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error)
1548 #if defined (SO_REUSEPORT)
1552 /* Linux always supports double binding for UDP, even on older kernels. */
1553 if (proto == ProtocolType_Udp)
1561 mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
1563 SocketHandle *sockethandle;
1565 if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle), (MonoFDHandle**) &sockethandle)) {
1566 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1570 if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
1571 mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
1572 mono_w32error_set_last (ERROR_INVALID_HANDLE);
1576 *duplicate_handle = handle;