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/utils/mono-poll.h>
46 #include <netinet/in.h>
47 #include <netinet/tcp.h>
49 #include <arpa/inet.h>
50 #ifdef HAVE_SYS_SENDFILE_H
51 #include <sys/sendfile.h>
55 #define DEBUG(...) g_message(__VA_ARGS__)
60 static guint32 startup_count=0;
61 static guint32 in_cleanup = 0;
63 static void socket_close (gpointer handle, gpointer data);
65 struct _WapiHandleOps _wapi_socket_ops = {
66 socket_close, /* close */
70 NULL, /* special_wait */
74 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
76 static void socket_ops_init (void)
78 /* No capabilities to register */
81 static void socket_close (gpointer handle, gpointer data)
84 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
86 DEBUG ("%s: closing socket handle %p", __func__, handle);
88 if (startup_count == 0 && !in_cleanup) {
89 WSASetLastError (WSANOTINITIALISED);
93 /* Shutdown the socket for reading, to interrupt any potential
94 * receives that may be blocking for data. See bug 75705.
96 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
99 ret = close (GPOINTER_TO_UINT(handle));
100 } while (ret == -1 && errno == EINTR &&
101 !_wapi_thread_cur_apc_pending ());
105 DEBUG ("%s: close error: %s", __func__, strerror (errno));
106 errnum = errno_to_WSA (errnum, __func__);
108 WSASetLastError (errnum);
112 socket_handle->saved_error = 0;
115 int WSAStartup(guint32 requested, WapiWSAData *data)
121 /* Insist on v2.0+ */
122 if (requested < MAKEWORD(2,0)) {
123 return(WSAVERNOTSUPPORTED);
128 /* I've no idea what is the minor version of the spec I read */
129 data->wHighVersion = MAKEWORD(2,2);
131 data->wVersion = requested < data->wHighVersion? requested:
134 DEBUG ("%s: high version 0x%x", __func__, data->wHighVersion);
136 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
137 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
143 cleanup_close (gpointer handle, gpointer data)
145 _wapi_handle_ops_close (handle, NULL);
151 DEBUG ("%s: cleaning up", __func__);
153 if (--startup_count) {
159 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
164 void WSASetLastError(int error)
166 SetLastError (error);
169 int WSAGetLastError(void)
171 return(GetLastError ());
174 int closesocket(guint32 fd)
176 gpointer handle = GUINT_TO_POINTER (fd);
178 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
179 WSASetLastError (WSAENOTSOCK);
183 _wapi_handle_unref (handle);
187 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
189 gpointer handle = GUINT_TO_POINTER (fd);
191 struct _WapiHandle_socket *socket_handle;
192 struct _WapiHandle_socket new_socket_handle = {0};
196 if (startup_count == 0) {
197 WSASetLastError (WSANOTINITIALISED);
198 return(INVALID_SOCKET);
201 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
202 WSASetLastError (WSAEFAULT);
203 return(INVALID_SOCKET);
206 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
207 WSASetLastError (WSAENOTSOCK);
208 return(INVALID_SOCKET);
211 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
212 (gpointer *)&socket_handle);
214 g_warning ("%s: error looking up socket handle %p",
216 WSASetLastError (WSAENOTSOCK);
217 return(INVALID_SOCKET);
221 new_fd = accept (fd, addr, addrlen);
222 } while (new_fd == -1 && errno == EINTR &&
223 !_wapi_thread_cur_apc_pending());
227 DEBUG ("%s: accept error: %s", __func__, strerror(errno));
229 errnum = errno_to_WSA (errnum, __func__);
230 WSASetLastError (errnum);
232 return(INVALID_SOCKET);
235 if (new_fd >= _wapi_fd_reserve) {
236 DEBUG ("%s: File descriptor is too big", __func__);
238 WSASetLastError (WSASYSCALLFAILURE);
242 return(INVALID_SOCKET);
245 new_socket_handle.domain = socket_handle->domain;
246 new_socket_handle.type = socket_handle->type;
247 new_socket_handle.protocol = socket_handle->protocol;
248 new_socket_handle.still_readable = 1;
250 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
252 if(new_handle == _WAPI_HANDLE_INVALID) {
253 g_warning ("%s: error creating socket handle", __func__);
254 WSASetLastError (ERROR_GEN_FAILURE);
255 return(INVALID_SOCKET);
258 DEBUG ("%s: returning newly accepted socket handle %p with",
259 __func__, new_handle);
264 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
266 gpointer handle = GUINT_TO_POINTER (fd);
269 if (startup_count == 0) {
270 WSASetLastError (WSANOTINITIALISED);
271 return(SOCKET_ERROR);
274 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
275 WSASetLastError (WSAENOTSOCK);
276 return(SOCKET_ERROR);
279 ret = bind (fd, my_addr, addrlen);
282 DEBUG ("%s: bind error: %s", __func__, strerror(errno));
283 errnum = errno_to_WSA (errnum, __func__);
284 WSASetLastError (errnum);
286 return(SOCKET_ERROR);
291 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
294 gpointer handle = GUINT_TO_POINTER (fd);
295 struct _WapiHandle_socket *socket_handle;
299 if (startup_count == 0) {
300 WSASetLastError (WSANOTINITIALISED);
301 return(SOCKET_ERROR);
304 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
305 WSASetLastError (WSAENOTSOCK);
306 return(SOCKET_ERROR);
309 if (connect (fd, serv_addr, addrlen) == -1) {
316 if (errno != EINTR) {
317 DEBUG ("%s: connect error: %s", __func__,
320 errnum = errno_to_WSA (errnum, __func__);
321 if (errnum == WSAEINPROGRESS)
322 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
324 WSASetLastError (errnum);
327 * On solaris x86 getsockopt (SO_ERROR) is not set after
328 * connect () fails so we need to save this error.
330 * But don't do this for EWOULDBLOCK (bug 317315)
332 if (errnum != WSAEWOULDBLOCK) {
333 ok = _wapi_lookup_handle (handle,
335 (gpointer *)&socket_handle);
337 /* ECONNRESET means the socket was closed by another thread */
338 /* Async close on mac raises ECONNABORTED. */
339 if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
340 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
342 socket_handle->saved_error = errnum;
345 return(SOCKET_ERROR);
349 fds.events = POLLOUT;
350 while (mono_poll (&fds, 1, -1) == -1 &&
351 !_wapi_thread_cur_apc_pending ()) {
352 if (errno != EINTR) {
353 errnum = errno_to_WSA (errno, __func__);
355 DEBUG ("%s: connect poll error: %s",
356 __func__, strerror (errno));
358 WSASetLastError (errnum);
359 return(SOCKET_ERROR);
363 len = sizeof(so_error);
364 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
366 errnum = errno_to_WSA (errno, __func__);
368 DEBUG ("%s: connect getsockopt error: %s",
369 __func__, strerror (errno));
371 WSASetLastError (errnum);
372 return(SOCKET_ERROR);
376 errnum = errno_to_WSA (so_error, __func__);
378 /* Need to save this socket error */
379 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
380 (gpointer *)&socket_handle);
382 g_warning ("%s: error looking up socket handle %p", __func__, handle);
384 socket_handle->saved_error = errnum;
387 DEBUG ("%s: connect getsockopt returned error: %s",
388 __func__, strerror (so_error));
390 WSASetLastError (errnum);
391 return(SOCKET_ERROR);
398 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
400 gpointer handle = GUINT_TO_POINTER (fd);
403 if (startup_count == 0) {
404 WSASetLastError (WSANOTINITIALISED);
405 return(SOCKET_ERROR);
408 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
409 WSASetLastError (WSAENOTSOCK);
410 return(SOCKET_ERROR);
413 ret = getpeername (fd, name, namelen);
416 DEBUG ("%s: getpeername error: %s", __func__,
419 errnum = errno_to_WSA (errnum, __func__);
420 WSASetLastError (errnum);
422 return(SOCKET_ERROR);
428 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
430 gpointer handle = GUINT_TO_POINTER (fd);
433 if (startup_count == 0) {
434 WSASetLastError (WSANOTINITIALISED);
435 return(SOCKET_ERROR);
438 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
439 WSASetLastError (WSAENOTSOCK);
440 return(SOCKET_ERROR);
443 ret = getsockname (fd, name, namelen);
446 DEBUG ("%s: getsockname error: %s", __func__,
449 errnum = errno_to_WSA (errnum, __func__);
450 WSASetLastError (errnum);
452 return(SOCKET_ERROR);
458 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
461 gpointer handle = GUINT_TO_POINTER (fd);
465 struct _WapiHandle_socket *socket_handle;
468 if (startup_count == 0) {
469 WSASetLastError (WSANOTINITIALISED);
470 return(SOCKET_ERROR);
473 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
474 WSASetLastError (WSAENOTSOCK);
475 return(SOCKET_ERROR);
479 if (level == SOL_SOCKET &&
480 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
482 *optlen = sizeof (tv);
485 ret = getsockopt (fd, level, optname, tmp_val, optlen);
488 DEBUG ("%s: getsockopt error: %s", __func__,
491 errnum = errno_to_WSA (errnum, __func__);
492 WSASetLastError (errnum);
494 return(SOCKET_ERROR);
497 if (level == SOL_SOCKET &&
498 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
499 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
500 *optlen = sizeof (int);
503 if (optname == SO_ERROR) {
504 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
505 (gpointer *)&socket_handle);
507 g_warning ("%s: error looking up socket handle %p",
510 /* can't extract the last error */
511 *((int *) optval) = errno_to_WSA (*((int *)optval),
514 if (*((int *)optval) != 0) {
515 *((int *) optval) = errno_to_WSA (*((int *)optval),
517 socket_handle->saved_error = *((int *)optval);
519 *((int *)optval) = socket_handle->saved_error;
527 int _wapi_listen(guint32 fd, int backlog)
529 gpointer handle = GUINT_TO_POINTER (fd);
532 if (startup_count == 0) {
533 WSASetLastError (WSANOTINITIALISED);
534 return(SOCKET_ERROR);
537 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
538 WSASetLastError (WSAENOTSOCK);
539 return(SOCKET_ERROR);
542 ret = listen (fd, backlog);
545 DEBUG ("%s: listen error: %s", __func__, strerror (errno));
547 errnum = errno_to_WSA (errnum, __func__);
548 WSASetLastError (errnum);
550 return(SOCKET_ERROR);
556 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
558 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
561 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
562 struct sockaddr *from, socklen_t *fromlen)
564 gpointer handle = GUINT_TO_POINTER (fd);
565 struct _WapiHandle_socket *socket_handle;
569 if (startup_count == 0) {
570 WSASetLastError (WSANOTINITIALISED);
571 return(SOCKET_ERROR);
574 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
575 WSASetLastError (WSAENOTSOCK);
576 return(SOCKET_ERROR);
580 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
581 } while (ret == -1 && errno == EINTR &&
582 !_wapi_thread_cur_apc_pending ());
584 if (ret == 0 && len > 0) {
585 /* According to the Linux man page, recvfrom only
586 * returns 0 when the socket has been shut down
587 * cleanly. Turn this into an EINTR to simulate win32
588 * behaviour of returning EINTR when a socket is
589 * closed while the recvfrom is blocking (we use a
590 * shutdown() in socket_close() to trigger this.) See
593 /* Distinguish between the socket being shut down at
594 * the local or remote ends, and reads that request 0
598 /* If this returns FALSE, it means the socket has been
599 * closed locally. If it returns TRUE, but
600 * still_readable != 1 then shutdown
601 * (SHUT_RD|SHUT_RDWR) has been called locally.
603 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
604 (gpointer *)&socket_handle);
605 if (ok == FALSE || socket_handle->still_readable != 1) {
613 DEBUG ("%s: recv error: %s", __func__, strerror(errno));
615 errnum = errno_to_WSA (errnum, __func__);
616 WSASetLastError (errnum);
618 return(SOCKET_ERROR);
624 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
626 gpointer handle = GUINT_TO_POINTER (fd);
627 struct _WapiHandle_socket *socket_handle;
631 if (startup_count == 0) {
632 WSASetLastError (WSANOTINITIALISED);
633 return(SOCKET_ERROR);
636 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
637 WSASetLastError (WSAENOTSOCK);
638 return(SOCKET_ERROR);
642 ret = recvmsg (fd, msg, recv_flags);
643 } while (ret == -1 && errno == EINTR &&
644 !_wapi_thread_cur_apc_pending ());
647 /* see _wapi_recvfrom */
648 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
649 (gpointer *)&socket_handle);
650 if (ok == FALSE || socket_handle->still_readable != 1) {
658 DEBUG ("%s: recvmsg error: %s", __func__, strerror(errno));
660 errnum = errno_to_WSA (errnum, __func__);
661 WSASetLastError (errnum);
663 return(SOCKET_ERROR);
668 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
670 gpointer handle = GUINT_TO_POINTER (fd);
673 if (startup_count == 0) {
674 WSASetLastError (WSANOTINITIALISED);
675 return(SOCKET_ERROR);
678 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
679 WSASetLastError (WSAENOTSOCK);
680 return(SOCKET_ERROR);
684 ret = send (fd, msg, len, send_flags);
685 } while (ret == -1 && errno == EINTR &&
686 !_wapi_thread_cur_apc_pending ());
690 DEBUG ("%s: send error: %s", __func__, strerror (errno));
693 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
694 * a blocking socket. See bug #599488 */
695 if (errnum == EAGAIN) {
696 ret = fcntl (fd, F_GETFL, 0);
697 if (ret != -1 && (ret & O_NONBLOCK) == 0)
700 #endif /* O_NONBLOCK */
701 errnum = errno_to_WSA (errnum, __func__);
702 WSASetLastError (errnum);
704 return(SOCKET_ERROR);
709 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
710 const struct sockaddr *to, socklen_t tolen)
712 gpointer handle = GUINT_TO_POINTER (fd);
715 if (startup_count == 0) {
716 WSASetLastError (WSANOTINITIALISED);
717 return(SOCKET_ERROR);
720 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
721 WSASetLastError (WSAENOTSOCK);
722 return(SOCKET_ERROR);
726 ret = sendto (fd, msg, len, send_flags, to, tolen);
727 } while (ret == -1 && errno == EINTR &&
728 !_wapi_thread_cur_apc_pending ());
732 DEBUG ("%s: send error: %s", __func__, strerror (errno));
734 errnum = errno_to_WSA (errnum, __func__);
735 WSASetLastError (errnum);
737 return(SOCKET_ERROR);
743 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
745 gpointer handle = GUINT_TO_POINTER (fd);
748 if (startup_count == 0) {
749 WSASetLastError (WSANOTINITIALISED);
750 return(SOCKET_ERROR);
753 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
754 WSASetLastError (WSAENOTSOCK);
755 return(SOCKET_ERROR);
759 ret = sendmsg (fd, msg, send_flags);
760 } while (ret == -1 && errno == EINTR &&
761 !_wapi_thread_cur_apc_pending ());
765 DEBUG ("%s: sendmsg error: %s", __func__, strerror (errno));
767 errnum = errno_to_WSA (errnum, __func__);
768 WSASetLastError (errnum);
770 return(SOCKET_ERROR);
775 int _wapi_setsockopt(guint32 fd, int level, int optname,
776 const void *optval, socklen_t optlen)
778 gpointer handle = GUINT_TO_POINTER (fd);
781 #if defined (__linux__)
782 /* This has its address taken so it cannot be moved to the if block which uses it */
787 if (startup_count == 0) {
788 WSASetLastError (WSANOTINITIALISED);
789 return(SOCKET_ERROR);
792 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
793 WSASetLastError (WSAENOTSOCK);
794 return(SOCKET_ERROR);
798 if (level == SOL_SOCKET &&
799 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
800 int ms = *((int *) optval);
801 tv.tv_sec = ms / 1000;
802 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
804 optlen = sizeof (tv);
805 #if defined (__linux__)
806 } else if (level == SOL_SOCKET &&
807 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
808 /* According to socket(7) the Linux kernel doubles the
809 * buffer sizes "to allow space for bookkeeping
812 bufsize = *((int *) optval);
819 ret = setsockopt (fd, level, optname, tmp_val, optlen);
822 DEBUG ("%s: setsockopt error: %s", __func__,
825 errnum = errno_to_WSA (errnum, __func__);
826 WSASetLastError (errnum);
828 return(SOCKET_ERROR);
831 #if defined (SO_REUSEPORT)
832 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
833 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
835 socklen_t type_len = sizeof (type);
837 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
838 if (type == SOCK_DGRAM)
839 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
847 int _wapi_shutdown(guint32 fd, int how)
849 struct _WapiHandle_socket *socket_handle;
851 gpointer handle = GUINT_TO_POINTER (fd);
854 if (startup_count == 0) {
855 WSASetLastError (WSANOTINITIALISED);
856 return(SOCKET_ERROR);
859 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
860 WSASetLastError (WSAENOTSOCK);
861 return(SOCKET_ERROR);
864 if (how == SHUT_RD ||
866 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
867 (gpointer *)&socket_handle);
869 g_warning ("%s: error looking up socket handle %p",
871 WSASetLastError (WSAENOTSOCK);
872 return(SOCKET_ERROR);
875 socket_handle->still_readable = 0;
878 ret = shutdown (fd, how);
881 DEBUG ("%s: shutdown error: %s", __func__,
884 errnum = errno_to_WSA (errnum, __func__);
885 WSASetLastError (errnum);
887 return(SOCKET_ERROR);
893 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
894 guint32 unused2, guint32 unused3)
896 struct _WapiHandle_socket socket_handle = {0};
900 socket_handle.domain = domain;
901 socket_handle.type = type;
902 socket_handle.protocol = protocol;
903 socket_handle.still_readable = 1;
905 fd = socket (domain, type, protocol);
906 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
908 /* Retry with protocol == 4 (see bug #54565) */
909 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
910 socket_handle.protocol = 4;
911 fd = socket (AF_INET, SOCK_RAW, 4);
916 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
917 errnum = errno_to_WSA (errnum, __func__);
918 WSASetLastError (errnum);
920 return(INVALID_SOCKET);
923 if (fd >= _wapi_fd_reserve) {
924 DEBUG ("%s: File descriptor is too big (%d >= %d)",
925 __func__, fd, _wapi_fd_reserve);
927 WSASetLastError (WSASYSCALLFAILURE);
930 return(INVALID_SOCKET);
933 /* .net seems to set this by default for SOCK_STREAM, not for
934 * SOCK_DGRAM (see bug #36322)
935 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
937 * It seems winsock has a rather different idea of what
938 * SO_REUSEADDR means. If it's set, then a new socket can be
939 * bound over an existing listening socket. There's a new
940 * windows-specific option called SO_EXCLUSIVEADDRUSE but
941 * using that means the socket MUST be closed properly, or a
942 * denial of service can occur. Luckily for us, winsock
943 * behaves as though any other system would when SO_REUSEADDR
944 * is true, so we don't need to do anything else here. See
946 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
951 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
956 DEBUG ("%s: Error setting SO_REUSEADDR", __func__);
958 errnum = errno_to_WSA (errnum, __func__);
959 WSASetLastError (errnum);
963 return(INVALID_SOCKET);
968 mono_once (&socket_ops_once, socket_ops_init);
970 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
971 if (handle == _WAPI_HANDLE_INVALID) {
972 g_warning ("%s: error creating socket handle", __func__);
973 WSASetLastError (WSASYSCALLFAILURE);
975 return(INVALID_SOCKET);
978 DEBUG ("%s: returning socket handle %p", __func__, handle);
983 struct hostent *_wapi_gethostbyname(const char *hostname)
987 if (startup_count == 0) {
988 WSASetLastError (WSANOTINITIALISED);
992 he = gethostbyname (hostname);
994 DEBUG ("%s: gethostbyname error: %s", __func__,
999 WSASetLastError (WSAHOST_NOT_FOUND);
1001 #if NO_ADDRESS != NO_DATA
1005 WSASetLastError (WSANO_DATA);
1008 WSASetLastError (WSANO_RECOVERY);
1011 WSASetLastError (WSATRY_AGAIN);
1014 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1022 static gboolean socket_disconnect (guint32 fd)
1024 struct _WapiHandle_socket *socket_handle;
1026 gpointer handle = GUINT_TO_POINTER (fd);
1029 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1030 (gpointer *)&socket_handle);
1032 g_warning ("%s: error looking up socket handle %p", __func__,
1034 WSASetLastError (WSAENOTSOCK);
1038 newsock = socket (socket_handle->domain, socket_handle->type,
1039 socket_handle->protocol);
1040 if (newsock == -1) {
1041 gint errnum = errno;
1043 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
1045 errnum = errno_to_WSA (errnum, __func__);
1046 WSASetLastError (errnum);
1051 /* According to Stevens "Advanced Programming in the UNIX
1052 * Environment: UNIX File I/O" dup2() is atomic so there
1053 * should not be a race condition between the old fd being
1054 * closed and the new socket fd being copied over
1057 ret = dup2 (newsock, fd);
1058 } while (ret == -1 && errno == EAGAIN);
1061 gint errnum = errno;
1063 DEBUG ("%s: dup2 error: %s", __func__, strerror (errno));
1065 errnum = errno_to_WSA (errnum, __func__);
1066 WSASetLastError (errnum);
1076 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1077 guint32 flags, guint32 reserved)
1079 DEBUG ("%s: called on socket %d!", __func__, fd);
1081 if (reserved != 0) {
1082 WSASetLastError (WSAEINVAL);
1086 /* We could check the socket type here and fail unless its
1087 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1088 * if we really wanted to
1091 return(socket_disconnect (fd));
1094 #define SF_BUFFER_SIZE 16384
1096 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1098 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1099 gint file = GPOINTER_TO_INT (fd);
1103 struct stat statbuf;
1105 n = fstat (file, &statbuf);
1108 errnum = errno_to_WSA (errnum, __func__);
1109 WSASetLastError (errnum);
1110 return SOCKET_ERROR;
1114 res = sendfile (socket, file, NULL, statbuf.st_size);
1115 #elif defined(DARWIN)
1116 /* TODO: header/tail could be sent in the 5th argument */
1117 /* TODO: Might not send the entire file for non-blocking sockets */
1118 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1120 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1123 errnum = errno_to_WSA (errnum, __func__);
1124 WSASetLastError (errnum);
1125 return SOCKET_ERROR;
1128 /* Default implementation */
1129 gint file = GPOINTER_TO_INT (fd);
1133 buffer = g_malloc (SF_BUFFER_SIZE);
1136 n = read (file, buffer, SF_BUFFER_SIZE);
1137 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1142 return 0; /* We're done reading */
1145 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1146 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1150 gint errnum = errno;
1151 errnum = errno_to_WSA (errnum, __func__);
1152 WSASetLastError (errnum);
1154 return SOCKET_ERROR;
1162 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1163 WapiTransmitFileBuffers *buffers, guint32 flags)
1165 gpointer sock = GUINT_TO_POINTER (socket);
1168 if (startup_count == 0) {
1169 WSASetLastError (WSANOTINITIALISED);
1173 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1174 WSASetLastError (WSAENOTSOCK);
1178 /* Write the header */
1179 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1180 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1181 if (ret == SOCKET_ERROR)
1185 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1186 if (ret == SOCKET_ERROR)
1189 /* Write the tail */
1190 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1191 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1192 if (ret == SOCKET_ERROR)
1196 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1197 closesocket (socket);
1206 } extension_functions[] = {
1207 {WSAID_DISCONNECTEX, wapi_disconnectex},
1208 {WSAID_TRANSMITFILE, TransmitFile},
1213 WSAIoctl (guint32 fd, gint32 command,
1214 gchar *input, gint i_len,
1215 gchar *output, gint o_len, glong *written,
1216 void *unused1, void *unused2)
1218 gpointer handle = GUINT_TO_POINTER (fd);
1220 gchar *buffer = NULL;
1222 if (startup_count == 0) {
1223 WSASetLastError (WSANOTINITIALISED);
1224 return(SOCKET_ERROR);
1227 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1228 WSASetLastError (WSAENOTSOCK);
1229 return SOCKET_ERROR;
1232 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1234 WapiGuid *guid = (WapiGuid *)input;
1236 if (i_len < sizeof(WapiGuid)) {
1237 /* As far as I can tell, windows doesn't
1238 * actually set an error here...
1240 WSASetLastError (WSAEINVAL);
1241 return(SOCKET_ERROR);
1244 if (o_len < sizeof(gpointer)) {
1246 WSASetLastError (WSAEINVAL);
1247 return(SOCKET_ERROR);
1250 if (output == NULL) {
1252 WSASetLastError (WSAEINVAL);
1253 return(SOCKET_ERROR);
1256 while(extension_functions[i].func != NULL) {
1257 if (!memcmp (guid, &extension_functions[i].guid,
1258 sizeof(WapiGuid))) {
1259 memcpy (output, &extension_functions[i].func,
1261 *written = sizeof(gpointer);
1268 WSASetLastError (WSAEINVAL);
1269 return(SOCKET_ERROR);
1272 if (command == SIO_KEEPALIVE_VALS) {
1274 uint32_t keepalivetime;
1275 uint32_t keepaliveinterval;
1277 if (i_len < (3 * sizeof (uint32_t))) {
1278 WSASetLastError (WSAEINVAL);
1279 return SOCKET_ERROR;
1281 memcpy (&onoff, input, sizeof (uint32_t));
1282 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1283 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1284 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1286 gint errnum = errno;
1287 errnum = errno_to_WSA (errnum, __func__);
1288 WSASetLastError (errnum);
1289 return SOCKET_ERROR;
1292 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1293 /* Values are in ms, but we need s */
1296 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1297 rem = keepalivetime % 1000;
1298 keepalivetime /= 1000;
1299 if (keepalivetime == 0 || rem >= 500)
1301 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1303 rem = keepaliveinterval % 1000;
1304 keepaliveinterval /= 1000;
1305 if (keepaliveinterval == 0 || rem >= 500)
1306 keepaliveinterval++;
1307 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1310 gint errnum = errno;
1311 errnum = errno_to_WSA (errnum, __func__);
1312 WSASetLastError (errnum);
1313 return SOCKET_ERROR;
1322 buffer = g_memdup (input, i_len);
1325 ret = ioctl (fd, command, buffer);
1327 gint errnum = errno;
1328 DEBUG("%s: WSAIoctl error: %s", __func__,
1331 errnum = errno_to_WSA (errnum, __func__);
1332 WSASetLastError (errnum);
1335 return(SOCKET_ERROR);
1338 if (buffer == NULL) {
1341 /* We just copy the buffer to the output. Some ioctls
1342 * don't even output any data, but, well...
1344 * NB windows returns WSAEFAULT if o_len is too small
1346 i_len = (i_len > o_len) ? o_len : i_len;
1348 if (i_len > 0 && output != NULL) {
1349 memcpy (output, buffer, i_len);
1359 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1360 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1362 gpointer handle = GUINT_TO_POINTER (fd);
1365 if (startup_count == 0) {
1366 WSASetLastError (WSANOTINITIALISED);
1367 return(SOCKET_ERROR);
1370 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1371 WSASetLastError (WSAENOTSOCK);
1372 return(SOCKET_ERROR);
1378 /* This works better than ioctl(...FIONBIO...)
1379 * on Linux (it causes connect to return
1380 * EINPROGRESS, but the ioctl doesn't seem to)
1382 ret = fcntl(fd, F_GETFL, 0);
1384 if (*(gboolean *)arg) {
1389 ret = fcntl(fd, F_SETFL, ret);
1392 #endif /* O_NONBLOCK */
1393 /* Unused in Mono */
1395 ret = ioctl (fd, command, arg);
1400 #if defined (PLATFORM_MACOSX)
1402 // ioctl (fd, FIONREAD, XXX) returns the size of
1403 // the UDP header as well on
1406 // Use getsockopt SO_NREAD instead to get the
1407 // right values for TCP and UDP.
1409 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1410 // be the value of the ip buffer.
1412 socklen_t optlen = sizeof (int);
1413 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1415 ret = ioctl (fd, command, arg);
1420 WSASetLastError (WSAEINVAL);
1421 return(SOCKET_ERROR);
1425 gint errnum = errno;
1426 DEBUG ("%s: ioctl error: %s", __func__, strerror (errno));
1428 errnum = errno_to_WSA (errnum, __func__);
1429 WSASetLastError (errnum);
1431 return(SOCKET_ERROR);
1437 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1438 fd_set *exceptfds, struct timeval *timeout)
1442 if (startup_count == 0) {
1443 WSASetLastError (WSANOTINITIALISED);
1444 return(SOCKET_ERROR);
1447 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1448 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1449 (writefds && FD_ISSET (maxfd, writefds)) ||
1450 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1456 WSASetLastError (WSAEINVAL);
1457 return(SOCKET_ERROR);
1461 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1463 } while (ret == -1 && errno == EINTR &&
1464 !_wapi_thread_cur_apc_pending ());
1467 gint errnum = errno;
1468 DEBUG ("%s: select error: %s", __func__, strerror (errno));
1469 errnum = errno_to_WSA (errnum, __func__);
1470 WSASetLastError (errnum);
1472 return(SOCKET_ERROR);
1478 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1480 gpointer handle = GUINT_TO_POINTER (fd);
1482 if (fd >= FD_SETSIZE) {
1483 WSASetLastError (WSAEINVAL);
1487 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1488 WSASetLastError (WSAENOTSOCK);
1495 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1497 gpointer handle = GUINT_TO_POINTER (fd);
1499 if (fd >= FD_SETSIZE) {
1500 WSASetLastError (WSAEINVAL);
1504 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1505 WSASetLastError (WSAENOTSOCK);
1509 return(FD_ISSET (fd, set));
1512 void _wapi_FD_SET(guint32 fd, fd_set *set)
1514 gpointer handle = GUINT_TO_POINTER (fd);
1516 if (fd >= FD_SETSIZE) {
1517 WSASetLastError (WSAEINVAL);
1521 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1522 WSASetLastError (WSAENOTSOCK);
1531 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1535 memset (hdr, 0, sizeof (struct msghdr));
1536 hdr->msg_iovlen = count;
1537 hdr->msg_iov = g_new0 (struct iovec, count);
1538 for (i = 0; i < count; i++) {
1539 hdr->msg_iov [i].iov_base = buffers [i].buf;
1540 hdr->msg_iov [i].iov_len = buffers [i].len;
1545 msghdr_iov_free (struct msghdr *hdr)
1547 g_free (hdr->msg_iov);
1550 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1551 guint32 *flags, WapiOverlapped *overlapped,
1552 WapiOverlappedCB *complete)
1557 g_assert (overlapped == NULL);
1558 g_assert (complete == NULL);
1560 wsabuf_to_msghdr (buffers, count, &hdr);
1561 ret = _wapi_recvmsg (fd, &hdr, *flags);
1562 msghdr_iov_free (&hdr);
1564 if(ret == SOCKET_ERROR) {
1569 *flags = hdr.msg_flags;
1574 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1575 guint32 flags, WapiOverlapped *overlapped,
1576 WapiOverlappedCB *complete)
1581 g_assert (overlapped == NULL);
1582 g_assert (complete == NULL);
1584 wsabuf_to_msghdr (buffers, count, &hdr);
1585 ret = _wapi_sendmsg (fd, &hdr, flags);
1586 msghdr_iov_free (&hdr);
1588 if(ret == SOCKET_ERROR)
1595 #endif /* ifndef DISABLE_SOCKETS */