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>
56 static guint32 startup_count=0;
57 static guint32 in_cleanup = 0;
59 static void socket_close (gpointer handle, gpointer data);
61 struct _WapiHandleOps _wapi_socket_ops = {
62 socket_close, /* close */
66 NULL, /* special_wait */
70 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
72 static void socket_ops_init (void)
74 /* No capabilities to register */
77 static void socket_close (gpointer handle, gpointer data)
80 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
83 g_message ("%s: closing socket handle %p", __func__, handle);
86 if (startup_count == 0 && !in_cleanup) {
87 WSASetLastError (WSANOTINITIALISED);
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 ());
104 g_message ("%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:
135 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
138 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
139 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
145 cleanup_close (gpointer handle, gpointer data)
147 _wapi_handle_ops_close (handle, NULL);
154 g_message ("%s: cleaning up", __func__);
157 if (--startup_count) {
163 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
168 void WSASetLastError(int error)
170 SetLastError (error);
173 int WSAGetLastError(void)
175 return(GetLastError ());
178 int closesocket(guint32 fd)
180 gpointer handle = GUINT_TO_POINTER (fd);
182 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
183 WSASetLastError (WSAENOTSOCK);
187 _wapi_handle_unref (handle);
191 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
193 gpointer handle = GUINT_TO_POINTER (fd);
195 struct _WapiHandle_socket *socket_handle;
196 struct _WapiHandle_socket new_socket_handle = {0};
200 if (startup_count == 0) {
201 WSASetLastError (WSANOTINITIALISED);
202 return(INVALID_SOCKET);
205 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
206 WSASetLastError (WSAEFAULT);
207 return(INVALID_SOCKET);
210 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
211 WSASetLastError (WSAENOTSOCK);
212 return(INVALID_SOCKET);
215 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
216 (gpointer *)&socket_handle);
218 g_warning ("%s: error looking up socket handle %p",
220 WSASetLastError (WSAENOTSOCK);
221 return(INVALID_SOCKET);
225 new_fd = accept (fd, addr, addrlen);
226 } while (new_fd == -1 && errno == EINTR &&
227 !_wapi_thread_cur_apc_pending());
232 g_message ("%s: accept error: %s", __func__, strerror(errno));
235 errnum = errno_to_WSA (errnum, __func__);
236 WSASetLastError (errnum);
238 return(INVALID_SOCKET);
241 if (new_fd >= _wapi_fd_reserve) {
243 g_message ("%s: File descriptor is too big", __func__);
246 WSASetLastError (WSASYSCALLFAILURE);
250 return(INVALID_SOCKET);
253 new_socket_handle.domain = socket_handle->domain;
254 new_socket_handle.type = socket_handle->type;
255 new_socket_handle.protocol = socket_handle->protocol;
256 new_socket_handle.still_readable = 1;
258 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
260 if(new_handle == _WAPI_HANDLE_INVALID) {
261 g_warning ("%s: error creating socket handle", __func__);
262 WSASetLastError (ERROR_GEN_FAILURE);
263 return(INVALID_SOCKET);
267 g_message ("%s: returning newly accepted socket handle %p with",
268 __func__, new_handle);
274 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
276 gpointer handle = GUINT_TO_POINTER (fd);
279 if (startup_count == 0) {
280 WSASetLastError (WSANOTINITIALISED);
281 return(SOCKET_ERROR);
284 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
285 WSASetLastError (WSAENOTSOCK);
286 return(SOCKET_ERROR);
289 ret = bind (fd, my_addr, addrlen);
293 g_message ("%s: bind error: %s", __func__, strerror(errno));
295 errnum = errno_to_WSA (errnum, __func__);
296 WSASetLastError (errnum);
298 return(SOCKET_ERROR);
303 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
306 gpointer handle = GUINT_TO_POINTER (fd);
307 struct _WapiHandle_socket *socket_handle;
311 if (startup_count == 0) {
312 WSASetLastError (WSANOTINITIALISED);
313 return(SOCKET_ERROR);
316 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
317 WSASetLastError (WSAENOTSOCK);
318 return(SOCKET_ERROR);
321 if (connect (fd, serv_addr, addrlen) == -1) {
328 if (errno != EINTR) {
330 g_message ("%s: connect error: %s", __func__,
334 errnum = errno_to_WSA (errnum, __func__);
335 if (errnum == WSAEINPROGRESS)
336 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
338 WSASetLastError (errnum);
341 * On solaris x86 getsockopt (SO_ERROR) is not set after
342 * connect () fails so we need to save this error.
344 * But don't do this for EWOULDBLOCK (bug 317315)
346 if (errnum != WSAEWOULDBLOCK) {
347 ok = _wapi_lookup_handle (handle,
349 (gpointer *)&socket_handle);
351 /* ECONNRESET means the socket was closed by another thread */
352 if (errnum != WSAECONNRESET)
353 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
355 socket_handle->saved_error = errnum;
358 return(SOCKET_ERROR);
362 fds.events = POLLOUT;
363 while (mono_poll (&fds, 1, -1) == -1 &&
364 !_wapi_thread_cur_apc_pending ()) {
365 if (errno != EINTR) {
366 errnum = errno_to_WSA (errno, __func__);
369 g_message ("%s: connect poll error: %s",
370 __func__, strerror (errno));
373 WSASetLastError (errnum);
374 return(SOCKET_ERROR);
378 len = sizeof(so_error);
379 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
381 errnum = errno_to_WSA (errno, __func__);
384 g_message ("%s: connect getsockopt error: %s",
385 __func__, strerror (errno));
388 WSASetLastError (errnum);
389 return(SOCKET_ERROR);
393 errnum = errno_to_WSA (so_error, __func__);
395 /* Need to save this socket error */
396 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
397 (gpointer *)&socket_handle);
399 g_warning ("%s: error looking up socket handle %p", __func__, handle);
401 socket_handle->saved_error = errnum;
405 g_message ("%s: connect getsockopt returned error: %s",
406 __func__, strerror (so_error));
409 WSASetLastError (errnum);
410 return(SOCKET_ERROR);
417 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
419 gpointer handle = GUINT_TO_POINTER (fd);
422 if (startup_count == 0) {
423 WSASetLastError (WSANOTINITIALISED);
424 return(SOCKET_ERROR);
427 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
428 WSASetLastError (WSAENOTSOCK);
429 return(SOCKET_ERROR);
432 ret = getpeername (fd, name, namelen);
436 g_message ("%s: getpeername error: %s", __func__,
440 errnum = errno_to_WSA (errnum, __func__);
441 WSASetLastError (errnum);
443 return(SOCKET_ERROR);
449 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
451 gpointer handle = GUINT_TO_POINTER (fd);
454 if (startup_count == 0) {
455 WSASetLastError (WSANOTINITIALISED);
456 return(SOCKET_ERROR);
459 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
460 WSASetLastError (WSAENOTSOCK);
461 return(SOCKET_ERROR);
464 ret = getsockname (fd, name, namelen);
468 g_message ("%s: getsockname error: %s", __func__,
472 errnum = errno_to_WSA (errnum, __func__);
473 WSASetLastError (errnum);
475 return(SOCKET_ERROR);
481 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
484 gpointer handle = GUINT_TO_POINTER (fd);
488 struct _WapiHandle_socket *socket_handle;
491 if (startup_count == 0) {
492 WSASetLastError (WSANOTINITIALISED);
493 return(SOCKET_ERROR);
496 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
497 WSASetLastError (WSAENOTSOCK);
498 return(SOCKET_ERROR);
502 if (level == SOL_SOCKET &&
503 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
505 *optlen = sizeof (tv);
508 ret = getsockopt (fd, level, optname, tmp_val, optlen);
512 g_message ("%s: getsockopt error: %s", __func__,
516 errnum = errno_to_WSA (errnum, __func__);
517 WSASetLastError (errnum);
519 return(SOCKET_ERROR);
522 if (level == SOL_SOCKET &&
523 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
524 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
525 *optlen = sizeof (int);
528 if (optname == SO_ERROR) {
529 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
530 (gpointer *)&socket_handle);
532 g_warning ("%s: error looking up socket handle %p",
535 /* can't extract the last error */
536 *((int *) optval) = errno_to_WSA (*((int *)optval),
539 if (*((int *)optval) != 0) {
540 *((int *) optval) = errno_to_WSA (*((int *)optval),
542 socket_handle->saved_error = *((int *)optval);
544 *((int *)optval) = socket_handle->saved_error;
552 int _wapi_listen(guint32 fd, int backlog)
554 gpointer handle = GUINT_TO_POINTER (fd);
557 if (startup_count == 0) {
558 WSASetLastError (WSANOTINITIALISED);
559 return(SOCKET_ERROR);
562 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
563 WSASetLastError (WSAENOTSOCK);
564 return(SOCKET_ERROR);
567 ret = listen (fd, backlog);
571 g_message ("%s: listen error: %s", __func__, strerror (errno));
574 errnum = errno_to_WSA (errnum, __func__);
575 WSASetLastError (errnum);
577 return(SOCKET_ERROR);
583 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
585 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
588 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
589 struct sockaddr *from, socklen_t *fromlen)
591 gpointer handle = GUINT_TO_POINTER (fd);
592 struct _WapiHandle_socket *socket_handle;
596 if (startup_count == 0) {
597 WSASetLastError (WSANOTINITIALISED);
598 return(SOCKET_ERROR);
601 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
602 WSASetLastError (WSAENOTSOCK);
603 return(SOCKET_ERROR);
607 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
608 } while (ret == -1 && errno == EINTR &&
609 !_wapi_thread_cur_apc_pending ());
611 if (ret == 0 && len > 0) {
612 /* According to the Linux man page, recvfrom only
613 * returns 0 when the socket has been shut down
614 * cleanly. Turn this into an EINTR to simulate win32
615 * behaviour of returning EINTR when a socket is
616 * closed while the recvfrom is blocking (we use a
617 * shutdown() in socket_close() to trigger this.) See
620 /* Distinguish between the socket being shut down at
621 * the local or remote ends, and reads that request 0
625 /* If this returns FALSE, it means the socket has been
626 * closed locally. If it returns TRUE, but
627 * still_readable != 1 then shutdown
628 * (SHUT_RD|SHUT_RDWR) has been called locally.
630 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
631 (gpointer *)&socket_handle);
632 if (ok == FALSE || socket_handle->still_readable != 1) {
641 g_message ("%s: recv error: %s", __func__, strerror(errno));
644 errnum = errno_to_WSA (errnum, __func__);
645 WSASetLastError (errnum);
647 return(SOCKET_ERROR);
653 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
655 gpointer handle = GUINT_TO_POINTER (fd);
656 struct _WapiHandle_socket *socket_handle;
660 if (startup_count == 0) {
661 WSASetLastError (WSANOTINITIALISED);
662 return(SOCKET_ERROR);
665 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
666 WSASetLastError (WSAENOTSOCK);
667 return(SOCKET_ERROR);
671 ret = recvmsg (fd, msg, recv_flags);
672 } while (ret == -1 && errno == EINTR &&
673 !_wapi_thread_cur_apc_pending ());
676 /* see _wapi_recvfrom */
677 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
678 (gpointer *)&socket_handle);
679 if (ok == FALSE || socket_handle->still_readable != 1) {
688 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
691 errnum = errno_to_WSA (errnum, __func__);
692 WSASetLastError (errnum);
694 return(SOCKET_ERROR);
699 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
701 gpointer handle = GUINT_TO_POINTER (fd);
704 if (startup_count == 0) {
705 WSASetLastError (WSANOTINITIALISED);
706 return(SOCKET_ERROR);
709 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
710 WSASetLastError (WSAENOTSOCK);
711 return(SOCKET_ERROR);
715 ret = send (fd, msg, len, send_flags);
716 } while (ret == -1 && errno == EINTR &&
717 !_wapi_thread_cur_apc_pending ());
722 g_message ("%s: send error: %s", __func__, strerror (errno));
726 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
727 * a blocking socket. See bug #599488 */
728 if (errnum == EAGAIN) {
729 ret = fcntl (fd, F_GETFL, 0);
730 if (ret != -1 && (ret & O_NONBLOCK) == 0)
733 #endif /* O_NONBLOCK */
734 errnum = errno_to_WSA (errnum, __func__);
735 WSASetLastError (errnum);
737 return(SOCKET_ERROR);
742 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
743 const struct sockaddr *to, socklen_t tolen)
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 = sendto (fd, msg, len, send_flags, to, tolen);
760 } while (ret == -1 && errno == EINTR &&
761 !_wapi_thread_cur_apc_pending ());
766 g_message ("%s: send error: %s", __func__, strerror (errno));
769 errnum = errno_to_WSA (errnum, __func__);
770 WSASetLastError (errnum);
772 return(SOCKET_ERROR);
778 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
780 gpointer handle = GUINT_TO_POINTER (fd);
783 if (startup_count == 0) {
784 WSASetLastError (WSANOTINITIALISED);
785 return(SOCKET_ERROR);
788 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
789 WSASetLastError (WSAENOTSOCK);
790 return(SOCKET_ERROR);
794 ret = sendmsg (fd, msg, send_flags);
795 } while (ret == -1 && errno == EINTR &&
796 !_wapi_thread_cur_apc_pending ());
801 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
804 errnum = errno_to_WSA (errnum, __func__);
805 WSASetLastError (errnum);
807 return(SOCKET_ERROR);
812 int _wapi_setsockopt(guint32 fd, int level, int optname,
813 const void *optval, socklen_t optlen)
815 gpointer handle = GUINT_TO_POINTER (fd);
820 if (startup_count == 0) {
821 WSASetLastError (WSANOTINITIALISED);
822 return(SOCKET_ERROR);
825 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
826 WSASetLastError (WSAENOTSOCK);
827 return(SOCKET_ERROR);
831 if (level == SOL_SOCKET &&
832 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
833 int ms = *((int *) optval);
834 tv.tv_sec = ms / 1000;
835 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
837 optlen = sizeof (tv);
838 #if defined (__linux__)
839 } else if (level == SOL_SOCKET &&
840 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
841 /* According to socket(7) the Linux kernel doubles the
842 * buffer sizes "to allow space for bookkeeping
845 int bufsize = *((int *) optval);
852 ret = setsockopt (fd, level, optname, tmp_val, optlen);
856 g_message ("%s: setsockopt error: %s", __func__,
860 errnum = errno_to_WSA (errnum, __func__);
861 WSASetLastError (errnum);
863 return(SOCKET_ERROR);
866 #if defined (SO_REUSEPORT)
867 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
868 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
870 socklen_t type_len = sizeof (type);
872 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
873 if (type == SOCK_DGRAM)
874 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
882 int _wapi_shutdown(guint32 fd, int how)
884 struct _WapiHandle_socket *socket_handle;
886 gpointer handle = GUINT_TO_POINTER (fd);
889 if (startup_count == 0) {
890 WSASetLastError (WSANOTINITIALISED);
891 return(SOCKET_ERROR);
894 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
895 WSASetLastError (WSAENOTSOCK);
896 return(SOCKET_ERROR);
899 if (how == SHUT_RD ||
901 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
902 (gpointer *)&socket_handle);
904 g_warning ("%s: error looking up socket handle %p",
906 WSASetLastError (WSAENOTSOCK);
907 return(SOCKET_ERROR);
910 socket_handle->still_readable = 0;
913 ret = shutdown (fd, how);
917 g_message ("%s: shutdown error: %s", __func__,
921 errnum = errno_to_WSA (errnum, __func__);
922 WSASetLastError (errnum);
924 return(SOCKET_ERROR);
930 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
931 guint32 unused2, guint32 unused3)
933 struct _WapiHandle_socket socket_handle = {0};
937 socket_handle.domain = domain;
938 socket_handle.type = type;
939 socket_handle.protocol = protocol;
940 socket_handle.still_readable = 1;
942 fd = socket (domain, type, protocol);
943 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
945 /* Retry with protocol == 4 (see bug #54565) */
946 socket_handle.protocol = 4;
947 fd = socket (AF_INET, SOCK_RAW, 4);
953 g_message ("%s: socket error: %s", __func__, strerror (errno));
955 errnum = errno_to_WSA (errnum, __func__);
956 WSASetLastError (errnum);
958 return(INVALID_SOCKET);
961 if (fd >= _wapi_fd_reserve) {
963 g_message ("%s: File descriptor is too big (%d >= %d)",
964 __func__, fd, _wapi_fd_reserve);
967 WSASetLastError (WSASYSCALLFAILURE);
970 return(INVALID_SOCKET);
973 /* .net seems to set this by default for SOCK_STREAM, not for
974 * SOCK_DGRAM (see bug #36322)
976 * It seems winsock has a rather different idea of what
977 * SO_REUSEADDR means. If it's set, then a new socket can be
978 * bound over an existing listening socket. There's a new
979 * windows-specific option called SO_EXCLUSIVEADDRUSE but
980 * using that means the socket MUST be closed properly, or a
981 * denial of service can occur. Luckily for us, winsock
982 * behaves as though any other system would when SO_REUSEADDR
983 * is true, so we don't need to do anything else here. See
989 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
995 g_message ("%s: Error setting SO_REUSEADDR", __func__);
998 errnum = errno_to_WSA (errnum, __func__);
999 WSASetLastError (errnum);
1003 return(INVALID_SOCKET);
1008 mono_once (&socket_ops_once, socket_ops_init);
1010 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
1011 if (handle == _WAPI_HANDLE_INVALID) {
1012 g_warning ("%s: error creating socket handle", __func__);
1013 WSASetLastError (WSASYSCALLFAILURE);
1015 return(INVALID_SOCKET);
1019 g_message ("%s: returning socket handle %p", __func__, handle);
1025 struct hostent *_wapi_gethostbyname(const char *hostname)
1029 if (startup_count == 0) {
1030 WSASetLastError (WSANOTINITIALISED);
1034 he = gethostbyname (hostname);
1037 g_message ("%s: gethostbyname error: %s", __func__,
1038 strerror (h_errno));
1042 case HOST_NOT_FOUND:
1043 WSASetLastError (WSAHOST_NOT_FOUND);
1045 #if NO_ADDRESS != NO_DATA
1049 WSASetLastError (WSANO_DATA);
1052 WSASetLastError (WSANO_RECOVERY);
1055 WSASetLastError (WSATRY_AGAIN);
1058 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1066 static gboolean socket_disconnect (guint32 fd)
1068 struct _WapiHandle_socket *socket_handle;
1070 gpointer handle = GUINT_TO_POINTER (fd);
1073 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1074 (gpointer *)&socket_handle);
1076 g_warning ("%s: error looking up socket handle %p", __func__,
1078 WSASetLastError (WSAENOTSOCK);
1082 newsock = socket (socket_handle->domain, socket_handle->type,
1083 socket_handle->protocol);
1084 if (newsock == -1) {
1085 gint errnum = errno;
1088 g_message ("%s: socket error: %s", __func__, strerror (errno));
1091 errnum = errno_to_WSA (errnum, __func__);
1092 WSASetLastError (errnum);
1097 /* According to Stevens "Advanced Programming in the UNIX
1098 * Environment: UNIX File I/O" dup2() is atomic so there
1099 * should not be a race condition between the old fd being
1100 * closed and the new socket fd being copied over
1103 ret = dup2 (newsock, fd);
1104 } while (ret == -1 && errno == EAGAIN);
1107 gint errnum = errno;
1110 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1113 errnum = errno_to_WSA (errnum, __func__);
1114 WSASetLastError (errnum);
1124 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1125 guint32 flags, guint32 reserved)
1128 g_message ("%s: called on socket %d!", __func__, fd);
1131 if (reserved != 0) {
1132 WSASetLastError (WSAEINVAL);
1136 /* We could check the socket type here and fail unless its
1137 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1138 * if we really wanted to
1141 return(socket_disconnect (fd));
1144 #define SF_BUFFER_SIZE 16384
1146 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1148 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1149 gint file = GPOINTER_TO_INT (fd);
1153 struct stat statbuf;
1155 n = fstat (file, &statbuf);
1158 errnum = errno_to_WSA (errnum, __func__);
1159 WSASetLastError (errnum);
1160 return SOCKET_ERROR;
1164 res = sendfile (socket, file, NULL, statbuf.st_size);
1165 #elif defined(DARWIN)
1166 /* TODO: header/tail could be sent in the 5th argument */
1167 /* TODO: Might not send the entire file for non-blocking sockets */
1168 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1170 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1173 errnum = errno_to_WSA (errnum, __func__);
1174 WSASetLastError (errnum);
1175 return SOCKET_ERROR;
1178 /* Default implementation */
1179 gint file = GPOINTER_TO_INT (fd);
1183 buffer = g_malloc (SF_BUFFER_SIZE);
1186 n = read (file, buffer, SF_BUFFER_SIZE);
1187 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1192 return 0; /* We're done reading */
1195 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1196 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1200 gint errnum = errno;
1201 errnum = errno_to_WSA (errnum, __func__);
1202 WSASetLastError (errnum);
1204 return SOCKET_ERROR;
1212 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1213 WapiTransmitFileBuffers *buffers, guint32 flags)
1215 gpointer sock = GUINT_TO_POINTER (socket);
1218 if (startup_count == 0) {
1219 WSASetLastError (WSANOTINITIALISED);
1223 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1224 WSASetLastError (WSAENOTSOCK);
1228 /* Write the header */
1229 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1230 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1231 if (ret == SOCKET_ERROR)
1235 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1236 if (ret == SOCKET_ERROR)
1239 /* Write the tail */
1240 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1241 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1242 if (ret == SOCKET_ERROR)
1246 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1247 closesocket (socket);
1256 } extension_functions[] = {
1257 {WSAID_DISCONNECTEX, wapi_disconnectex},
1258 {WSAID_TRANSMITFILE, TransmitFile},
1263 WSAIoctl (guint32 fd, gint32 command,
1264 gchar *input, gint i_len,
1265 gchar *output, gint o_len, glong *written,
1266 void *unused1, void *unused2)
1268 gpointer handle = GUINT_TO_POINTER (fd);
1270 gchar *buffer = NULL;
1272 if (startup_count == 0) {
1273 WSASetLastError (WSANOTINITIALISED);
1274 return(SOCKET_ERROR);
1277 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1278 WSASetLastError (WSAENOTSOCK);
1279 return SOCKET_ERROR;
1282 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1284 WapiGuid *guid = (WapiGuid *)input;
1286 if (i_len < sizeof(WapiGuid)) {
1287 /* As far as I can tell, windows doesn't
1288 * actually set an error here...
1290 WSASetLastError (WSAEINVAL);
1291 return(SOCKET_ERROR);
1294 if (o_len < sizeof(gpointer)) {
1296 WSASetLastError (WSAEINVAL);
1297 return(SOCKET_ERROR);
1300 if (output == NULL) {
1302 WSASetLastError (WSAEINVAL);
1303 return(SOCKET_ERROR);
1306 while(extension_functions[i].func != NULL) {
1307 if (!memcmp (guid, &extension_functions[i].guid,
1308 sizeof(WapiGuid))) {
1309 memcpy (output, &extension_functions[i].func,
1311 *written = sizeof(gpointer);
1318 WSASetLastError (WSAEINVAL);
1319 return(SOCKET_ERROR);
1322 if (command == SIO_KEEPALIVE_VALS) {
1324 uint32_t keepalivetime;
1325 uint32_t keepaliveinterval;
1327 if (i_len < (3 * sizeof (uint32_t))) {
1328 WSASetLastError (WSAEINVAL);
1329 return SOCKET_ERROR;
1331 memcpy (&onoff, input, sizeof (uint32_t));
1332 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1333 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1334 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1336 gint errnum = errno;
1337 errnum = errno_to_WSA (errnum, __func__);
1338 WSASetLastError (errnum);
1339 return SOCKET_ERROR;
1342 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1343 /* Values are in ms, but we need s */
1346 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1347 rem = keepalivetime % 1000;
1348 keepalivetime /= 1000;
1349 if (keepalivetime == 0 || rem >= 500)
1351 ret = setsockopt (fd, SOL_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1353 rem = keepaliveinterval % 1000;
1354 keepaliveinterval /= 1000;
1355 if (keepaliveinterval == 0 || rem >= 500)
1356 keepaliveinterval++;
1357 ret = setsockopt (fd, SOL_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1360 gint errnum = errno;
1361 errnum = errno_to_WSA (errnum, __func__);
1362 WSASetLastError (errnum);
1363 return SOCKET_ERROR;
1372 buffer = g_memdup (input, i_len);
1375 ret = ioctl (fd, command, buffer);
1377 gint errnum = errno;
1379 g_message("%s: WSAIoctl error: %s", __func__,
1383 errnum = errno_to_WSA (errnum, __func__);
1384 WSASetLastError (errnum);
1387 return(SOCKET_ERROR);
1390 if (buffer == NULL) {
1393 /* We just copy the buffer to the output. Some ioctls
1394 * don't even output any data, but, well...
1396 * NB windows returns WSAEFAULT if o_len is too small
1398 i_len = (i_len > o_len) ? o_len : i_len;
1400 if (i_len > 0 && output != NULL) {
1401 memcpy (output, buffer, i_len);
1411 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1412 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1414 gpointer handle = GUINT_TO_POINTER (fd);
1417 if (startup_count == 0) {
1418 WSASetLastError (WSANOTINITIALISED);
1419 return(SOCKET_ERROR);
1422 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1423 WSASetLastError (WSAENOTSOCK);
1424 return(SOCKET_ERROR);
1430 /* This works better than ioctl(...FIONBIO...)
1431 * on Linux (it causes connect to return
1432 * EINPROGRESS, but the ioctl doesn't seem to)
1434 ret = fcntl(fd, F_GETFL, 0);
1436 if (*(gboolean *)arg) {
1441 ret = fcntl(fd, F_SETFL, ret);
1444 #endif /* O_NONBLOCK */
1445 /* Unused in Mono */
1447 ret = ioctl (fd, command, arg);
1452 #if defined (PLATFORM_MACOSX)
1454 // ioctl (fd, FIONREAD, XXX) returns the size of
1455 // the UDP header as well on
1458 // Use getsockopt SO_NREAD instead to get the
1459 // right values for TCP and UDP.
1461 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1462 // be the value of the ip buffer.
1464 socklen_t optlen = sizeof (int);
1465 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1467 ret = ioctl (fd, command, arg);
1472 WSASetLastError (WSAEINVAL);
1473 return(SOCKET_ERROR);
1477 gint errnum = errno;
1479 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1482 errnum = errno_to_WSA (errnum, __func__);
1483 WSASetLastError (errnum);
1485 return(SOCKET_ERROR);
1491 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1492 fd_set *exceptfds, struct timeval *timeout)
1496 if (startup_count == 0) {
1497 WSASetLastError (WSANOTINITIALISED);
1498 return(SOCKET_ERROR);
1501 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1502 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1503 (writefds && FD_ISSET (maxfd, writefds)) ||
1504 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1510 WSASetLastError (WSAEINVAL);
1511 return(SOCKET_ERROR);
1515 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1517 } while (ret == -1 && errno == EINTR &&
1518 !_wapi_thread_cur_apc_pending ());
1521 gint errnum = errno;
1523 g_message ("%s: select error: %s", __func__, strerror (errno));
1525 errnum = errno_to_WSA (errnum, __func__);
1526 WSASetLastError (errnum);
1528 return(SOCKET_ERROR);
1534 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1536 gpointer handle = GUINT_TO_POINTER (fd);
1538 if (fd >= FD_SETSIZE) {
1539 WSASetLastError (WSAEINVAL);
1543 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1544 WSASetLastError (WSAENOTSOCK);
1551 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1553 gpointer handle = GUINT_TO_POINTER (fd);
1555 if (fd >= FD_SETSIZE) {
1556 WSASetLastError (WSAEINVAL);
1560 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1561 WSASetLastError (WSAENOTSOCK);
1565 return(FD_ISSET (fd, set));
1568 void _wapi_FD_SET(guint32 fd, fd_set *set)
1570 gpointer handle = GUINT_TO_POINTER (fd);
1572 if (fd >= FD_SETSIZE) {
1573 WSASetLastError (WSAEINVAL);
1577 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1578 WSASetLastError (WSAENOTSOCK);
1587 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1591 memset (hdr, 0, sizeof (struct msghdr));
1592 hdr->msg_iovlen = count;
1593 hdr->msg_iov = g_new0 (struct iovec, count);
1594 for (i = 0; i < count; i++) {
1595 hdr->msg_iov [i].iov_base = buffers [i].buf;
1596 hdr->msg_iov [i].iov_len = buffers [i].len;
1601 msghdr_iov_free (struct msghdr *hdr)
1603 g_free (hdr->msg_iov);
1606 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1607 guint32 *flags, WapiOverlapped *overlapped,
1608 WapiOverlappedCB *complete)
1613 g_assert (overlapped == NULL);
1614 g_assert (complete == NULL);
1616 wsabuf_to_msghdr (buffers, count, &hdr);
1617 ret = _wapi_recvmsg (fd, &hdr, *flags);
1618 msghdr_iov_free (&hdr);
1620 if(ret == SOCKET_ERROR) {
1625 *flags = hdr.msg_flags;
1630 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1631 guint32 flags, WapiOverlapped *overlapped,
1632 WapiOverlappedCB *complete)
1637 g_assert (overlapped == NULL);
1638 g_assert (complete == NULL);
1640 wsabuf_to_msghdr (buffers, count, &hdr);
1641 ret = _wapi_sendmsg (fd, &hdr, flags);
1642 msghdr_iov_free (&hdr);
1644 if(ret == SOCKET_ERROR)
1651 #endif /* ifndef DISABLE_SOCKETS */