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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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_SOCKET
, "%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
;