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 #include <mono/io-layer/wapi.h>
32 #include <mono/io-layer/wapi-private.h>
33 #include <mono/io-layer/socket-private.h>
34 #include <mono/io-layer/handles-private.h>
35 #include <mono/io-layer/socket-wrappers.h>
39 static guint32 startup_count=0;
40 static GPtrArray *sockets=NULL;
41 static pthread_key_t error_key;
42 static mono_once_t error_key_once=MONO_ONCE_INIT;
44 static void socket_close_private (gpointer handle);
46 struct _WapiHandleOps _wapi_socket_ops = {
47 NULL, /* close_shared */
48 socket_close_private, /* close_private */
54 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
56 static void socket_ops_init (void)
58 /* No capabilities to register */
61 static void socket_close_private (gpointer handle)
63 struct _WapiHandlePrivate_socket *socket_private_handle;
68 g_message(G_GNUC_PRETTY_FUNCTION ": closing socket handle %p",
72 if(startup_count==0) {
73 WSASetLastError(WSANOTINITIALISED);
77 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
78 NULL, (gpointer *)&socket_private_handle);
80 g_warning (G_GNUC_PRETTY_FUNCTION
81 ": error looking up socket handle %p", handle);
82 WSASetLastError(WSAENOTSOCK);
86 g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle));
88 ret=close(socket_private_handle->fd);
92 g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
95 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
96 WSASetLastError (errnum);
102 int WSAStartup(guint32 requested, WapiWSAData *data)
108 /* Insist on v2.0+ */
109 if(requested < MAKEWORD(2,0)) {
110 return(WSAVERNOTSUPPORTED);
113 if(startup_count==0) {
114 sockets=g_ptr_array_new();
119 /* I've no idea what is the minor version of the spec I read */
120 data->wHighVersion=MAKEWORD(2,0);
122 data->wVersion=requested < data->wHighVersion? requested:
126 g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
130 strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
131 strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
141 g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
144 if(--startup_count) {
149 /* Close down all sockets */
150 for(i=0; i<sockets->len; i++) {
153 handle=g_ptr_array_index(sockets, i);
154 _wapi_handle_ops_close_private (handle);
157 g_ptr_array_free(sockets, FALSE);
163 static void error_init(void)
167 ret = pthread_key_create(&error_key, NULL);
171 void WSASetLastError(int error)
175 mono_once(&error_key_once, error_init);
176 ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
180 int WSAGetLastError(void)
185 mono_once(&error_key_once, error_init);
186 errptr=pthread_getspecific(error_key);
187 err=GPOINTER_TO_INT(errptr);
192 int closesocket(guint32 handle)
194 _wapi_handle_unref (GUINT_TO_POINTER (handle));
198 guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
201 struct _WapiHandlePrivate_socket *socket_private_handle;
202 struct _WapiHandlePrivate_socket *new_socket_private_handle;
207 guint32 ret = INVALID_SOCKET;
209 if(startup_count==0) {
210 WSASetLastError(WSANOTINITIALISED);
211 return(INVALID_SOCKET);
214 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
215 NULL, (gpointer *)&socket_private_handle);
217 g_warning (G_GNUC_PRETTY_FUNCTION
218 ": error looking up socket handle 0x%x", handle);
219 WSASetLastError(WSAENOTSOCK);
220 return(INVALID_SOCKET);
223 fd=accept(socket_private_handle->fd, addr, addrlen);
227 g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
231 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
232 WSASetLastError (errnum);
234 return(INVALID_SOCKET);
237 new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
238 if(new_handle==_WAPI_HANDLE_INVALID) {
239 g_warning (G_GNUC_PRETTY_FUNCTION
240 ": error creating socket handle");
241 return(INVALID_SOCKET);
244 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
246 thr_ret = _wapi_handle_lock_handle (new_handle);
247 g_assert (thr_ret == 0);
249 ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
250 (gpointer *)&new_socket_private_handle);
252 g_warning (G_GNUC_PRETTY_FUNCTION
253 ": error looking up socket handle 0x%x", handle);
256 ret = GPOINTER_TO_UINT (new_handle);
258 new_socket_private_handle->fd=fd;
261 g_message(G_GNUC_PRETTY_FUNCTION
262 ": returning newly accepted socket handle %p with fd %d",
263 new_handle, new_socket_private_handle->fd);
267 thr_ret = _wapi_handle_unlock_handle (new_handle);
268 g_assert (thr_ret == 0);
269 pthread_cleanup_pop (0);
274 int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
276 struct _WapiHandlePrivate_socket *socket_private_handle;
280 if(startup_count==0) {
281 WSASetLastError(WSANOTINITIALISED);
282 return(SOCKET_ERROR);
285 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
286 NULL, (gpointer *)&socket_private_handle);
288 g_warning (G_GNUC_PRETTY_FUNCTION
289 ": error looking up socket handle 0x%x", handle);
290 WSASetLastError(WSAENOTSOCK);
291 return(SOCKET_ERROR);
294 ret=bind(socket_private_handle->fd, my_addr, addrlen);
298 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
301 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
302 WSASetLastError (errnum);
304 return(SOCKET_ERROR);
309 int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
312 struct _WapiHandlePrivate_socket *socket_private_handle;
317 if(startup_count==0) {
318 WSASetLastError(WSANOTINITIALISED);
319 return(SOCKET_ERROR);
322 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
323 NULL, (gpointer *)&socket_private_handle);
325 g_warning (G_GNUC_PRETTY_FUNCTION
326 ": error looking up socket handle 0x%x", handle);
327 WSASetLastError(WSAENOTSOCK);
328 return(SOCKET_ERROR);
331 ret=connect(socket_private_handle->fd, serv_addr, addrlen);
332 if(ret==-1 && errno==EACCES) {
333 /* Try setting SO_BROADCAST and connecting again, but
334 * keep the original errno
340 ret=setsockopt (socket_private_handle->fd, SOL_SOCKET,
341 SO_BROADCAST, &true, sizeof(true));
343 ret=connect (socket_private_handle->fd, serv_addr,
346 } else if (ret==-1) {
352 g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
355 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
356 WSASetLastError (errnum);
358 return(SOCKET_ERROR);
363 int _wapi_getpeername(guint32 handle, struct sockaddr *name,
366 struct _WapiHandlePrivate_socket *socket_private_handle;
370 if(startup_count==0) {
371 WSASetLastError(WSANOTINITIALISED);
372 return(SOCKET_ERROR);
375 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
376 NULL, (gpointer *)&socket_private_handle);
378 g_warning (G_GNUC_PRETTY_FUNCTION
379 ": error looking up socket handle 0x%x", handle);
380 WSASetLastError(WSAENOTSOCK);
381 return(SOCKET_ERROR);
384 ret=getpeername(socket_private_handle->fd, name, namelen);
388 g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
392 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
393 WSASetLastError (errnum);
395 return(SOCKET_ERROR);
401 int _wapi_getsockname(guint32 handle, struct sockaddr *name,
404 struct _WapiHandlePrivate_socket *socket_private_handle;
408 if(startup_count==0) {
409 WSASetLastError(WSANOTINITIALISED);
410 return(SOCKET_ERROR);
413 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
414 NULL, (gpointer *)&socket_private_handle);
416 g_warning (G_GNUC_PRETTY_FUNCTION
417 ": error looking up socket handle 0x%x", handle);
418 WSASetLastError(WSAENOTSOCK);
419 return(SOCKET_ERROR);
422 ret=getsockname(socket_private_handle->fd, name, namelen);
426 g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
430 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
431 WSASetLastError (errnum);
433 return(SOCKET_ERROR);
439 int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval,
442 struct _WapiHandlePrivate_socket *socket_private_handle;
446 if(startup_count==0) {
447 WSASetLastError(WSANOTINITIALISED);
448 return(SOCKET_ERROR);
451 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
452 NULL, (gpointer *)&socket_private_handle);
454 g_warning (G_GNUC_PRETTY_FUNCTION
455 ": error looking up socket handle 0x%x", handle);
456 WSASetLastError(WSAENOTSOCK);
457 return(SOCKET_ERROR);
460 ret=getsockopt(socket_private_handle->fd, level, optname, optval,
465 g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
469 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
470 WSASetLastError (errnum);
472 return(SOCKET_ERROR);
478 int _wapi_listen(guint32 handle, int backlog)
480 struct _WapiHandlePrivate_socket *socket_private_handle;
484 if(startup_count==0) {
485 WSASetLastError(WSANOTINITIALISED);
486 return(SOCKET_ERROR);
489 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
490 NULL, (gpointer *)&socket_private_handle);
492 g_warning (G_GNUC_PRETTY_FUNCTION
493 ": error looking up socket handle 0x%x", handle);
494 WSASetLastError(WSAENOTSOCK);
495 return(SOCKET_ERROR);
498 ret=listen(socket_private_handle->fd, backlog);
502 g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
506 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
507 WSASetLastError (errnum);
509 return(SOCKET_ERROR);
515 int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags)
517 return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0));
520 int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags,
521 struct sockaddr *from, socklen_t *fromlen)
523 #ifndef HAVE_MSG_NOSIGNAL
524 void (*old_sigpipe)(int); // old SIGPIPE handler
526 struct _WapiHandlePrivate_socket *socket_private_handle;
530 if(startup_count==0) {
531 WSASetLastError(WSANOTINITIALISED);
532 return(SOCKET_ERROR);
535 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
536 NULL, (gpointer *)&socket_private_handle);
538 g_warning (G_GNUC_PRETTY_FUNCTION
539 ": error looking up socket handle 0x%x", handle);
540 WSASetLastError(WSAENOTSOCK);
541 return(SOCKET_ERROR);
544 #ifdef HAVE_MSG_NOSIGNAL
545 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
548 old_sigpipe = signal(SIGPIPE, SIG_IGN);
549 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from,
551 signal(SIGPIPE, old_sigpipe);
557 g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
561 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
562 WSASetLastError (errnum);
564 return(SOCKET_ERROR);
569 int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags)
571 #ifndef HAVE_MSG_NOSIGNAL
572 void (*old_sigpipe)(int); // old SIGPIPE handler
574 struct _WapiHandlePrivate_socket *socket_private_handle;
578 if(startup_count==0) {
579 WSASetLastError(WSANOTINITIALISED);
580 return(SOCKET_ERROR);
583 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
584 NULL, (gpointer *)&socket_private_handle);
586 g_warning (G_GNUC_PRETTY_FUNCTION
587 ": error looking up socket handle 0x%x", handle);
588 WSASetLastError(WSAENOTSOCK);
589 return(SOCKET_ERROR);
592 #ifdef HAVE_MSG_NOSIGNAL
593 ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL);
595 old_sigpipe = signal(SIGPIPE, SIG_IGN);
596 ret=send(socket_private_handle->fd, msg, len, send_flags);
597 signal(SIGPIPE, old_sigpipe);
602 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
606 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
607 WSASetLastError (errnum);
609 return(SOCKET_ERROR);
614 int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags,
615 const struct sockaddr *to, socklen_t tolen)
617 #ifndef HAVE_MSG_NOSIGNAL
618 void (*old_sigpipe)(int); // old SIGPIPE handler
620 struct _WapiHandlePrivate_socket *socket_private_handle;
624 if(startup_count==0) {
625 WSASetLastError(WSANOTINITIALISED);
626 return(SOCKET_ERROR);
629 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
630 NULL, (gpointer *)&socket_private_handle);
632 g_warning (G_GNUC_PRETTY_FUNCTION
633 ": error looking up socket handle 0x%x", handle);
634 WSASetLastError(WSAENOTSOCK);
635 return(SOCKET_ERROR);
638 #ifdef HAVE_MSG_NOSIGNAL
639 ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
641 old_sigpipe = signal(SIGPIPE, SIG_IGN);
642 ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen);
643 signal(SIGPIPE, old_sigpipe);
648 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
652 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
653 WSASetLastError (errnum);
655 return(SOCKET_ERROR);
660 int _wapi_setsockopt(guint32 handle, int level, int optname,
661 const void *optval, socklen_t optlen)
663 struct _WapiHandlePrivate_socket *socket_private_handle;
667 if(startup_count==0) {
668 WSASetLastError(WSANOTINITIALISED);
669 return(SOCKET_ERROR);
672 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
673 NULL, (gpointer *)&socket_private_handle);
675 g_warning (G_GNUC_PRETTY_FUNCTION
676 ": error looking up socket handle 0x%x", handle);
677 WSASetLastError(WSAENOTSOCK);
678 return(SOCKET_ERROR);
681 ret=setsockopt(socket_private_handle->fd, level, optname, optval,
686 g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
690 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
691 WSASetLastError (errnum);
693 return(SOCKET_ERROR);
699 int _wapi_shutdown(guint32 handle, int how)
701 struct _WapiHandlePrivate_socket *socket_private_handle;
705 if(startup_count==0) {
706 WSASetLastError(WSANOTINITIALISED);
707 return(SOCKET_ERROR);
710 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
711 NULL, (gpointer *)&socket_private_handle);
713 g_warning (G_GNUC_PRETTY_FUNCTION
714 ": error looking up socket handle 0x%x", handle);
715 WSASetLastError(WSAENOTSOCK);
716 return(SOCKET_ERROR);
719 ret=shutdown(socket_private_handle->fd, how);
723 g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
727 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
728 WSASetLastError (errnum);
730 return(SOCKET_ERROR);
736 guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
738 struct _WapiHandlePrivate_socket *socket_private_handle;
743 guint32 ret = INVALID_SOCKET;
745 fd=socket(domain, type, protocol);
746 if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
747 /* Retry with protocol == 4 (see bug #54565) */
748 fd = socket (AF_INET, SOCK_RAW, 4);
754 g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
756 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
757 WSASetLastError (errnum);
759 return(INVALID_SOCKET);
762 mono_once (&socket_ops_once, socket_ops_init);
764 handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
765 if(handle==_WAPI_HANDLE_INVALID) {
766 g_warning (G_GNUC_PRETTY_FUNCTION
767 ": error creating socket handle");
768 return(INVALID_SOCKET);
771 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
773 thr_ret = _wapi_handle_lock_handle (handle);
774 g_assert (thr_ret == 0);
776 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
777 (gpointer *)&socket_private_handle);
779 g_warning (G_GNUC_PRETTY_FUNCTION
780 ": error looking up socket handle %p", handle);
783 ret = GPOINTER_TO_UINT (handle);
785 socket_private_handle->fd=fd;
788 g_message(G_GNUC_PRETTY_FUNCTION
789 ": returning socket handle %p with fd %d", handle,
790 socket_private_handle->fd);
794 thr_ret = _wapi_handle_unlock_handle (handle);
795 g_assert (thr_ret == 0);
796 pthread_cleanup_pop (0);
801 struct hostent *_wapi_gethostbyname(const char *hostname)
805 if(startup_count==0) {
806 WSASetLastError(WSANOTINITIALISED);
810 he=gethostbyname(hostname);
813 g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
819 WSASetLastError(WSAHOST_NOT_FOUND);
821 #if NO_ADDRESS != NO_DATA
825 WSASetLastError(WSANO_DATA);
828 WSASetLastError(WSANO_RECOVERY);
831 WSASetLastError(WSATRY_AGAIN);
834 g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
843 WSAIoctl (guint32 handle, gint32 command,
844 gchar *input, gint i_len,
845 gchar *output, gint o_len, glong *written,
846 void *unused1, void *unused2)
848 struct _WapiHandlePrivate_socket *socket_private_handle;
851 gchar *buffer = NULL;
853 if(startup_count==0) {
854 WSASetLastError(WSANOTINITIALISED);
855 return(SOCKET_ERROR);
858 ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
859 NULL, (gpointer *)&socket_private_handle);
862 g_warning (G_GNUC_PRETTY_FUNCTION
863 ": error looking up socket handle 0x%x", handle);
864 WSASetLastError (WSAENOTSOCK);
869 buffer = g_memdup (input, i_len);
871 ret = ioctl (socket_private_handle->fd, command, buffer);
875 g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
879 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
880 WSASetLastError (errnum);
886 if (buffer == NULL) {
889 /* We just copy the buffer to the output. Some ioctls
890 * don't even output any data, but, well... */
891 i_len = (i_len > o_len) ? o_len : i_len;
892 memcpy (output, buffer, i_len);
900 int ioctlsocket(guint32 handle, gint32 command, gpointer arg)
902 struct _WapiHandlePrivate_socket *socket_private_handle;
906 if(startup_count==0) {
907 WSASetLastError(WSANOTINITIALISED);
908 return(SOCKET_ERROR);
911 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
912 NULL, (gpointer *)&socket_private_handle);
914 g_warning (G_GNUC_PRETTY_FUNCTION
915 ": error looking up socket handle 0x%x", handle);
916 WSASetLastError(WSAENOTSOCK);
917 return(SOCKET_ERROR);
920 if(command!=FIONBIO &&
922 command!=SIOCATMARK) {
923 /* Not listed in the MSDN specs, but ioctl(2) returns
924 * this if command is invalid
926 WSASetLastError(WSAEINVAL);
927 return(SOCKET_ERROR);
931 /* This works better than ioctl(...FIONBIO...) on Linux (it causes
932 * connect to return EINPROGRESS, but the ioctl doesn't seem to)
934 if(command==FIONBIO) {
935 ret=fcntl(socket_private_handle->fd, F_GETFL, 0);
937 if(*(gboolean *)arg) {
942 ret=fcntl(socket_private_handle->fd, F_SETFL, ret);
945 #endif /* O_NONBLOCK */
947 ret=ioctl(socket_private_handle->fd, command, arg);
952 g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
956 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
957 WSASetLastError (errnum);
959 return(SOCKET_ERROR);
965 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
966 fd_set *exceptfds, struct timeval *timeout)
970 if(startup_count==0) {
971 WSASetLastError(WSANOTINITIALISED);
972 return(SOCKET_ERROR);
975 ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
979 g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
982 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
983 WSASetLastError (errnum);
985 return(SOCKET_ERROR);
991 void _wapi_FD_CLR(guint32 handle, fd_set *set)
993 struct _WapiHandlePrivate_socket *socket_private_handle;
996 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
997 NULL, (gpointer *)&socket_private_handle);
999 g_warning (G_GNUC_PRETTY_FUNCTION
1000 ": error looking up socket handle 0x%x", handle);
1001 WSASetLastError(WSAENOTSOCK);
1005 FD_CLR(socket_private_handle->fd, set);
1008 int _wapi_FD_ISSET(guint32 handle, fd_set *set)
1010 struct _WapiHandlePrivate_socket *socket_private_handle;
1013 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1014 NULL, (gpointer *)&socket_private_handle);
1016 g_warning (G_GNUC_PRETTY_FUNCTION
1017 ": error looking up socket handle 0x%x", handle);
1018 WSASetLastError(WSAENOTSOCK);
1022 return(FD_ISSET(socket_private_handle->fd, set));
1025 void _wapi_FD_SET(guint32 handle, fd_set *set)
1027 struct _WapiHandlePrivate_socket *socket_private_handle;
1030 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1031 NULL, (gpointer *)&socket_private_handle);
1033 g_warning (G_GNUC_PRETTY_FUNCTION
1034 ": error looking up socket handle 0x%x", handle);
1035 WSASetLastError(WSAENOTSOCK);
1039 FD_SET(socket_private_handle->fd, set);
1042 #ifndef PLATFORM_WIN32
1048 SocketAsyncCB callback;
1052 async_notifier (union sigval sig)
1054 notifier_data_t *ndata = sig.sival_ptr;
1058 error = aio_return (ndata->aio);
1060 error = _wapi_get_win32_error (error);
1067 ndata->callback (error, numbytes, ndata->ares);
1068 g_free (ndata->aio);
1073 do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
1074 guint32 numbytes, guint32 *out_bytes,
1076 SocketAsyncCB callback)
1078 struct _WapiHandlePrivate_socket *socket_private_handle;
1083 notifier_data_t *ndata;
1085 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1086 NULL, (gpointer *)&socket_private_handle);
1088 g_warning (G_GNUC_PRETTY_FUNCTION
1089 ": error looking up socket handle 0x%x", (guint) handle);
1090 WSASetLastError (WSAENOTSOCK);
1094 fd = socket_private_handle->fd;
1096 ndata = g_new0 (notifier_data_t, 1);
1097 aio = g_new0 (struct aiocb, 1);
1100 ndata->callback = callback;
1102 aio->aio_fildes = fd;
1103 aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
1104 aio->aio_nbytes = numbytes;
1105 aio->aio_offset = 0;
1106 aio->aio_buf = buffer;
1107 aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
1108 aio->aio_sigevent.sigev_notify_function = async_notifier;
1109 aio->aio_sigevent.sigev_value.sival_ptr = ndata;
1112 result = aio_read (aio);
1114 result = aio_write (aio);
1118 WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
1122 result = aio_error (aio);
1124 numbytes = aio_return (aio);
1126 WSASetLastError (errno_to_WSA (result, "do_aio_call"));
1131 *out_bytes = numbytes;
1136 gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
1138 guint32 *bytesread, gpointer ares,
1139 SocketAsyncCB callback)
1141 return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
1144 gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
1146 guint32 *byteswritten, gpointer ares,
1147 SocketAsyncCB callback)
1149 return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
1152 #endif /* !PLATFORM_WIN32 */