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 #include <sys/ioctl.h>
19 #ifdef HAVE_SYS_FILIO_H
20 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
22 #ifdef HAVE_SYS_SOCKIO_H
23 #include <sys/sockio.h> /* defines SIOCATMARK */
28 #ifndef HAVE_MSG_NOSIGNAL
32 #include <mono/io-layer/wapi.h>
33 #include <mono/io-layer/wapi-private.h>
34 #include <mono/io-layer/socket-private.h>
35 #include <mono/io-layer/handles-private.h>
36 #include <mono/io-layer/socket-wrappers.h>
40 static guint32 startup_count=0;
42 static void socket_close (gpointer handle, gpointer data);
44 struct _WapiHandleOps _wapi_socket_ops = {
45 socket_close, /* close */
49 NULL, /* special_wait */
53 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
55 static void socket_ops_init (void)
57 /* No capabilities to register */
60 static void socket_close (gpointer handle, gpointer data)
63 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
66 g_message ("%s: closing socket handle %p", __func__, handle);
69 if (startup_count == 0) {
70 WSASetLastError (WSANOTINITIALISED);
74 /* Shutdown the socket for reading, to interrupt any potential
75 * receives that may be blocking for data. See bug 75705.
77 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
80 ret = close (GPOINTER_TO_UINT(handle));
81 } while (ret == -1 && errno == EINTR &&
82 !_wapi_thread_cur_apc_pending ());
87 g_message ("%s: close error: %s", __func__, strerror (errno));
89 errnum = errno_to_WSA (errnum, __func__);
90 WSASetLastError (errnum);
93 socket_handle->saved_error = 0;
96 int WSAStartup(guint32 requested, WapiWSAData *data)
102 /* Insist on v2.0+ */
103 if (requested < MAKEWORD(2,0)) {
104 return(WSAVERNOTSUPPORTED);
109 /* I've no idea what is the minor version of the spec I read */
110 data->wHighVersion = MAKEWORD(2,2);
112 data->wVersion = requested < data->wHighVersion? requested:
116 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
119 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
120 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
126 cleanup_close (gpointer handle, gpointer data)
128 _wapi_handle_ops_close (handle, NULL);
135 g_message ("%s: cleaning up", __func__);
138 if (--startup_count) {
143 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
147 void WSASetLastError(int error)
149 SetLastError (error);
152 int WSAGetLastError(void)
154 return(GetLastError ());
157 int closesocket(guint32 fd)
159 gpointer handle = GUINT_TO_POINTER (fd);
161 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
162 WSASetLastError (WSAENOTSOCK);
166 _wapi_handle_unref (handle);
170 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
172 gpointer handle = GUINT_TO_POINTER (fd);
174 struct _WapiHandle_socket *socket_handle;
175 struct _WapiHandle_socket new_socket_handle = {0};
179 if (startup_count == 0) {
180 WSASetLastError (WSANOTINITIALISED);
181 return(INVALID_SOCKET);
184 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
185 WSASetLastError (WSAEFAULT);
186 return(INVALID_SOCKET);
189 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
190 WSASetLastError (WSAENOTSOCK);
191 return(INVALID_SOCKET);
194 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
195 (gpointer *)&socket_handle);
197 g_warning ("%s: error looking up socket handle %p",
199 WSASetLastError (WSAENOTSOCK);
200 return(INVALID_SOCKET);
204 new_fd = accept (fd, addr, addrlen);
205 } while (new_fd == -1 && errno == EINTR &&
206 !_wapi_thread_cur_apc_pending());
211 g_message ("%s: accept error: %s", __func__, strerror(errno));
214 errnum = errno_to_WSA (errnum, __func__);
215 WSASetLastError (errnum);
217 return(INVALID_SOCKET);
220 if (new_fd >= _wapi_fd_reserve) {
222 g_message ("%s: File descriptor is too big", __func__);
225 WSASetLastError (WSASYSCALLFAILURE);
229 return(INVALID_SOCKET);
232 new_socket_handle.domain = socket_handle->domain;
233 new_socket_handle.type = socket_handle->type;
234 new_socket_handle.protocol = socket_handle->protocol;
235 new_socket_handle.still_readable = 1;
237 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
239 if(new_handle == _WAPI_HANDLE_INVALID) {
240 g_warning ("%s: error creating socket handle", __func__);
241 WSASetLastError (ERROR_GEN_FAILURE);
242 return(INVALID_SOCKET);
246 g_message ("%s: returning newly accepted socket handle %p with",
247 __func__, new_handle);
253 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
255 gpointer handle = GUINT_TO_POINTER (fd);
258 if (startup_count == 0) {
259 WSASetLastError (WSANOTINITIALISED);
260 return(SOCKET_ERROR);
263 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
264 WSASetLastError (WSAENOTSOCK);
265 return(SOCKET_ERROR);
268 ret = bind (fd, my_addr, addrlen);
272 g_message ("%s: bind error: %s", __func__, strerror(errno));
274 errnum = errno_to_WSA (errnum, __func__);
275 WSASetLastError (errnum);
277 return(SOCKET_ERROR);
282 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
285 gpointer handle = GUINT_TO_POINTER (fd);
286 struct _WapiHandle_socket *socket_handle;
290 if (startup_count == 0) {
291 WSASetLastError (WSANOTINITIALISED);
292 return(SOCKET_ERROR);
295 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
296 WSASetLastError (WSAENOTSOCK);
297 return(SOCKET_ERROR);
300 if (connect (fd, serv_addr, addrlen) == -1) {
307 if (errno != EINTR) {
309 g_message ("%s: connect error: %s", __func__,
313 errnum = errno_to_WSA (errnum, __func__);
314 if (errnum == WSAEINPROGRESS)
315 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
317 WSASetLastError (errnum);
320 * On solaris x86 getsockopt (SO_ERROR) is not set after
321 * connect () fails so we need to save this error.
323 * But don't do this for EWOULDBLOCK (bug 317315)
325 if (errnum != WSAEWOULDBLOCK) {
326 ok = _wapi_lookup_handle (handle,
328 (gpointer *)&socket_handle);
330 g_warning ("%s: error looking up socket handle %p", __func__, handle);
332 socket_handle->saved_error = errnum;
335 return(SOCKET_ERROR);
339 fds.events = POLLOUT;
340 while (poll (&fds, 1, -1) == -1 &&
341 !_wapi_thread_cur_apc_pending ()) {
342 if (errno != EINTR) {
343 errnum = errno_to_WSA (errno, __func__);
346 g_message ("%s: connect poll error: %s",
347 __func__, strerror (errno));
350 WSASetLastError (errnum);
351 return(SOCKET_ERROR);
355 len = sizeof(so_error);
356 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
358 errnum = errno_to_WSA (errno, __func__);
361 g_message ("%s: connect getsockopt error: %s",
362 __func__, strerror (errno));
365 WSASetLastError (errnum);
366 return(SOCKET_ERROR);
370 errnum = errno_to_WSA (so_error, __func__);
372 /* Need to save this socket error */
373 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
374 (gpointer *)&socket_handle);
376 g_warning ("%s: error looking up socket handle %p", __func__, handle);
378 socket_handle->saved_error = errnum;
382 g_message ("%s: connect getsockopt returned error: %s",
383 __func__, strerror (so_error));
386 WSASetLastError (errnum);
387 return(SOCKET_ERROR);
394 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
396 gpointer handle = GUINT_TO_POINTER (fd);
399 if (startup_count == 0) {
400 WSASetLastError (WSANOTINITIALISED);
401 return(SOCKET_ERROR);
404 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
405 WSASetLastError (WSAENOTSOCK);
406 return(SOCKET_ERROR);
409 ret = getpeername (fd, name, namelen);
413 g_message ("%s: getpeername error: %s", __func__,
417 errnum = errno_to_WSA (errnum, __func__);
418 WSASetLastError (errnum);
420 return(SOCKET_ERROR);
426 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
428 gpointer handle = GUINT_TO_POINTER (fd);
431 if (startup_count == 0) {
432 WSASetLastError (WSANOTINITIALISED);
433 return(SOCKET_ERROR);
436 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
437 WSASetLastError (WSAENOTSOCK);
438 return(SOCKET_ERROR);
441 ret = getsockname (fd, name, namelen);
445 g_message ("%s: getsockname error: %s", __func__,
449 errnum = errno_to_WSA (errnum, __func__);
450 WSASetLastError (errnum);
452 return(SOCKET_ERROR);
458 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
461 gpointer handle = GUINT_TO_POINTER (fd);
465 struct _WapiHandle_socket *socket_handle;
468 if (startup_count == 0) {
469 WSASetLastError (WSANOTINITIALISED);
470 return(SOCKET_ERROR);
473 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
474 WSASetLastError (WSAENOTSOCK);
475 return(SOCKET_ERROR);
479 if (level == SOL_SOCKET &&
480 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
482 *optlen = sizeof (tv);
485 ret = getsockopt (fd, level, optname, tmp_val, optlen);
489 g_message ("%s: getsockopt error: %s", __func__,
493 errnum = errno_to_WSA (errnum, __func__);
494 WSASetLastError (errnum);
496 return(SOCKET_ERROR);
499 if (level == SOL_SOCKET &&
500 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
501 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
502 *optlen = sizeof (int);
505 if (optname == SO_ERROR) {
506 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
507 (gpointer *)&socket_handle);
509 g_warning ("%s: error looking up socket handle %p",
512 /* can't extract the last error */
513 *((int *) optval) = errno_to_WSA (*((int *)optval),
516 if (*((int *)optval) != 0) {
517 *((int *) optval) = errno_to_WSA (*((int *)optval),
519 socket_handle->saved_error = *((int *)optval);
521 *((int *)optval) = socket_handle->saved_error;
529 int _wapi_listen(guint32 fd, int backlog)
531 gpointer handle = GUINT_TO_POINTER (fd);
534 if (startup_count == 0) {
535 WSASetLastError (WSANOTINITIALISED);
536 return(SOCKET_ERROR);
539 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
540 WSASetLastError (WSAENOTSOCK);
541 return(SOCKET_ERROR);
544 ret = listen (fd, backlog);
548 g_message ("%s: listen error: %s", __func__, strerror (errno));
551 errnum = errno_to_WSA (errnum, __func__);
552 WSASetLastError (errnum);
554 return(SOCKET_ERROR);
560 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
562 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
565 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
566 struct sockaddr *from, socklen_t *fromlen)
568 gpointer handle = GUINT_TO_POINTER (fd);
569 struct _WapiHandle_socket *socket_handle;
573 if (startup_count == 0) {
574 WSASetLastError (WSANOTINITIALISED);
575 return(SOCKET_ERROR);
578 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
579 WSASetLastError (WSAENOTSOCK);
580 return(SOCKET_ERROR);
584 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
585 } while (ret == -1 && errno == EINTR &&
586 !_wapi_thread_cur_apc_pending ());
588 if (ret == 0 && len > 0) {
589 /* According to the Linux man page, recvfrom only
590 * returns 0 when the socket has been shut down
591 * cleanly. Turn this into an EINTR to simulate win32
592 * behaviour of returning EINTR when a socket is
593 * closed while the recvfrom is blocking (we use a
594 * shutdown() in socket_close() to trigger this.) See
597 /* Distinguish between the socket being shut down at
598 * the local or remote ends, and reads that request 0
602 /* If this returns FALSE, it means the socket has been
603 * closed locally. If it returns TRUE, but
604 * still_readable != 1 then shutdown
605 * (SHUT_RD|SHUT_RDWR) has been called locally.
607 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
608 (gpointer *)&socket_handle);
609 if (ok == FALSE || socket_handle->still_readable != 1) {
618 g_message ("%s: recv error: %s", __func__, strerror(errno));
621 errnum = errno_to_WSA (errnum, __func__);
622 WSASetLastError (errnum);
624 return(SOCKET_ERROR);
629 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
631 gpointer handle = GUINT_TO_POINTER (fd);
634 if (startup_count == 0) {
635 WSASetLastError (WSANOTINITIALISED);
636 return(SOCKET_ERROR);
639 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
640 WSASetLastError (WSAENOTSOCK);
641 return(SOCKET_ERROR);
645 ret = send (fd, msg, len, send_flags);
646 } while (ret == -1 && errno == EINTR &&
647 !_wapi_thread_cur_apc_pending ());
652 g_message ("%s: send error: %s", __func__, strerror (errno));
655 errnum = errno_to_WSA (errnum, __func__);
656 WSASetLastError (errnum);
658 return(SOCKET_ERROR);
663 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
664 const struct sockaddr *to, socklen_t tolen)
666 gpointer handle = GUINT_TO_POINTER (fd);
669 if (startup_count == 0) {
670 WSASetLastError (WSANOTINITIALISED);
671 return(SOCKET_ERROR);
674 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
675 WSASetLastError (WSAENOTSOCK);
676 return(SOCKET_ERROR);
680 ret = sendto (fd, msg, len, send_flags, to, tolen);
681 } while (ret == -1 && errno == EINTR &&
682 !_wapi_thread_cur_apc_pending ());
687 g_message ("%s: send error: %s", __func__, strerror (errno));
690 errnum = errno_to_WSA (errnum, __func__);
691 WSASetLastError (errnum);
693 return(SOCKET_ERROR);
698 int _wapi_setsockopt(guint32 fd, int level, int optname,
699 const void *optval, socklen_t optlen)
701 gpointer handle = GUINT_TO_POINTER (fd);
706 if (startup_count == 0) {
707 WSASetLastError (WSANOTINITIALISED);
708 return(SOCKET_ERROR);
711 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
712 WSASetLastError (WSAENOTSOCK);
713 return(SOCKET_ERROR);
717 if (level == SOL_SOCKET &&
718 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
719 int ms = *((int *) optval);
720 tv.tv_sec = ms / 1000;
721 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
723 optlen = sizeof (tv);
724 #if defined (__linux__)
725 } else if (level == SOL_SOCKET &&
726 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
727 /* According to socket(7) the Linux kernel doubles the
728 * buffer sizes "to allow space for bookkeeping
731 int bufsize = *((int *) optval);
738 ret = setsockopt (fd, level, optname, tmp_val, optlen);
742 g_message ("%s: setsockopt error: %s", __func__,
746 errnum = errno_to_WSA (errnum, __func__);
747 WSASetLastError (errnum);
749 return(SOCKET_ERROR);
752 #if defined(__FreeBSD__)
753 /* FreeBSD's multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
754 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
756 int type_len = sizeof (type);
758 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
759 if (type == SOCK_DGRAM)
760 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
768 int _wapi_shutdown(guint32 fd, int how)
770 struct _WapiHandle_socket *socket_handle;
772 gpointer handle = GUINT_TO_POINTER (fd);
775 if (startup_count == 0) {
776 WSASetLastError (WSANOTINITIALISED);
777 return(SOCKET_ERROR);
780 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
781 WSASetLastError (WSAENOTSOCK);
782 return(SOCKET_ERROR);
785 if (how == SHUT_RD ||
787 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
788 (gpointer *)&socket_handle);
790 g_warning ("%s: error looking up socket handle %p",
792 WSASetLastError (WSAENOTSOCK);
793 return(SOCKET_ERROR);
796 socket_handle->still_readable = 0;
799 ret = shutdown (fd, how);
803 g_message ("%s: shutdown error: %s", __func__,
807 errnum = errno_to_WSA (errnum, __func__);
808 WSASetLastError (errnum);
810 return(SOCKET_ERROR);
816 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
817 guint32 unused2, guint32 unused3)
819 struct _WapiHandle_socket socket_handle = {0};
823 socket_handle.domain = domain;
824 socket_handle.type = type;
825 socket_handle.protocol = protocol;
826 socket_handle.still_readable = 1;
828 fd = socket (domain, type, protocol);
829 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
831 /* Retry with protocol == 4 (see bug #54565) */
832 socket_handle.protocol = 4;
833 fd = socket (AF_INET, SOCK_RAW, 4);
839 g_message ("%s: socket error: %s", __func__, strerror (errno));
841 errnum = errno_to_WSA (errnum, __func__);
842 WSASetLastError (errnum);
844 return(INVALID_SOCKET);
847 if (fd >= _wapi_fd_reserve) {
849 g_message ("%s: File descriptor is too big (%d >= %d)",
850 __func__, fd, _wapi_fd_reserve);
853 WSASetLastError (WSASYSCALLFAILURE);
856 return(INVALID_SOCKET);
859 /* .net seems to set this by default for SOCK_STREAM, not for
860 * SOCK_DGRAM (see bug #36322)
862 * It seems winsock has a rather different idea of what
863 * SO_REUSEADDR means. If it's set, then a new socket can be
864 * bound over an existing listening socket. There's a new
865 * windows-specific option called SO_EXCLUSIVEADDRUSE but
866 * using that means the socket MUST be closed properly, or a
867 * denial of service can occur. Luckily for us, winsock
868 * behaves as though any other system would when SO_REUSEADDR
869 * is true, so we don't need to do anything else here. See
875 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
881 g_message ("%s: Error setting SO_REUSEADDR", __func__);
884 errnum = errno_to_WSA (errnum, __func__);
885 WSASetLastError (errnum);
889 return(INVALID_SOCKET);
894 mono_once (&socket_ops_once, socket_ops_init);
896 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
897 if (handle == _WAPI_HANDLE_INVALID) {
898 g_warning ("%s: error creating socket handle", __func__);
899 WSASetLastError (WSASYSCALLFAILURE);
901 return(INVALID_SOCKET);
905 g_message ("%s: returning socket handle %p", __func__, handle);
911 struct hostent *_wapi_gethostbyname(const char *hostname)
915 if (startup_count == 0) {
916 WSASetLastError (WSANOTINITIALISED);
920 he = gethostbyname (hostname);
923 g_message ("%s: gethostbyname error: %s", __func__,
929 WSASetLastError (WSAHOST_NOT_FOUND);
931 #if NO_ADDRESS != NO_DATA
935 WSASetLastError (WSANO_DATA);
938 WSASetLastError (WSANO_RECOVERY);
941 WSASetLastError (WSATRY_AGAIN);
944 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
952 static gboolean socket_disconnect (guint32 fd)
954 struct _WapiHandle_socket *socket_handle;
956 gpointer handle = GUINT_TO_POINTER (fd);
959 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
960 (gpointer *)&socket_handle);
962 g_warning ("%s: error looking up socket handle %p", __func__,
964 WSASetLastError (WSAENOTSOCK);
968 newsock = socket (socket_handle->domain, socket_handle->type,
969 socket_handle->protocol);
974 g_message ("%s: socket error: %s", __func__, strerror (errno));
977 errnum = errno_to_WSA (errnum, __func__);
978 WSASetLastError (errnum);
983 /* According to Stevens "Advanced Programming in the UNIX
984 * Environment: UNIX File I/O" dup2() is atomic so there
985 * should not be a race condition between the old fd being
986 * closed and the new socket fd being copied over
989 ret = dup2 (newsock, fd);
990 } while (ret == -1 && errno == EAGAIN);
996 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
999 errnum = errno_to_WSA (errnum, __func__);
1000 WSASetLastError (errnum);
1010 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1011 guint32 flags, guint32 reserved)
1014 g_message ("%s: called on socket %d!", __func__, fd);
1017 if (reserved != 0) {
1018 WSASetLastError (WSAEINVAL);
1022 /* We could check the socket type here and fail unless its
1023 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1024 * if we really wanted to
1027 return(socket_disconnect (fd));
1030 /* NB only supports NULL file handle, NULL buffers and
1031 * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
1032 * Shouldn't actually ever need to be called anyway though, because we
1033 * have DisconnectEx ().
1035 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
1036 guint32 num_write, guint32 num_per_send,
1037 WapiOverlapped *overlapped,
1038 WapiTransmitFileBuffers *buffers,
1039 WapiTransmitFileFlags flags)
1042 g_message ("%s: called on socket %d!", __func__, fd);
1045 g_assert (file == NULL);
1046 g_assert (overlapped == NULL);
1047 g_assert (buffers == NULL);
1048 g_assert (num_write == 0);
1049 g_assert (num_per_send == 0);
1050 g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
1052 return(socket_disconnect (fd));
1059 } extension_functions[] = {
1060 {WSAID_DISCONNECTEX, wapi_disconnectex},
1061 {WSAID_TRANSMITFILE, wapi_transmitfile},
1066 WSAIoctl (guint32 fd, gint32 command,
1067 gchar *input, gint i_len,
1068 gchar *output, gint o_len, glong *written,
1069 void *unused1, void *unused2)
1071 gpointer handle = GUINT_TO_POINTER (fd);
1073 gchar *buffer = NULL;
1075 if (startup_count == 0) {
1076 WSASetLastError (WSANOTINITIALISED);
1077 return(SOCKET_ERROR);
1080 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1081 WSASetLastError (WSAENOTSOCK);
1082 return SOCKET_ERROR;
1085 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1087 WapiGuid *guid = (WapiGuid *)input;
1089 if (i_len < sizeof(WapiGuid)) {
1090 /* As far as I can tell, windows doesn't
1091 * actually set an error here...
1093 WSASetLastError (WSAEINVAL);
1094 return(SOCKET_ERROR);
1097 if (o_len < sizeof(gpointer)) {
1099 WSASetLastError (WSAEINVAL);
1100 return(SOCKET_ERROR);
1103 if (output == NULL) {
1105 WSASetLastError (WSAEINVAL);
1106 return(SOCKET_ERROR);
1109 while(extension_functions[i].func != NULL) {
1110 if (!memcmp (guid, &extension_functions[i].guid,
1111 sizeof(WapiGuid))) {
1112 memcpy (output, &extension_functions[i].func,
1114 *written = sizeof(gpointer);
1121 WSASetLastError (WSAEINVAL);
1122 return(SOCKET_ERROR);
1126 buffer = g_memdup (input, i_len);
1129 ret = ioctl (fd, command, buffer);
1131 gint errnum = errno;
1133 g_message("%s: WSAIoctl error: %s", __func__,
1137 errnum = errno_to_WSA (errnum, __func__);
1138 WSASetLastError (errnum);
1141 return(SOCKET_ERROR);
1144 if (buffer == NULL) {
1147 /* We just copy the buffer to the output. Some ioctls
1148 * don't even output any data, but, well...
1150 * NB windows returns WSAEFAULT if o_len is too small
1152 i_len = (i_len > o_len) ? o_len : i_len;
1154 if (i_len > 0 && output != NULL) {
1155 memcpy (output, buffer, i_len);
1165 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1167 gpointer handle = GUINT_TO_POINTER (fd);
1170 if (startup_count == 0) {
1171 WSASetLastError (WSANOTINITIALISED);
1172 return(SOCKET_ERROR);
1175 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1176 WSASetLastError (WSAENOTSOCK);
1177 return(SOCKET_ERROR);
1183 /* This works better than ioctl(...FIONBIO...)
1184 * on Linux (it causes connect to return
1185 * EINPROGRESS, but the ioctl doesn't seem to)
1187 ret = fcntl(fd, F_GETFL, 0);
1189 if (*(gboolean *)arg) {
1194 ret = fcntl(fd, F_SETFL, ret);
1197 #endif /* O_NONBLOCK */
1200 ret = ioctl (fd, command, arg);
1203 WSASetLastError (WSAEINVAL);
1204 return(SOCKET_ERROR);
1208 gint errnum = errno;
1210 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1213 errnum = errno_to_WSA (errnum, __func__);
1214 WSASetLastError (errnum);
1216 return(SOCKET_ERROR);
1222 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1223 fd_set *exceptfds, struct timeval *timeout)
1227 if (startup_count == 0) {
1228 WSASetLastError (WSANOTINITIALISED);
1229 return(SOCKET_ERROR);
1232 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1233 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1234 (writefds && FD_ISSET (maxfd, writefds)) ||
1235 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1241 WSASetLastError (WSAEINVAL);
1242 return(SOCKET_ERROR);
1246 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1248 } while (ret == -1 && errno == EINTR &&
1249 !_wapi_thread_cur_apc_pending ());
1252 gint errnum = errno;
1254 g_message ("%s: select error: %s", __func__, strerror (errno));
1256 errnum = errno_to_WSA (errnum, __func__);
1257 WSASetLastError (errnum);
1259 return(SOCKET_ERROR);
1265 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1267 gpointer handle = GUINT_TO_POINTER (fd);
1269 if (fd >= FD_SETSIZE) {
1270 WSASetLastError (WSAEINVAL);
1274 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1275 WSASetLastError (WSAENOTSOCK);
1282 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1284 gpointer handle = GUINT_TO_POINTER (fd);
1286 if (fd >= FD_SETSIZE) {
1287 WSASetLastError (WSAEINVAL);
1291 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1292 WSASetLastError (WSAENOTSOCK);
1296 return(FD_ISSET (fd, set));
1299 void _wapi_FD_SET(guint32 fd, fd_set *set)
1301 gpointer handle = GUINT_TO_POINTER (fd);
1303 if (fd >= FD_SETSIZE) {
1304 WSASetLastError (WSAEINVAL);
1308 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1309 WSASetLastError (WSAENOTSOCK);
1316 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1317 guint32 *flags, WapiOverlapped *overlapped,
1318 WapiOverlappedCB *complete)
1320 int ret, i, buflen = 0, offset = 0, copylen;
1323 g_assert (overlapped == NULL);
1324 g_assert (complete == NULL);
1326 for(i = 0; i < count; i++) {
1327 buflen += buffers[i].len;
1330 recvbuf = g_new0 (gint8, buflen);
1331 ret = _wapi_recvfrom (fd, recvbuf, buflen, *flags, NULL, 0);
1332 if(ret == SOCKET_ERROR) {
1337 for(i = 0; i < count; i++) {
1338 copylen = buffers[i].len > (buflen - offset)? (buflen - offset):buffers[i].len;
1339 memcpy (buffers[i].buf, recvbuf + offset, copylen);
1341 if (copylen != buffers[i].len) {
1351 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1352 guint32 flags, WapiOverlapped *overlapped,
1353 WapiOverlappedCB *complete)
1355 int ret, i, buflen = 0, offset = 0, copylen;
1358 g_assert (overlapped == NULL);
1359 g_assert (complete == NULL);
1361 for(i = 0; i < count; i++) {
1362 buflen += buffers[i].len;
1365 sendbuf = g_new0 (gint8, buflen);
1366 for(i = 0; i < count; i++) {
1367 copylen = buffers[i].len;
1368 memcpy (sendbuf + offset, buffers[i].buf, copylen);
1372 ret = _wapi_sendto (fd, sendbuf, buflen, flags, NULL, 0);
1373 if(ret == SOCKET_ERROR) {