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 if (socket_private_handle->fd_mapped.assigned == TRUE) {
101 /* Blank out the mapping, to make catching errors easier */
102 _wapi_handle_fd_offset_store (socket_private_handle->fd_mapped.fd, NULL);
105 ret=close(socket_private_handle->fd_mapped.fd);
107 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
112 g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
115 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
116 WSASetLastError (errnum);
121 WSASetLastError(WSAENOTSOCK);
125 int WSAStartup(guint32 requested, WapiWSAData *data)
131 /* Insist on v2.0+ */
132 if(requested < MAKEWORD(2,0)) {
133 return(WSAVERNOTSUPPORTED);
136 if(startup_count==0) {
137 sockets=g_ptr_array_new();
142 /* I've no idea what is the minor version of the spec I read */
143 data->wHighVersion=MAKEWORD(2,0);
145 data->wVersion=requested < data->wHighVersion? requested:
149 g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
153 strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
154 strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
164 g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
167 if(--startup_count) {
172 /* Close down all sockets */
173 for(i=0; i<sockets->len; i++) {
176 handle=g_ptr_array_index(sockets, i);
177 _wapi_handle_ops_close_private (handle);
180 g_ptr_array_free(sockets, FALSE);
186 static void error_init(void)
190 ret = pthread_key_create(&error_key, NULL);
194 void WSASetLastError(int error)
198 mono_once(&error_key_once, error_init);
199 ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
203 int WSAGetLastError(void)
208 mono_once(&error_key_once, error_init);
209 errptr=pthread_getspecific(error_key);
210 err=GPOINTER_TO_INT(errptr);
215 int closesocket(guint32 fd_handle)
217 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd_handle));
219 if (handle == NULL ||
220 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
221 WSASetLastError (WSAENOTSOCK);
225 _wapi_handle_unref (handle);
229 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
231 struct _WapiHandlePrivate_socket *new_socket_private_handle;
232 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
237 guint32 ret = INVALID_SOCKET;
239 if(startup_count==0) {
240 WSASetLastError(WSANOTINITIALISED);
241 return(INVALID_SOCKET);
244 if (handle == NULL ||
245 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
246 WSASetLastError(WSAENOTSOCK);
247 return(INVALID_SOCKET);
251 new_fd=accept(fd, addr, addrlen);
253 while (new_fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
258 g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
262 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
263 WSASetLastError (errnum);
265 return(INVALID_SOCKET);
268 if (new_fd >= _wapi_fd_offset_table_size) {
270 g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
273 WSASetLastError (WSASYSCALLFAILURE);
277 return(INVALID_SOCKET);
280 new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
281 if(new_handle==_WAPI_HANDLE_INVALID) {
282 g_warning (G_GNUC_PRETTY_FUNCTION
283 ": error creating socket handle");
284 WSASetLastError (ERROR_GEN_FAILURE);
285 return(INVALID_SOCKET);
288 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
290 thr_ret = _wapi_handle_lock_handle (new_handle);
291 g_assert (thr_ret == 0);
293 ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
294 (gpointer *)&new_socket_private_handle);
296 g_warning (G_GNUC_PRETTY_FUNCTION
297 ": error looking up new socket handle %p",
302 _wapi_handle_fd_offset_store (new_fd, new_handle);
305 new_socket_private_handle->fd_mapped.fd = new_fd;
306 new_socket_private_handle->fd_mapped.assigned = TRUE;
309 g_message(G_GNUC_PRETTY_FUNCTION
310 ": returning newly accepted socket handle %p with fd %d",
311 new_handle, new_socket_private_handle->fd_mapped.fd);
315 thr_ret = _wapi_handle_unlock_handle (new_handle);
316 g_assert (thr_ret == 0);
317 pthread_cleanup_pop (0);
322 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
324 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
327 if(startup_count==0) {
328 WSASetLastError(WSANOTINITIALISED);
329 return(SOCKET_ERROR);
332 if (handle == NULL ||
333 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
334 WSASetLastError(WSAENOTSOCK);
335 return(SOCKET_ERROR);
338 ret=bind(fd, my_addr, addrlen);
342 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
345 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
346 WSASetLastError (errnum);
348 return(SOCKET_ERROR);
353 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
356 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
360 if(startup_count==0) {
361 WSASetLastError(WSANOTINITIALISED);
362 return(SOCKET_ERROR);
365 if (handle == NULL ||
366 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
367 WSASetLastError(WSAENOTSOCK);
368 return(SOCKET_ERROR);
372 ret=connect(fd, serv_addr, addrlen);
374 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
376 if(ret==-1 && errno==EACCES) {
377 /* Try setting SO_BROADCAST and connecting again, but
378 * keep the original errno
384 ret=setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
388 ret=connect (fd, serv_addr, addrlen);
390 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
392 } else if (ret==-1) {
398 g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
401 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
402 WSASetLastError (errnum);
404 return(SOCKET_ERROR);
409 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
411 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
414 if(startup_count==0) {
415 WSASetLastError(WSANOTINITIALISED);
416 return(SOCKET_ERROR);
419 if (handle == NULL ||
420 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
421 WSASetLastError(WSAENOTSOCK);
422 return(SOCKET_ERROR);
425 ret=getpeername(fd, name, namelen);
429 g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
433 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
434 WSASetLastError (errnum);
436 return(SOCKET_ERROR);
442 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
444 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
447 if(startup_count==0) {
448 WSASetLastError(WSANOTINITIALISED);
449 return(SOCKET_ERROR);
452 if (handle == NULL ||
453 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
454 WSASetLastError(WSAENOTSOCK);
455 return(SOCKET_ERROR);
458 ret=getsockname(fd, name, namelen);
462 g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
466 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
467 WSASetLastError (errnum);
469 return(SOCKET_ERROR);
475 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
478 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
481 if(startup_count==0) {
482 WSASetLastError(WSANOTINITIALISED);
483 return(SOCKET_ERROR);
486 if (handle == NULL ||
487 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
488 WSASetLastError(WSAENOTSOCK);
489 return(SOCKET_ERROR);
492 ret=getsockopt(fd, level, optname, optval, optlen);
496 g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
500 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
501 WSASetLastError (errnum);
503 return(SOCKET_ERROR);
509 int _wapi_listen(guint32 fd, int backlog)
511 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
514 if(startup_count==0) {
515 WSASetLastError(WSANOTINITIALISED);
516 return(SOCKET_ERROR);
519 if (handle == NULL ||
520 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
521 WSASetLastError(WSAENOTSOCK);
522 return(SOCKET_ERROR);
525 ret=listen(fd, backlog);
529 g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
533 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
534 WSASetLastError (errnum);
536 return(SOCKET_ERROR);
542 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
544 return(_wapi_recvfrom(fd, buf, len, recv_flags, NULL, 0));
547 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
548 struct sockaddr *from, socklen_t *fromlen)
550 #ifndef HAVE_MSG_NOSIGNAL
551 void (*old_sigpipe)(int); // old SIGPIPE handler
553 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
556 if(startup_count==0) {
557 WSASetLastError(WSANOTINITIALISED);
558 return(SOCKET_ERROR);
561 if (handle == NULL ||
562 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
563 WSASetLastError(WSAENOTSOCK);
564 return(SOCKET_ERROR);
567 #ifdef HAVE_MSG_NOSIGNAL
569 ret=recvfrom(fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
572 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
574 old_sigpipe = signal(SIGPIPE, SIG_IGN);
576 ret=recvfrom(fd, buf, len, recv_flags, from, fromlen);
578 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
579 signal(SIGPIPE, old_sigpipe);
585 g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
589 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
590 WSASetLastError (errnum);
592 return(SOCKET_ERROR);
597 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
599 #ifndef HAVE_MSG_NOSIGNAL
600 void (*old_sigpipe)(int); // old SIGPIPE handler
602 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
605 if(startup_count==0) {
606 WSASetLastError(WSANOTINITIALISED);
607 return(SOCKET_ERROR);
610 if (handle == NULL ||
611 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
612 WSASetLastError(WSAENOTSOCK);
613 return(SOCKET_ERROR);
616 #ifdef HAVE_MSG_NOSIGNAL
618 ret=send(fd, msg, len, send_flags | MSG_NOSIGNAL);
620 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
622 old_sigpipe = signal(SIGPIPE, SIG_IGN);
624 ret=send(fd, msg, len, send_flags);
626 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
627 signal(SIGPIPE, old_sigpipe);
632 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
636 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
637 WSASetLastError (errnum);
639 return(SOCKET_ERROR);
644 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
645 const struct sockaddr *to, socklen_t tolen)
647 #ifndef HAVE_MSG_NOSIGNAL
648 void (*old_sigpipe)(int); // old SIGPIPE handler
650 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
653 if(startup_count==0) {
654 WSASetLastError(WSANOTINITIALISED);
655 return(SOCKET_ERROR);
658 if (handle == NULL ||
659 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
660 WSASetLastError(WSAENOTSOCK);
661 return(SOCKET_ERROR);
664 #ifdef HAVE_MSG_NOSIGNAL
666 ret=sendto(fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
668 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
670 old_sigpipe = signal(SIGPIPE, SIG_IGN);
672 ret=sendto(fd, msg, len, send_flags, to, tolen);
674 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
675 signal(SIGPIPE, old_sigpipe);
680 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
684 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
685 WSASetLastError (errnum);
687 return(SOCKET_ERROR);
692 int _wapi_setsockopt(guint32 fd, int level, int optname,
693 const void *optval, socklen_t optlen)
695 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
698 if(startup_count==0) {
699 WSASetLastError(WSANOTINITIALISED);
700 return(SOCKET_ERROR);
703 if (handle == NULL ||
704 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
705 WSASetLastError(WSAENOTSOCK);
706 return(SOCKET_ERROR);
709 ret=setsockopt(fd, level, optname, optval, optlen);
713 g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
717 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
718 WSASetLastError (errnum);
720 return(SOCKET_ERROR);
726 int _wapi_shutdown(guint32 fd, int how)
728 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
731 if(startup_count==0) {
732 WSASetLastError(WSANOTINITIALISED);
733 return(SOCKET_ERROR);
736 if (handle == NULL ||
737 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
738 WSASetLastError(WSAENOTSOCK);
739 return(SOCKET_ERROR);
742 ret=shutdown(fd, how);
746 g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
750 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
751 WSASetLastError (errnum);
753 return(SOCKET_ERROR);
759 guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
761 struct _WapiHandlePrivate_socket *socket_private_handle;
766 guint32 ret = INVALID_SOCKET;
768 fd=socket(domain, type, protocol);
769 if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
770 /* Retry with protocol == 4 (see bug #54565) */
771 fd = socket (AF_INET, SOCK_RAW, 4);
777 g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
779 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
780 WSASetLastError (errnum);
782 return(INVALID_SOCKET);
785 if (fd >= _wapi_fd_offset_table_size) {
787 g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
790 WSASetLastError (WSASYSCALLFAILURE);
793 return(INVALID_SOCKET);
797 mono_once (&socket_ops_once, socket_ops_init);
799 handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
800 if(handle==_WAPI_HANDLE_INVALID) {
801 g_warning (G_GNUC_PRETTY_FUNCTION
802 ": error creating socket handle");
803 return(INVALID_SOCKET);
806 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
808 thr_ret = _wapi_handle_lock_handle (handle);
809 g_assert (thr_ret == 0);
811 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
812 (gpointer *)&socket_private_handle);
814 g_warning (G_GNUC_PRETTY_FUNCTION
815 ": error looking up socket handle %p", handle);
819 _wapi_handle_fd_offset_store (fd, handle);
822 socket_private_handle->fd_mapped.fd = fd;
823 socket_private_handle->fd_mapped.assigned = TRUE;
826 g_message(G_GNUC_PRETTY_FUNCTION
827 ": returning socket handle %p with fd %d", handle,
828 socket_private_handle->fd_mapped.fd);
832 thr_ret = _wapi_handle_unlock_handle (handle);
833 g_assert (thr_ret == 0);
834 pthread_cleanup_pop (0);
839 struct hostent *_wapi_gethostbyname(const char *hostname)
843 if(startup_count==0) {
844 WSASetLastError(WSANOTINITIALISED);
848 he=gethostbyname(hostname);
851 g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
857 WSASetLastError(WSAHOST_NOT_FOUND);
859 #if NO_ADDRESS != NO_DATA
863 WSASetLastError(WSANO_DATA);
866 WSASetLastError(WSANO_RECOVERY);
869 WSASetLastError(WSATRY_AGAIN);
872 g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
881 WSAIoctl (guint32 fd, gint32 command,
882 gchar *input, gint i_len,
883 gchar *output, gint o_len, glong *written,
884 void *unused1, void *unused2)
886 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
888 gchar *buffer = NULL;
890 if(startup_count==0) {
891 WSASetLastError(WSANOTINITIALISED);
892 return(SOCKET_ERROR);
895 if (handle == NULL ||
896 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
897 WSASetLastError (WSAENOTSOCK);
902 buffer = g_memdup (input, i_len);
904 ret = ioctl (fd, command, buffer);
908 g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
912 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
913 WSASetLastError (errnum);
919 if (buffer == NULL) {
922 /* We just copy the buffer to the output. Some ioctls
923 * don't even output any data, but, well... */
924 i_len = (i_len > o_len) ? o_len : i_len;
925 memcpy (output, buffer, i_len);
933 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
935 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
938 if(startup_count==0) {
939 WSASetLastError(WSANOTINITIALISED);
940 return(SOCKET_ERROR);
943 if (handle == NULL ||
944 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
945 WSASetLastError(WSAENOTSOCK);
946 return(SOCKET_ERROR);
949 if(command!=FIONBIO &&
951 command!=SIOCATMARK) {
952 /* Not listed in the MSDN specs, but ioctl(2) returns
953 * this if command is invalid
955 WSASetLastError(WSAEINVAL);
956 return(SOCKET_ERROR);
960 /* This works better than ioctl(...FIONBIO...) on Linux (it causes
961 * connect to return EINPROGRESS, but the ioctl doesn't seem to)
963 if(command==FIONBIO) {
964 ret=fcntl(fd, F_GETFL, 0);
966 if(*(gboolean *)arg) {
971 ret=fcntl(fd, F_SETFL, ret);
974 #endif /* O_NONBLOCK */
976 ret=ioctl(fd, command, arg);
981 g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
985 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
986 WSASetLastError (errnum);
988 return(SOCKET_ERROR);
994 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
995 fd_set *exceptfds, struct timeval *timeout)
999 if(startup_count==0) {
1000 WSASetLastError(WSANOTINITIALISED);
1001 return(SOCKET_ERROR);
1005 ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
1007 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
1010 gint errnum = errno;
1012 g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
1015 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
1016 WSASetLastError (errnum);
1018 return(SOCKET_ERROR);
1024 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1026 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1028 if (handle == NULL ||
1029 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1030 WSASetLastError(WSAENOTSOCK);
1037 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1039 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1041 if (handle == NULL ||
1042 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1043 WSASetLastError(WSAENOTSOCK);
1047 return(FD_ISSET(fd, set));
1050 void _wapi_FD_SET(guint32 fd, fd_set *set)
1052 gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
1054 if (handle == NULL ||
1055 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1056 WSASetLastError(WSAENOTSOCK);
1068 SocketAsyncCB callback;
1071 #define SIGPTR(a) a.SIGVAL_PTR
1074 async_notifier (union sigval sig)
1076 notifier_data_t *ndata = SIGPTR (sig);
1080 error = aio_return (ndata->aio);
1082 error = _wapi_get_win32_file_error (error);
1089 ndata->callback (error, numbytes, ndata->ares);
1090 g_free (ndata->aio);
1095 do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer,
1096 guint32 numbytes, guint32 *out_bytes,
1098 SocketAsyncCB callback)
1100 gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
1101 int fd = GPOINTER_TO_UINT (fd_handle);
1104 notifier_data_t *ndata;
1106 if (handle == NULL ||
1107 _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1108 WSASetLastError (WSAENOTSOCK);
1112 ndata = g_new0 (notifier_data_t, 1);
1113 aio = g_new0 (struct aiocb, 1);
1116 ndata->callback = callback;
1118 aio->aio_fildes = fd;
1119 aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
1120 aio->aio_nbytes = numbytes;
1121 aio->aio_offset = 0;
1122 aio->aio_buf = buffer;
1123 aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
1124 aio->aio_sigevent.sigev_notify_function = async_notifier;
1125 SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
1128 result = aio_read (aio);
1130 result = aio_write (aio);
1134 WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
1138 result = aio_error (aio);
1140 numbytes = aio_return (aio);
1142 WSASetLastError (errno_to_WSA (result, "do_aio_call"));
1147 *out_bytes = numbytes;
1152 gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
1154 guint32 *bytesread, gpointer ares,
1155 SocketAsyncCB callback)
1157 return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
1160 gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
1162 guint32 *byteswritten, gpointer ares,
1163 SocketAsyncCB callback)
1165 return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
1168 #endif /* USE_AIO */