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);
63 struct _WapiHandleOps _wapi_socket_ops = {
64 socket_close, /* close */
68 NULL, /* special_wait */
72 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
74 static void socket_ops_init (void)
76 /* No capabilities to register */
79 static void socket_close (gpointer handle, gpointer data)
82 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
84 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle);
86 /* Shutdown the socket for reading, to interrupt any potential
87 * receives that may be blocking for data. See bug 75705.
89 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
92 ret = close (GPOINTER_TO_UINT(handle));
93 } while (ret == -1 && errno == EINTR &&
94 !_wapi_thread_cur_apc_pending ());
98 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, strerror (errno));
99 errnum = errno_to_WSA (errnum, __func__);
101 WSASetLastError (errnum);
105 socket_handle->saved_error = 0;
109 cleanup_close (gpointer handle, gpointer data)
111 _wapi_handle_ops_close (handle, NULL);
115 void _wapi_cleanup_networking(void)
117 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
120 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
124 void WSASetLastError(int error)
126 SetLastError (error);
129 int WSAGetLastError(void)
131 return(GetLastError ());
134 int closesocket(guint32 fd)
136 gpointer handle = GUINT_TO_POINTER (fd);
138 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
139 WSASetLastError (WSAENOTSOCK);
143 _wapi_handle_unref (handle);
147 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
149 gpointer handle = GUINT_TO_POINTER (fd);
151 struct _WapiHandle_socket *socket_handle;
152 struct _WapiHandle_socket new_socket_handle = {0};
156 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
157 WSASetLastError (WSAEFAULT);
158 return(INVALID_SOCKET);
161 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
162 WSASetLastError (WSAENOTSOCK);
163 return(INVALID_SOCKET);
166 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
167 (gpointer *)&socket_handle);
169 g_warning ("%s: error looking up socket handle %p",
171 WSASetLastError (WSAENOTSOCK);
172 return(INVALID_SOCKET);
176 new_fd = accept (fd, addr, addrlen);
177 } while (new_fd == -1 && errno == EINTR &&
178 !_wapi_thread_cur_apc_pending());
182 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, strerror(errno));
184 errnum = errno_to_WSA (errnum, __func__);
185 WSASetLastError (errnum);
187 return(INVALID_SOCKET);
190 if (new_fd >= _wapi_fd_reserve) {
191 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
193 WSASetLastError (WSASYSCALLFAILURE);
197 return(INVALID_SOCKET);
200 new_socket_handle.domain = socket_handle->domain;
201 new_socket_handle.type = socket_handle->type;
202 new_socket_handle.protocol = socket_handle->protocol;
203 new_socket_handle.still_readable = 1;
205 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
207 if(new_handle == _WAPI_HANDLE_INVALID) {
208 g_warning ("%s: error creating socket handle", __func__);
209 WSASetLastError (ERROR_GEN_FAILURE);
210 return(INVALID_SOCKET);
213 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
214 __func__, new_handle);
219 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
221 gpointer handle = GUINT_TO_POINTER (fd);
224 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
225 WSASetLastError (WSAENOTSOCK);
226 return(SOCKET_ERROR);
229 ret = bind (fd, my_addr, addrlen);
232 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, strerror(errno));
233 errnum = errno_to_WSA (errnum, __func__);
234 WSASetLastError (errnum);
236 return(SOCKET_ERROR);
241 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
244 gpointer handle = GUINT_TO_POINTER (fd);
245 struct _WapiHandle_socket *socket_handle;
249 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
250 WSASetLastError (WSAENOTSOCK);
251 return(SOCKET_ERROR);
254 if (connect (fd, serv_addr, addrlen) == -1) {
261 if (errno != EINTR) {
262 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
265 errnum = errno_to_WSA (errnum, __func__);
266 if (errnum == WSAEINPROGRESS)
267 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
269 WSASetLastError (errnum);
272 * On solaris x86 getsockopt (SO_ERROR) is not set after
273 * connect () fails so we need to save this error.
275 * But don't do this for EWOULDBLOCK (bug 317315)
277 if (errnum != WSAEWOULDBLOCK) {
278 ok = _wapi_lookup_handle (handle,
280 (gpointer *)&socket_handle);
282 /* ECONNRESET means the socket was closed by another thread */
283 /* Async close on mac raises ECONNABORTED. */
284 if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
285 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
287 socket_handle->saved_error = errnum;
290 return(SOCKET_ERROR);
294 fds.events = MONO_POLLOUT;
295 while (mono_poll (&fds, 1, -1) == -1 &&
296 !_wapi_thread_cur_apc_pending ()) {
297 if (errno != EINTR) {
298 errnum = errno_to_WSA (errno, __func__);
300 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s",
301 __func__, strerror (errno));
303 WSASetLastError (errnum);
304 return(SOCKET_ERROR);
308 len = sizeof(so_error);
309 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
311 errnum = errno_to_WSA (errno, __func__);
313 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s",
314 __func__, strerror (errno));
316 WSASetLastError (errnum);
317 return(SOCKET_ERROR);
321 errnum = errno_to_WSA (so_error, __func__);
323 /* Need to save this socket error */
324 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
325 (gpointer *)&socket_handle);
327 g_warning ("%s: error looking up socket handle %p", __func__, handle);
329 socket_handle->saved_error = errnum;
332 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
333 __func__, strerror (so_error));
335 WSASetLastError (errnum);
336 return(SOCKET_ERROR);
343 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
345 gpointer handle = GUINT_TO_POINTER (fd);
348 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
349 WSASetLastError (WSAENOTSOCK);
350 return(SOCKET_ERROR);
353 ret = getpeername (fd, name, namelen);
356 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__,
359 errnum = errno_to_WSA (errnum, __func__);
360 WSASetLastError (errnum);
362 return(SOCKET_ERROR);
368 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
370 gpointer handle = GUINT_TO_POINTER (fd);
373 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
374 WSASetLastError (WSAENOTSOCK);
375 return(SOCKET_ERROR);
378 ret = getsockname (fd, name, namelen);
381 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__,
384 errnum = errno_to_WSA (errnum, __func__);
385 WSASetLastError (errnum);
387 return(SOCKET_ERROR);
393 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
396 gpointer handle = GUINT_TO_POINTER (fd);
400 struct _WapiHandle_socket *socket_handle;
403 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
404 WSASetLastError (WSAENOTSOCK);
405 return(SOCKET_ERROR);
409 if (level == SOL_SOCKET &&
410 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
412 *optlen = sizeof (tv);
415 ret = getsockopt (fd, level, optname, tmp_val, optlen);
418 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__,
421 errnum = errno_to_WSA (errnum, __func__);
422 WSASetLastError (errnum);
424 return(SOCKET_ERROR);
427 if (level == SOL_SOCKET &&
428 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
429 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
430 *optlen = sizeof (int);
433 if (optname == SO_ERROR) {
434 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
435 (gpointer *)&socket_handle);
437 g_warning ("%s: error looking up socket handle %p",
440 /* can't extract the last error */
441 *((int *) optval) = errno_to_WSA (*((int *)optval),
444 if (*((int *)optval) != 0) {
445 *((int *) optval) = errno_to_WSA (*((int *)optval),
447 socket_handle->saved_error = *((int *)optval);
449 *((int *)optval) = socket_handle->saved_error;
457 int _wapi_listen(guint32 fd, int backlog)
459 gpointer handle = GUINT_TO_POINTER (fd);
462 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
463 WSASetLastError (WSAENOTSOCK);
464 return(SOCKET_ERROR);
467 ret = listen (fd, backlog);
470 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, strerror (errno));
472 errnum = errno_to_WSA (errnum, __func__);
473 WSASetLastError (errnum);
475 return(SOCKET_ERROR);
481 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
483 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
486 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
487 struct sockaddr *from, socklen_t *fromlen)
489 gpointer handle = GUINT_TO_POINTER (fd);
490 struct _WapiHandle_socket *socket_handle;
494 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
495 WSASetLastError (WSAENOTSOCK);
496 return(SOCKET_ERROR);
500 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
501 } while (ret == -1 && errno == EINTR &&
502 !_wapi_thread_cur_apc_pending ());
504 if (ret == 0 && len > 0) {
505 /* According to the Linux man page, recvfrom only
506 * returns 0 when the socket has been shut down
507 * cleanly. Turn this into an EINTR to simulate win32
508 * behaviour of returning EINTR when a socket is
509 * closed while the recvfrom is blocking (we use a
510 * shutdown() in socket_close() to trigger this.) See
513 /* Distinguish between the socket being shut down at
514 * the local or remote ends, and reads that request 0
518 /* If this returns FALSE, it means the socket has been
519 * closed locally. If it returns TRUE, but
520 * still_readable != 1 then shutdown
521 * (SHUT_RD|SHUT_RDWR) has been called locally.
523 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
524 (gpointer *)&socket_handle);
525 if (ok == FALSE || socket_handle->still_readable != 1) {
533 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, strerror(errno));
535 errnum = errno_to_WSA (errnum, __func__);
536 WSASetLastError (errnum);
538 return(SOCKET_ERROR);
544 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
546 gpointer handle = GUINT_TO_POINTER (fd);
547 struct _WapiHandle_socket *socket_handle;
551 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
552 WSASetLastError (WSAENOTSOCK);
553 return(SOCKET_ERROR);
557 ret = recvmsg (fd, msg, recv_flags);
558 } while (ret == -1 && errno == EINTR &&
559 !_wapi_thread_cur_apc_pending ());
562 /* see _wapi_recvfrom */
563 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
564 (gpointer *)&socket_handle);
565 if (ok == FALSE || socket_handle->still_readable != 1) {
573 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, strerror(errno));
575 errnum = errno_to_WSA (errnum, __func__);
576 WSASetLastError (errnum);
578 return(SOCKET_ERROR);
583 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
585 gpointer handle = GUINT_TO_POINTER (fd);
588 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
589 WSASetLastError (WSAENOTSOCK);
590 return(SOCKET_ERROR);
594 ret = send (fd, msg, len, send_flags);
595 } while (ret == -1 && errno == EINTR &&
596 !_wapi_thread_cur_apc_pending ());
600 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno));
603 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
604 * a blocking socket. See bug #599488 */
605 if (errnum == EAGAIN) {
606 ret = fcntl (fd, F_GETFL, 0);
607 if (ret != -1 && (ret & O_NONBLOCK) == 0)
610 #endif /* O_NONBLOCK */
611 errnum = errno_to_WSA (errnum, __func__);
612 WSASetLastError (errnum);
614 return(SOCKET_ERROR);
619 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
620 const struct sockaddr *to, socklen_t tolen)
622 gpointer handle = GUINT_TO_POINTER (fd);
625 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
626 WSASetLastError (WSAENOTSOCK);
627 return(SOCKET_ERROR);
631 ret = sendto (fd, msg, len, send_flags, to, tolen);
632 } while (ret == -1 && errno == EINTR &&
633 !_wapi_thread_cur_apc_pending ());
637 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno));
639 errnum = errno_to_WSA (errnum, __func__);
640 WSASetLastError (errnum);
642 return(SOCKET_ERROR);
648 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
650 gpointer handle = GUINT_TO_POINTER (fd);
653 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
654 WSASetLastError (WSAENOTSOCK);
655 return(SOCKET_ERROR);
659 ret = sendmsg (fd, msg, send_flags);
660 } while (ret == -1 && errno == EINTR &&
661 !_wapi_thread_cur_apc_pending ());
665 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, strerror (errno));
667 errnum = errno_to_WSA (errnum, __func__);
668 WSASetLastError (errnum);
670 return(SOCKET_ERROR);
675 int _wapi_setsockopt(guint32 fd, int level, int optname,
676 const void *optval, socklen_t optlen)
678 gpointer handle = GUINT_TO_POINTER (fd);
681 #if defined (__linux__)
682 /* This has its address taken so it cannot be moved to the if block which uses it */
687 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
688 WSASetLastError (WSAENOTSOCK);
689 return(SOCKET_ERROR);
693 if (level == SOL_SOCKET &&
694 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
695 int ms = *((int *) optval);
696 tv.tv_sec = ms / 1000;
697 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
699 optlen = sizeof (tv);
701 #if defined (__linux__)
702 else if (level == SOL_SOCKET &&
703 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
704 /* According to socket(7) the Linux kernel doubles the
705 * buffer sizes "to allow space for bookkeeping
708 bufsize = *((int *) optval);
715 ret = setsockopt (fd, level, optname, tmp_val, optlen);
718 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__,
721 errnum = errno_to_WSA (errnum, __func__);
722 WSASetLastError (errnum);
724 return(SOCKET_ERROR);
727 #if defined (SO_REUSEPORT)
728 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
729 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
731 socklen_t type_len = sizeof (type);
733 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
734 if (type == SOCK_DGRAM || type == SOCK_STREAM)
735 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
743 int _wapi_shutdown(guint32 fd, int how)
745 struct _WapiHandle_socket *socket_handle;
747 gpointer handle = GUINT_TO_POINTER (fd);
750 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
751 WSASetLastError (WSAENOTSOCK);
752 return(SOCKET_ERROR);
755 if (how == SHUT_RD ||
757 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
758 (gpointer *)&socket_handle);
760 g_warning ("%s: error looking up socket handle %p",
762 WSASetLastError (WSAENOTSOCK);
763 return(SOCKET_ERROR);
766 socket_handle->still_readable = 0;
769 ret = shutdown (fd, how);
772 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__,
775 errnum = errno_to_WSA (errnum, __func__);
776 WSASetLastError (errnum);
778 return(SOCKET_ERROR);
784 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
785 guint32 unused2, guint32 unused3)
787 struct _WapiHandle_socket socket_handle = {0};
791 socket_handle.domain = domain;
792 socket_handle.type = type;
793 socket_handle.protocol = protocol;
794 socket_handle.still_readable = 1;
796 fd = socket (domain, type, protocol);
797 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
799 /* Retry with protocol == 4 (see bug #54565) */
800 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
801 socket_handle.protocol = 4;
802 fd = socket (AF_INET, SOCK_RAW, 4);
807 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno));
808 errnum = errno_to_WSA (errnum, __func__);
809 WSASetLastError (errnum);
811 return(INVALID_SOCKET);
814 if (fd >= _wapi_fd_reserve) {
815 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
816 __func__, fd, _wapi_fd_reserve);
818 WSASetLastError (WSASYSCALLFAILURE);
821 return(INVALID_SOCKET);
824 /* .net seems to set this by default for SOCK_STREAM, not for
825 * SOCK_DGRAM (see bug #36322)
826 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
828 * It seems winsock has a rather different idea of what
829 * SO_REUSEADDR means. If it's set, then a new socket can be
830 * bound over an existing listening socket. There's a new
831 * windows-specific option called SO_EXCLUSIVEADDRUSE but
832 * using that means the socket MUST be closed properly, or a
833 * denial of service can occur. Luckily for us, winsock
834 * behaves as though any other system would when SO_REUSEADDR
835 * is true, so we don't need to do anything else here. See
837 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
842 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true_,
847 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
849 errnum = errno_to_WSA (errnum, __func__);
850 WSASetLastError (errnum);
854 return(INVALID_SOCKET);
859 mono_once (&socket_ops_once, socket_ops_init);
861 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
862 if (handle == _WAPI_HANDLE_INVALID) {
863 g_warning ("%s: error creating socket handle", __func__);
864 WSASetLastError (WSASYSCALLFAILURE);
866 return(INVALID_SOCKET);
869 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle);
874 static gboolean socket_disconnect (guint32 fd)
876 struct _WapiHandle_socket *socket_handle;
878 gpointer handle = GUINT_TO_POINTER (fd);
881 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
882 (gpointer *)&socket_handle);
884 g_warning ("%s: error looking up socket handle %p", __func__,
886 WSASetLastError (WSAENOTSOCK);
890 newsock = socket (socket_handle->domain, socket_handle->type,
891 socket_handle->protocol);
895 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno));
897 errnum = errno_to_WSA (errnum, __func__);
898 WSASetLastError (errnum);
903 /* According to Stevens "Advanced Programming in the UNIX
904 * Environment: UNIX File I/O" dup2() is atomic so there
905 * should not be a race condition between the old fd being
906 * closed and the new socket fd being copied over
909 ret = dup2 (newsock, fd);
910 } while (ret == -1 && errno == EAGAIN);
915 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, strerror (errno));
917 errnum = errno_to_WSA (errnum, __func__);
918 WSASetLastError (errnum);
928 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
929 guint32 flags, guint32 reserved)
931 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, fd);
934 WSASetLastError (WSAEINVAL);
938 /* We could check the socket type here and fail unless its
939 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
940 * if we really wanted to
943 return(socket_disconnect (fd));
946 #define SF_BUFFER_SIZE 16384
948 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
950 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
951 gint file = GPOINTER_TO_INT (fd);
957 n = fstat (file, &statbuf);
960 errnum = errno_to_WSA (errnum, __func__);
961 WSASetLastError (errnum);
966 res = sendfile (socket, file, NULL, statbuf.st_size);
967 #elif defined(DARWIN)
968 /* TODO: header/tail could be sent in the 5th argument */
969 /* TODO: Might not send the entire file for non-blocking sockets */
970 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
972 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
975 errnum = errno_to_WSA (errnum, __func__);
976 WSASetLastError (errnum);
980 /* Default implementation */
981 gint file = GPOINTER_TO_INT (fd);
985 buffer = g_malloc (SF_BUFFER_SIZE);
988 n = read (file, buffer, SF_BUFFER_SIZE);
989 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
994 return 0; /* We're done reading */
997 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
998 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1002 gint errnum = errno;
1003 errnum = errno_to_WSA (errnum, __func__);
1004 WSASetLastError (errnum);
1006 return SOCKET_ERROR;
1014 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1015 WapiTransmitFileBuffers *buffers, guint32 flags)
1017 gpointer sock = GUINT_TO_POINTER (socket);
1020 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1021 WSASetLastError (WSAENOTSOCK);
1025 /* Write the header */
1026 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1027 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1028 if (ret == SOCKET_ERROR)
1032 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1033 if (ret == SOCKET_ERROR)
1036 /* Write the tail */
1037 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1038 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1039 if (ret == SOCKET_ERROR)
1043 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1044 closesocket (socket);
1053 } extension_functions[] = {
1054 {WSAID_DISCONNECTEX, wapi_disconnectex},
1055 {WSAID_TRANSMITFILE, TransmitFile},
1060 WSAIoctl (guint32 fd, gint32 command,
1061 gchar *input, gint i_len,
1062 gchar *output, gint o_len, glong *written,
1063 void *unused1, void *unused2)
1065 gpointer handle = GUINT_TO_POINTER (fd);
1067 gchar *buffer = NULL;
1069 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1070 WSASetLastError (WSAENOTSOCK);
1071 return SOCKET_ERROR;
1074 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1076 WapiGuid *guid = (WapiGuid *)input;
1078 if (i_len < sizeof(WapiGuid)) {
1079 /* As far as I can tell, windows doesn't
1080 * actually set an error here...
1082 WSASetLastError (WSAEINVAL);
1083 return(SOCKET_ERROR);
1086 if (o_len < sizeof(gpointer)) {
1088 WSASetLastError (WSAEINVAL);
1089 return(SOCKET_ERROR);
1092 if (output == NULL) {
1094 WSASetLastError (WSAEINVAL);
1095 return(SOCKET_ERROR);
1098 while(extension_functions[i].func != NULL) {
1099 if (!memcmp (guid, &extension_functions[i].guid,
1100 sizeof(WapiGuid))) {
1101 memcpy (output, &extension_functions[i].func,
1103 *written = sizeof(gpointer);
1110 WSASetLastError (WSAEINVAL);
1111 return(SOCKET_ERROR);
1114 if (command == SIO_KEEPALIVE_VALS) {
1116 uint32_t keepalivetime;
1117 uint32_t keepaliveinterval;
1119 if (i_len < (3 * sizeof (uint32_t))) {
1120 WSASetLastError (WSAEINVAL);
1121 return SOCKET_ERROR;
1123 memcpy (&onoff, input, sizeof (uint32_t));
1124 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1125 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1126 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1128 gint errnum = errno;
1129 errnum = errno_to_WSA (errnum, __func__);
1130 WSASetLastError (errnum);
1131 return SOCKET_ERROR;
1134 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1135 /* Values are in ms, but we need s */
1138 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1139 rem = keepalivetime % 1000;
1140 keepalivetime /= 1000;
1141 if (keepalivetime == 0 || rem >= 500)
1143 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1145 rem = keepaliveinterval % 1000;
1146 keepaliveinterval /= 1000;
1147 if (keepaliveinterval == 0 || rem >= 500)
1148 keepaliveinterval++;
1149 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1152 gint errnum = errno;
1153 errnum = errno_to_WSA (errnum, __func__);
1154 WSASetLastError (errnum);
1155 return SOCKET_ERROR;
1164 buffer = (char *)g_memdup (input, i_len);
1167 ret = ioctl (fd, command, buffer);
1169 gint errnum = errno;
1170 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__,
1173 errnum = errno_to_WSA (errnum, __func__);
1174 WSASetLastError (errnum);
1177 return(SOCKET_ERROR);
1180 if (buffer == NULL) {
1183 /* We just copy the buffer to the output. Some ioctls
1184 * don't even output any data, but, well...
1186 * NB windows returns WSAEFAULT if o_len is too small
1188 i_len = (i_len > o_len) ? o_len : i_len;
1190 if (i_len > 0 && output != NULL) {
1191 memcpy (output, buffer, i_len);
1201 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1202 int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
1204 gpointer handle = GUINT_TO_POINTER (fd);
1207 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1208 WSASetLastError (WSAENOTSOCK);
1209 return(SOCKET_ERROR);
1215 /* This works better than ioctl(...FIONBIO...)
1216 * on Linux (it causes connect to return
1217 * EINPROGRESS, but the ioctl doesn't seem to)
1219 ret = fcntl(fd, F_GETFL, 0);
1221 if (*(gboolean *)arg) {
1226 ret = fcntl(fd, F_SETFL, ret);
1229 #endif /* O_NONBLOCK */
1230 /* Unused in Mono */
1232 ret = ioctl (fd, command, arg);
1237 #if defined (PLATFORM_MACOSX)
1239 // ioctl (fd, FIONREAD, XXX) returns the size of
1240 // the UDP header as well on
1243 // Use getsockopt SO_NREAD instead to get the
1244 // right values for TCP and UDP.
1246 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1247 // be the value of the ip buffer.
1249 socklen_t optlen = sizeof (int);
1250 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1252 ret = ioctl (fd, command, arg);
1257 WSASetLastError (WSAEINVAL);
1258 return(SOCKET_ERROR);
1262 gint errnum = errno;
1263 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, strerror (errno));
1265 errnum = errno_to_WSA (errnum, __func__);
1266 WSASetLastError (errnum);
1268 return(SOCKET_ERROR);
1274 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1275 fd_set *exceptfds, struct timeval *timeout)
1279 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1280 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1281 (writefds && FD_ISSET (maxfd, writefds)) ||
1282 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1288 WSASetLastError (WSAEINVAL);
1289 return(SOCKET_ERROR);
1293 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1295 } while (ret == -1 && errno == EINTR &&
1296 !_wapi_thread_cur_apc_pending ());
1299 gint errnum = errno;
1300 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: select error: %s", __func__, strerror (errno));
1301 errnum = errno_to_WSA (errnum, __func__);
1302 WSASetLastError (errnum);
1304 return(SOCKET_ERROR);
1310 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1312 gpointer handle = GUINT_TO_POINTER (fd);
1314 if (fd >= FD_SETSIZE) {
1315 WSASetLastError (WSAEINVAL);
1319 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1320 WSASetLastError (WSAENOTSOCK);
1327 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1329 gpointer handle = GUINT_TO_POINTER (fd);
1331 if (fd >= FD_SETSIZE) {
1332 WSASetLastError (WSAEINVAL);
1336 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1337 WSASetLastError (WSAENOTSOCK);
1341 return(FD_ISSET (fd, set));
1344 void _wapi_FD_SET(guint32 fd, fd_set *set)
1346 gpointer handle = GUINT_TO_POINTER (fd);
1348 if (fd >= FD_SETSIZE) {
1349 WSASetLastError (WSAEINVAL);
1353 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1354 WSASetLastError (WSAENOTSOCK);
1363 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1367 memset (hdr, 0, sizeof (struct msghdr));
1368 hdr->msg_iovlen = count;
1369 hdr->msg_iov = g_new0 (struct iovec, count);
1370 for (i = 0; i < count; i++) {
1371 hdr->msg_iov [i].iov_base = buffers [i].buf;
1372 hdr->msg_iov [i].iov_len = buffers [i].len;
1377 msghdr_iov_free (struct msghdr *hdr)
1379 g_free (hdr->msg_iov);
1382 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1383 guint32 *flags, WapiOverlapped *overlapped,
1384 WapiOverlappedCB *complete)
1389 g_assert (overlapped == NULL);
1390 g_assert (complete == NULL);
1392 wsabuf_to_msghdr (buffers, count, &hdr);
1393 ret = _wapi_recvmsg (fd, &hdr, *flags);
1394 msghdr_iov_free (&hdr);
1396 if(ret == SOCKET_ERROR) {
1401 *flags = hdr.msg_flags;
1406 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1407 guint32 flags, WapiOverlapped *overlapped,
1408 WapiOverlappedCB *complete)
1413 g_assert (overlapped == NULL);
1414 g_assert (complete == NULL);
1416 wsabuf_to_msghdr (buffers, count, &hdr);
1417 ret = _wapi_sendmsg (fd, &hdr, flags);
1418 msghdr_iov_free (&hdr);
1420 if(ret == SOCKET_ERROR)
1427 #endif /* ifndef DISABLE_SOCKETS */