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 #ifdef HAVE_NETINET_TCP_H
26 #include <arpa/inet.h>
36 #ifdef HAVE_SYS_IOCTL_H
37 #include <sys/ioctl.h>
39 #ifdef HAVE_SYS_FILIO_H
40 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
42 #ifdef HAVE_SYS_SOCKIO_H
43 #include <sys/sockio.h> /* defines SIOCATMARK */
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"
58 #include "icall-decl.h"
59 #include "utils/mono-errno.h"
62 MonoFDHandle fdhandle
;
71 socket_data_create (MonoFDType type
, gint fd
)
73 SocketHandle
*sockethandle
;
75 sockethandle
= g_new0 (SocketHandle
, 1);
76 mono_fdhandle_init ((MonoFDHandle
*) sockethandle
, type
, fd
);
82 socket_data_close (MonoFDHandle
*fdhandle
)
85 SocketHandle
* sockethandle
;
88 sockethandle
= (SocketHandle
*) fdhandle
;
89 g_assert (sockethandle
);
91 info
= mono_thread_info_current ();
93 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: closing fd %d", __func__
, ((MonoFDHandle
*) sockethandle
)->fd
);
95 /* Shutdown the socket for reading, to interrupt any potential
96 * receives that may be blocking for data. See bug 75705. */
98 shutdown (((MonoFDHandle
*) sockethandle
)->fd
, SHUT_RD
);
103 ret
= close (((MonoFDHandle
*) sockethandle
)->fd
);
106 if (errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
))
110 sockethandle
->saved_error
= 0;
114 socket_data_destroy (MonoFDHandle
*fdhandle
)
116 SocketHandle
*sockethandle
;
118 sockethandle
= (SocketHandle
*) fdhandle
;
119 g_assert (sockethandle
);
121 g_free (sockethandle
);
125 mono_w32socket_initialize (void)
127 MonoFDHandleCallback socket_data_callbacks
;
128 memset (&socket_data_callbacks
, 0, sizeof (socket_data_callbacks
));
129 socket_data_callbacks
.close
= socket_data_close
;
130 socket_data_callbacks
.destroy
= socket_data_destroy
;
132 mono_fdhandle_register (MONO_FDTYPE_SOCKET
, &socket_data_callbacks
);
136 mono_w32socket_cleanup (void)
141 mono_w32socket_accept (SOCKET sock
, struct sockaddr
*addr
, socklen_t
*addrlen
, gboolean blocking
)
143 SocketHandle
*sockethandle
, *accepted_socket_data
;
144 MonoThreadInfo
*info
;
147 if (addr
!= NULL
&& *addrlen
< sizeof(struct sockaddr
)) {
148 mono_w32socket_set_last_error (WSAEFAULT
);
149 return INVALID_SOCKET
;
152 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
153 mono_w32error_set_last (WSAENOTSOCK
);
154 return INVALID_SOCKET
;
157 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
158 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
159 mono_w32error_set_last (WSAENOTSOCK
);
160 return INVALID_SOCKET
;
163 info
= mono_thread_info_current ();
167 accepted_fd
= accept (((MonoFDHandle
*) sockethandle
)->fd
, addr
, addrlen
);
169 } while (accepted_fd
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
171 if (accepted_fd
== -1) {
172 gint error
= mono_w32socket_convert_error (errno
);
173 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: accept error: %s", __func__
, g_strerror(errno
));
174 mono_w32socket_set_last_error (error
);
175 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
176 return INVALID_SOCKET
;
179 accepted_socket_data
= socket_data_create (MONO_FDTYPE_SOCKET
, accepted_fd
);
180 accepted_socket_data
->domain
= sockethandle
->domain
;
181 accepted_socket_data
->type
= sockethandle
->type
;
182 accepted_socket_data
->protocol
= sockethandle
->protocol
;
183 accepted_socket_data
->still_readable
= 1;
185 mono_fdhandle_insert ((MonoFDHandle
*) accepted_socket_data
);
187 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
));
189 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
190 return ((MonoFDHandle
*) accepted_socket_data
)->fd
;
194 mono_w32socket_connect (SOCKET sock
, const struct sockaddr
*addr
, socklen_t addrlen
, gboolean blocking
)
196 SocketHandle
*sockethandle
;
199 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
200 mono_w32error_set_last (WSAENOTSOCK
);
204 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
205 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
206 mono_w32error_set_last (WSAENOTSOCK
);
211 ret
= connect (((MonoFDHandle
*) sockethandle
)->fd
, addr
, addrlen
);
214 MonoThreadInfo
*info
;
216 gint errnum
, so_error
;
221 if (errno
!= EINTR
) {
222 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: connect error: %s", __func__
,
223 g_strerror (errnum
));
225 errnum
= mono_w32socket_convert_error (errnum
);
226 if (errnum
== WSAEINPROGRESS
)
227 errnum
= WSAEWOULDBLOCK
; /* see bug #73053 */
229 mono_w32socket_set_last_error (errnum
);
232 * On solaris x86 getsockopt (SO_ERROR) is not set after
233 * connect () fails so we need to save this error.
235 * But don't do this for EWOULDBLOCK (bug 317315)
237 if (errnum
!= WSAEWOULDBLOCK
) {
238 /* ECONNRESET means the socket was closed by another thread */
239 /* Async close on mac raises ECONNABORTED. */
240 sockethandle
->saved_error
= errnum
;
242 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
246 info
= mono_thread_info_current ();
248 fds
.fd
= ((MonoFDHandle
*) sockethandle
)->fd
;
249 fds
.events
= MONO_POLLOUT
;
252 ret
= mono_poll (&fds
, 1, -1);
254 if (ret
!= -1 || mono_thread_info_is_interrupt_state (info
))
257 if (errno
!= EINTR
) {
259 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: connect poll error: %s", __func__
, g_strerror (errno
));
260 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
261 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
266 len
= sizeof(so_error
);
268 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_ERROR
, &so_error
, &len
);
272 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: connect getsockopt error: %s", __func__
, g_strerror (errno
));
273 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
274 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
279 gint errnum
= mono_w32socket_convert_error (so_error
);
281 /* Need to save this socket error */
282 sockethandle
->saved_error
= errnum
;
284 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: connect getsockopt returned error: %s",
285 __func__
, g_strerror (so_error
));
287 mono_w32socket_set_last_error (errnum
);
288 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
293 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
298 mono_w32socket_recv (SOCKET sock
, char *buf
, int len
, int flags
, gboolean blocking
)
300 return mono_w32socket_recvfrom (sock
, buf
, len
, flags
, NULL
, 0, blocking
);
304 mono_w32socket_recvfrom (SOCKET sock
, char *buf
, int len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
, gboolean blocking
)
306 SocketHandle
*sockethandle
;
308 MonoThreadInfo
*info
;
310 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
311 mono_w32error_set_last (WSAENOTSOCK
);
315 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
316 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
317 mono_w32error_set_last (WSAENOTSOCK
);
321 info
= mono_thread_info_current ();
325 ret
= recvfrom (((MonoFDHandle
*) sockethandle
)->fd
, buf
, len
, flags
, from
, fromlen
);
327 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
329 if (ret
== 0 && len
> 0) {
330 /* According to the Linux man page, recvfrom only
331 * returns 0 when the socket has been shut down
332 * cleanly. Turn this into an EINTR to simulate win32
333 * behaviour of returning EINTR when a socket is
334 * closed while the recvfrom is blocking (we use a
335 * shutdown() in socket_close() to trigger this.) See
338 /* Distinguish between the socket being shut down at
339 * the local or remote ends, and reads that request 0
343 /* If this returns FALSE, it means the socket has been
344 * closed locally. If it returns TRUE, but
345 * still_readable != 1 then shutdown
346 * (SHUT_RD|SHUT_RDWR) has been called locally.
348 if (sockethandle
->still_readable
!= 1) {
350 mono_set_errno (EINTR
);
356 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: recv error: %s", __func__
, g_strerror(errno
));
357 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
358 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
361 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
366 wsabuf_to_msghdr (WSABUF
*buffers
, guint32 count
, struct msghdr
*hdr
)
370 memset (hdr
, 0, sizeof (struct msghdr
));
371 hdr
->msg_iovlen
= count
;
372 hdr
->msg_iov
= g_new0 (struct iovec
, count
);
373 for (i
= 0; i
< count
; i
++) {
374 hdr
->msg_iov
[i
].iov_base
= buffers
[i
].buf
;
375 hdr
->msg_iov
[i
].iov_len
= buffers
[i
].len
;
380 msghdr_iov_free (struct msghdr
*hdr
)
382 g_free (hdr
->msg_iov
);
386 mono_w32socket_recvbuffers (SOCKET sock
, WSABUF
*buffers
, guint32 count
, guint32
*received
, guint32
*flags
, gpointer overlapped
, gpointer complete
, gboolean blocking
)
388 SocketHandle
*sockethandle
;
389 MonoThreadInfo
*info
;
393 g_assert (overlapped
== NULL
);
394 g_assert (complete
== NULL
);
396 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
397 mono_w32error_set_last (WSAENOTSOCK
);
401 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
402 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
403 mono_w32error_set_last (WSAENOTSOCK
);
407 info
= mono_thread_info_current ();
409 wsabuf_to_msghdr (buffers
, count
, &hdr
);
413 ret
= recvmsg (((MonoFDHandle
*) sockethandle
)->fd
, &hdr
, *flags
);
415 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
417 msghdr_iov_free (&hdr
);
420 /* see mono_w32socket_recvfrom */
421 if (sockethandle
->still_readable
!= 1) {
423 mono_set_errno (EINTR
);
429 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: recvmsg error: %s", __func__
, g_strerror(errno
));
430 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
431 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
436 *flags
= hdr
.msg_flags
;
438 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
443 mono_w32socket_send (SOCKET sock
, void *buf
, int len
, int flags
, gboolean blocking
)
445 SocketHandle
*sockethandle
;
447 MonoThreadInfo
*info
;
449 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
450 mono_w32error_set_last (WSAENOTSOCK
);
454 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
455 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
456 mono_w32error_set_last (WSAENOTSOCK
);
460 info
= mono_thread_info_current ();
464 ret
= send (((MonoFDHandle
*) sockethandle
)->fd
, buf
, len
, flags
);
466 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
470 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: send error: %s", __func__
, g_strerror (errno
));
473 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
474 * a blocking socket. See bug #599488 */
475 if (errnum
== EAGAIN
) {
477 ret
= fcntl (((MonoFDHandle
*) sockethandle
)->fd
, F_GETFL
, 0);
479 if (ret
!= -1 && (ret
& O_NONBLOCK
) == 0)
482 #endif /* O_NONBLOCK */
483 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
484 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
487 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
492 mono_w32socket_sendto (SOCKET sock
, const char *buf
, int len
, int flags
, const struct sockaddr
*to
, int tolen
, gboolean blocking
)
494 SocketHandle
*sockethandle
;
496 MonoThreadInfo
*info
;
498 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
499 mono_w32error_set_last (WSAENOTSOCK
);
503 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
504 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
505 mono_w32error_set_last (WSAENOTSOCK
);
509 info
= mono_thread_info_current ();
513 ret
= sendto (((MonoFDHandle
*) sockethandle
)->fd
, buf
, len
, flags
, to
, tolen
);
515 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
519 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: send error: %s", __func__
, g_strerror (errno
));
520 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
521 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
524 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
529 mono_w32socket_sendbuffers (SOCKET sock
, WSABUF
*buffers
, guint32 count
, guint32
*sent
, guint32 flags
, gpointer overlapped
, gpointer complete
, gboolean blocking
)
532 MonoThreadInfo
*info
;
533 SocketHandle
*sockethandle
;
536 g_assert (overlapped
== NULL
);
537 g_assert (complete
== NULL
);
539 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
540 mono_w32error_set_last (WSAENOTSOCK
);
544 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
545 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
546 mono_w32error_set_last (WSAENOTSOCK
);
550 info
= mono_thread_info_current ();
552 wsabuf_to_msghdr (buffers
, count
, &hdr
);
556 ret
= sendmsg (((MonoFDHandle
*) sockethandle
)->fd
, &hdr
, flags
);
558 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
560 msghdr_iov_free (&hdr
);
564 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: sendmsg error: %s", __func__
, g_strerror (errno
));
565 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
566 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
571 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
575 #define SF_BUFFER_SIZE 16384
578 mono_w32socket_transmit_file (SOCKET sock
, gpointer file_handle
, gpointer lpTransmitBuffers
, guint32 flags
, gboolean blocking
)
580 MonoThreadInfo
*info
;
581 SocketHandle
*sockethandle
;
584 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
589 TRANSMIT_FILE_BUFFERS
*buffers
= (TRANSMIT_FILE_BUFFERS
*)lpTransmitBuffers
;
591 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
592 mono_w32error_set_last (WSAENOTSOCK
);
596 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
597 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
598 mono_w32error_set_last (WSAENOTSOCK
);
602 /* Write the header */
603 if (buffers
!= NULL
&& buffers
->Head
!= NULL
&& buffers
->HeadLength
> 0) {
604 ret
= mono_w32socket_send (((MonoFDHandle
*) sockethandle
)->fd
, buffers
->Head
, buffers
->HeadLength
, 0, FALSE
);
605 if (ret
== SOCKET_ERROR
) {
606 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
611 info
= mono_thread_info_current ();
613 file
= GPOINTER_TO_INT (file_handle
);
615 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
617 ret
= fstat (file
, &statbuf
);
621 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
622 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
629 ret
= sendfile (((MonoFDHandle
*) sockethandle
)->fd
, file
, NULL
, statbuf
.st_size
);
630 #elif defined(DARWIN)
631 /* TODO: header/tail could be sent in the 5th argument */
632 /* TODO: Might not send the entire file for non-blocking sockets */
633 ret
= sendfile (file
, ((MonoFDHandle
*) sockethandle
)->fd
, 0, &statbuf
.st_size
, NULL
, 0);
636 } while (ret
!= -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
638 buffer
= g_malloc (SF_BUFFER_SIZE
);
643 ret
= read (file
, buffer
, SF_BUFFER_SIZE
);
645 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
647 if (ret
== -1 || ret
== 0)
652 ret
= send (((MonoFDHandle
*) sockethandle
)->fd
, buffer
, ret
, 0); /* short sends? enclose this in a loop? */
654 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
655 } while (ret
!= -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
662 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
663 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
668 if (buffers
!= NULL
&& buffers
->Tail
!= NULL
&& buffers
->TailLength
> 0) {
669 ret
= mono_w32socket_send (((MonoFDHandle
*) sockethandle
)->fd
, buffers
->Tail
, buffers
->TailLength
, 0, FALSE
);
670 if (ret
== SOCKET_ERROR
) {
671 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
676 if ((flags
& TF_DISCONNECT
) == TF_DISCONNECT
)
677 mono_w32socket_close (((MonoFDHandle
*) sockethandle
)->fd
);
679 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
684 mono_w32socket_socket (int domain
, int type
, int protocol
)
686 SocketHandle
*sockethandle
;
691 fd
= socket (domain
, type
, protocol
);
694 if (domain
== AF_INET
&& type
== SOCK_RAW
&& protocol
== 0) {
695 /* Retry with protocol == 4 (see bug #54565) */
696 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
702 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: socket error: %s", __func__
, g_strerror (errno
));
703 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
704 return INVALID_SOCKET
;
707 sockethandle
= socket_data_create(MONO_FDTYPE_SOCKET
, fd
);
708 sockethandle
->domain
= domain
;
709 sockethandle
->type
= type
;
710 sockethandle
->protocol
= protocol
;
711 sockethandle
->still_readable
= 1;
713 /* .net seems to set this by default for SOCK_STREAM, not for
714 * SOCK_DGRAM (see bug #36322)
715 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
717 * It seems winsock has a rather different idea of what
718 * SO_REUSEADDR means. If it's set, then a new socket can be
719 * bound over an existing listening socket. There's a new
720 * windows-specific option called SO_EXCLUSIVEADDRUSE but
721 * using that means the socket MUST be closed properly, or a
722 * denial of service can occur. Luckily for us, winsock
723 * behaves as though any other system would when SO_REUSEADDR
724 * is true, so we don't need to do anything else here. See
726 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
733 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_REUSEADDR
, &true_
, sizeof (true_
));
737 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: Error setting SO_REUSEADDR", __func__
);
738 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
741 close (((MonoFDHandle
*) sockethandle
)->fd
);
744 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
745 return INVALID_SOCKET
;
749 mono_fdhandle_insert ((MonoFDHandle
*) sockethandle
);
751 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: returning socket handle %p", __func__
, GINT_TO_POINTER(((MonoFDHandle
*) sockethandle
)->fd
));
753 return ((MonoFDHandle
*) sockethandle
)->fd
;
757 mono_w32socket_bind (SOCKET sock
, struct sockaddr
*addr
, socklen_t addrlen
)
759 SocketHandle
*sockethandle
;
762 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
763 mono_w32error_set_last (WSAENOTSOCK
);
767 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
768 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
769 mono_w32error_set_last (WSAENOTSOCK
);
774 ret
= bind (((MonoFDHandle
*) sockethandle
)->fd
, addr
, addrlen
);
778 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: bind error: %s", __func__
, g_strerror(errno
));
779 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
780 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
784 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
789 mono_w32socket_getpeername (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
791 SocketHandle
*sockethandle
;
794 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
795 mono_w32error_set_last (WSAENOTSOCK
);
799 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
800 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
801 mono_w32error_set_last (WSAENOTSOCK
);
805 #ifdef HAVE_GETPEERNAME
807 ret
= getpeername (((MonoFDHandle
*) sockethandle
)->fd
, name
, namelen
);
814 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getpeername error: %s", __func__
, g_strerror (errno
));
815 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
816 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
820 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
825 mono_w32socket_getsockname (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
827 SocketHandle
*sockethandle
;
830 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
831 mono_w32error_set_last (WSAENOTSOCK
);
835 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
836 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
837 mono_w32error_set_last (WSAENOTSOCK
);
842 ret
= getsockname (((MonoFDHandle
*) sockethandle
)->fd
, name
, namelen
);
846 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockname error: %s", __func__
, g_strerror (errno
));
847 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
848 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
852 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
857 mono_w32socket_getsockopt (SOCKET sock
, gint level
, gint optname
, gpointer optval
, socklen_t
*optlen
)
859 SocketHandle
*sockethandle
;
864 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
865 mono_w32error_set_last (WSAENOTSOCK
);
869 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
870 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
871 mono_w32error_set_last (WSAENOTSOCK
);
876 if (level
== SOL_SOCKET
&&
877 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
879 *optlen
= sizeof (tv
);
883 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, optname
, tmp_val
, optlen
);
887 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockopt error: %s", __func__
, g_strerror (errno
));
888 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
889 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
893 if (level
== SOL_SOCKET
&& (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
894 *((int *) optval
) = tv
.tv_sec
* 1000 + (tv
.tv_usec
/ 1000); // milli from micro
895 *optlen
= sizeof (int);
898 if (optname
== SO_ERROR
) {
899 if (*((int *)optval
) != 0) {
900 *((int *) optval
) = mono_w32socket_convert_error (*((int *)optval
));
901 sockethandle
->saved_error
= *((int *)optval
);
903 *((int *)optval
) = sockethandle
->saved_error
;
907 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
912 mono_w32socket_setsockopt (SOCKET sock
, gint level
, gint optname
, gconstpointer optval
, socklen_t optlen
)
914 SocketHandle
*sockethandle
;
916 gconstpointer tmp_val
;
917 #if defined (__linux__)
918 /* This has its address taken so it cannot be moved to the if block which uses it */
923 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
924 mono_w32error_set_last (WSAENOTSOCK
);
928 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
929 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
930 mono_w32error_set_last (WSAENOTSOCK
);
935 if (level
== SOL_SOCKET
&&
936 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
937 int ms
= *((int *) optval
);
938 tv
.tv_sec
= ms
/ 1000;
939 tv
.tv_usec
= (ms
% 1000) * 1000; // micro from milli
941 optlen
= sizeof (tv
);
943 #if defined (__linux__)
944 else if (level
== SOL_SOCKET
&&
945 (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
)) {
946 /* According to socket(7) the Linux kernel doubles the
947 * buffer sizes "to allow space for bookkeeping
950 bufsize
= *((int *) optval
);
958 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, optname
, tmp_val
, optlen
);
962 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: setsockopt error: %s", __func__
, g_strerror (errno
));
963 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
964 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
968 #if defined (SO_REUSEPORT)
969 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
970 if (level
== SOL_SOCKET
&& optname
== SO_REUSEADDR
) {
972 socklen_t type_len
= sizeof (type
);
975 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, SO_TYPE
, &type
, &type_len
);
978 if (type
== SOCK_DGRAM
|| type
== SOCK_STREAM
) {
980 setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, SO_REUSEPORT
, tmp_val
, optlen
);
987 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
992 mono_w32socket_listen (SOCKET sock
, gint backlog
)
994 SocketHandle
*sockethandle
;
997 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
998 mono_w32error_set_last (WSAENOTSOCK
);
1002 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1003 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1004 mono_w32error_set_last (WSAENOTSOCK
);
1005 return SOCKET_ERROR
;
1009 ret
= listen (((MonoFDHandle
*) sockethandle
)->fd
, backlog
);
1012 gint errnum
= errno
;
1013 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: listen error: %s", __func__
, g_strerror (errno
));
1014 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1015 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1016 return SOCKET_ERROR
;
1019 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1024 mono_w32socket_shutdown (SOCKET sock
, gint how
)
1026 SocketHandle
*sockethandle
;
1029 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1030 mono_w32error_set_last (WSAENOTSOCK
);
1031 return SOCKET_ERROR
;
1034 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1035 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1036 mono_w32error_set_last (WSAENOTSOCK
);
1037 return SOCKET_ERROR
;
1040 if (how
== SHUT_RD
|| how
== SHUT_RDWR
)
1041 sockethandle
->still_readable
= 0;
1044 ret
= shutdown (((MonoFDHandle
*) sockethandle
)->fd
, how
);
1047 gint errnum
= errno
;
1048 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: shutdown error: %s", __func__
, g_strerror (errno
));
1049 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1050 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1051 return SOCKET_ERROR
;
1054 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1059 mono_w32socket_disconnect (SOCKET sock
, gboolean reuse
)
1061 SocketHandle
*sockethandle
;
1065 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: called on socket %d!", __func__
, sock
);
1067 /* We could check the socket type here and fail unless its
1068 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1069 * if we really wanted to */
1071 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1072 mono_w32error_set_last (WSAENOTSOCK
);
1073 return SOCKET_ERROR
;
1076 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1077 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1078 mono_w32error_set_last (WSAENOTSOCK
);
1079 return SOCKET_ERROR
;
1083 newsock
= socket (sockethandle
->domain
, sockethandle
->type
, sockethandle
->protocol
);
1085 if (newsock
== -1) {
1086 gint errnum
= errno
;
1087 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: socket error: %s", __func__
, g_strerror (errnum
));
1088 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1089 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1090 return SOCKET_ERROR
;
1093 /* According to Stevens "Advanced Programming in the UNIX
1094 * Environment: UNIX File I/O" dup2() is atomic so there
1095 * should not be a race condition between the old fd being
1096 * closed and the new socket fd being copied over */
1099 ret
= dup2 (newsock
, ((MonoFDHandle
*) sockethandle
)->fd
);
1101 } while (ret
== -1 && errno
== EAGAIN
);
1104 gint errnum
= errno
;
1105 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: dup2 error: %s", __func__
, g_strerror (errnum
));
1106 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1107 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1108 return SOCKET_ERROR
;
1115 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1120 extension_disconect (SOCKET sock
, OVERLAPPED
*overlapped
, guint32 flags
, guint32 reserved
)
1123 MONO_ENTER_GC_UNSAFE
;
1124 ret
= mono_w32socket_disconnect (sock
, flags
& TF_REUSE_SOCKET
) == 0;
1125 MONO_EXIT_GC_UNSAFE
;
1130 extension_transmit_file (SOCKET sock
, gpointer file_handle
, guint32 bytes_to_write
, guint32 bytes_per_send
,
1131 OVERLAPPED
*ol
, TRANSMIT_FILE_BUFFERS
*buffers
, guint32 flags
)
1134 MONO_ENTER_GC_UNSAFE
;
1135 ret
= mono_w32socket_transmit_file (sock
, file_handle
, buffers
, flags
, FALSE
);
1136 MONO_EXIT_GC_UNSAFE
;
1144 } extension_functions
[] = {
1145 { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, (gpointer
)extension_disconect
},
1146 { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, (gpointer
)extension_transmit_file
},
1151 mono_w32socket_ioctl (SOCKET sock
, gint32 command
, gchar
*input
, gint inputlen
, gchar
*output
, gint outputlen
, glong
*written
)
1153 SocketHandle
*sockethandle
;
1157 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1158 mono_w32error_set_last (WSAENOTSOCK
);
1159 return SOCKET_ERROR
;
1162 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1163 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1164 mono_w32error_set_last (WSAENOTSOCK
);
1165 return SOCKET_ERROR
;
1168 if (command
== 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1172 if (inputlen
< sizeof(GUID
)) {
1173 /* As far as I can tell, windows doesn't
1174 * actually set an error here...
1176 mono_w32socket_set_last_error (WSAEINVAL
);
1177 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1178 return SOCKET_ERROR
;
1181 if (outputlen
< sizeof(gpointer
)) {
1183 mono_w32socket_set_last_error (WSAEINVAL
);
1184 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1185 return SOCKET_ERROR
;
1188 if (output
== NULL
) {
1190 mono_w32socket_set_last_error (WSAEINVAL
);
1191 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1192 return SOCKET_ERROR
;
1195 guid
= (GUID
*) input
;
1196 for (i
= 0; extension_functions
[i
].func
; i
++) {
1197 if (memcmp (guid
, &extension_functions
[i
].guid
, sizeof(GUID
)) == 0) {
1198 memcpy (output
, &extension_functions
[i
].func
, sizeof(gpointer
));
1199 *written
= sizeof(gpointer
);
1200 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1205 mono_w32socket_set_last_error (WSAEINVAL
);
1206 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1207 return SOCKET_ERROR
;
1210 if (command
== 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1213 if (inputlen
< 3 * sizeof (guint32
)) {
1214 mono_w32socket_set_last_error (WSAEINVAL
);
1215 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1216 return SOCKET_ERROR
;
1219 onoff
= *((guint32
*) input
);
1222 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_KEEPALIVE
, &onoff
, sizeof (guint32
));
1225 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno
));
1226 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1227 return SOCKET_ERROR
;
1230 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1232 /* Values are in ms, but we need s */
1233 guint32 keepalivetime
, keepaliveinterval
, rem
;
1235 keepalivetime
= *(((guint32
*) input
) + 1);
1236 keepaliveinterval
= *(((guint32
*) input
) + 2);
1238 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1239 rem
= keepalivetime
% 1000;
1240 keepalivetime
/= 1000;
1241 if (keepalivetime
== 0 || rem
>= 500)
1244 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, &keepalivetime
, sizeof (guint32
));
1247 rem
= keepaliveinterval
% 1000;
1248 keepaliveinterval
/= 1000;
1249 if (keepaliveinterval
== 0 || rem
>= 500)
1250 keepaliveinterval
++;
1252 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, &keepaliveinterval
, sizeof (guint32
));
1256 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno
));
1257 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1258 return SOCKET_ERROR
;
1261 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1266 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1270 buffer
= inputlen
> 0 ? (gchar
*) g_memdup (input
, inputlen
) : NULL
;
1273 ret
= ioctl (((MonoFDHandle
*) sockethandle
)->fd
, command
, buffer
);
1278 gint errnum
= errno
;
1279 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: WSAIoctl error: %s", __func__
, g_strerror (errno
));
1280 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1281 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1282 return SOCKET_ERROR
;
1287 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1291 /* We just copy the buffer to the output. Some ioctls
1292 * don't even output any data, but, well...
1294 * NB windows returns WSAEFAULT if outputlen is too small */
1295 inputlen
= (inputlen
> outputlen
) ? outputlen
: inputlen
;
1297 if (inputlen
> 0 && output
!= NULL
)
1298 memcpy (output
, buffer
, inputlen
);
1301 *written
= inputlen
;
1303 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1308 mono_w32socket_close (SOCKET sock
)
1310 if (!mono_fdhandle_close (sock
)) {
1311 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1319 mono_w32socket_set_blocking (SOCKET sock
, gboolean blocking
)
1322 SocketHandle
*sockethandle
;
1325 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1326 mono_w32error_set_last (WSAENOTSOCK
);
1327 return SOCKET_ERROR
;
1330 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1331 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1332 mono_w32error_set_last (WSAENOTSOCK
);
1333 return SOCKET_ERROR
;
1336 /* This works better than ioctl(...FIONBIO...)
1337 * on Linux (it causes connect to return
1338 * EINPROGRESS, but the ioctl doesn't seem to) */
1340 ret
= fcntl (((MonoFDHandle
*) sockethandle
)->fd
, F_GETFL
, 0);
1343 gint errnum
= mono_w32socket_convert_error (errno
);
1344 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: fcntl(F_GETFL) error: %s", __func__
, g_strerror (errno
));
1345 mono_w32socket_set_last_error (errnum
);
1346 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1347 return SOCKET_ERROR
;
1351 ret
= fcntl (((MonoFDHandle
*) sockethandle
)->fd
, F_SETFL
, blocking
? (ret
& (~O_NONBLOCK
)) : (ret
| (O_NONBLOCK
)));
1354 gint errnum
= mono_w32socket_convert_error (errno
);
1355 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: fcntl(F_SETFL) error: %s", __func__
, g_strerror (errno
));
1356 mono_w32socket_set_last_error (errnum
);
1357 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1358 return SOCKET_ERROR
;
1361 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1364 mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED
);
1365 return SOCKET_ERROR
;
1366 #endif /* O_NONBLOCK */
1370 mono_w32socket_get_available (SOCKET sock
, guint64
*amount
)
1372 SocketHandle
*sockethandle
;
1375 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1376 mono_w32error_set_last (WSAENOTSOCK
);
1377 return SOCKET_ERROR
;
1380 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1381 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1382 mono_w32error_set_last (WSAENOTSOCK
);
1383 return SOCKET_ERROR
;
1386 #if defined (HOST_DARWIN)
1387 // ioctl (socket, FIONREAD, XXX) returns the size of
1388 // the UDP header as well on Darwin.
1390 // Use getsockopt SO_NREAD instead to get the
1391 // right values for TCP and UDP.
1393 // ai_canonname can be null in some cases on darwin,
1394 // where the runtime assumes it will be the value of
1397 socklen_t optlen
= sizeof (int);
1399 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_NREAD
, (gulong
*) amount
, &optlen
);
1402 gint errnum
= mono_w32socket_convert_error (errno
);
1403 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockopt error: %s", __func__
, g_strerror (errno
));
1404 mono_w32socket_set_last_error (errnum
);
1405 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1406 return SOCKET_ERROR
;
1410 ret
= ioctl (((MonoFDHandle
*) sockethandle
)->fd
, FIONREAD
, (gulong
*) amount
);
1413 gint errnum
= mono_w32socket_convert_error (errno
);
1414 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: ioctl error: %s", __func__
, g_strerror (errno
));
1415 mono_w32socket_set_last_error (errnum
);
1416 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1417 return SOCKET_ERROR
;
1421 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1426 mono_w32socket_set_last_error (gint32 error
)
1428 mono_w32error_set_last (error
);
1432 mono_w32socket_get_last_error (void)
1434 return mono_w32error_get_last ();
1438 mono_w32socket_convert_error (gint error
)
1441 case 0: return ERROR_SUCCESS
;
1442 case EACCES
: return WSAEACCES
;
1444 case EADDRINUSE
: return WSAEADDRINUSE
;
1447 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
1449 #if EAGAIN != EWOULDBLOCK
1450 case EAGAIN
: return WSAEWOULDBLOCK
;
1453 case EALREADY
: return WSAEALREADY
;
1455 case EBADF
: return WSAENOTSOCK
;
1457 case ECONNABORTED
: return WSAENETDOWN
;
1460 case ECONNREFUSED
: return WSAECONNREFUSED
;
1463 case ECONNRESET
: return WSAECONNRESET
;
1465 case EDOM
: return WSAEINVAL
; /* not a precise match, best wecan do. */
1466 case EFAULT
: return WSAEFAULT
;
1468 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
1471 case EINPROGRESS
: return WSAEINPROGRESS
;
1473 case EINTR
: return WSAEINTR
;
1474 case EINVAL
: return WSAEINVAL
;
1475 case EIO
: return WSA_INVALID_HANDLE
; /* not a precise match, best we can do. */
1477 case EISCONN
: return WSAEISCONN
;
1479 case ELOOP
: return WSAELOOP
;
1480 case ENFILE
: return WSAEMFILE
; /* not a precise match, best we can do. */
1481 case EMFILE
: return WSAEMFILE
;
1483 case EMSGSIZE
: return WSAEMSGSIZE
;
1485 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
1487 case ENETUNREACH
: return WSAENETUNREACH
;
1490 case ENOBUFS
: return WSAENOBUFS
; /* not documented */
1492 case ENOMEM
: return WSAENOBUFS
;
1494 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
1497 case ENOSR
: return WSAENETDOWN
;
1500 case ENOTCONN
: return WSAENOTCONN
;
1502 case ENOTDIR
: return WSA_INVALID_PARAMETER
; /* not a precise match, best we can do. */
1504 case ENOTSOCK
: return WSAENOTSOCK
;
1506 case ENOTTY
: return WSAENOTSOCK
;
1508 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
1510 case EPERM
: return WSAEACCES
;
1511 case EPIPE
: return WSAESHUTDOWN
;
1512 #ifdef EPROTONOSUPPORT
1513 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
1516 case ERESTARTSYS
: return WSAENETDOWN
;
1518 /*FIXME: case EROFS: return WSAE????; */
1519 #ifdef ESOCKTNOSUPPORT
1520 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
1523 case ETIMEDOUT
: return WSAETIMEDOUT
;
1526 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
1528 #ifdef EADDRNOTAVAIL
1529 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
1531 /* This might happen with unix sockets */
1532 case ENOENT
: return WSAECONNREFUSED
;
1534 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
1537 case EHOSTDOWN
: return WSAEHOSTDOWN
;
1540 case ENETDOWN
: return WSAENETDOWN
;
1542 case ENODEV
: return WSAENETDOWN
;
1544 case EPROTOTYPE
: return WSAEPROTOTYPE
;
1547 case ENXIO
: return WSAENXIO
;
1550 case ENONET
: return WSAENETUNREACH
;
1553 case ENOKEY
: return WSAENETUNREACH
;
1556 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__
, error
, g_strerror (error
));
1561 ves_icall_System_Net_Sockets_Socket_SupportPortReuse_icall (MonoProtocolType proto
)
1563 #if defined (SO_REUSEPORT)
1567 /* Linux always supports double binding for UDP, even on older kernels. */
1568 if (proto
== ProtocolType_Udp
)
1576 mono_w32socket_duplicate (gpointer handle
, gint32 targetProcessId
, gpointer
*duplicate_handle
)
1578 SocketHandle
*sockethandle
;
1580 if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle
), (MonoFDHandle
**) &sockethandle
)) {
1581 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1585 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1586 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1587 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1591 *duplicate_handle
= handle
;