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
, int 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
, TRANSMIT_FILE_BUFFERS
*buffers
, guint32 flags
, gboolean blocking
)
580 MonoThreadInfo
*info
;
581 SocketHandle
*sockethandle
;
584 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
590 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
591 mono_w32error_set_last (WSAENOTSOCK
);
595 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
596 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
597 mono_w32error_set_last (WSAENOTSOCK
);
601 /* Write the header */
602 if (buffers
!= NULL
&& buffers
->Head
!= NULL
&& buffers
->HeadLength
> 0) {
603 ret
= mono_w32socket_send (((MonoFDHandle
*) sockethandle
)->fd
, buffers
->Head
, buffers
->HeadLength
, 0, FALSE
);
604 if (ret
== SOCKET_ERROR
) {
605 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
610 info
= mono_thread_info_current ();
612 file
= GPOINTER_TO_INT (file_handle
);
614 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
616 ret
= fstat (file
, &statbuf
);
620 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
621 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
628 ret
= sendfile (((MonoFDHandle
*) sockethandle
)->fd
, file
, NULL
, statbuf
.st_size
);
629 #elif defined(DARWIN)
630 /* TODO: header/tail could be sent in the 5th argument */
631 /* TODO: Might not send the entire file for non-blocking sockets */
632 ret
= sendfile (file
, ((MonoFDHandle
*) sockethandle
)->fd
, 0, &statbuf
.st_size
, NULL
, 0);
635 } while (ret
!= -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
637 buffer
= g_malloc (SF_BUFFER_SIZE
);
642 ret
= read (file
, buffer
, SF_BUFFER_SIZE
);
644 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
646 if (ret
== -1 || ret
== 0)
651 ret
= send (((MonoFDHandle
*) sockethandle
)->fd
, buffer
, ret
, 0); /* short sends? enclose this in a loop? */
653 } while (ret
== -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
654 } while (ret
!= -1 && errno
== EINTR
&& !mono_thread_info_is_interrupt_state (info
));
661 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
662 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
667 if (buffers
!= NULL
&& buffers
->Tail
!= NULL
&& buffers
->TailLength
> 0) {
668 ret
= mono_w32socket_send (((MonoFDHandle
*) sockethandle
)->fd
, buffers
->Tail
, buffers
->TailLength
, 0, FALSE
);
669 if (ret
== SOCKET_ERROR
) {
670 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
675 if ((flags
& TF_DISCONNECT
) == TF_DISCONNECT
)
676 mono_w32socket_close (((MonoFDHandle
*) sockethandle
)->fd
);
678 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
683 mono_w32socket_socket (int domain
, int type
, int protocol
)
685 SocketHandle
*sockethandle
;
690 fd
= socket (domain
, type
, protocol
);
693 if (domain
== AF_INET
&& type
== SOCK_RAW
&& protocol
== 0) {
694 /* Retry with protocol == 4 (see bug #54565) */
695 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
701 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: socket error: %s", __func__
, g_strerror (errno
));
702 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
703 return INVALID_SOCKET
;
706 sockethandle
= socket_data_create(MONO_FDTYPE_SOCKET
, fd
);
707 sockethandle
->domain
= domain
;
708 sockethandle
->type
= type
;
709 sockethandle
->protocol
= protocol
;
710 sockethandle
->still_readable
= 1;
712 /* .net seems to set this by default for SOCK_STREAM, not for
713 * SOCK_DGRAM (see bug #36322)
714 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
716 * It seems winsock has a rather different idea of what
717 * SO_REUSEADDR means. If it's set, then a new socket can be
718 * bound over an existing listening socket. There's a new
719 * windows-specific option called SO_EXCLUSIVEADDRUSE but
720 * using that means the socket MUST be closed properly, or a
721 * denial of service can occur. Luckily for us, winsock
722 * behaves as though any other system would when SO_REUSEADDR
723 * is true, so we don't need to do anything else here. See
725 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
732 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_REUSEADDR
, &true_
, sizeof (true_
));
736 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: Error setting SO_REUSEADDR", __func__
);
737 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
740 close (((MonoFDHandle
*) sockethandle
)->fd
);
743 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
744 return INVALID_SOCKET
;
748 mono_fdhandle_insert ((MonoFDHandle
*) sockethandle
);
750 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: returning socket handle %p", __func__
, GINT_TO_POINTER(((MonoFDHandle
*) sockethandle
)->fd
));
752 return ((MonoFDHandle
*) sockethandle
)->fd
;
756 mono_w32socket_bind (SOCKET sock
, struct sockaddr
*addr
, socklen_t addrlen
)
758 SocketHandle
*sockethandle
;
761 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
762 mono_w32error_set_last (WSAENOTSOCK
);
766 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
767 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
768 mono_w32error_set_last (WSAENOTSOCK
);
773 ret
= bind (((MonoFDHandle
*) sockethandle
)->fd
, addr
, addrlen
);
777 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: bind error: %s", __func__
, g_strerror(errno
));
778 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
779 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
783 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
788 mono_w32socket_getpeername (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
790 SocketHandle
*sockethandle
;
793 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
794 mono_w32error_set_last (WSAENOTSOCK
);
798 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
799 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
800 mono_w32error_set_last (WSAENOTSOCK
);
804 #ifdef HAVE_GETPEERNAME
806 ret
= getpeername (((MonoFDHandle
*) sockethandle
)->fd
, name
, namelen
);
813 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getpeername error: %s", __func__
, g_strerror (errno
));
814 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
815 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
819 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
824 mono_w32socket_getsockname (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
826 SocketHandle
*sockethandle
;
829 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
830 mono_w32error_set_last (WSAENOTSOCK
);
834 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
835 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
836 mono_w32error_set_last (WSAENOTSOCK
);
841 ret
= getsockname (((MonoFDHandle
*) sockethandle
)->fd
, name
, namelen
);
845 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockname error: %s", __func__
, g_strerror (errno
));
846 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
847 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
851 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
856 mono_w32socket_getsockopt (SOCKET sock
, gint level
, gint optname
, gpointer optval
, socklen_t
*optlen
)
858 SocketHandle
*sockethandle
;
863 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
864 mono_w32error_set_last (WSAENOTSOCK
);
868 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
869 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
870 mono_w32error_set_last (WSAENOTSOCK
);
875 if (level
== SOL_SOCKET
&&
876 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
878 *optlen
= sizeof (tv
);
882 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, optname
, tmp_val
, optlen
);
886 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockopt error: %s", __func__
, g_strerror (errno
));
887 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
888 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
892 if (level
== SOL_SOCKET
&& (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
893 *((int *) optval
) = tv
.tv_sec
* 1000 + (tv
.tv_usec
/ 1000); // milli from micro
894 *optlen
= sizeof (int);
897 if (optname
== SO_ERROR
) {
898 if (*((int *)optval
) != 0) {
899 *((int *) optval
) = mono_w32socket_convert_error (*((int *)optval
));
900 sockethandle
->saved_error
= *((int *)optval
);
902 *((int *)optval
) = sockethandle
->saved_error
;
906 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
911 mono_w32socket_setsockopt (SOCKET sock
, gint level
, gint optname
, gconstpointer optval
, socklen_t optlen
)
913 SocketHandle
*sockethandle
;
915 gconstpointer tmp_val
;
916 #if defined (__linux__)
917 /* This has its address taken so it cannot be moved to the if block which uses it */
922 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
923 mono_w32error_set_last (WSAENOTSOCK
);
927 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
928 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
929 mono_w32error_set_last (WSAENOTSOCK
);
934 if (level
== SOL_SOCKET
&&
935 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
936 int ms
= *((int *) optval
);
937 tv
.tv_sec
= ms
/ 1000;
938 tv
.tv_usec
= (ms
% 1000) * 1000; // micro from milli
940 optlen
= sizeof (tv
);
942 #if defined (__linux__)
943 else if (level
== SOL_SOCKET
&&
944 (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
)) {
945 /* According to socket(7) the Linux kernel doubles the
946 * buffer sizes "to allow space for bookkeeping
949 bufsize
= *((int *) optval
);
957 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, optname
, tmp_val
, optlen
);
961 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: setsockopt error: %s", __func__
, g_strerror (errno
));
962 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
963 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
967 #if defined (SO_REUSEPORT)
968 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
969 if (level
== SOL_SOCKET
&& optname
== SO_REUSEADDR
) {
971 socklen_t type_len
= sizeof (type
);
974 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, SO_TYPE
, &type
, &type_len
);
977 if (type
== SOCK_DGRAM
|| type
== SOCK_STREAM
) {
979 setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, level
, SO_REUSEPORT
, tmp_val
, optlen
);
986 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
991 mono_w32socket_listen (SOCKET sock
, gint backlog
)
993 SocketHandle
*sockethandle
;
996 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
997 mono_w32error_set_last (WSAENOTSOCK
);
1001 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1002 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1003 mono_w32error_set_last (WSAENOTSOCK
);
1004 return SOCKET_ERROR
;
1008 ret
= listen (((MonoFDHandle
*) sockethandle
)->fd
, backlog
);
1011 gint errnum
= errno
;
1012 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: listen error: %s", __func__
, g_strerror (errno
));
1013 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1014 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1015 return SOCKET_ERROR
;
1018 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1023 mono_w32socket_shutdown (SOCKET sock
, gint how
)
1025 SocketHandle
*sockethandle
;
1028 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1029 mono_w32error_set_last (WSAENOTSOCK
);
1030 return SOCKET_ERROR
;
1033 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1034 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1035 mono_w32error_set_last (WSAENOTSOCK
);
1036 return SOCKET_ERROR
;
1039 if (how
== SHUT_RD
|| how
== SHUT_RDWR
)
1040 sockethandle
->still_readable
= 0;
1043 ret
= shutdown (((MonoFDHandle
*) sockethandle
)->fd
, how
);
1046 gint errnum
= errno
;
1047 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: shutdown error: %s", __func__
, g_strerror (errno
));
1048 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1049 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1050 return SOCKET_ERROR
;
1053 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1058 mono_w32socket_disconnect (SOCKET sock
, gboolean reuse
)
1060 SocketHandle
*sockethandle
;
1064 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: called on socket %d!", __func__
, sock
);
1066 /* We could check the socket type here and fail unless its
1067 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1068 * if we really wanted to */
1070 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1071 mono_w32error_set_last (WSAENOTSOCK
);
1072 return SOCKET_ERROR
;
1075 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1076 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1077 mono_w32error_set_last (WSAENOTSOCK
);
1078 return SOCKET_ERROR
;
1082 newsock
= socket (sockethandle
->domain
, sockethandle
->type
, sockethandle
->protocol
);
1084 if (newsock
== -1) {
1085 gint errnum
= errno
;
1086 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: socket error: %s", __func__
, g_strerror (errnum
));
1087 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1088 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1089 return SOCKET_ERROR
;
1092 /* According to Stevens "Advanced Programming in the UNIX
1093 * Environment: UNIX File I/O" dup2() is atomic so there
1094 * should not be a race condition between the old fd being
1095 * closed and the new socket fd being copied over */
1098 ret
= dup2 (newsock
, ((MonoFDHandle
*) sockethandle
)->fd
);
1100 } while (ret
== -1 && errno
== EAGAIN
);
1103 gint errnum
= errno
;
1104 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: dup2 error: %s", __func__
, g_strerror (errnum
));
1105 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1106 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1107 return SOCKET_ERROR
;
1114 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1119 extension_disconect (SOCKET sock
, OVERLAPPED
*overlapped
, guint32 flags
, guint32 reserved
)
1122 MONO_ENTER_GC_UNSAFE
;
1123 ret
= mono_w32socket_disconnect (sock
, flags
& TF_REUSE_SOCKET
) == 0;
1124 MONO_EXIT_GC_UNSAFE
;
1129 extension_transmit_file (SOCKET sock
, gpointer file_handle
, guint32 bytes_to_write
, guint32 bytes_per_send
,
1130 OVERLAPPED
*ol
, TRANSMIT_FILE_BUFFERS
*buffers
, guint32 flags
)
1133 MONO_ENTER_GC_UNSAFE
;
1134 ret
= mono_w32socket_transmit_file (sock
, file_handle
, buffers
, flags
, FALSE
);
1135 MONO_EXIT_GC_UNSAFE
;
1143 } extension_functions
[] = {
1144 { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, (gpointer
)extension_disconect
},
1145 { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, (gpointer
)extension_transmit_file
},
1150 mono_w32socket_ioctl (SOCKET sock
, gint32 command
, gchar
*input
, gint inputlen
, gchar
*output
, gint outputlen
, glong
*written
)
1152 SocketHandle
*sockethandle
;
1156 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1157 mono_w32error_set_last (WSAENOTSOCK
);
1158 return SOCKET_ERROR
;
1161 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1162 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1163 mono_w32error_set_last (WSAENOTSOCK
);
1164 return SOCKET_ERROR
;
1167 if (command
== 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1171 if (inputlen
< sizeof(GUID
)) {
1172 /* As far as I can tell, windows doesn't
1173 * actually set an error here...
1175 mono_w32socket_set_last_error (WSAEINVAL
);
1176 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1177 return SOCKET_ERROR
;
1180 if (outputlen
< sizeof(gpointer
)) {
1182 mono_w32socket_set_last_error (WSAEINVAL
);
1183 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1184 return SOCKET_ERROR
;
1187 if (output
== NULL
) {
1189 mono_w32socket_set_last_error (WSAEINVAL
);
1190 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1191 return SOCKET_ERROR
;
1194 guid
= (GUID
*) input
;
1195 for (i
= 0; extension_functions
[i
].func
; i
++) {
1196 if (memcmp (guid
, &extension_functions
[i
].guid
, sizeof(GUID
)) == 0) {
1197 memcpy (output
, &extension_functions
[i
].func
, sizeof(gpointer
));
1198 *written
= sizeof(gpointer
);
1199 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1204 mono_w32socket_set_last_error (WSAEINVAL
);
1205 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1206 return SOCKET_ERROR
;
1209 if (command
== 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1212 if (inputlen
< 3 * sizeof (guint32
)) {
1213 mono_w32socket_set_last_error (WSAEINVAL
);
1214 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1215 return SOCKET_ERROR
;
1218 onoff
= *((guint32
*) input
);
1221 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_KEEPALIVE
, &onoff
, sizeof (guint32
));
1224 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno
));
1225 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1226 return SOCKET_ERROR
;
1229 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1231 /* Values are in ms, but we need s */
1232 guint32 keepalivetime
, keepaliveinterval
, rem
;
1234 keepalivetime
= *(((guint32
*) input
) + 1);
1235 keepaliveinterval
= *(((guint32
*) input
) + 2);
1237 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1238 rem
= keepalivetime
% 1000;
1239 keepalivetime
/= 1000;
1240 if (keepalivetime
== 0 || rem
>= 500)
1243 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, &keepalivetime
, sizeof (guint32
));
1246 rem
= keepaliveinterval
% 1000;
1247 keepaliveinterval
/= 1000;
1248 if (keepaliveinterval
== 0 || rem
>= 500)
1249 keepaliveinterval
++;
1251 ret
= setsockopt (((MonoFDHandle
*) sockethandle
)->fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, &keepaliveinterval
, sizeof (guint32
));
1255 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno
));
1256 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1257 return SOCKET_ERROR
;
1260 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1265 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1269 buffer
= inputlen
> 0 ? (gchar
*) g_memdup (input
, inputlen
) : NULL
;
1272 ret
= ioctl (((MonoFDHandle
*) sockethandle
)->fd
, command
, buffer
);
1277 gint errnum
= errno
;
1278 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: WSAIoctl error: %s", __func__
, g_strerror (errno
));
1279 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum
));
1280 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1281 return SOCKET_ERROR
;
1286 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1290 /* We just copy the buffer to the output. Some ioctls
1291 * don't even output any data, but, well...
1293 * NB windows returns WSAEFAULT if outputlen is too small */
1294 inputlen
= (inputlen
> outputlen
) ? outputlen
: inputlen
;
1296 if (inputlen
> 0 && output
!= NULL
)
1297 memcpy (output
, buffer
, inputlen
);
1300 *written
= inputlen
;
1302 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1307 mono_w32socket_close (SOCKET sock
)
1309 if (!mono_fdhandle_close (sock
)) {
1310 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1318 mono_w32socket_set_blocking (SOCKET sock
, gboolean blocking
)
1321 SocketHandle
*sockethandle
;
1324 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1325 mono_w32error_set_last (WSAENOTSOCK
);
1326 return SOCKET_ERROR
;
1329 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1330 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1331 mono_w32error_set_last (WSAENOTSOCK
);
1332 return SOCKET_ERROR
;
1335 /* This works better than ioctl(...FIONBIO...)
1336 * on Linux (it causes connect to return
1337 * EINPROGRESS, but the ioctl doesn't seem to) */
1339 ret
= fcntl (((MonoFDHandle
*) sockethandle
)->fd
, F_GETFL
, 0);
1342 gint errnum
= mono_w32socket_convert_error (errno
);
1343 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: fcntl(F_GETFL) error: %s", __func__
, g_strerror (errno
));
1344 mono_w32socket_set_last_error (errnum
);
1345 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1346 return SOCKET_ERROR
;
1350 ret
= fcntl (((MonoFDHandle
*) sockethandle
)->fd
, F_SETFL
, blocking
? (ret
& (~O_NONBLOCK
)) : (ret
| (O_NONBLOCK
)));
1353 gint errnum
= mono_w32socket_convert_error (errno
);
1354 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: fcntl(F_SETFL) error: %s", __func__
, g_strerror (errno
));
1355 mono_w32socket_set_last_error (errnum
);
1356 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1357 return SOCKET_ERROR
;
1360 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1363 mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED
);
1364 return SOCKET_ERROR
;
1365 #endif /* O_NONBLOCK */
1369 mono_w32socket_get_available (SOCKET sock
, guint64
*amount
)
1371 SocketHandle
*sockethandle
;
1374 if (!mono_fdhandle_lookup_and_ref(sock
, (MonoFDHandle
**) &sockethandle
)) {
1375 mono_w32error_set_last (WSAENOTSOCK
);
1376 return SOCKET_ERROR
;
1379 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1380 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1381 mono_w32error_set_last (WSAENOTSOCK
);
1382 return SOCKET_ERROR
;
1385 #if defined (HOST_DARWIN)
1386 // ioctl (socket, FIONREAD, XXX) returns the size of
1387 // the UDP header as well on Darwin.
1389 // Use getsockopt SO_NREAD instead to get the
1390 // right values for TCP and UDP.
1392 // ai_canonname can be null in some cases on darwin,
1393 // where the runtime assumes it will be the value of
1396 socklen_t optlen
= sizeof (int);
1398 ret
= getsockopt (((MonoFDHandle
*) sockethandle
)->fd
, SOL_SOCKET
, SO_NREAD
, (gulong
*) amount
, &optlen
);
1401 gint errnum
= mono_w32socket_convert_error (errno
);
1402 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: getsockopt error: %s", __func__
, g_strerror (errno
));
1403 mono_w32socket_set_last_error (errnum
);
1404 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1405 return SOCKET_ERROR
;
1409 ret
= ioctl (((MonoFDHandle
*) sockethandle
)->fd
, FIONREAD
, (gulong
*) amount
);
1412 gint errnum
= mono_w32socket_convert_error (errno
);
1413 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_SOCKET
, "%s: ioctl error: %s", __func__
, g_strerror (errno
));
1414 mono_w32socket_set_last_error (errnum
);
1415 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1416 return SOCKET_ERROR
;
1420 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1425 mono_w32socket_set_last_error (gint32 error
)
1427 mono_w32error_set_last (error
);
1431 mono_w32socket_get_last_error (void)
1433 return mono_w32error_get_last ();
1437 mono_w32socket_convert_error (gint error
)
1440 case 0: return ERROR_SUCCESS
;
1441 case EACCES
: return WSAEACCES
;
1443 case EADDRINUSE
: return WSAEADDRINUSE
;
1446 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
1448 #if EAGAIN != EWOULDBLOCK
1449 case EAGAIN
: return WSAEWOULDBLOCK
;
1452 case EALREADY
: return WSAEALREADY
;
1454 case EBADF
: return WSAENOTSOCK
;
1456 case ECONNABORTED
: return WSAENETDOWN
;
1459 case ECONNREFUSED
: return WSAECONNREFUSED
;
1462 case ECONNRESET
: return WSAECONNRESET
;
1464 case EDOM
: return WSAEINVAL
; /* not a precise match, best wecan do. */
1465 case EFAULT
: return WSAEFAULT
;
1467 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
1470 case EINPROGRESS
: return WSAEINPROGRESS
;
1472 case EINTR
: return WSAEINTR
;
1473 case EINVAL
: return WSAEINVAL
;
1474 case EIO
: return WSA_INVALID_HANDLE
; /* not a precise match, best we can do. */
1476 case EISCONN
: return WSAEISCONN
;
1478 case ELOOP
: return WSAELOOP
;
1479 case ENFILE
: return WSAEMFILE
; /* not a precise match, best we can do. */
1480 case EMFILE
: return WSAEMFILE
;
1482 case EMSGSIZE
: return WSAEMSGSIZE
;
1484 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
1486 case ENETUNREACH
: return WSAENETUNREACH
;
1489 case ENOBUFS
: return WSAENOBUFS
; /* not documented */
1491 case ENOMEM
: return WSAENOBUFS
;
1493 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
1496 case ENOSR
: return WSAENETDOWN
;
1499 case ENOTCONN
: return WSAENOTCONN
;
1501 case ENOTDIR
: return WSA_INVALID_PARAMETER
; /* not a precise match, best we can do. */
1503 case ENOTSOCK
: return WSAENOTSOCK
;
1505 case ENOTTY
: return WSAENOTSOCK
;
1507 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
1509 case EPERM
: return WSAEACCES
;
1510 case EPIPE
: return WSAESHUTDOWN
;
1511 #ifdef EPROTONOSUPPORT
1512 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
1515 case ERESTARTSYS
: return WSAENETDOWN
;
1517 /*FIXME: case EROFS: return WSAE????; */
1518 #ifdef ESOCKTNOSUPPORT
1519 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
1522 case ETIMEDOUT
: return WSAETIMEDOUT
;
1525 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
1527 #ifdef EADDRNOTAVAIL
1528 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
1530 /* This might happen with unix sockets */
1531 case ENOENT
: return WSAECONNREFUSED
;
1533 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
1536 case EHOSTDOWN
: return WSAEHOSTDOWN
;
1539 case ENETDOWN
: return WSAENETDOWN
;
1541 case ENODEV
: return WSAENETDOWN
;
1543 case EPROTOTYPE
: return WSAEPROTOTYPE
;
1546 case ENXIO
: return WSAENXIO
;
1549 case ENONET
: return WSAENETUNREACH
;
1552 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__
, error
, g_strerror (error
));
1556 #ifndef ENABLE_NETCORE
1558 ves_icall_System_Net_Sockets_Socket_SupportPortReuse_icall (MonoProtocolType proto
)
1560 #if defined (SO_REUSEPORT)
1564 /* Linux always supports double binding for UDP, even on older kernels. */
1565 if (proto
== ProtocolType_Udp
)
1574 mono_w32socket_duplicate (gpointer handle
, gint32 targetProcessId
, gpointer
*duplicate_handle
)
1576 SocketHandle
*sockethandle
;
1578 if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle
), (MonoFDHandle
**) &sockethandle
)) {
1579 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1583 if (((MonoFDHandle
*) sockethandle
)->type
!= MONO_FDTYPE_SOCKET
) {
1584 mono_fdhandle_unref ((MonoFDHandle
*) sockethandle
);
1585 mono_w32error_set_last (ERROR_INVALID_HANDLE
);
1589 *duplicate_handle
= handle
;