2 * sockets.c: Socket handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
12 #ifndef DISABLE_SOCKETS
18 #include <sys/types.h>
19 #include <sys/socket.h>
23 #ifdef HAVE_SYS_IOCTL_H
24 # include <sys/ioctl.h>
26 #ifdef HAVE_SYS_FILIO_H
27 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
29 #ifdef HAVE_SYS_SOCKIO_H
30 #include <sys/sockio.h> /* defines SIOCATMARK */
35 #ifndef HAVE_MSG_NOSIGNAL
39 #include <mono/io-layer/wapi.h>
40 #include <mono/io-layer/wapi-private.h>
41 #include <mono/io-layer/socket-private.h>
42 #include <mono/io-layer/handles-private.h>
43 #include <mono/io-layer/socket-wrappers.h>
44 #include <mono/io-layer/io-trace.h>
45 #include <mono/utils/mono-poll.h>
46 #include <mono/utils/mono-once.h>
47 #include <mono/utils/mono-logger-internals.h>
49 #include <netinet/in.h>
50 #include <netinet/tcp.h>
51 #include <arpa/inet.h>
52 #ifdef HAVE_SYS_SENDFILE_H
53 #include <sys/sendfile.h>
59 static guint32 in_cleanup = 0;
61 static void socket_close (gpointer handle, gpointer data);
62 static void socket_details (gpointer data);
63 static const gchar* socket_typename (void);
64 static gsize socket_typesize (void);
66 static WapiHandleOps _wapi_socket_ops = {
67 socket_close, /* close */
71 NULL, /* special_wait */
73 socket_details, /* details */
74 socket_typename, /* typename */
75 socket_typesize, /* typesize */
79 _wapi_socket_init (void)
81 _wapi_handle_register_ops (WAPI_HANDLE_SOCKET, &_wapi_socket_ops);
84 static void socket_close (gpointer handle, gpointer data)
87 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
89 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle);
91 /* Shutdown the socket for reading, to interrupt any potential
92 * receives that may be blocking for data. See bug 75705.
94 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
97 ret = close (GPOINTER_TO_UINT(handle));
98 } while (ret == -1 && errno == EINTR &&
99 !_wapi_thread_cur_apc_pending ());
103 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, strerror (errno));
104 errnum = errno_to_WSA (errnum, __func__);
106 WSASetLastError (errnum);
110 socket_handle->saved_error = 0;
113 static void socket_details (gpointer data)
115 /* FIXME: do something */
118 static const gchar* socket_typename (void)
123 static gsize socket_typesize (void)
125 return sizeof (struct _WapiHandle_socket);
129 cleanup_close (gpointer handle, gpointer data, gpointer user_data)
131 if (_wapi_handle_type (handle) == WAPI_HANDLE_SOCKET)
132 _wapi_handle_ops_close (handle, data);
137 void _wapi_cleanup_networking(void)
139 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
142 _wapi_handle_foreach (cleanup_close, NULL);
146 void WSASetLastError(int error)
148 SetLastError (error);
151 int WSAGetLastError(void)
153 return(GetLastError ());
156 int closesocket(guint32 fd)
158 gpointer handle = GUINT_TO_POINTER (fd);
160 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
161 WSASetLastError (WSAENOTSOCK);
165 _wapi_handle_unref (handle);
169 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
171 gpointer handle = GUINT_TO_POINTER (fd);
173 struct _WapiHandle_socket *socket_handle;
174 struct _WapiHandle_socket new_socket_handle = {0};
178 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
179 WSASetLastError (WSAEFAULT);
180 return(INVALID_SOCKET);
183 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
184 WSASetLastError (WSAENOTSOCK);
185 return(INVALID_SOCKET);
188 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
189 (gpointer *)&socket_handle);
191 g_warning ("%s: error looking up socket handle %p",
193 WSASetLastError (WSAENOTSOCK);
194 return(INVALID_SOCKET);
198 new_fd = accept (fd, addr, addrlen);
199 } while (new_fd == -1 && errno == EINTR &&
200 !_wapi_thread_cur_apc_pending());
204 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, strerror(errno));
206 errnum = errno_to_WSA (errnum, __func__);
207 WSASetLastError (errnum);
209 return(INVALID_SOCKET);
212 if (new_fd >= _wapi_fd_reserve) {
213 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
215 WSASetLastError (WSASYSCALLFAILURE);
219 return(INVALID_SOCKET);
222 new_socket_handle.domain = socket_handle->domain;
223 new_socket_handle.type = socket_handle->type;
224 new_socket_handle.protocol = socket_handle->protocol;
225 new_socket_handle.still_readable = 1;
227 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
229 if(new_handle == _WAPI_HANDLE_INVALID) {
230 g_warning ("%s: error creating socket handle", __func__);
231 WSASetLastError (ERROR_GEN_FAILURE);
232 return(INVALID_SOCKET);
235 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
236 __func__, new_handle);
241 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
243 gpointer handle = GUINT_TO_POINTER (fd);
246 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
247 WSASetLastError (WSAENOTSOCK);
248 return(SOCKET_ERROR);
251 ret = bind (fd, my_addr, addrlen);
254 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, strerror(errno));
255 errnum = errno_to_WSA (errnum, __func__);
256 WSASetLastError (errnum);
258 return(SOCKET_ERROR);
263 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
266 gpointer handle = GUINT_TO_POINTER (fd);
267 struct _WapiHandle_socket *socket_handle;
271 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
272 WSASetLastError (WSAENOTSOCK);
273 return(SOCKET_ERROR);
276 if (connect (fd, serv_addr, addrlen) == -1) {
283 if (errno != EINTR) {
284 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
287 errnum = errno_to_WSA (errnum, __func__);
288 if (errnum == WSAEINPROGRESS)
289 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
291 WSASetLastError (errnum);
294 * On solaris x86 getsockopt (SO_ERROR) is not set after
295 * connect () fails so we need to save this error.
297 * But don't do this for EWOULDBLOCK (bug 317315)
299 if (errnum != WSAEWOULDBLOCK) {
300 ok = _wapi_lookup_handle (handle,
302 (gpointer *)&socket_handle);
304 /* ECONNRESET means the socket was closed by another thread */
305 /* Async close on mac raises ECONNABORTED. */
306 if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
307 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
309 socket_handle->saved_error = errnum;
312 return(SOCKET_ERROR);
316 fds.events = MONO_POLLOUT;
317 while (mono_poll (&fds, 1, -1) == -1 &&
318 !_wapi_thread_cur_apc_pending ()) {
319 if (errno != EINTR) {
320 errnum = errno_to_WSA (errno, __func__);
322 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s",
323 __func__, strerror (errno));
325 WSASetLastError (errnum);
326 return(SOCKET_ERROR);
330 len = sizeof(so_error);
331 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
333 errnum = errno_to_WSA (errno, __func__);
335 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s",
336 __func__, strerror (errno));
338 WSASetLastError (errnum);
339 return(SOCKET_ERROR);
343 errnum = errno_to_WSA (so_error, __func__);
345 /* Need to save this socket error */
346 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
347 (gpointer *)&socket_handle);
349 g_warning ("%s: error looking up socket handle %p", __func__, handle);
351 socket_handle->saved_error = errnum;
354 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
355 __func__, strerror (so_error));
357 WSASetLastError (errnum);
358 return(SOCKET_ERROR);
365 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
367 gpointer handle = GUINT_TO_POINTER (fd);
370 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
371 WSASetLastError (WSAENOTSOCK);
372 return(SOCKET_ERROR);
375 ret = getpeername (fd, name, namelen);
378 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__,
381 errnum = errno_to_WSA (errnum, __func__);
382 WSASetLastError (errnum);
384 return(SOCKET_ERROR);
390 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
392 gpointer handle = GUINT_TO_POINTER (fd);
395 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
396 WSASetLastError (WSAENOTSOCK);
397 return(SOCKET_ERROR);
400 ret = getsockname (fd, name, namelen);
403 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__,
406 errnum = errno_to_WSA (errnum, __func__);
407 WSASetLastError (errnum);
409 return(SOCKET_ERROR);
415 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
418 gpointer handle = GUINT_TO_POINTER (fd);
422 struct _WapiHandle_socket *socket_handle;
425 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
426 WSASetLastError (WSAENOTSOCK);
427 return(SOCKET_ERROR);
431 if (level == SOL_SOCKET &&
432 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
434 *optlen = sizeof (tv);
437 ret = getsockopt (fd, level, optname, tmp_val, optlen);
440 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__,
443 errnum = errno_to_WSA (errnum, __func__);
444 WSASetLastError (errnum);
446 return(SOCKET_ERROR);
449 if (level == SOL_SOCKET &&
450 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
451 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
452 *optlen = sizeof (int);
455 if (optname == SO_ERROR) {
456 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
457 (gpointer *)&socket_handle);
459 g_warning ("%s: error looking up socket handle %p",
462 /* can't extract the last error */
463 *((int *) optval) = errno_to_WSA (*((int *)optval),
466 if (*((int *)optval) != 0) {
467 *((int *) optval) = errno_to_WSA (*((int *)optval),
469 socket_handle->saved_error = *((int *)optval);
471 *((int *)optval) = socket_handle->saved_error;
479 int _wapi_listen(guint32 fd, int backlog)
481 gpointer handle = GUINT_TO_POINTER (fd);
484 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
485 WSASetLastError (WSAENOTSOCK);
486 return(SOCKET_ERROR);
489 ret = listen (fd, backlog);
492 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, strerror (errno));
494 errnum = errno_to_WSA (errnum, __func__);
495 WSASetLastError (errnum);
497 return(SOCKET_ERROR);
503 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
505 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
508 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
509 struct sockaddr *from, socklen_t *fromlen)
511 gpointer handle = GUINT_TO_POINTER (fd);
512 struct _WapiHandle_socket *socket_handle;
516 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
517 WSASetLastError (WSAENOTSOCK);
518 return(SOCKET_ERROR);
522 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
523 } while (ret == -1 && errno == EINTR &&
524 !_wapi_thread_cur_apc_pending ());
526 if (ret == 0 && len > 0) {
527 /* According to the Linux man page, recvfrom only
528 * returns 0 when the socket has been shut down
529 * cleanly. Turn this into an EINTR to simulate win32
530 * behaviour of returning EINTR when a socket is
531 * closed while the recvfrom is blocking (we use a
532 * shutdown() in socket_close() to trigger this.) See
535 /* Distinguish between the socket being shut down at
536 * the local or remote ends, and reads that request 0
540 /* If this returns FALSE, it means the socket has been
541 * closed locally. If it returns TRUE, but
542 * still_readable != 1 then shutdown
543 * (SHUT_RD|SHUT_RDWR) has been called locally.
545 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
546 (gpointer *)&socket_handle);
547 if (ok == FALSE || socket_handle->still_readable != 1) {
555 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, strerror(errno));
557 errnum = errno_to_WSA (errnum, __func__);
558 WSASetLastError (errnum);
560 return(SOCKET_ERROR);
566 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
568 gpointer handle = GUINT_TO_POINTER (fd);
569 struct _WapiHandle_socket *socket_handle;
573 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
574 WSASetLastError (WSAENOTSOCK);
575 return(SOCKET_ERROR);
579 ret = recvmsg (fd, msg, recv_flags);
580 } while (ret == -1 && errno == EINTR &&
581 !_wapi_thread_cur_apc_pending ());
584 /* see _wapi_recvfrom */
585 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
586 (gpointer *)&socket_handle);
587 if (ok == FALSE || socket_handle->still_readable != 1) {
595 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, strerror(errno));
597 errnum = errno_to_WSA (errnum, __func__);
598 WSASetLastError (errnum);
600 return(SOCKET_ERROR);
605 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
607 gpointer handle = GUINT_TO_POINTER (fd);
610 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
611 WSASetLastError (WSAENOTSOCK);
612 return(SOCKET_ERROR);
616 ret = send (fd, msg, len, send_flags);
617 } while (ret == -1 && errno == EINTR &&
618 !_wapi_thread_cur_apc_pending ());
622 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno));
625 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
626 * a blocking socket. See bug #599488 */
627 if (errnum == EAGAIN) {
628 ret = fcntl (fd, F_GETFL, 0);
629 if (ret != -1 && (ret & O_NONBLOCK) == 0)
632 #endif /* O_NONBLOCK */
633 errnum = errno_to_WSA (errnum, __func__);
634 WSASetLastError (errnum);
636 return(SOCKET_ERROR);
641 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
642 const struct sockaddr *to, socklen_t tolen)
644 gpointer handle = GUINT_TO_POINTER (fd);
647 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
648 WSASetLastError (WSAENOTSOCK);
649 return(SOCKET_ERROR);
653 ret = sendto (fd, msg, len, send_flags, to, tolen);
654 } while (ret == -1 && errno == EINTR &&
655 !_wapi_thread_cur_apc_pending ());
659 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno));
661 errnum = errno_to_WSA (errnum, __func__);
662 WSASetLastError (errnum);
664 return(SOCKET_ERROR);
670 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
672 gpointer handle = GUINT_TO_POINTER (fd);
675 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
676 WSASetLastError (WSAENOTSOCK);
677 return(SOCKET_ERROR);
681 ret = sendmsg (fd, msg, send_flags);
682 } while (ret == -1 && errno == EINTR &&
683 !_wapi_thread_cur_apc_pending ());
687 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, strerror (errno));
689 errnum = errno_to_WSA (errnum, __func__);
690 WSASetLastError (errnum);
692 return(SOCKET_ERROR);
697 int _wapi_setsockopt(guint32 fd, int level, int optname,
698 const void *optval, socklen_t optlen)
700 gpointer handle = GUINT_TO_POINTER (fd);
703 #if defined (__linux__)
704 /* This has its address taken so it cannot be moved to the if block which uses it */
709 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
710 WSASetLastError (WSAENOTSOCK);
711 return(SOCKET_ERROR);
715 if (level == SOL_SOCKET &&
716 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
717 int ms = *((int *) optval);
718 tv.tv_sec = ms / 1000;
719 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
721 optlen = sizeof (tv);
723 #if defined (__linux__)
724 else if (level == SOL_SOCKET &&
725 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
726 /* According to socket(7) the Linux kernel doubles the
727 * buffer sizes "to allow space for bookkeeping
730 bufsize = *((int *) optval);
737 ret = setsockopt (fd, level, optname, tmp_val, optlen);
740 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__,
743 errnum = errno_to_WSA (errnum, __func__);
744 WSASetLastError (errnum);
746 return(SOCKET_ERROR);
749 #if defined (SO_REUSEPORT)
750 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
751 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
753 socklen_t type_len = sizeof (type);
755 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
756 if (type == SOCK_DGRAM || type == SOCK_STREAM)
757 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
765 int _wapi_shutdown(guint32 fd, int how)
767 struct _WapiHandle_socket *socket_handle;
769 gpointer handle = GUINT_TO_POINTER (fd);
772 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
773 WSASetLastError (WSAENOTSOCK);
774 return(SOCKET_ERROR);
777 if (how == SHUT_RD ||
779 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
780 (gpointer *)&socket_handle);
782 g_warning ("%s: error looking up socket handle %p",
784 WSASetLastError (WSAENOTSOCK);
785 return(SOCKET_ERROR);
788 socket_handle->still_readable = 0;
791 ret = shutdown (fd, how);
794 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__,
797 errnum = errno_to_WSA (errnum, __func__);
798 WSASetLastError (errnum);
800 return(SOCKET_ERROR);
806 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
807 guint32 unused2, guint32 unused3)
809 struct _WapiHandle_socket socket_handle = {0};
813 socket_handle.domain = domain;
814 socket_handle.type = type;
815 socket_handle.protocol = protocol;
816 socket_handle.still_readable = 1;
818 fd = socket (domain, type, protocol);
819 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
821 /* Retry with protocol == 4 (see bug #54565) */
822 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
823 socket_handle.protocol = 4;
824 fd = socket (AF_INET, SOCK_RAW, 4);
829 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno));
830 errnum = errno_to_WSA (errnum, __func__);
831 WSASetLastError (errnum);
833 return(INVALID_SOCKET);
836 if (fd >= _wapi_fd_reserve) {
837 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
838 __func__, fd, _wapi_fd_reserve);
840 WSASetLastError (WSASYSCALLFAILURE);
843 return(INVALID_SOCKET);
846 /* .net seems to set this by default for SOCK_STREAM, not for
847 * SOCK_DGRAM (see bug #36322)
848 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
850 * It seems winsock has a rather different idea of what
851 * SO_REUSEADDR means. If it's set, then a new socket can be
852 * bound over an existing listening socket. There's a new
853 * windows-specific option called SO_EXCLUSIVEADDRUSE but
854 * using that means the socket MUST be closed properly, or a
855 * denial of service can occur. Luckily for us, winsock
856 * behaves as though any other system would when SO_REUSEADDR
857 * is true, so we don't need to do anything else here. See
859 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
864 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true_,
869 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
871 errnum = errno_to_WSA (errnum, __func__);
872 WSASetLastError (errnum);
876 return(INVALID_SOCKET);
881 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
882 if (handle == _WAPI_HANDLE_INVALID) {
883 g_warning ("%s: error creating socket handle", __func__);
884 WSASetLastError (WSASYSCALLFAILURE);
886 return(INVALID_SOCKET);
889 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle);
894 static gboolean socket_disconnect (guint32 fd)
896 struct _WapiHandle_socket *socket_handle;
898 gpointer handle = GUINT_TO_POINTER (fd);
901 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
902 (gpointer *)&socket_handle);
904 g_warning ("%s: error looking up socket handle %p", __func__,
906 WSASetLastError (WSAENOTSOCK);
910 newsock = socket (socket_handle->domain, socket_handle->type,
911 socket_handle->protocol);
915 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno));
917 errnum = errno_to_WSA (errnum, __func__);
918 WSASetLastError (errnum);
923 /* According to Stevens "Advanced Programming in the UNIX
924 * Environment: UNIX File I/O" dup2() is atomic so there
925 * should not be a race condition between the old fd being
926 * closed and the new socket fd being copied over
929 ret = dup2 (newsock, fd);
930 } while (ret == -1 && errno == EAGAIN);
935 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, strerror (errno));
937 errnum = errno_to_WSA (errnum, __func__);
938 WSASetLastError (errnum);
948 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
949 guint32 flags, guint32 reserved)
951 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, fd);
954 WSASetLastError (WSAEINVAL);
958 /* We could check the socket type here and fail unless its
959 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
960 * if we really wanted to
963 return(socket_disconnect (fd));
966 #define SF_BUFFER_SIZE 16384
968 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
970 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
971 gint file = GPOINTER_TO_INT (fd);
977 n = fstat (file, &statbuf);
980 errnum = errno_to_WSA (errnum, __func__);
981 WSASetLastError (errnum);
986 res = sendfile (socket, file, NULL, statbuf.st_size);
987 #elif defined(DARWIN)
988 /* TODO: header/tail could be sent in the 5th argument */
989 /* TODO: Might not send the entire file for non-blocking sockets */
990 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
992 } while (res != -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
995 errnum = errno_to_WSA (errnum, __func__);
996 WSASetLastError (errnum);
1000 /* Default implementation */
1001 gint file = GPOINTER_TO_INT (fd);
1005 buffer = g_malloc (SF_BUFFER_SIZE);
1008 n = read (file, buffer, SF_BUFFER_SIZE);
1009 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1014 return 0; /* We're done reading */
1017 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1018 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1019 } while (n != -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1022 gint errnum = errno;
1023 errnum = errno_to_WSA (errnum, __func__);
1024 WSASetLastError (errnum);
1026 return SOCKET_ERROR;
1034 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1035 WapiTransmitFileBuffers *buffers, guint32 flags)
1037 gpointer sock = GUINT_TO_POINTER (socket);
1040 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1041 WSASetLastError (WSAENOTSOCK);
1045 /* Write the header */
1046 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1047 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1048 if (ret == SOCKET_ERROR)
1052 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1053 if (ret == SOCKET_ERROR)
1056 /* Write the tail */
1057 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1058 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1059 if (ret == SOCKET_ERROR)
1063 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1064 closesocket (socket);
1073 } extension_functions[] = {
1074 {WSAID_DISCONNECTEX, wapi_disconnectex},
1075 {WSAID_TRANSMITFILE, TransmitFile},
1080 WSAIoctl (guint32 fd, gint32 command,
1081 gchar *input, gint i_len,
1082 gchar *output, gint o_len, glong *written,
1083 void *unused1, void *unused2)
1085 gpointer handle = GUINT_TO_POINTER (fd);
1087 gchar *buffer = NULL;
1089 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1090 WSASetLastError (WSAENOTSOCK);
1091 return SOCKET_ERROR;
1094 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1096 WapiGuid *guid = (WapiGuid *)input;
1098 if (i_len < sizeof(WapiGuid)) {
1099 /* As far as I can tell, windows doesn't
1100 * actually set an error here...
1102 WSASetLastError (WSAEINVAL);
1103 return(SOCKET_ERROR);
1106 if (o_len < sizeof(gpointer)) {
1108 WSASetLastError (WSAEINVAL);
1109 return(SOCKET_ERROR);
1112 if (output == NULL) {
1114 WSASetLastError (WSAEINVAL);
1115 return(SOCKET_ERROR);
1118 while(extension_functions[i].func != NULL) {
1119 if (!memcmp (guid, &extension_functions[i].guid,
1120 sizeof(WapiGuid))) {
1121 memcpy (output, &extension_functions[i].func,
1123 *written = sizeof(gpointer);
1130 WSASetLastError (WSAEINVAL);
1131 return(SOCKET_ERROR);
1134 if (command == SIO_KEEPALIVE_VALS) {
1136 uint32_t keepalivetime;
1137 uint32_t keepaliveinterval;
1139 if (i_len < (3 * sizeof (uint32_t))) {
1140 WSASetLastError (WSAEINVAL);
1141 return SOCKET_ERROR;
1143 memcpy (&onoff, input, sizeof (uint32_t));
1144 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1145 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1146 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1148 gint errnum = errno;
1149 errnum = errno_to_WSA (errnum, __func__);
1150 WSASetLastError (errnum);
1151 return SOCKET_ERROR;
1154 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1155 /* Values are in ms, but we need s */
1158 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1159 rem = keepalivetime % 1000;
1160 keepalivetime /= 1000;
1161 if (keepalivetime == 0 || rem >= 500)
1163 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1165 rem = keepaliveinterval % 1000;
1166 keepaliveinterval /= 1000;
1167 if (keepaliveinterval == 0 || rem >= 500)
1168 keepaliveinterval++;
1169 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1172 gint errnum = errno;
1173 errnum = errno_to_WSA (errnum, __func__);
1174 WSASetLastError (errnum);
1175 return SOCKET_ERROR;
1184 buffer = (char *)g_memdup (input, i_len);
1187 ret = ioctl (fd, command, buffer);
1189 gint errnum = errno;
1190 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__,
1193 errnum = errno_to_WSA (errnum, __func__);
1194 WSASetLastError (errnum);
1197 return(SOCKET_ERROR);
1200 if (buffer == NULL) {
1203 /* We just copy the buffer to the output. Some ioctls
1204 * don't even output any data, but, well...
1206 * NB windows returns WSAEFAULT if o_len is too small
1208 i_len = (i_len > o_len) ? o_len : i_len;
1210 if (i_len > 0 && output != NULL) {
1211 memcpy (output, buffer, i_len);
1221 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1222 int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
1224 gpointer handle = GUINT_TO_POINTER (fd);
1227 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1228 WSASetLastError (WSAENOTSOCK);
1229 return(SOCKET_ERROR);
1235 /* This works better than ioctl(...FIONBIO...)
1236 * on Linux (it causes connect to return
1237 * EINPROGRESS, but the ioctl doesn't seem to)
1239 ret = fcntl(fd, F_GETFL, 0);
1241 if (*(gboolean *)arg) {
1246 ret = fcntl(fd, F_SETFL, ret);
1249 #endif /* O_NONBLOCK */
1250 /* Unused in Mono */
1252 ret = ioctl (fd, command, arg);
1257 #if defined (PLATFORM_MACOSX)
1259 // ioctl (fd, FIONREAD, XXX) returns the size of
1260 // the UDP header as well on
1263 // Use getsockopt SO_NREAD instead to get the
1264 // right values for TCP and UDP.
1266 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1267 // be the value of the ip buffer.
1269 socklen_t optlen = sizeof (int);
1270 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1272 ret = ioctl (fd, command, arg);
1277 WSASetLastError (WSAEINVAL);
1278 return(SOCKET_ERROR);
1282 gint errnum = errno;
1283 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, strerror (errno));
1285 errnum = errno_to_WSA (errnum, __func__);
1286 WSASetLastError (errnum);
1288 return(SOCKET_ERROR);
1294 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1295 fd_set *exceptfds, struct timeval *timeout)
1299 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1300 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1301 (writefds && FD_ISSET (maxfd, writefds)) ||
1302 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1308 WSASetLastError (WSAEINVAL);
1309 return(SOCKET_ERROR);
1313 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1315 } while (ret == -1 && errno == EINTR &&
1316 !_wapi_thread_cur_apc_pending ());
1319 gint errnum = errno;
1320 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: select error: %s", __func__, strerror (errno));
1321 errnum = errno_to_WSA (errnum, __func__);
1322 WSASetLastError (errnum);
1324 return(SOCKET_ERROR);
1330 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1332 gpointer handle = GUINT_TO_POINTER (fd);
1334 if (fd >= FD_SETSIZE) {
1335 WSASetLastError (WSAEINVAL);
1339 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1340 WSASetLastError (WSAENOTSOCK);
1347 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1349 gpointer handle = GUINT_TO_POINTER (fd);
1351 if (fd >= FD_SETSIZE) {
1352 WSASetLastError (WSAEINVAL);
1356 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1357 WSASetLastError (WSAENOTSOCK);
1361 return(FD_ISSET (fd, set));
1364 void _wapi_FD_SET(guint32 fd, fd_set *set)
1366 gpointer handle = GUINT_TO_POINTER (fd);
1368 if (fd >= FD_SETSIZE) {
1369 WSASetLastError (WSAEINVAL);
1373 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1374 WSASetLastError (WSAENOTSOCK);
1383 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1387 memset (hdr, 0, sizeof (struct msghdr));
1388 hdr->msg_iovlen = count;
1389 hdr->msg_iov = g_new0 (struct iovec, count);
1390 for (i = 0; i < count; i++) {
1391 hdr->msg_iov [i].iov_base = buffers [i].buf;
1392 hdr->msg_iov [i].iov_len = buffers [i].len;
1397 msghdr_iov_free (struct msghdr *hdr)
1399 g_free (hdr->msg_iov);
1402 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1403 guint32 *flags, WapiOverlapped *overlapped,
1404 WapiOverlappedCB *complete)
1409 g_assert (overlapped == NULL);
1410 g_assert (complete == NULL);
1412 wsabuf_to_msghdr (buffers, count, &hdr);
1413 ret = _wapi_recvmsg (fd, &hdr, *flags);
1414 msghdr_iov_free (&hdr);
1416 if(ret == SOCKET_ERROR) {
1421 *flags = hdr.msg_flags;
1426 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1427 guint32 flags, WapiOverlapped *overlapped,
1428 WapiOverlappedCB *complete)
1433 g_assert (overlapped == NULL);
1434 g_assert (complete == NULL);
1436 wsabuf_to_msghdr (buffers, count, &hdr);
1437 ret = _wapi_sendmsg (fd, &hdr, flags);
1438 msghdr_iov_free (&hdr);
1440 if(ret == SOCKET_ERROR)
1447 #endif /* ifndef DISABLE_SOCKETS */