2 * sockets.c: Socket handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #ifdef HAVE_SYS_IOCTL_H
18 # include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
24 #ifdef HAVE_SYS_SOCKIO_H
25 #include <sys/sockio.h> /* defines SIOCATMARK */
30 #ifndef HAVE_MSG_NOSIGNAL
34 #include <mono/io-layer/wapi.h>
35 #include <mono/io-layer/wapi-private.h>
36 #include <mono/io-layer/socket-private.h>
37 #include <mono/io-layer/handles-private.h>
38 #include <mono/io-layer/socket-wrappers.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
43 #include <arpa/inet.h>
47 static guint32 startup_count=0;
49 static void socket_close (gpointer handle, gpointer data);
51 struct _WapiHandleOps _wapi_socket_ops = {
52 socket_close, /* close */
56 NULL, /* special_wait */
60 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
62 static void socket_ops_init (void)
64 /* No capabilities to register */
67 static void socket_close (gpointer handle, gpointer data)
70 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
73 g_message ("%s: closing socket handle %p", __func__, handle);
76 if (startup_count == 0) {
77 WSASetLastError (WSANOTINITIALISED);
81 /* Shutdown the socket for reading, to interrupt any potential
82 * receives that may be blocking for data. See bug 75705.
84 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
87 ret = close (GPOINTER_TO_UINT(handle));
88 } while (ret == -1 && errno == EINTR &&
89 !_wapi_thread_cur_apc_pending ());
94 g_message ("%s: close error: %s", __func__, strerror (errno));
96 errnum = errno_to_WSA (errnum, __func__);
97 WSASetLastError (errnum);
100 socket_handle->saved_error = 0;
103 int WSAStartup(guint32 requested, WapiWSAData *data)
109 /* Insist on v2.0+ */
110 if (requested < MAKEWORD(2,0)) {
111 return(WSAVERNOTSUPPORTED);
116 /* I've no idea what is the minor version of the spec I read */
117 data->wHighVersion = MAKEWORD(2,2);
119 data->wVersion = requested < data->wHighVersion? requested:
123 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
126 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
127 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
133 cleanup_close (gpointer handle, gpointer data)
135 _wapi_handle_ops_close (handle, NULL);
142 g_message ("%s: cleaning up", __func__);
145 if (--startup_count) {
150 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
154 void WSASetLastError(int error)
156 SetLastError (error);
159 int WSAGetLastError(void)
161 return(GetLastError ());
164 int closesocket(guint32 fd)
166 gpointer handle = GUINT_TO_POINTER (fd);
168 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
169 WSASetLastError (WSAENOTSOCK);
173 _wapi_handle_unref (handle);
177 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
179 gpointer handle = GUINT_TO_POINTER (fd);
181 struct _WapiHandle_socket *socket_handle;
182 struct _WapiHandle_socket new_socket_handle = {0};
186 if (startup_count == 0) {
187 WSASetLastError (WSANOTINITIALISED);
188 return(INVALID_SOCKET);
191 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
192 WSASetLastError (WSAEFAULT);
193 return(INVALID_SOCKET);
196 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
197 WSASetLastError (WSAENOTSOCK);
198 return(INVALID_SOCKET);
201 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
202 (gpointer *)&socket_handle);
204 g_warning ("%s: error looking up socket handle %p",
206 WSASetLastError (WSAENOTSOCK);
207 return(INVALID_SOCKET);
211 new_fd = accept (fd, addr, addrlen);
212 } while (new_fd == -1 && errno == EINTR &&
213 !_wapi_thread_cur_apc_pending());
218 g_message ("%s: accept error: %s", __func__, strerror(errno));
221 errnum = errno_to_WSA (errnum, __func__);
222 WSASetLastError (errnum);
224 return(INVALID_SOCKET);
227 if (new_fd >= _wapi_fd_reserve) {
229 g_message ("%s: File descriptor is too big", __func__);
232 WSASetLastError (WSASYSCALLFAILURE);
236 return(INVALID_SOCKET);
239 new_socket_handle.domain = socket_handle->domain;
240 new_socket_handle.type = socket_handle->type;
241 new_socket_handle.protocol = socket_handle->protocol;
242 new_socket_handle.still_readable = 1;
244 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
246 if(new_handle == _WAPI_HANDLE_INVALID) {
247 g_warning ("%s: error creating socket handle", __func__);
248 WSASetLastError (ERROR_GEN_FAILURE);
249 return(INVALID_SOCKET);
253 g_message ("%s: returning newly accepted socket handle %p with",
254 __func__, new_handle);
260 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
262 gpointer handle = GUINT_TO_POINTER (fd);
265 if (startup_count == 0) {
266 WSASetLastError (WSANOTINITIALISED);
267 return(SOCKET_ERROR);
270 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
271 WSASetLastError (WSAENOTSOCK);
272 return(SOCKET_ERROR);
275 ret = bind (fd, my_addr, addrlen);
279 g_message ("%s: bind error: %s", __func__, strerror(errno));
281 errnum = errno_to_WSA (errnum, __func__);
282 WSASetLastError (errnum);
284 return(SOCKET_ERROR);
289 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
292 gpointer handle = GUINT_TO_POINTER (fd);
293 struct _WapiHandle_socket *socket_handle;
297 if (startup_count == 0) {
298 WSASetLastError (WSANOTINITIALISED);
299 return(SOCKET_ERROR);
302 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
303 WSASetLastError (WSAENOTSOCK);
304 return(SOCKET_ERROR);
307 if (connect (fd, serv_addr, addrlen) == -1) {
314 if (errno != EINTR) {
316 g_message ("%s: connect error: %s", __func__,
320 errnum = errno_to_WSA (errnum, __func__);
321 if (errnum == WSAEINPROGRESS)
322 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
324 WSASetLastError (errnum);
327 * On solaris x86 getsockopt (SO_ERROR) is not set after
328 * connect () fails so we need to save this error.
330 * But don't do this for EWOULDBLOCK (bug 317315)
332 if (errnum != WSAEWOULDBLOCK) {
333 ok = _wapi_lookup_handle (handle,
335 (gpointer *)&socket_handle);
337 /* ECONNRESET means the socket was closed by another thread */
338 if (errnum != WSAECONNRESET)
339 g_warning ("%s: error looking up socket handle %p", __func__, handle);
341 socket_handle->saved_error = errnum;
344 return(SOCKET_ERROR);
348 fds.events = POLLOUT;
349 while (poll (&fds, 1, -1) == -1 &&
350 !_wapi_thread_cur_apc_pending ()) {
351 if (errno != EINTR) {
352 errnum = errno_to_WSA (errno, __func__);
355 g_message ("%s: connect poll error: %s",
356 __func__, strerror (errno));
359 WSASetLastError (errnum);
360 return(SOCKET_ERROR);
364 len = sizeof(so_error);
365 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
367 errnum = errno_to_WSA (errno, __func__);
370 g_message ("%s: connect getsockopt error: %s",
371 __func__, strerror (errno));
374 WSASetLastError (errnum);
375 return(SOCKET_ERROR);
379 errnum = errno_to_WSA (so_error, __func__);
381 /* Need to save this socket error */
382 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
383 (gpointer *)&socket_handle);
385 g_warning ("%s: error looking up socket handle %p", __func__, handle);
387 socket_handle->saved_error = errnum;
391 g_message ("%s: connect getsockopt returned error: %s",
392 __func__, strerror (so_error));
395 WSASetLastError (errnum);
396 return(SOCKET_ERROR);
403 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
405 gpointer handle = GUINT_TO_POINTER (fd);
408 if (startup_count == 0) {
409 WSASetLastError (WSANOTINITIALISED);
410 return(SOCKET_ERROR);
413 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
414 WSASetLastError (WSAENOTSOCK);
415 return(SOCKET_ERROR);
418 ret = getpeername (fd, name, namelen);
422 g_message ("%s: getpeername error: %s", __func__,
426 errnum = errno_to_WSA (errnum, __func__);
427 WSASetLastError (errnum);
429 return(SOCKET_ERROR);
435 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
437 gpointer handle = GUINT_TO_POINTER (fd);
440 if (startup_count == 0) {
441 WSASetLastError (WSANOTINITIALISED);
442 return(SOCKET_ERROR);
445 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
446 WSASetLastError (WSAENOTSOCK);
447 return(SOCKET_ERROR);
450 ret = getsockname (fd, name, namelen);
454 g_message ("%s: getsockname error: %s", __func__,
458 errnum = errno_to_WSA (errnum, __func__);
459 WSASetLastError (errnum);
461 return(SOCKET_ERROR);
467 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
470 gpointer handle = GUINT_TO_POINTER (fd);
474 struct _WapiHandle_socket *socket_handle;
477 if (startup_count == 0) {
478 WSASetLastError (WSANOTINITIALISED);
479 return(SOCKET_ERROR);
482 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
483 WSASetLastError (WSAENOTSOCK);
484 return(SOCKET_ERROR);
488 if (level == SOL_SOCKET &&
489 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
491 *optlen = sizeof (tv);
494 ret = getsockopt (fd, level, optname, tmp_val, optlen);
498 g_message ("%s: getsockopt error: %s", __func__,
502 errnum = errno_to_WSA (errnum, __func__);
503 WSASetLastError (errnum);
505 return(SOCKET_ERROR);
508 if (level == SOL_SOCKET &&
509 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
510 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
511 *optlen = sizeof (int);
514 if (optname == SO_ERROR) {
515 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
516 (gpointer *)&socket_handle);
518 g_warning ("%s: error looking up socket handle %p",
521 /* can't extract the last error */
522 *((int *) optval) = errno_to_WSA (*((int *)optval),
525 if (*((int *)optval) != 0) {
526 *((int *) optval) = errno_to_WSA (*((int *)optval),
528 socket_handle->saved_error = *((int *)optval);
530 *((int *)optval) = socket_handle->saved_error;
538 int _wapi_listen(guint32 fd, int backlog)
540 gpointer handle = GUINT_TO_POINTER (fd);
543 if (startup_count == 0) {
544 WSASetLastError (WSANOTINITIALISED);
545 return(SOCKET_ERROR);
548 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
549 WSASetLastError (WSAENOTSOCK);
550 return(SOCKET_ERROR);
553 ret = listen (fd, backlog);
557 g_message ("%s: listen error: %s", __func__, strerror (errno));
560 errnum = errno_to_WSA (errnum, __func__);
561 WSASetLastError (errnum);
563 return(SOCKET_ERROR);
569 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
571 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
574 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
575 struct sockaddr *from, socklen_t *fromlen)
577 gpointer handle = GUINT_TO_POINTER (fd);
578 struct _WapiHandle_socket *socket_handle;
582 if (startup_count == 0) {
583 WSASetLastError (WSANOTINITIALISED);
584 return(SOCKET_ERROR);
587 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
588 WSASetLastError (WSAENOTSOCK);
589 return(SOCKET_ERROR);
593 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
594 } while (ret == -1 && errno == EINTR &&
595 !_wapi_thread_cur_apc_pending ());
597 if (ret == 0 && len > 0) {
598 /* According to the Linux man page, recvfrom only
599 * returns 0 when the socket has been shut down
600 * cleanly. Turn this into an EINTR to simulate win32
601 * behaviour of returning EINTR when a socket is
602 * closed while the recvfrom is blocking (we use a
603 * shutdown() in socket_close() to trigger this.) See
606 /* Distinguish between the socket being shut down at
607 * the local or remote ends, and reads that request 0
611 /* If this returns FALSE, it means the socket has been
612 * closed locally. If it returns TRUE, but
613 * still_readable != 1 then shutdown
614 * (SHUT_RD|SHUT_RDWR) has been called locally.
616 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
617 (gpointer *)&socket_handle);
618 if (ok == FALSE || socket_handle->still_readable != 1) {
627 g_message ("%s: recv error: %s", __func__, strerror(errno));
630 errnum = errno_to_WSA (errnum, __func__);
631 WSASetLastError (errnum);
633 return(SOCKET_ERROR);
639 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
641 gpointer handle = GUINT_TO_POINTER (fd);
642 struct _WapiHandle_socket *socket_handle;
646 if (startup_count == 0) {
647 WSASetLastError (WSANOTINITIALISED);
648 return(SOCKET_ERROR);
651 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
652 WSASetLastError (WSAENOTSOCK);
653 return(SOCKET_ERROR);
657 ret = recvmsg (fd, msg, recv_flags);
658 } while (ret == -1 && errno == EINTR &&
659 !_wapi_thread_cur_apc_pending ());
662 /* see _wapi_recvfrom */
663 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
664 (gpointer *)&socket_handle);
665 if (ok == FALSE || socket_handle->still_readable != 1) {
674 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
677 errnum = errno_to_WSA (errnum, __func__);
678 WSASetLastError (errnum);
680 return(SOCKET_ERROR);
685 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
687 gpointer handle = GUINT_TO_POINTER (fd);
690 if (startup_count == 0) {
691 WSASetLastError (WSANOTINITIALISED);
692 return(SOCKET_ERROR);
695 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
696 WSASetLastError (WSAENOTSOCK);
697 return(SOCKET_ERROR);
701 ret = send (fd, msg, len, send_flags);
702 } while (ret == -1 && errno == EINTR &&
703 !_wapi_thread_cur_apc_pending ());
708 g_message ("%s: send error: %s", __func__, strerror (errno));
711 errnum = errno_to_WSA (errnum, __func__);
712 WSASetLastError (errnum);
714 return(SOCKET_ERROR);
719 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
720 const struct sockaddr *to, socklen_t tolen)
722 gpointer handle = GUINT_TO_POINTER (fd);
725 if (startup_count == 0) {
726 WSASetLastError (WSANOTINITIALISED);
727 return(SOCKET_ERROR);
730 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
731 WSASetLastError (WSAENOTSOCK);
732 return(SOCKET_ERROR);
736 ret = sendto (fd, msg, len, send_flags, to, tolen);
737 } while (ret == -1 && errno == EINTR &&
738 !_wapi_thread_cur_apc_pending ());
743 g_message ("%s: send error: %s", __func__, strerror (errno));
746 errnum = errno_to_WSA (errnum, __func__);
747 WSASetLastError (errnum);
749 return(SOCKET_ERROR);
755 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
757 gpointer handle = GUINT_TO_POINTER (fd);
760 if (startup_count == 0) {
761 WSASetLastError (WSANOTINITIALISED);
762 return(SOCKET_ERROR);
765 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
766 WSASetLastError (WSAENOTSOCK);
767 return(SOCKET_ERROR);
771 ret = sendmsg (fd, msg, send_flags);
772 } while (ret == -1 && errno == EINTR &&
773 !_wapi_thread_cur_apc_pending ());
778 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
781 errnum = errno_to_WSA (errnum, __func__);
782 WSASetLastError (errnum);
784 return(SOCKET_ERROR);
789 int _wapi_setsockopt(guint32 fd, int level, int optname,
790 const void *optval, socklen_t optlen)
792 gpointer handle = GUINT_TO_POINTER (fd);
797 if (startup_count == 0) {
798 WSASetLastError (WSANOTINITIALISED);
799 return(SOCKET_ERROR);
802 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
803 WSASetLastError (WSAENOTSOCK);
804 return(SOCKET_ERROR);
808 if (level == SOL_SOCKET &&
809 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
810 int ms = *((int *) optval);
811 tv.tv_sec = ms / 1000;
812 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
814 optlen = sizeof (tv);
815 #if defined (__linux__)
816 } else if (level == SOL_SOCKET &&
817 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
818 /* According to socket(7) the Linux kernel doubles the
819 * buffer sizes "to allow space for bookkeeping
822 int bufsize = *((int *) optval);
829 ret = setsockopt (fd, level, optname, tmp_val, optlen);
833 g_message ("%s: setsockopt error: %s", __func__,
837 errnum = errno_to_WSA (errnum, __func__);
838 WSASetLastError (errnum);
840 return(SOCKET_ERROR);
843 #if defined (SO_REUSEPORT)
844 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
845 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
847 int type_len = sizeof (type);
849 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
850 if (type == SOCK_DGRAM)
851 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
859 int _wapi_shutdown(guint32 fd, int how)
861 struct _WapiHandle_socket *socket_handle;
863 gpointer handle = GUINT_TO_POINTER (fd);
866 if (startup_count == 0) {
867 WSASetLastError (WSANOTINITIALISED);
868 return(SOCKET_ERROR);
871 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
872 WSASetLastError (WSAENOTSOCK);
873 return(SOCKET_ERROR);
876 if (how == SHUT_RD ||
878 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
879 (gpointer *)&socket_handle);
881 g_warning ("%s: error looking up socket handle %p",
883 WSASetLastError (WSAENOTSOCK);
884 return(SOCKET_ERROR);
887 socket_handle->still_readable = 0;
890 ret = shutdown (fd, how);
894 g_message ("%s: shutdown error: %s", __func__,
898 errnum = errno_to_WSA (errnum, __func__);
899 WSASetLastError (errnum);
901 return(SOCKET_ERROR);
907 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
908 guint32 unused2, guint32 unused3)
910 struct _WapiHandle_socket socket_handle = {0};
914 socket_handle.domain = domain;
915 socket_handle.type = type;
916 socket_handle.protocol = protocol;
917 socket_handle.still_readable = 1;
919 fd = socket (domain, type, protocol);
920 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
922 /* Retry with protocol == 4 (see bug #54565) */
923 socket_handle.protocol = 4;
924 fd = socket (AF_INET, SOCK_RAW, 4);
930 g_message ("%s: socket error: %s", __func__, strerror (errno));
932 errnum = errno_to_WSA (errnum, __func__);
933 WSASetLastError (errnum);
935 return(INVALID_SOCKET);
938 if (fd >= _wapi_fd_reserve) {
940 g_message ("%s: File descriptor is too big (%d >= %d)",
941 __func__, fd, _wapi_fd_reserve);
944 WSASetLastError (WSASYSCALLFAILURE);
947 return(INVALID_SOCKET);
950 /* .net seems to set this by default for SOCK_STREAM, not for
951 * SOCK_DGRAM (see bug #36322)
953 * It seems winsock has a rather different idea of what
954 * SO_REUSEADDR means. If it's set, then a new socket can be
955 * bound over an existing listening socket. There's a new
956 * windows-specific option called SO_EXCLUSIVEADDRUSE but
957 * using that means the socket MUST be closed properly, or a
958 * denial of service can occur. Luckily for us, winsock
959 * behaves as though any other system would when SO_REUSEADDR
960 * is true, so we don't need to do anything else here. See
966 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
972 g_message ("%s: Error setting SO_REUSEADDR", __func__);
975 errnum = errno_to_WSA (errnum, __func__);
976 WSASetLastError (errnum);
980 return(INVALID_SOCKET);
985 mono_once (&socket_ops_once, socket_ops_init);
987 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
988 if (handle == _WAPI_HANDLE_INVALID) {
989 g_warning ("%s: error creating socket handle", __func__);
990 WSASetLastError (WSASYSCALLFAILURE);
992 return(INVALID_SOCKET);
996 g_message ("%s: returning socket handle %p", __func__, handle);
1002 struct hostent *_wapi_gethostbyname(const char *hostname)
1006 if (startup_count == 0) {
1007 WSASetLastError (WSANOTINITIALISED);
1011 he = gethostbyname (hostname);
1014 g_message ("%s: gethostbyname error: %s", __func__,
1015 strerror (h_errno));
1019 case HOST_NOT_FOUND:
1020 WSASetLastError (WSAHOST_NOT_FOUND);
1022 #if NO_ADDRESS != NO_DATA
1026 WSASetLastError (WSANO_DATA);
1029 WSASetLastError (WSANO_RECOVERY);
1032 WSASetLastError (WSATRY_AGAIN);
1035 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1043 static gboolean socket_disconnect (guint32 fd)
1045 struct _WapiHandle_socket *socket_handle;
1047 gpointer handle = GUINT_TO_POINTER (fd);
1050 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1051 (gpointer *)&socket_handle);
1053 g_warning ("%s: error looking up socket handle %p", __func__,
1055 WSASetLastError (WSAENOTSOCK);
1059 newsock = socket (socket_handle->domain, socket_handle->type,
1060 socket_handle->protocol);
1061 if (newsock == -1) {
1062 gint errnum = errno;
1065 g_message ("%s: socket error: %s", __func__, strerror (errno));
1068 errnum = errno_to_WSA (errnum, __func__);
1069 WSASetLastError (errnum);
1074 /* According to Stevens "Advanced Programming in the UNIX
1075 * Environment: UNIX File I/O" dup2() is atomic so there
1076 * should not be a race condition between the old fd being
1077 * closed and the new socket fd being copied over
1080 ret = dup2 (newsock, fd);
1081 } while (ret == -1 && errno == EAGAIN);
1084 gint errnum = errno;
1087 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1090 errnum = errno_to_WSA (errnum, __func__);
1091 WSASetLastError (errnum);
1101 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1102 guint32 flags, guint32 reserved)
1105 g_message ("%s: called on socket %d!", __func__, fd);
1108 if (reserved != 0) {
1109 WSASetLastError (WSAEINVAL);
1113 /* We could check the socket type here and fail unless its
1114 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1115 * if we really wanted to
1118 return(socket_disconnect (fd));
1121 /* NB only supports NULL file handle, NULL buffers and
1122 * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
1123 * Shouldn't actually ever need to be called anyway though, because we
1124 * have DisconnectEx ().
1126 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
1127 guint32 num_write, guint32 num_per_send,
1128 WapiOverlapped *overlapped,
1129 WapiTransmitFileBuffers *buffers,
1130 WapiTransmitFileFlags flags)
1133 g_message ("%s: called on socket %d!", __func__, fd);
1136 g_assert (file == NULL);
1137 g_assert (overlapped == NULL);
1138 g_assert (buffers == NULL);
1139 g_assert (num_write == 0);
1140 g_assert (num_per_send == 0);
1141 g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
1143 return(socket_disconnect (fd));
1150 } extension_functions[] = {
1151 {WSAID_DISCONNECTEX, wapi_disconnectex},
1152 {WSAID_TRANSMITFILE, wapi_transmitfile},
1157 WSAIoctl (guint32 fd, gint32 command,
1158 gchar *input, gint i_len,
1159 gchar *output, gint o_len, glong *written,
1160 void *unused1, void *unused2)
1162 gpointer handle = GUINT_TO_POINTER (fd);
1164 gchar *buffer = NULL;
1166 if (startup_count == 0) {
1167 WSASetLastError (WSANOTINITIALISED);
1168 return(SOCKET_ERROR);
1171 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1172 WSASetLastError (WSAENOTSOCK);
1173 return SOCKET_ERROR;
1176 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1178 WapiGuid *guid = (WapiGuid *)input;
1180 if (i_len < sizeof(WapiGuid)) {
1181 /* As far as I can tell, windows doesn't
1182 * actually set an error here...
1184 WSASetLastError (WSAEINVAL);
1185 return(SOCKET_ERROR);
1188 if (o_len < sizeof(gpointer)) {
1190 WSASetLastError (WSAEINVAL);
1191 return(SOCKET_ERROR);
1194 if (output == NULL) {
1196 WSASetLastError (WSAEINVAL);
1197 return(SOCKET_ERROR);
1200 while(extension_functions[i].func != NULL) {
1201 if (!memcmp (guid, &extension_functions[i].guid,
1202 sizeof(WapiGuid))) {
1203 memcpy (output, &extension_functions[i].func,
1205 *written = sizeof(gpointer);
1212 WSASetLastError (WSAEINVAL);
1213 return(SOCKET_ERROR);
1217 buffer = g_memdup (input, i_len);
1220 ret = ioctl (fd, command, buffer);
1222 gint errnum = errno;
1224 g_message("%s: WSAIoctl error: %s", __func__,
1228 errnum = errno_to_WSA (errnum, __func__);
1229 WSASetLastError (errnum);
1232 return(SOCKET_ERROR);
1235 if (buffer == NULL) {
1238 /* We just copy the buffer to the output. Some ioctls
1239 * don't even output any data, but, well...
1241 * NB windows returns WSAEFAULT if o_len is too small
1243 i_len = (i_len > o_len) ? o_len : i_len;
1245 if (i_len > 0 && output != NULL) {
1246 memcpy (output, buffer, i_len);
1256 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1257 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1259 gpointer handle = GUINT_TO_POINTER (fd);
1262 if (startup_count == 0) {
1263 WSASetLastError (WSANOTINITIALISED);
1264 return(SOCKET_ERROR);
1267 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1268 WSASetLastError (WSAENOTSOCK);
1269 return(SOCKET_ERROR);
1275 /* This works better than ioctl(...FIONBIO...)
1276 * on Linux (it causes connect to return
1277 * EINPROGRESS, but the ioctl doesn't seem to)
1279 ret = fcntl(fd, F_GETFL, 0);
1281 if (*(gboolean *)arg) {
1286 ret = fcntl(fd, F_SETFL, ret);
1289 #endif /* O_NONBLOCK */
1290 /* Unused in Mono */
1292 ret = ioctl (fd, command, arg);
1297 #if defined (PLATFORM_MACOSX)
1299 // ioctl (fd, FIONREAD, XXX) returns the size of
1300 // the UDP header as well on
1303 // Use getsockopt SO_NREAD instead to get the
1304 // right values for TCP and UDP.
1306 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1307 // be the value of the ip buffer.
1309 socklen_t optlen = sizeof (int);
1310 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1312 ret = ioctl (fd, command, arg);
1317 WSASetLastError (WSAEINVAL);
1318 return(SOCKET_ERROR);
1322 gint errnum = errno;
1324 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1327 errnum = errno_to_WSA (errnum, __func__);
1328 WSASetLastError (errnum);
1330 return(SOCKET_ERROR);
1336 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1337 fd_set *exceptfds, struct timeval *timeout)
1341 if (startup_count == 0) {
1342 WSASetLastError (WSANOTINITIALISED);
1343 return(SOCKET_ERROR);
1346 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1347 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1348 (writefds && FD_ISSET (maxfd, writefds)) ||
1349 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1355 WSASetLastError (WSAEINVAL);
1356 return(SOCKET_ERROR);
1360 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1362 } while (ret == -1 && errno == EINTR &&
1363 !_wapi_thread_cur_apc_pending ());
1366 gint errnum = errno;
1368 g_message ("%s: select error: %s", __func__, strerror (errno));
1370 errnum = errno_to_WSA (errnum, __func__);
1371 WSASetLastError (errnum);
1373 return(SOCKET_ERROR);
1379 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1381 gpointer handle = GUINT_TO_POINTER (fd);
1383 if (fd >= FD_SETSIZE) {
1384 WSASetLastError (WSAEINVAL);
1388 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1389 WSASetLastError (WSAENOTSOCK);
1396 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1398 gpointer handle = GUINT_TO_POINTER (fd);
1400 if (fd >= FD_SETSIZE) {
1401 WSASetLastError (WSAEINVAL);
1405 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1406 WSASetLastError (WSAENOTSOCK);
1410 return(FD_ISSET (fd, set));
1413 void _wapi_FD_SET(guint32 fd, fd_set *set)
1415 gpointer handle = GUINT_TO_POINTER (fd);
1417 if (fd >= FD_SETSIZE) {
1418 WSASetLastError (WSAEINVAL);
1422 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1423 WSASetLastError (WSAENOTSOCK);
1432 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1436 memset (hdr, 0, sizeof (struct msghdr));
1437 hdr->msg_iovlen = count;
1438 hdr->msg_iov = g_new0 (struct iovec, count);
1439 for (i = 0; i < count; i++) {
1440 hdr->msg_iov [i].iov_base = buffers [i].buf;
1441 hdr->msg_iov [i].iov_len = buffers [i].len;
1446 msghdr_iov_free (struct msghdr *hdr)
1448 g_free (hdr->msg_iov);
1451 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1452 guint32 *flags, WapiOverlapped *overlapped,
1453 WapiOverlappedCB *complete)
1458 g_assert (overlapped == NULL);
1459 g_assert (complete == NULL);
1461 wsabuf_to_msghdr (buffers, count, &hdr);
1462 ret = _wapi_recvmsg (fd, &hdr, *flags);
1463 msghdr_iov_free (&hdr);
1465 if(ret == SOCKET_ERROR) {
1470 *flags = hdr.msg_flags;
1475 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1476 guint32 flags, WapiOverlapped *overlapped,
1477 WapiOverlappedCB *complete)
1482 g_assert (overlapped == NULL);
1483 g_assert (complete == NULL);
1485 wsabuf_to_msghdr (buffers, count, &hdr);
1486 ret = _wapi_sendmsg (fd, &hdr, flags);
1487 msghdr_iov_free (&hdr);
1489 if(ret == SOCKET_ERROR)