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>
18 #ifdef HAVE_SYS_FILIO_H
19 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
21 #ifdef HAVE_SYS_SOCKIO_H
22 #include <sys/sockio.h> /* defines SIOCATMARK */
27 #ifndef HAVE_MSG_NOSIGNAL
31 #ifndef PLATFORM_WIN32
35 #elif defined(HAVE_SYS_AIO_H)
43 #include <mono/io-layer/wapi.h>
44 #include <mono/io-layer/wapi-private.h>
45 #include <mono/io-layer/socket-private.h>
46 #include <mono/io-layer/handles-private.h>
47 #include <mono/io-layer/socket-wrappers.h>
51 static guint32 startup_count=0;
52 static GPtrArray *sockets=NULL;
53 static pthread_key_t error_key;
54 static mono_once_t error_key_once=MONO_ONCE_INIT;
56 static void socket_close_private (gpointer handle);
58 struct _WapiHandleOps _wapi_socket_ops = {
59 NULL, /* close_shared */
60 socket_close_private, /* close_private */
66 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
68 static void socket_ops_init (void)
70 /* No capabilities to register */
73 static void socket_close_private (gpointer handle)
75 struct _WapiHandlePrivate_socket *socket_private_handle;
80 g_message(G_GNUC_PRETTY_FUNCTION ": closing socket handle %p",
84 if(startup_count==0) {
85 WSASetLastError(WSANOTINITIALISED);
89 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
90 NULL, (gpointer *)&socket_private_handle);
92 g_warning (G_GNUC_PRETTY_FUNCTION
93 ": error looking up socket handle %p", handle);
94 WSASetLastError(WSAENOTSOCK);
98 g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle));
100 /* Blank out the mapping, to make catching errors easier */
101 _wapi_handle_fd_offset_store (socket_private_handle->fd, NULL);
104 ret=close(socket_private_handle->fd);
106 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
111 g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
114 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
115 WSASetLastError (errnum);
121 int WSAStartup(guint32 requested, WapiWSAData *data)
127 /* Insist on v2.0+ */
128 if(requested < MAKEWORD(2,0)) {
129 return(WSAVERNOTSUPPORTED);
132 if(startup_count==0) {
133 sockets=g_ptr_array_new();
138 /* I've no idea what is the minor version of the spec I read */
139 data->wHighVersion=MAKEWORD(2,0);
141 data->wVersion=requested < data->wHighVersion? requested:
145 g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
149 strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
150 strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
160 g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
163 if(--startup_count) {
168 /* Close down all sockets */
169 for(i=0; i<sockets->len; i++) {
172 handle=g_ptr_array_index(sockets, i);
173 _wapi_handle_ops_close_private (handle);
176 g_ptr_array_free(sockets, FALSE);
182 static void error_init(void)
186 ret = pthread_key_create(&error_key, NULL);
190 void WSASetLastError(int error)
194 mono_once(&error_key_once, error_init);
195 ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
199 int WSAGetLastError(void)
204 mono_once(&error_key_once, error_init);
205 errptr=pthread_getspecific(error_key);
206 err=GPOINTER_TO_INT(errptr);
211 int closesocket(guint32 fd_handle)
213 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd_handle));
215 if (handle == NULL ||
216 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
217 WSASetLastError (WSAENOTSOCK);
221 _wapi_handle_unref (handle);
225 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
227 struct _WapiHandlePrivate_socket *new_socket_private_handle;
228 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
233 guint32 ret = INVALID_SOCKET;
235 if(startup_count==0) {
236 WSASetLastError(WSANOTINITIALISED);
237 return(INVALID_SOCKET);
240 if (handle == NULL ||
241 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
242 WSASetLastError(WSAENOTSOCK);
243 return(INVALID_SOCKET);
247 new_fd=accept(fd, addr, addrlen);
249 while (new_fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
254 g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
258 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
259 WSASetLastError (errnum);
261 return(INVALID_SOCKET);
264 if (new_fd >= _wapi_fd_offset_table_size) {
266 g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
269 WSASetLastError (WSASYSCALLFAILURE);
273 return(INVALID_SOCKET);
276 new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
277 if(new_handle==_WAPI_HANDLE_INVALID) {
278 g_warning (G_GNUC_PRETTY_FUNCTION
279 ": error creating socket handle");
280 WSASetLastError (ERROR_GEN_FAILURE);
281 return(INVALID_SOCKET);
284 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
286 thr_ret = _wapi_handle_lock_handle (new_handle);
287 g_assert (thr_ret == 0);
289 ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
290 (gpointer *)&new_socket_private_handle);
292 g_warning (G_GNUC_PRETTY_FUNCTION
293 ": error looking up new socket handle %p",
298 _wapi_handle_fd_offset_store (new_fd, new_handle);
301 new_socket_private_handle->fd=new_fd;
304 g_message(G_GNUC_PRETTY_FUNCTION
305 ": returning newly accepted socket handle %p with fd %d",
306 new_handle, new_socket_private_handle->fd);
310 thr_ret = _wapi_handle_unlock_handle (new_handle);
311 g_assert (thr_ret == 0);
312 pthread_cleanup_pop (0);
317 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
319 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
322 if(startup_count==0) {
323 WSASetLastError(WSANOTINITIALISED);
324 return(SOCKET_ERROR);
327 if (handle == NULL ||
328 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
329 WSASetLastError(WSAENOTSOCK);
330 return(SOCKET_ERROR);
333 ret=bind(fd, my_addr, addrlen);
337 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
340 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
341 WSASetLastError (errnum);
343 return(SOCKET_ERROR);
348 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
351 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
355 if(startup_count==0) {
356 WSASetLastError(WSANOTINITIALISED);
357 return(SOCKET_ERROR);
360 if (handle == NULL ||
361 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
362 WSASetLastError(WSAENOTSOCK);
363 return(SOCKET_ERROR);
367 ret=connect(fd, serv_addr, addrlen);
369 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
371 if(ret==-1 && errno==EACCES) {
372 /* Try setting SO_BROADCAST and connecting again, but
373 * keep the original errno
379 ret=setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
383 ret=connect (fd, serv_addr, addrlen);
385 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
387 } else if (ret==-1) {
393 g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
396 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
397 WSASetLastError (errnum);
399 return(SOCKET_ERROR);
404 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
406 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
409 if(startup_count==0) {
410 WSASetLastError(WSANOTINITIALISED);
411 return(SOCKET_ERROR);
414 if (handle == NULL ||
415 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
416 WSASetLastError(WSAENOTSOCK);
417 return(SOCKET_ERROR);
420 ret=getpeername(fd, name, namelen);
424 g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
428 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
429 WSASetLastError (errnum);
431 return(SOCKET_ERROR);
437 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
439 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
442 if(startup_count==0) {
443 WSASetLastError(WSANOTINITIALISED);
444 return(SOCKET_ERROR);
447 if (handle == NULL ||
448 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
449 WSASetLastError(WSAENOTSOCK);
450 return(SOCKET_ERROR);
453 ret=getsockname(fd, name, namelen);
457 g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
461 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
462 WSASetLastError (errnum);
464 return(SOCKET_ERROR);
470 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
473 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
476 if(startup_count==0) {
477 WSASetLastError(WSANOTINITIALISED);
478 return(SOCKET_ERROR);
481 if (handle == NULL ||
482 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
483 WSASetLastError(WSAENOTSOCK);
484 return(SOCKET_ERROR);
487 ret=getsockopt(fd, level, optname, optval, optlen);
491 g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
495 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
496 WSASetLastError (errnum);
498 return(SOCKET_ERROR);
504 int _wapi_listen(guint32 fd, int backlog)
506 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
509 if(startup_count==0) {
510 WSASetLastError(WSANOTINITIALISED);
511 return(SOCKET_ERROR);
514 if (handle == NULL ||
515 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
516 WSASetLastError(WSAENOTSOCK);
517 return(SOCKET_ERROR);
520 ret=listen(fd, backlog);
524 g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
528 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
529 WSASetLastError (errnum);
531 return(SOCKET_ERROR);
537 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
539 return(_wapi_recvfrom(fd, buf, len, recv_flags, NULL, 0));
542 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
543 struct sockaddr *from, socklen_t *fromlen)
545 #ifndef HAVE_MSG_NOSIGNAL
546 void (*old_sigpipe)(int); // old SIGPIPE handler
548 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
551 if(startup_count==0) {
552 WSASetLastError(WSANOTINITIALISED);
553 return(SOCKET_ERROR);
556 if (handle == NULL ||
557 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
558 WSASetLastError(WSAENOTSOCK);
559 return(SOCKET_ERROR);
562 #ifdef HAVE_MSG_NOSIGNAL
564 ret=recvfrom(fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
567 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
569 old_sigpipe = signal(SIGPIPE, SIG_IGN);
571 ret=recvfrom(fd, buf, len, recv_flags, from, fromlen);
573 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
574 signal(SIGPIPE, old_sigpipe);
580 g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
584 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
585 WSASetLastError (errnum);
587 return(SOCKET_ERROR);
592 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
594 #ifndef HAVE_MSG_NOSIGNAL
595 void (*old_sigpipe)(int); // old SIGPIPE handler
597 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
600 if(startup_count==0) {
601 WSASetLastError(WSANOTINITIALISED);
602 return(SOCKET_ERROR);
605 if (handle == NULL ||
606 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
607 WSASetLastError(WSAENOTSOCK);
608 return(SOCKET_ERROR);
611 #ifdef HAVE_MSG_NOSIGNAL
613 ret=send(fd, msg, len, send_flags | MSG_NOSIGNAL);
615 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
617 old_sigpipe = signal(SIGPIPE, SIG_IGN);
619 ret=send(fd, msg, len, send_flags);
621 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
622 signal(SIGPIPE, old_sigpipe);
627 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
631 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
632 WSASetLastError (errnum);
634 return(SOCKET_ERROR);
639 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
640 const struct sockaddr *to, socklen_t tolen)
642 #ifndef HAVE_MSG_NOSIGNAL
643 void (*old_sigpipe)(int); // old SIGPIPE handler
645 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
648 if(startup_count==0) {
649 WSASetLastError(WSANOTINITIALISED);
650 return(SOCKET_ERROR);
653 if (handle == NULL ||
654 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
655 WSASetLastError(WSAENOTSOCK);
656 return(SOCKET_ERROR);
659 #ifdef HAVE_MSG_NOSIGNAL
661 ret=sendto(fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
663 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
665 old_sigpipe = signal(SIGPIPE, SIG_IGN);
667 ret=sendto(fd, msg, len, send_flags, to, tolen);
669 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
670 signal(SIGPIPE, old_sigpipe);
675 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
679 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
680 WSASetLastError (errnum);
682 return(SOCKET_ERROR);
687 int _wapi_setsockopt(guint32 fd, int level, int optname,
688 const void *optval, socklen_t optlen)
690 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
693 if(startup_count==0) {
694 WSASetLastError(WSANOTINITIALISED);
695 return(SOCKET_ERROR);
698 if (handle == NULL ||
699 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
700 WSASetLastError(WSAENOTSOCK);
701 return(SOCKET_ERROR);
704 ret=setsockopt(fd, level, optname, optval, optlen);
708 g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
712 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
713 WSASetLastError (errnum);
715 return(SOCKET_ERROR);
721 int _wapi_shutdown(guint32 fd, int how)
723 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
726 if(startup_count==0) {
727 WSASetLastError(WSANOTINITIALISED);
728 return(SOCKET_ERROR);
731 if (handle == NULL ||
732 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
733 WSASetLastError(WSAENOTSOCK);
734 return(SOCKET_ERROR);
737 ret=shutdown(fd, how);
741 g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
745 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
746 WSASetLastError (errnum);
748 return(SOCKET_ERROR);
754 guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
756 struct _WapiHandlePrivate_socket *socket_private_handle;
761 guint32 ret = INVALID_SOCKET;
763 fd=socket(domain, type, protocol);
764 if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
765 /* Retry with protocol == 4 (see bug #54565) */
766 fd = socket (AF_INET, SOCK_RAW, 4);
772 g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
774 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
775 WSASetLastError (errnum);
777 return(INVALID_SOCKET);
780 if (fd >= _wapi_fd_offset_table_size) {
782 g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
785 WSASetLastError (WSASYSCALLFAILURE);
788 return(INVALID_SOCKET);
792 mono_once (&socket_ops_once, socket_ops_init);
794 handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
795 if(handle==_WAPI_HANDLE_INVALID) {
796 g_warning (G_GNUC_PRETTY_FUNCTION
797 ": error creating socket handle");
798 return(INVALID_SOCKET);
801 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
803 thr_ret = _wapi_handle_lock_handle (handle);
804 g_assert (thr_ret == 0);
806 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
807 (gpointer *)&socket_private_handle);
809 g_warning (G_GNUC_PRETTY_FUNCTION
810 ": error looking up socket handle %p", handle);
814 _wapi_handle_fd_offset_store (fd, handle);
817 socket_private_handle->fd=fd;
820 g_message(G_GNUC_PRETTY_FUNCTION
821 ": returning socket handle %p with fd %d", handle,
822 socket_private_handle->fd);
826 thr_ret = _wapi_handle_unlock_handle (handle);
827 g_assert (thr_ret == 0);
828 pthread_cleanup_pop (0);
833 struct hostent *_wapi_gethostbyname(const char *hostname)
837 if(startup_count==0) {
838 WSASetLastError(WSANOTINITIALISED);
842 he=gethostbyname(hostname);
845 g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
851 WSASetLastError(WSAHOST_NOT_FOUND);
853 #if NO_ADDRESS != NO_DATA
857 WSASetLastError(WSANO_DATA);
860 WSASetLastError(WSANO_RECOVERY);
863 WSASetLastError(WSATRY_AGAIN);
866 g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
875 WSAIoctl (guint32 fd, gint32 command,
876 gchar *input, gint i_len,
877 gchar *output, gint o_len, glong *written,
878 void *unused1, void *unused2)
880 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
882 gchar *buffer = NULL;
884 if(startup_count==0) {
885 WSASetLastError(WSANOTINITIALISED);
886 return(SOCKET_ERROR);
889 if (handle == NULL ||
890 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
891 WSASetLastError (WSAENOTSOCK);
896 buffer = g_memdup (input, i_len);
898 ret = ioctl (fd, command, buffer);
902 g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
906 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
907 WSASetLastError (errnum);
913 if (buffer == NULL) {
916 /* We just copy the buffer to the output. Some ioctls
917 * don't even output any data, but, well... */
918 i_len = (i_len > o_len) ? o_len : i_len;
919 memcpy (output, buffer, i_len);
927 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
929 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
932 if(startup_count==0) {
933 WSASetLastError(WSANOTINITIALISED);
934 return(SOCKET_ERROR);
937 if (handle == NULL ||
938 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
939 WSASetLastError(WSAENOTSOCK);
940 return(SOCKET_ERROR);
943 if(command!=FIONBIO &&
945 command!=SIOCATMARK) {
946 /* Not listed in the MSDN specs, but ioctl(2) returns
947 * this if command is invalid
949 WSASetLastError(WSAEINVAL);
950 return(SOCKET_ERROR);
954 /* This works better than ioctl(...FIONBIO...) on Linux (it causes
955 * connect to return EINPROGRESS, but the ioctl doesn't seem to)
957 if(command==FIONBIO) {
958 ret=fcntl(fd, F_GETFL, 0);
960 if(*(gboolean *)arg) {
965 ret=fcntl(fd, F_SETFL, ret);
968 #endif /* O_NONBLOCK */
970 ret=ioctl(fd, command, arg);
975 g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
979 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
980 WSASetLastError (errnum);
982 return(SOCKET_ERROR);
988 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
989 fd_set *exceptfds, struct timeval *timeout)
993 if(startup_count==0) {
994 WSASetLastError(WSANOTINITIALISED);
995 return(SOCKET_ERROR);
999 ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
1001 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
1004 gint errnum = errno;
1006 g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
1009 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
1010 WSASetLastError (errnum);
1012 return(SOCKET_ERROR);
1018 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1020 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1022 if (handle == NULL ||
1023 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1024 WSASetLastError(WSAENOTSOCK);
1031 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1033 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1035 if (handle == NULL ||
1036 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1037 WSASetLastError(WSAENOTSOCK);
1041 return(FD_ISSET(fd, set));
1044 void _wapi_FD_SET(guint32 fd, fd_set *set)
1046 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1048 if (handle == NULL ||
1049 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1050 WSASetLastError(WSAENOTSOCK);
1062 SocketAsyncCB callback;
1065 #define SIGPTR(a) a.SIGVAL_PTR
1068 async_notifier (union sigval sig)
1070 notifier_data_t *ndata = SIGPTR (sig);
1074 error = aio_return (ndata->aio);
1076 error = _wapi_get_win32_file_error (error);
1083 ndata->callback (error, numbytes, ndata->ares);
1084 g_free (ndata->aio);
1089 do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer,
1090 guint32 numbytes, guint32 *out_bytes,
1092 SocketAsyncCB callback)
1094 gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
1095 int fd = GPOINTER_TO_UINT (fd_handle);
1098 notifier_data_t *ndata;
1100 if (handle == NULL ||
1101 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1102 WSASetLastError (WSAENOTSOCK);
1106 ndata = g_new0 (notifier_data_t, 1);
1107 aio = g_new0 (struct aiocb, 1);
1110 ndata->callback = callback;
1112 aio->aio_fildes = fd;
1113 aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
1114 aio->aio_nbytes = numbytes;
1115 aio->aio_offset = 0;
1116 aio->aio_buf = buffer;
1117 aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
1118 aio->aio_sigevent.sigev_notify_function = async_notifier;
1119 SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
1122 result = aio_read (aio);
1124 result = aio_write (aio);
1128 WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
1132 result = aio_error (aio);
1134 numbytes = aio_return (aio);
1136 WSASetLastError (errno_to_WSA (result, "do_aio_call"));
1141 *out_bytes = numbytes;
1146 gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
1148 guint32 *bytesread, gpointer ares,
1149 SocketAsyncCB callback)
1151 return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
1154 gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
1156 guint32 *byteswritten, gpointer ares,
1157 SocketAsyncCB callback)
1159 return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
1162 #endif /* USE_AIO */