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 */