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;
58 static void socket_close (gpointer handle, gpointer data);
60 struct _WapiHandleOps _wapi_socket_ops = {
61 socket_close, /* close */
65 NULL, /* special_wait */
69 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
71 static void socket_ops_init (void)
73 /* No capabilities to register */
76 static void socket_close (gpointer handle, gpointer data)
79 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
82 g_message ("%s: closing socket handle %p", __func__, handle);
85 if (startup_count == 0) {
86 WSASetLastError (WSANOTINITIALISED);
90 /* Shutdown the socket for reading, to interrupt any potential
91 * receives that may be blocking for data. See bug 75705.
93 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
96 ret = close (GPOINTER_TO_UINT(handle));
97 } while (ret == -1 && errno == EINTR &&
98 !_wapi_thread_cur_apc_pending ());
103 g_message ("%s: close error: %s", __func__, strerror (errno));
105 errnum = errno_to_WSA (errnum, __func__);
106 WSASetLastError (errnum);
109 socket_handle->saved_error = 0;
112 int WSAStartup(guint32 requested, WapiWSAData *data)
118 /* Insist on v2.0+ */
119 if (requested < MAKEWORD(2,0)) {
120 return(WSAVERNOTSUPPORTED);
125 /* I've no idea what is the minor version of the spec I read */
126 data->wHighVersion = MAKEWORD(2,2);
128 data->wVersion = requested < data->wHighVersion? requested:
132 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
135 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
136 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
142 cleanup_close (gpointer handle, gpointer data)
144 _wapi_handle_ops_close (handle, NULL);
151 g_message ("%s: cleaning up", __func__);
154 if (--startup_count) {
159 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
163 void WSASetLastError(int error)
165 SetLastError (error);
168 int WSAGetLastError(void)
170 return(GetLastError ());
173 int closesocket(guint32 fd)
175 gpointer handle = GUINT_TO_POINTER (fd);
177 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
178 WSASetLastError (WSAENOTSOCK);
182 _wapi_handle_unref (handle);
186 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
188 gpointer handle = GUINT_TO_POINTER (fd);
190 struct _WapiHandle_socket *socket_handle;
191 struct _WapiHandle_socket new_socket_handle = {0};
195 if (startup_count == 0) {
196 WSASetLastError (WSANOTINITIALISED);
197 return(INVALID_SOCKET);
200 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
201 WSASetLastError (WSAEFAULT);
202 return(INVALID_SOCKET);
205 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
206 WSASetLastError (WSAENOTSOCK);
207 return(INVALID_SOCKET);
210 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
211 (gpointer *)&socket_handle);
213 g_warning ("%s: error looking up socket handle %p",
215 WSASetLastError (WSAENOTSOCK);
216 return(INVALID_SOCKET);
220 new_fd = accept (fd, addr, addrlen);
221 } while (new_fd == -1 && errno == EINTR &&
222 !_wapi_thread_cur_apc_pending());
227 g_message ("%s: accept error: %s", __func__, strerror(errno));
230 errnum = errno_to_WSA (errnum, __func__);
231 WSASetLastError (errnum);
233 return(INVALID_SOCKET);
236 if (new_fd >= _wapi_fd_reserve) {
238 g_message ("%s: File descriptor is too big", __func__);
241 WSASetLastError (WSASYSCALLFAILURE);
245 return(INVALID_SOCKET);
248 new_socket_handle.domain = socket_handle->domain;
249 new_socket_handle.type = socket_handle->type;
250 new_socket_handle.protocol = socket_handle->protocol;
251 new_socket_handle.still_readable = 1;
253 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
255 if(new_handle == _WAPI_HANDLE_INVALID) {
256 g_warning ("%s: error creating socket handle", __func__);
257 WSASetLastError (ERROR_GEN_FAILURE);
258 return(INVALID_SOCKET);
262 g_message ("%s: returning newly accepted socket handle %p with",
263 __func__, new_handle);
269 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
271 gpointer handle = GUINT_TO_POINTER (fd);
274 if (startup_count == 0) {
275 WSASetLastError (WSANOTINITIALISED);
276 return(SOCKET_ERROR);
279 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
280 WSASetLastError (WSAENOTSOCK);
281 return(SOCKET_ERROR);
284 ret = bind (fd, my_addr, addrlen);
288 g_message ("%s: bind error: %s", __func__, strerror(errno));
290 errnum = errno_to_WSA (errnum, __func__);
291 WSASetLastError (errnum);
293 return(SOCKET_ERROR);
298 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
301 gpointer handle = GUINT_TO_POINTER (fd);
302 struct _WapiHandle_socket *socket_handle;
306 if (startup_count == 0) {
307 WSASetLastError (WSANOTINITIALISED);
308 return(SOCKET_ERROR);
311 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
312 WSASetLastError (WSAENOTSOCK);
313 return(SOCKET_ERROR);
316 if (connect (fd, serv_addr, addrlen) == -1) {
323 if (errno != EINTR) {
325 g_message ("%s: connect error: %s", __func__,
329 errnum = errno_to_WSA (errnum, __func__);
330 if (errnum == WSAEINPROGRESS)
331 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
333 WSASetLastError (errnum);
336 * On solaris x86 getsockopt (SO_ERROR) is not set after
337 * connect () fails so we need to save this error.
339 * But don't do this for EWOULDBLOCK (bug 317315)
341 if (errnum != WSAEWOULDBLOCK) {
342 ok = _wapi_lookup_handle (handle,
344 (gpointer *)&socket_handle);
346 /* ECONNRESET means the socket was closed by another thread */
347 if (errnum != WSAECONNRESET)
348 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
350 socket_handle->saved_error = errnum;
353 return(SOCKET_ERROR);
357 fds.events = POLLOUT;
358 while (mono_poll (&fds, 1, -1) == -1 &&
359 !_wapi_thread_cur_apc_pending ()) {
360 if (errno != EINTR) {
361 errnum = errno_to_WSA (errno, __func__);
364 g_message ("%s: connect poll error: %s",
365 __func__, strerror (errno));
368 WSASetLastError (errnum);
369 return(SOCKET_ERROR);
373 len = sizeof(so_error);
374 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
376 errnum = errno_to_WSA (errno, __func__);
379 g_message ("%s: connect getsockopt error: %s",
380 __func__, strerror (errno));
383 WSASetLastError (errnum);
384 return(SOCKET_ERROR);
388 errnum = errno_to_WSA (so_error, __func__);
390 /* Need to save this socket error */
391 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
392 (gpointer *)&socket_handle);
394 g_warning ("%s: error looking up socket handle %p", __func__, handle);
396 socket_handle->saved_error = errnum;
400 g_message ("%s: connect getsockopt returned error: %s",
401 __func__, strerror (so_error));
404 WSASetLastError (errnum);
405 return(SOCKET_ERROR);
412 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
414 gpointer handle = GUINT_TO_POINTER (fd);
417 if (startup_count == 0) {
418 WSASetLastError (WSANOTINITIALISED);
419 return(SOCKET_ERROR);
422 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
423 WSASetLastError (WSAENOTSOCK);
424 return(SOCKET_ERROR);
427 ret = getpeername (fd, name, namelen);
431 g_message ("%s: getpeername error: %s", __func__,
435 errnum = errno_to_WSA (errnum, __func__);
436 WSASetLastError (errnum);
438 return(SOCKET_ERROR);
444 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
446 gpointer handle = GUINT_TO_POINTER (fd);
449 if (startup_count == 0) {
450 WSASetLastError (WSANOTINITIALISED);
451 return(SOCKET_ERROR);
454 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
455 WSASetLastError (WSAENOTSOCK);
456 return(SOCKET_ERROR);
459 ret = getsockname (fd, name, namelen);
463 g_message ("%s: getsockname error: %s", __func__,
467 errnum = errno_to_WSA (errnum, __func__);
468 WSASetLastError (errnum);
470 return(SOCKET_ERROR);
476 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
479 gpointer handle = GUINT_TO_POINTER (fd);
483 struct _WapiHandle_socket *socket_handle;
486 if (startup_count == 0) {
487 WSASetLastError (WSANOTINITIALISED);
488 return(SOCKET_ERROR);
491 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
492 WSASetLastError (WSAENOTSOCK);
493 return(SOCKET_ERROR);
497 if (level == SOL_SOCKET &&
498 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
500 *optlen = sizeof (tv);
503 ret = getsockopt (fd, level, optname, tmp_val, optlen);
507 g_message ("%s: getsockopt error: %s", __func__,
511 errnum = errno_to_WSA (errnum, __func__);
512 WSASetLastError (errnum);
514 return(SOCKET_ERROR);
517 if (level == SOL_SOCKET &&
518 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
519 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
520 *optlen = sizeof (int);
523 if (optname == SO_ERROR) {
524 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
525 (gpointer *)&socket_handle);
527 g_warning ("%s: error looking up socket handle %p",
530 /* can't extract the last error */
531 *((int *) optval) = errno_to_WSA (*((int *)optval),
534 if (*((int *)optval) != 0) {
535 *((int *) optval) = errno_to_WSA (*((int *)optval),
537 socket_handle->saved_error = *((int *)optval);
539 *((int *)optval) = socket_handle->saved_error;
547 int _wapi_listen(guint32 fd, int backlog)
549 gpointer handle = GUINT_TO_POINTER (fd);
552 if (startup_count == 0) {
553 WSASetLastError (WSANOTINITIALISED);
554 return(SOCKET_ERROR);
557 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
558 WSASetLastError (WSAENOTSOCK);
559 return(SOCKET_ERROR);
562 ret = listen (fd, backlog);
566 g_message ("%s: listen error: %s", __func__, strerror (errno));
569 errnum = errno_to_WSA (errnum, __func__);
570 WSASetLastError (errnum);
572 return(SOCKET_ERROR);
578 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
580 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
583 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
584 struct sockaddr *from, socklen_t *fromlen)
586 gpointer handle = GUINT_TO_POINTER (fd);
587 struct _WapiHandle_socket *socket_handle;
591 if (startup_count == 0) {
592 WSASetLastError (WSANOTINITIALISED);
593 return(SOCKET_ERROR);
596 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
597 WSASetLastError (WSAENOTSOCK);
598 return(SOCKET_ERROR);
602 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
603 } while (ret == -1 && errno == EINTR &&
604 !_wapi_thread_cur_apc_pending ());
606 if (ret == 0 && len > 0) {
607 /* According to the Linux man page, recvfrom only
608 * returns 0 when the socket has been shut down
609 * cleanly. Turn this into an EINTR to simulate win32
610 * behaviour of returning EINTR when a socket is
611 * closed while the recvfrom is blocking (we use a
612 * shutdown() in socket_close() to trigger this.) See
615 /* Distinguish between the socket being shut down at
616 * the local or remote ends, and reads that request 0
620 /* If this returns FALSE, it means the socket has been
621 * closed locally. If it returns TRUE, but
622 * still_readable != 1 then shutdown
623 * (SHUT_RD|SHUT_RDWR) has been called locally.
625 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
626 (gpointer *)&socket_handle);
627 if (ok == FALSE || socket_handle->still_readable != 1) {
636 g_message ("%s: recv error: %s", __func__, strerror(errno));
639 errnum = errno_to_WSA (errnum, __func__);
640 WSASetLastError (errnum);
642 return(SOCKET_ERROR);
648 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
650 gpointer handle = GUINT_TO_POINTER (fd);
651 struct _WapiHandle_socket *socket_handle;
655 if (startup_count == 0) {
656 WSASetLastError (WSANOTINITIALISED);
657 return(SOCKET_ERROR);
660 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
661 WSASetLastError (WSAENOTSOCK);
662 return(SOCKET_ERROR);
666 ret = recvmsg (fd, msg, recv_flags);
667 } while (ret == -1 && errno == EINTR &&
668 !_wapi_thread_cur_apc_pending ());
671 /* see _wapi_recvfrom */
672 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
673 (gpointer *)&socket_handle);
674 if (ok == FALSE || socket_handle->still_readable != 1) {
683 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
686 errnum = errno_to_WSA (errnum, __func__);
687 WSASetLastError (errnum);
689 return(SOCKET_ERROR);
694 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
696 gpointer handle = GUINT_TO_POINTER (fd);
699 if (startup_count == 0) {
700 WSASetLastError (WSANOTINITIALISED);
701 return(SOCKET_ERROR);
704 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
705 WSASetLastError (WSAENOTSOCK);
706 return(SOCKET_ERROR);
710 ret = send (fd, msg, len, send_flags);
711 } while (ret == -1 && errno == EINTR &&
712 !_wapi_thread_cur_apc_pending ());
717 g_message ("%s: send error: %s", __func__, strerror (errno));
721 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
722 * a blocking socket. See bug #599488 */
723 if (errnum == EAGAIN) {
724 ret = fcntl (fd, F_GETFL, 0);
725 if (ret != -1 && (ret & O_NONBLOCK) == 0)
728 #endif /* O_NONBLOCK */
729 errnum = errno_to_WSA (errnum, __func__);
730 WSASetLastError (errnum);
732 return(SOCKET_ERROR);
737 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
738 const struct sockaddr *to, socklen_t tolen)
740 gpointer handle = GUINT_TO_POINTER (fd);
743 if (startup_count == 0) {
744 WSASetLastError (WSANOTINITIALISED);
745 return(SOCKET_ERROR);
748 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
749 WSASetLastError (WSAENOTSOCK);
750 return(SOCKET_ERROR);
754 ret = sendto (fd, msg, len, send_flags, to, tolen);
755 } while (ret == -1 && errno == EINTR &&
756 !_wapi_thread_cur_apc_pending ());
761 g_message ("%s: send error: %s", __func__, strerror (errno));
764 errnum = errno_to_WSA (errnum, __func__);
765 WSASetLastError (errnum);
767 return(SOCKET_ERROR);
773 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
775 gpointer handle = GUINT_TO_POINTER (fd);
778 if (startup_count == 0) {
779 WSASetLastError (WSANOTINITIALISED);
780 return(SOCKET_ERROR);
783 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
784 WSASetLastError (WSAENOTSOCK);
785 return(SOCKET_ERROR);
789 ret = sendmsg (fd, msg, send_flags);
790 } while (ret == -1 && errno == EINTR &&
791 !_wapi_thread_cur_apc_pending ());
796 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
799 errnum = errno_to_WSA (errnum, __func__);
800 WSASetLastError (errnum);
802 return(SOCKET_ERROR);
807 int _wapi_setsockopt(guint32 fd, int level, int optname,
808 const void *optval, socklen_t optlen)
810 gpointer handle = GUINT_TO_POINTER (fd);
815 if (startup_count == 0) {
816 WSASetLastError (WSANOTINITIALISED);
817 return(SOCKET_ERROR);
820 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
821 WSASetLastError (WSAENOTSOCK);
822 return(SOCKET_ERROR);
826 if (level == SOL_SOCKET &&
827 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
828 int ms = *((int *) optval);
829 tv.tv_sec = ms / 1000;
830 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
832 optlen = sizeof (tv);
833 #if defined (__linux__)
834 } else if (level == SOL_SOCKET &&
835 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
836 /* According to socket(7) the Linux kernel doubles the
837 * buffer sizes "to allow space for bookkeeping
840 int bufsize = *((int *) optval);
847 ret = setsockopt (fd, level, optname, tmp_val, optlen);
851 g_message ("%s: setsockopt error: %s", __func__,
855 errnum = errno_to_WSA (errnum, __func__);
856 WSASetLastError (errnum);
858 return(SOCKET_ERROR);
861 #if defined (SO_REUSEPORT)
862 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
863 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
865 socklen_t type_len = sizeof (type);
867 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
868 if (type == SOCK_DGRAM)
869 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
877 int _wapi_shutdown(guint32 fd, int how)
879 struct _WapiHandle_socket *socket_handle;
881 gpointer handle = GUINT_TO_POINTER (fd);
884 if (startup_count == 0) {
885 WSASetLastError (WSANOTINITIALISED);
886 return(SOCKET_ERROR);
889 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
890 WSASetLastError (WSAENOTSOCK);
891 return(SOCKET_ERROR);
894 if (how == SHUT_RD ||
896 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
897 (gpointer *)&socket_handle);
899 g_warning ("%s: error looking up socket handle %p",
901 WSASetLastError (WSAENOTSOCK);
902 return(SOCKET_ERROR);
905 socket_handle->still_readable = 0;
908 ret = shutdown (fd, how);
912 g_message ("%s: shutdown error: %s", __func__,
916 errnum = errno_to_WSA (errnum, __func__);
917 WSASetLastError (errnum);
919 return(SOCKET_ERROR);
925 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
926 guint32 unused2, guint32 unused3)
928 struct _WapiHandle_socket socket_handle = {0};
932 socket_handle.domain = domain;
933 socket_handle.type = type;
934 socket_handle.protocol = protocol;
935 socket_handle.still_readable = 1;
937 fd = socket (domain, type, protocol);
938 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
940 /* Retry with protocol == 4 (see bug #54565) */
941 socket_handle.protocol = 4;
942 fd = socket (AF_INET, SOCK_RAW, 4);
948 g_message ("%s: socket error: %s", __func__, strerror (errno));
950 errnum = errno_to_WSA (errnum, __func__);
951 WSASetLastError (errnum);
953 return(INVALID_SOCKET);
956 if (fd >= _wapi_fd_reserve) {
958 g_message ("%s: File descriptor is too big (%d >= %d)",
959 __func__, fd, _wapi_fd_reserve);
962 WSASetLastError (WSASYSCALLFAILURE);
965 return(INVALID_SOCKET);
968 /* .net seems to set this by default for SOCK_STREAM, not for
969 * SOCK_DGRAM (see bug #36322)
971 * It seems winsock has a rather different idea of what
972 * SO_REUSEADDR means. If it's set, then a new socket can be
973 * bound over an existing listening socket. There's a new
974 * windows-specific option called SO_EXCLUSIVEADDRUSE but
975 * using that means the socket MUST be closed properly, or a
976 * denial of service can occur. Luckily for us, winsock
977 * behaves as though any other system would when SO_REUSEADDR
978 * is true, so we don't need to do anything else here. See
984 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
990 g_message ("%s: Error setting SO_REUSEADDR", __func__);
993 errnum = errno_to_WSA (errnum, __func__);
994 WSASetLastError (errnum);
998 return(INVALID_SOCKET);
1003 mono_once (&socket_ops_once, socket_ops_init);
1005 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
1006 if (handle == _WAPI_HANDLE_INVALID) {
1007 g_warning ("%s: error creating socket handle", __func__);
1008 WSASetLastError (WSASYSCALLFAILURE);
1010 return(INVALID_SOCKET);
1014 g_message ("%s: returning socket handle %p", __func__, handle);
1020 struct hostent *_wapi_gethostbyname(const char *hostname)
1024 if (startup_count == 0) {
1025 WSASetLastError (WSANOTINITIALISED);
1029 he = gethostbyname (hostname);
1032 g_message ("%s: gethostbyname error: %s", __func__,
1033 strerror (h_errno));
1037 case HOST_NOT_FOUND:
1038 WSASetLastError (WSAHOST_NOT_FOUND);
1040 #if NO_ADDRESS != NO_DATA
1044 WSASetLastError (WSANO_DATA);
1047 WSASetLastError (WSANO_RECOVERY);
1050 WSASetLastError (WSATRY_AGAIN);
1053 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1061 static gboolean socket_disconnect (guint32 fd)
1063 struct _WapiHandle_socket *socket_handle;
1065 gpointer handle = GUINT_TO_POINTER (fd);
1068 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1069 (gpointer *)&socket_handle);
1071 g_warning ("%s: error looking up socket handle %p", __func__,
1073 WSASetLastError (WSAENOTSOCK);
1077 newsock = socket (socket_handle->domain, socket_handle->type,
1078 socket_handle->protocol);
1079 if (newsock == -1) {
1080 gint errnum = errno;
1083 g_message ("%s: socket error: %s", __func__, strerror (errno));
1086 errnum = errno_to_WSA (errnum, __func__);
1087 WSASetLastError (errnum);
1092 /* According to Stevens "Advanced Programming in the UNIX
1093 * Environment: UNIX File I/O" dup2() is atomic so there
1094 * should not be a race condition between the old fd being
1095 * closed and the new socket fd being copied over
1098 ret = dup2 (newsock, fd);
1099 } while (ret == -1 && errno == EAGAIN);
1102 gint errnum = errno;
1105 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1108 errnum = errno_to_WSA (errnum, __func__);
1109 WSASetLastError (errnum);
1119 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1120 guint32 flags, guint32 reserved)
1123 g_message ("%s: called on socket %d!", __func__, fd);
1126 if (reserved != 0) {
1127 WSASetLastError (WSAEINVAL);
1131 /* We could check the socket type here and fail unless its
1132 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1133 * if we really wanted to
1136 return(socket_disconnect (fd));
1139 #define SF_BUFFER_SIZE 16384
1141 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1143 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1144 gint file = GPOINTER_TO_INT (fd);
1148 struct stat statbuf;
1150 n = fstat (file, &statbuf);
1153 errnum = errno_to_WSA (errnum, __func__);
1154 WSASetLastError (errnum);
1155 return SOCKET_ERROR;
1159 res = sendfile (socket, file, NULL, statbuf.st_size);
1160 #elif defined(DARWIN)
1161 /* TODO: header/tail could be sent in the 5th argument */
1162 /* TODO: Might not send the entire file for non-blocking sockets */
1163 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1165 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1168 errnum = errno_to_WSA (errnum, __func__);
1169 WSASetLastError (errnum);
1170 return SOCKET_ERROR;
1173 /* Default implementation */
1174 gint file = GPOINTER_TO_INT (fd);
1178 buffer = g_malloc (SF_BUFFER_SIZE);
1181 n = read (file, buffer, SF_BUFFER_SIZE);
1182 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1187 return 0; /* We're done reading */
1190 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1191 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1195 gint errnum = errno;
1196 errnum = errno_to_WSA (errnum, __func__);
1197 WSASetLastError (errnum);
1199 return SOCKET_ERROR;
1207 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1208 WapiTransmitFileBuffers *buffers, guint32 flags)
1210 gpointer sock = GUINT_TO_POINTER (socket);
1213 if (startup_count == 0) {
1214 WSASetLastError (WSANOTINITIALISED);
1218 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1219 WSASetLastError (WSAENOTSOCK);
1223 /* Write the header */
1224 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1225 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1226 if (ret == SOCKET_ERROR)
1230 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1231 if (ret == SOCKET_ERROR)
1234 /* Write the tail */
1235 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1236 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1237 if (ret == SOCKET_ERROR)
1241 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1242 closesocket (socket);
1251 } extension_functions[] = {
1252 {WSAID_DISCONNECTEX, wapi_disconnectex},
1253 {WSAID_TRANSMITFILE, TransmitFile},
1258 WSAIoctl (guint32 fd, gint32 command,
1259 gchar *input, gint i_len,
1260 gchar *output, gint o_len, glong *written,
1261 void *unused1, void *unused2)
1263 gpointer handle = GUINT_TO_POINTER (fd);
1265 gchar *buffer = NULL;
1267 if (startup_count == 0) {
1268 WSASetLastError (WSANOTINITIALISED);
1269 return(SOCKET_ERROR);
1272 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1273 WSASetLastError (WSAENOTSOCK);
1274 return SOCKET_ERROR;
1277 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1279 WapiGuid *guid = (WapiGuid *)input;
1281 if (i_len < sizeof(WapiGuid)) {
1282 /* As far as I can tell, windows doesn't
1283 * actually set an error here...
1285 WSASetLastError (WSAEINVAL);
1286 return(SOCKET_ERROR);
1289 if (o_len < sizeof(gpointer)) {
1291 WSASetLastError (WSAEINVAL);
1292 return(SOCKET_ERROR);
1295 if (output == NULL) {
1297 WSASetLastError (WSAEINVAL);
1298 return(SOCKET_ERROR);
1301 while(extension_functions[i].func != NULL) {
1302 if (!memcmp (guid, &extension_functions[i].guid,
1303 sizeof(WapiGuid))) {
1304 memcpy (output, &extension_functions[i].func,
1306 *written = sizeof(gpointer);
1313 WSASetLastError (WSAEINVAL);
1314 return(SOCKET_ERROR);
1318 buffer = g_memdup (input, i_len);
1321 ret = ioctl (fd, command, buffer);
1323 gint errnum = errno;
1325 g_message("%s: WSAIoctl error: %s", __func__,
1329 errnum = errno_to_WSA (errnum, __func__);
1330 WSASetLastError (errnum);
1333 return(SOCKET_ERROR);
1336 if (buffer == NULL) {
1339 /* We just copy the buffer to the output. Some ioctls
1340 * don't even output any data, but, well...
1342 * NB windows returns WSAEFAULT if o_len is too small
1344 i_len = (i_len > o_len) ? o_len : i_len;
1346 if (i_len > 0 && output != NULL) {
1347 memcpy (output, buffer, i_len);
1357 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1358 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1360 gpointer handle = GUINT_TO_POINTER (fd);
1363 if (startup_count == 0) {
1364 WSASetLastError (WSANOTINITIALISED);
1365 return(SOCKET_ERROR);
1368 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1369 WSASetLastError (WSAENOTSOCK);
1370 return(SOCKET_ERROR);
1376 /* This works better than ioctl(...FIONBIO...)
1377 * on Linux (it causes connect to return
1378 * EINPROGRESS, but the ioctl doesn't seem to)
1380 ret = fcntl(fd, F_GETFL, 0);
1382 if (*(gboolean *)arg) {
1387 ret = fcntl(fd, F_SETFL, ret);
1390 #endif /* O_NONBLOCK */
1391 /* Unused in Mono */
1393 ret = ioctl (fd, command, arg);
1398 #if defined (PLATFORM_MACOSX)
1400 // ioctl (fd, FIONREAD, XXX) returns the size of
1401 // the UDP header as well on
1404 // Use getsockopt SO_NREAD instead to get the
1405 // right values for TCP and UDP.
1407 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1408 // be the value of the ip buffer.
1410 socklen_t optlen = sizeof (int);
1411 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1413 ret = ioctl (fd, command, arg);
1418 WSASetLastError (WSAEINVAL);
1419 return(SOCKET_ERROR);
1423 gint errnum = errno;
1425 g_message ("%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;
1469 g_message ("%s: select error: %s", __func__, strerror (errno));
1471 errnum = errno_to_WSA (errnum, __func__);
1472 WSASetLastError (errnum);
1474 return(SOCKET_ERROR);
1480 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1482 gpointer handle = GUINT_TO_POINTER (fd);
1484 if (fd >= FD_SETSIZE) {
1485 WSASetLastError (WSAEINVAL);
1489 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1490 WSASetLastError (WSAENOTSOCK);
1497 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1499 gpointer handle = GUINT_TO_POINTER (fd);
1501 if (fd >= FD_SETSIZE) {
1502 WSASetLastError (WSAEINVAL);
1506 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1507 WSASetLastError (WSAENOTSOCK);
1511 return(FD_ISSET (fd, set));
1514 void _wapi_FD_SET(guint32 fd, fd_set *set)
1516 gpointer handle = GUINT_TO_POINTER (fd);
1518 if (fd >= FD_SETSIZE) {
1519 WSASetLastError (WSAEINVAL);
1523 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1524 WSASetLastError (WSAENOTSOCK);
1533 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1537 memset (hdr, 0, sizeof (struct msghdr));
1538 hdr->msg_iovlen = count;
1539 hdr->msg_iov = g_new0 (struct iovec, count);
1540 for (i = 0; i < count; i++) {
1541 hdr->msg_iov [i].iov_base = buffers [i].buf;
1542 hdr->msg_iov [i].iov_len = buffers [i].len;
1547 msghdr_iov_free (struct msghdr *hdr)
1549 g_free (hdr->msg_iov);
1552 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1553 guint32 *flags, WapiOverlapped *overlapped,
1554 WapiOverlappedCB *complete)
1559 g_assert (overlapped == NULL);
1560 g_assert (complete == NULL);
1562 wsabuf_to_msghdr (buffers, count, &hdr);
1563 ret = _wapi_recvmsg (fd, &hdr, *flags);
1564 msghdr_iov_free (&hdr);
1566 if(ret == SOCKET_ERROR) {
1571 *flags = hdr.msg_flags;
1576 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1577 guint32 flags, WapiOverlapped *overlapped,
1578 WapiOverlappedCB *complete)
1583 g_assert (overlapped == NULL);
1584 g_assert (complete == NULL);
1586 wsabuf_to_msghdr (buffers, count, &hdr);
1587 ret = _wapi_sendmsg (fd, &hdr, flags);
1588 msghdr_iov_free (&hdr);
1590 if(ret == SOCKET_ERROR)
1597 #endif /* ifndef DISABLE_SOCKETS */