2 * sockets.c: Socket handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
10 #ifndef DISABLE_SOCKETS
17 #include <sys/types.h>
18 #include <sys/socket.h>
22 #ifdef HAVE_SYS_IOCTL_H
23 # include <sys/ioctl.h>
25 #ifdef HAVE_SYS_FILIO_H
26 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
28 #ifdef HAVE_SYS_SOCKIO_H
29 #include <sys/sockio.h> /* defines SIOCATMARK */
34 #ifndef HAVE_MSG_NOSIGNAL
38 #include <mono/io-layer/wapi.h>
39 #include <mono/io-layer/wapi-private.h>
40 #include <mono/io-layer/socket-private.h>
41 #include <mono/io-layer/handles-private.h>
42 #include <mono/io-layer/socket-wrappers.h>
43 #include <mono/utils/mono-poll.h>
45 #include <netinet/in.h>
46 #include <netinet/tcp.h>
48 #include <arpa/inet.h>
49 #ifdef HAVE_SYS_SENDFILE_H
50 #include <sys/sendfile.h>
55 static guint32 startup_count=0;
57 static void socket_close (gpointer handle, gpointer data);
59 struct _WapiHandleOps _wapi_socket_ops = {
60 socket_close, /* close */
64 NULL, /* special_wait */
68 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
70 static void socket_ops_init (void)
72 /* No capabilities to register */
75 static void socket_close (gpointer handle, gpointer data)
78 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
81 g_message ("%s: closing socket handle %p", __func__, handle);
84 if (startup_count == 0) {
85 WSASetLastError (WSANOTINITIALISED);
89 /* Shutdown the socket for reading, to interrupt any potential
90 * receives that may be blocking for data. See bug 75705.
92 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
95 ret = close (GPOINTER_TO_UINT(handle));
96 } while (ret == -1 && errno == EINTR &&
97 !_wapi_thread_cur_apc_pending ());
102 g_message ("%s: close error: %s", __func__, strerror (errno));
104 errnum = errno_to_WSA (errnum, __func__);
105 WSASetLastError (errnum);
108 socket_handle->saved_error = 0;
111 int WSAStartup(guint32 requested, WapiWSAData *data)
117 /* Insist on v2.0+ */
118 if (requested < MAKEWORD(2,0)) {
119 return(WSAVERNOTSUPPORTED);
124 /* I've no idea what is the minor version of the spec I read */
125 data->wHighVersion = MAKEWORD(2,2);
127 data->wVersion = requested < data->wHighVersion? requested:
131 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
134 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
135 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
141 cleanup_close (gpointer handle, gpointer data)
143 _wapi_handle_ops_close (handle, NULL);
150 g_message ("%s: cleaning up", __func__);
153 if (--startup_count) {
158 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
162 void WSASetLastError(int error)
164 SetLastError (error);
167 int WSAGetLastError(void)
169 return(GetLastError ());
172 int closesocket(guint32 fd)
174 gpointer handle = GUINT_TO_POINTER (fd);
176 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
177 WSASetLastError (WSAENOTSOCK);
181 _wapi_handle_unref (handle);
185 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
187 gpointer handle = GUINT_TO_POINTER (fd);
189 struct _WapiHandle_socket *socket_handle;
190 struct _WapiHandle_socket new_socket_handle = {0};
194 if (startup_count == 0) {
195 WSASetLastError (WSANOTINITIALISED);
196 return(INVALID_SOCKET);
199 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
200 WSASetLastError (WSAEFAULT);
201 return(INVALID_SOCKET);
204 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
205 WSASetLastError (WSAENOTSOCK);
206 return(INVALID_SOCKET);
209 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
210 (gpointer *)&socket_handle);
212 g_warning ("%s: error looking up socket handle %p",
214 WSASetLastError (WSAENOTSOCK);
215 return(INVALID_SOCKET);
219 new_fd = accept (fd, addr, addrlen);
220 } while (new_fd == -1 && errno == EINTR &&
221 !_wapi_thread_cur_apc_pending());
226 g_message ("%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) {
237 g_message ("%s: File descriptor is too big", __func__);
240 WSASetLastError (WSASYSCALLFAILURE);
244 return(INVALID_SOCKET);
247 new_socket_handle.domain = socket_handle->domain;
248 new_socket_handle.type = socket_handle->type;
249 new_socket_handle.protocol = socket_handle->protocol;
250 new_socket_handle.still_readable = 1;
252 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
254 if(new_handle == _WAPI_HANDLE_INVALID) {
255 g_warning ("%s: error creating socket handle", __func__);
256 WSASetLastError (ERROR_GEN_FAILURE);
257 return(INVALID_SOCKET);
261 g_message ("%s: returning newly accepted socket handle %p with",
262 __func__, new_handle);
268 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
270 gpointer handle = GUINT_TO_POINTER (fd);
273 if (startup_count == 0) {
274 WSASetLastError (WSANOTINITIALISED);
275 return(SOCKET_ERROR);
278 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
279 WSASetLastError (WSAENOTSOCK);
280 return(SOCKET_ERROR);
283 ret = bind (fd, my_addr, addrlen);
287 g_message ("%s: bind error: %s", __func__, strerror(errno));
289 errnum = errno_to_WSA (errnum, __func__);
290 WSASetLastError (errnum);
292 return(SOCKET_ERROR);
297 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
300 gpointer handle = GUINT_TO_POINTER (fd);
301 struct _WapiHandle_socket *socket_handle;
305 if (startup_count == 0) {
306 WSASetLastError (WSANOTINITIALISED);
307 return(SOCKET_ERROR);
310 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
311 WSASetLastError (WSAENOTSOCK);
312 return(SOCKET_ERROR);
315 if (connect (fd, serv_addr, addrlen) == -1) {
322 if (errno != EINTR) {
324 g_message ("%s: connect error: %s", __func__,
328 errnum = errno_to_WSA (errnum, __func__);
329 if (errnum == WSAEINPROGRESS)
330 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
332 WSASetLastError (errnum);
335 * On solaris x86 getsockopt (SO_ERROR) is not set after
336 * connect () fails so we need to save this error.
338 * But don't do this for EWOULDBLOCK (bug 317315)
340 if (errnum != WSAEWOULDBLOCK) {
341 ok = _wapi_lookup_handle (handle,
343 (gpointer *)&socket_handle);
345 /* ECONNRESET means the socket was closed by another thread */
346 if (errnum != WSAECONNRESET)
347 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
349 socket_handle->saved_error = errnum;
352 return(SOCKET_ERROR);
356 fds.events = POLLOUT;
357 while (mono_poll (&fds, 1, -1) == -1 &&
358 !_wapi_thread_cur_apc_pending ()) {
359 if (errno != EINTR) {
360 errnum = errno_to_WSA (errno, __func__);
363 g_message ("%s: connect poll error: %s",
364 __func__, strerror (errno));
367 WSASetLastError (errnum);
368 return(SOCKET_ERROR);
372 len = sizeof(so_error);
373 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
375 errnum = errno_to_WSA (errno, __func__);
378 g_message ("%s: connect getsockopt error: %s",
379 __func__, strerror (errno));
382 WSASetLastError (errnum);
383 return(SOCKET_ERROR);
387 errnum = errno_to_WSA (so_error, __func__);
389 /* Need to save this socket error */
390 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
391 (gpointer *)&socket_handle);
393 g_warning ("%s: error looking up socket handle %p", __func__, handle);
395 socket_handle->saved_error = errnum;
399 g_message ("%s: connect getsockopt returned error: %s",
400 __func__, strerror (so_error));
403 WSASetLastError (errnum);
404 return(SOCKET_ERROR);
411 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
413 gpointer handle = GUINT_TO_POINTER (fd);
416 if (startup_count == 0) {
417 WSASetLastError (WSANOTINITIALISED);
418 return(SOCKET_ERROR);
421 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
422 WSASetLastError (WSAENOTSOCK);
423 return(SOCKET_ERROR);
426 ret = getpeername (fd, name, namelen);
430 g_message ("%s: getpeername error: %s", __func__,
434 errnum = errno_to_WSA (errnum, __func__);
435 WSASetLastError (errnum);
437 return(SOCKET_ERROR);
443 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
445 gpointer handle = GUINT_TO_POINTER (fd);
448 if (startup_count == 0) {
449 WSASetLastError (WSANOTINITIALISED);
450 return(SOCKET_ERROR);
453 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
454 WSASetLastError (WSAENOTSOCK);
455 return(SOCKET_ERROR);
458 ret = getsockname (fd, name, namelen);
462 g_message ("%s: getsockname error: %s", __func__,
466 errnum = errno_to_WSA (errnum, __func__);
467 WSASetLastError (errnum);
469 return(SOCKET_ERROR);
475 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
478 gpointer handle = GUINT_TO_POINTER (fd);
482 struct _WapiHandle_socket *socket_handle;
485 if (startup_count == 0) {
486 WSASetLastError (WSANOTINITIALISED);
487 return(SOCKET_ERROR);
490 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
491 WSASetLastError (WSAENOTSOCK);
492 return(SOCKET_ERROR);
496 if (level == SOL_SOCKET &&
497 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
499 *optlen = sizeof (tv);
502 ret = getsockopt (fd, level, optname, tmp_val, optlen);
506 g_message ("%s: getsockopt error: %s", __func__,
510 errnum = errno_to_WSA (errnum, __func__);
511 WSASetLastError (errnum);
513 return(SOCKET_ERROR);
516 if (level == SOL_SOCKET &&
517 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
518 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
519 *optlen = sizeof (int);
522 if (optname == SO_ERROR) {
523 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
524 (gpointer *)&socket_handle);
526 g_warning ("%s: error looking up socket handle %p",
529 /* can't extract the last error */
530 *((int *) optval) = errno_to_WSA (*((int *)optval),
533 if (*((int *)optval) != 0) {
534 *((int *) optval) = errno_to_WSA (*((int *)optval),
536 socket_handle->saved_error = *((int *)optval);
538 *((int *)optval) = socket_handle->saved_error;
546 int _wapi_listen(guint32 fd, int backlog)
548 gpointer handle = GUINT_TO_POINTER (fd);
551 if (startup_count == 0) {
552 WSASetLastError (WSANOTINITIALISED);
553 return(SOCKET_ERROR);
556 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
557 WSASetLastError (WSAENOTSOCK);
558 return(SOCKET_ERROR);
561 ret = listen (fd, backlog);
565 g_message ("%s: listen error: %s", __func__, strerror (errno));
568 errnum = errno_to_WSA (errnum, __func__);
569 WSASetLastError (errnum);
571 return(SOCKET_ERROR);
577 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
579 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
582 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
583 struct sockaddr *from, socklen_t *fromlen)
585 gpointer handle = GUINT_TO_POINTER (fd);
586 struct _WapiHandle_socket *socket_handle;
590 if (startup_count == 0) {
591 WSASetLastError (WSANOTINITIALISED);
592 return(SOCKET_ERROR);
595 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
596 WSASetLastError (WSAENOTSOCK);
597 return(SOCKET_ERROR);
601 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
602 } while (ret == -1 && errno == EINTR &&
603 !_wapi_thread_cur_apc_pending ());
605 if (ret == 0 && len > 0) {
606 /* According to the Linux man page, recvfrom only
607 * returns 0 when the socket has been shut down
608 * cleanly. Turn this into an EINTR to simulate win32
609 * behaviour of returning EINTR when a socket is
610 * closed while the recvfrom is blocking (we use a
611 * shutdown() in socket_close() to trigger this.) See
614 /* Distinguish between the socket being shut down at
615 * the local or remote ends, and reads that request 0
619 /* If this returns FALSE, it means the socket has been
620 * closed locally. If it returns TRUE, but
621 * still_readable != 1 then shutdown
622 * (SHUT_RD|SHUT_RDWR) has been called locally.
624 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
625 (gpointer *)&socket_handle);
626 if (ok == FALSE || socket_handle->still_readable != 1) {
635 g_message ("%s: recv error: %s", __func__, strerror(errno));
638 errnum = errno_to_WSA (errnum, __func__);
639 WSASetLastError (errnum);
641 return(SOCKET_ERROR);
647 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
649 gpointer handle = GUINT_TO_POINTER (fd);
650 struct _WapiHandle_socket *socket_handle;
654 if (startup_count == 0) {
655 WSASetLastError (WSANOTINITIALISED);
656 return(SOCKET_ERROR);
659 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
660 WSASetLastError (WSAENOTSOCK);
661 return(SOCKET_ERROR);
665 ret = recvmsg (fd, msg, recv_flags);
666 } while (ret == -1 && errno == EINTR &&
667 !_wapi_thread_cur_apc_pending ());
670 /* see _wapi_recvfrom */
671 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
672 (gpointer *)&socket_handle);
673 if (ok == FALSE || socket_handle->still_readable != 1) {
682 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
685 errnum = errno_to_WSA (errnum, __func__);
686 WSASetLastError (errnum);
688 return(SOCKET_ERROR);
693 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
695 gpointer handle = GUINT_TO_POINTER (fd);
698 if (startup_count == 0) {
699 WSASetLastError (WSANOTINITIALISED);
700 return(SOCKET_ERROR);
703 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
704 WSASetLastError (WSAENOTSOCK);
705 return(SOCKET_ERROR);
709 ret = send (fd, msg, len, send_flags);
710 } while (ret == -1 && errno == EINTR &&
711 !_wapi_thread_cur_apc_pending ());
716 g_message ("%s: send error: %s", __func__, strerror (errno));
719 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
720 * a blocking socket. See bug #599488 */
721 if (errnum == EAGAIN) {
724 ret = ioctlsocket (fd, FIONBIO, (gulong *) &nonblock);
725 if (ret != SOCKET_ERROR && !nonblock)
728 errnum = errno_to_WSA (errnum, __func__);
729 WSASetLastError (errnum);
731 return(SOCKET_ERROR);
736 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
737 const struct sockaddr *to, socklen_t tolen)
739 gpointer handle = GUINT_TO_POINTER (fd);
742 if (startup_count == 0) {
743 WSASetLastError (WSANOTINITIALISED);
744 return(SOCKET_ERROR);
747 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
748 WSASetLastError (WSAENOTSOCK);
749 return(SOCKET_ERROR);
753 ret = sendto (fd, msg, len, send_flags, to, tolen);
754 } while (ret == -1 && errno == EINTR &&
755 !_wapi_thread_cur_apc_pending ());
760 g_message ("%s: send error: %s", __func__, strerror (errno));
763 errnum = errno_to_WSA (errnum, __func__);
764 WSASetLastError (errnum);
766 return(SOCKET_ERROR);
772 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
774 gpointer handle = GUINT_TO_POINTER (fd);
777 if (startup_count == 0) {
778 WSASetLastError (WSANOTINITIALISED);
779 return(SOCKET_ERROR);
782 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
783 WSASetLastError (WSAENOTSOCK);
784 return(SOCKET_ERROR);
788 ret = sendmsg (fd, msg, send_flags);
789 } while (ret == -1 && errno == EINTR &&
790 !_wapi_thread_cur_apc_pending ());
795 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
798 errnum = errno_to_WSA (errnum, __func__);
799 WSASetLastError (errnum);
801 return(SOCKET_ERROR);
806 int _wapi_setsockopt(guint32 fd, int level, int optname,
807 const void *optval, socklen_t optlen)
809 gpointer handle = GUINT_TO_POINTER (fd);
814 if (startup_count == 0) {
815 WSASetLastError (WSANOTINITIALISED);
816 return(SOCKET_ERROR);
819 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
820 WSASetLastError (WSAENOTSOCK);
821 return(SOCKET_ERROR);
825 if (level == SOL_SOCKET &&
826 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
827 int ms = *((int *) optval);
828 tv.tv_sec = ms / 1000;
829 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
831 optlen = sizeof (tv);
832 #if defined (__linux__)
833 } else if (level == SOL_SOCKET &&
834 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
835 /* According to socket(7) the Linux kernel doubles the
836 * buffer sizes "to allow space for bookkeeping
839 int bufsize = *((int *) optval);
846 ret = setsockopt (fd, level, optname, tmp_val, optlen);
850 g_message ("%s: setsockopt error: %s", __func__,
854 errnum = errno_to_WSA (errnum, __func__);
855 WSASetLastError (errnum);
857 return(SOCKET_ERROR);
860 #if defined (SO_REUSEPORT)
861 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
862 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
864 socklen_t type_len = sizeof (type);
866 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
867 if (type == SOCK_DGRAM)
868 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
876 int _wapi_shutdown(guint32 fd, int how)
878 struct _WapiHandle_socket *socket_handle;
880 gpointer handle = GUINT_TO_POINTER (fd);
883 if (startup_count == 0) {
884 WSASetLastError (WSANOTINITIALISED);
885 return(SOCKET_ERROR);
888 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
889 WSASetLastError (WSAENOTSOCK);
890 return(SOCKET_ERROR);
893 if (how == SHUT_RD ||
895 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
896 (gpointer *)&socket_handle);
898 g_warning ("%s: error looking up socket handle %p",
900 WSASetLastError (WSAENOTSOCK);
901 return(SOCKET_ERROR);
904 socket_handle->still_readable = 0;
907 ret = shutdown (fd, how);
911 g_message ("%s: shutdown error: %s", __func__,
915 errnum = errno_to_WSA (errnum, __func__);
916 WSASetLastError (errnum);
918 return(SOCKET_ERROR);
924 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
925 guint32 unused2, guint32 unused3)
927 struct _WapiHandle_socket socket_handle = {0};
931 socket_handle.domain = domain;
932 socket_handle.type = type;
933 socket_handle.protocol = protocol;
934 socket_handle.still_readable = 1;
936 fd = socket (domain, type, protocol);
937 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
939 /* Retry with protocol == 4 (see bug #54565) */
940 socket_handle.protocol = 4;
941 fd = socket (AF_INET, SOCK_RAW, 4);
947 g_message ("%s: socket error: %s", __func__, strerror (errno));
949 errnum = errno_to_WSA (errnum, __func__);
950 WSASetLastError (errnum);
952 return(INVALID_SOCKET);
955 if (fd >= _wapi_fd_reserve) {
957 g_message ("%s: File descriptor is too big (%d >= %d)",
958 __func__, fd, _wapi_fd_reserve);
961 WSASetLastError (WSASYSCALLFAILURE);
964 return(INVALID_SOCKET);
967 /* .net seems to set this by default for SOCK_STREAM, not for
968 * SOCK_DGRAM (see bug #36322)
970 * It seems winsock has a rather different idea of what
971 * SO_REUSEADDR means. If it's set, then a new socket can be
972 * bound over an existing listening socket. There's a new
973 * windows-specific option called SO_EXCLUSIVEADDRUSE but
974 * using that means the socket MUST be closed properly, or a
975 * denial of service can occur. Luckily for us, winsock
976 * behaves as though any other system would when SO_REUSEADDR
977 * is true, so we don't need to do anything else here. See
983 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
989 g_message ("%s: Error setting SO_REUSEADDR", __func__);
992 errnum = errno_to_WSA (errnum, __func__);
993 WSASetLastError (errnum);
997 return(INVALID_SOCKET);
1002 mono_once (&socket_ops_once, socket_ops_init);
1004 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
1005 if (handle == _WAPI_HANDLE_INVALID) {
1006 g_warning ("%s: error creating socket handle", __func__);
1007 WSASetLastError (WSASYSCALLFAILURE);
1009 return(INVALID_SOCKET);
1013 g_message ("%s: returning socket handle %p", __func__, handle);
1019 struct hostent *_wapi_gethostbyname(const char *hostname)
1023 if (startup_count == 0) {
1024 WSASetLastError (WSANOTINITIALISED);
1028 he = gethostbyname (hostname);
1031 g_message ("%s: gethostbyname error: %s", __func__,
1032 strerror (h_errno));
1036 case HOST_NOT_FOUND:
1037 WSASetLastError (WSAHOST_NOT_FOUND);
1039 #if NO_ADDRESS != NO_DATA
1043 WSASetLastError (WSANO_DATA);
1046 WSASetLastError (WSANO_RECOVERY);
1049 WSASetLastError (WSATRY_AGAIN);
1052 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1060 static gboolean socket_disconnect (guint32 fd)
1062 struct _WapiHandle_socket *socket_handle;
1064 gpointer handle = GUINT_TO_POINTER (fd);
1067 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1068 (gpointer *)&socket_handle);
1070 g_warning ("%s: error looking up socket handle %p", __func__,
1072 WSASetLastError (WSAENOTSOCK);
1076 newsock = socket (socket_handle->domain, socket_handle->type,
1077 socket_handle->protocol);
1078 if (newsock == -1) {
1079 gint errnum = errno;
1082 g_message ("%s: socket error: %s", __func__, strerror (errno));
1085 errnum = errno_to_WSA (errnum, __func__);
1086 WSASetLastError (errnum);
1091 /* According to Stevens "Advanced Programming in the UNIX
1092 * Environment: UNIX File I/O" dup2() is atomic so there
1093 * should not be a race condition between the old fd being
1094 * closed and the new socket fd being copied over
1097 ret = dup2 (newsock, fd);
1098 } while (ret == -1 && errno == EAGAIN);
1101 gint errnum = errno;
1104 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1107 errnum = errno_to_WSA (errnum, __func__);
1108 WSASetLastError (errnum);
1118 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1119 guint32 flags, guint32 reserved)
1122 g_message ("%s: called on socket %d!", __func__, fd);
1125 if (reserved != 0) {
1126 WSASetLastError (WSAEINVAL);
1130 /* We could check the socket type here and fail unless its
1131 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1132 * if we really wanted to
1135 return(socket_disconnect (fd));
1138 #define SF_BUFFER_SIZE 16384
1140 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1142 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1143 gint file = GPOINTER_TO_INT (fd);
1147 struct stat statbuf;
1149 n = fstat (file, &statbuf);
1152 errnum = errno_to_WSA (errnum, __func__);
1153 WSASetLastError (errnum);
1154 return SOCKET_ERROR;
1158 res = sendfile (socket, file, NULL, statbuf.st_size);
1159 #elif defined(DARWIN)
1160 /* TODO: header/tail could be sent in the 5th argument */
1161 /* TODO: Might not send the entire file for non-blocking sockets */
1162 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1164 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1167 errnum = errno_to_WSA (errnum, __func__);
1168 WSASetLastError (errnum);
1169 return SOCKET_ERROR;
1172 /* Default implementation */
1173 gint file = GPOINTER_TO_INT (fd);
1177 buffer = g_malloc (SF_BUFFER_SIZE);
1180 n = read (file, buffer, SF_BUFFER_SIZE);
1181 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1186 return 0; /* We're done reading */
1189 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1190 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1194 gint errnum = errno;
1195 errnum = errno_to_WSA (errnum, __func__);
1196 WSASetLastError (errnum);
1198 return SOCKET_ERROR;
1206 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1207 WapiTransmitFileBuffers *buffers, guint32 flags)
1209 gpointer sock = GUINT_TO_POINTER (socket);
1212 if (startup_count == 0) {
1213 WSASetLastError (WSANOTINITIALISED);
1217 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1218 WSASetLastError (WSAENOTSOCK);
1222 /* Write the header */
1223 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1224 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1225 if (ret == SOCKET_ERROR)
1229 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1230 if (ret == SOCKET_ERROR)
1233 /* Write the tail */
1234 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1235 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1236 if (ret == SOCKET_ERROR)
1240 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1241 closesocket (socket);
1250 } extension_functions[] = {
1251 {WSAID_DISCONNECTEX, wapi_disconnectex},
1252 {WSAID_TRANSMITFILE, TransmitFile},
1257 WSAIoctl (guint32 fd, gint32 command,
1258 gchar *input, gint i_len,
1259 gchar *output, gint o_len, glong *written,
1260 void *unused1, void *unused2)
1262 gpointer handle = GUINT_TO_POINTER (fd);
1264 gchar *buffer = NULL;
1266 if (startup_count == 0) {
1267 WSASetLastError (WSANOTINITIALISED);
1268 return(SOCKET_ERROR);
1271 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1272 WSASetLastError (WSAENOTSOCK);
1273 return SOCKET_ERROR;
1276 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1278 WapiGuid *guid = (WapiGuid *)input;
1280 if (i_len < sizeof(WapiGuid)) {
1281 /* As far as I can tell, windows doesn't
1282 * actually set an error here...
1284 WSASetLastError (WSAEINVAL);
1285 return(SOCKET_ERROR);
1288 if (o_len < sizeof(gpointer)) {
1290 WSASetLastError (WSAEINVAL);
1291 return(SOCKET_ERROR);
1294 if (output == NULL) {
1296 WSASetLastError (WSAEINVAL);
1297 return(SOCKET_ERROR);
1300 while(extension_functions[i].func != NULL) {
1301 if (!memcmp (guid, &extension_functions[i].guid,
1302 sizeof(WapiGuid))) {
1303 memcpy (output, &extension_functions[i].func,
1305 *written = sizeof(gpointer);
1312 WSASetLastError (WSAEINVAL);
1313 return(SOCKET_ERROR);
1317 buffer = g_memdup (input, i_len);
1320 ret = ioctl (fd, command, buffer);
1322 gint errnum = errno;
1324 g_message("%s: WSAIoctl error: %s", __func__,
1328 errnum = errno_to_WSA (errnum, __func__);
1329 WSASetLastError (errnum);
1332 return(SOCKET_ERROR);
1335 if (buffer == NULL) {
1338 /* We just copy the buffer to the output. Some ioctls
1339 * don't even output any data, but, well...
1341 * NB windows returns WSAEFAULT if o_len is too small
1343 i_len = (i_len > o_len) ? o_len : i_len;
1345 if (i_len > 0 && output != NULL) {
1346 memcpy (output, buffer, i_len);
1356 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1357 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1359 gpointer handle = GUINT_TO_POINTER (fd);
1362 if (startup_count == 0) {
1363 WSASetLastError (WSANOTINITIALISED);
1364 return(SOCKET_ERROR);
1367 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1368 WSASetLastError (WSAENOTSOCK);
1369 return(SOCKET_ERROR);
1375 /* This works better than ioctl(...FIONBIO...)
1376 * on Linux (it causes connect to return
1377 * EINPROGRESS, but the ioctl doesn't seem to)
1379 ret = fcntl(fd, F_GETFL, 0);
1381 if (*(gboolean *)arg) {
1386 ret = fcntl(fd, F_SETFL, ret);
1389 #endif /* O_NONBLOCK */
1390 /* Unused in Mono */
1392 ret = ioctl (fd, command, arg);
1397 #if defined (PLATFORM_MACOSX)
1399 // ioctl (fd, FIONREAD, XXX) returns the size of
1400 // the UDP header as well on
1403 // Use getsockopt SO_NREAD instead to get the
1404 // right values for TCP and UDP.
1406 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1407 // be the value of the ip buffer.
1409 socklen_t optlen = sizeof (int);
1410 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1412 ret = ioctl (fd, command, arg);
1417 WSASetLastError (WSAEINVAL);
1418 return(SOCKET_ERROR);
1422 gint errnum = errno;
1424 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1427 errnum = errno_to_WSA (errnum, __func__);
1428 WSASetLastError (errnum);
1430 return(SOCKET_ERROR);
1436 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1437 fd_set *exceptfds, struct timeval *timeout)
1441 if (startup_count == 0) {
1442 WSASetLastError (WSANOTINITIALISED);
1443 return(SOCKET_ERROR);
1446 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1447 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1448 (writefds && FD_ISSET (maxfd, writefds)) ||
1449 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1455 WSASetLastError (WSAEINVAL);
1456 return(SOCKET_ERROR);
1460 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1462 } while (ret == -1 && errno == EINTR &&
1463 !_wapi_thread_cur_apc_pending ());
1466 gint errnum = errno;
1468 g_message ("%s: select error: %s", __func__, strerror (errno));
1470 errnum = errno_to_WSA (errnum, __func__);
1471 WSASetLastError (errnum);
1473 return(SOCKET_ERROR);
1479 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1481 gpointer handle = GUINT_TO_POINTER (fd);
1483 if (fd >= FD_SETSIZE) {
1484 WSASetLastError (WSAEINVAL);
1488 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1489 WSASetLastError (WSAENOTSOCK);
1496 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1498 gpointer handle = GUINT_TO_POINTER (fd);
1500 if (fd >= FD_SETSIZE) {
1501 WSASetLastError (WSAEINVAL);
1505 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1506 WSASetLastError (WSAENOTSOCK);
1510 return(FD_ISSET (fd, set));
1513 void _wapi_FD_SET(guint32 fd, fd_set *set)
1515 gpointer handle = GUINT_TO_POINTER (fd);
1517 if (fd >= FD_SETSIZE) {
1518 WSASetLastError (WSAEINVAL);
1522 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1523 WSASetLastError (WSAENOTSOCK);
1532 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1536 memset (hdr, 0, sizeof (struct msghdr));
1537 hdr->msg_iovlen = count;
1538 hdr->msg_iov = g_new0 (struct iovec, count);
1539 for (i = 0; i < count; i++) {
1540 hdr->msg_iov [i].iov_base = buffers [i].buf;
1541 hdr->msg_iov [i].iov_len = buffers [i].len;
1546 msghdr_iov_free (struct msghdr *hdr)
1548 g_free (hdr->msg_iov);
1551 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1552 guint32 *flags, WapiOverlapped *overlapped,
1553 WapiOverlappedCB *complete)
1558 g_assert (overlapped == NULL);
1559 g_assert (complete == NULL);
1561 wsabuf_to_msghdr (buffers, count, &hdr);
1562 ret = _wapi_recvmsg (fd, &hdr, *flags);
1563 msghdr_iov_free (&hdr);
1565 if(ret == SOCKET_ERROR) {
1570 *flags = hdr.msg_flags;
1575 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1576 guint32 flags, WapiOverlapped *overlapped,
1577 WapiOverlappedCB *complete)
1582 g_assert (overlapped == NULL);
1583 g_assert (complete == NULL);
1585 wsabuf_to_msghdr (buffers, count, &hdr);
1586 ret = _wapi_sendmsg (fd, &hdr, flags);
1587 msghdr_iov_free (&hdr);
1589 if(ret == SOCKET_ERROR)
1596 #endif /* ifndef DISABLE_SOCKETS */