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));
101 ret=close(socket_private_handle->fd);
103 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
108 g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
111 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
112 WSASetLastError (errnum);
118 int WSAStartup(guint32 requested, WapiWSAData *data)
124 /* Insist on v2.0+ */
125 if(requested < MAKEWORD(2,0)) {
126 return(WSAVERNOTSUPPORTED);
129 if(startup_count==0) {
130 sockets=g_ptr_array_new();
135 /* I've no idea what is the minor version of the spec I read */
136 data->wHighVersion=MAKEWORD(2,0);
138 data->wVersion=requested < data->wHighVersion? requested:
142 g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
146 strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
147 strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
157 g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
160 if(--startup_count) {
165 /* Close down all sockets */
166 for(i=0; i<sockets->len; i++) {
169 handle=g_ptr_array_index(sockets, i);
170 _wapi_handle_ops_close_private (handle);
173 g_ptr_array_free(sockets, FALSE);
179 static void error_init(void)
183 ret = pthread_key_create(&error_key, NULL);
187 void WSASetLastError(int error)
191 mono_once(&error_key_once, error_init);
192 ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
196 int WSAGetLastError(void)
201 mono_once(&error_key_once, error_init);
202 errptr=pthread_getspecific(error_key);
203 err=GPOINTER_TO_INT(errptr);
208 int closesocket(guint32 handle)
210 _wapi_handle_unref (GUINT_TO_POINTER (handle));
214 guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
217 struct _WapiHandlePrivate_socket *socket_private_handle;
218 struct _WapiHandlePrivate_socket *new_socket_private_handle;
223 guint32 ret = INVALID_SOCKET;
225 if(startup_count==0) {
226 WSASetLastError(WSANOTINITIALISED);
227 return(INVALID_SOCKET);
230 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
231 NULL, (gpointer *)&socket_private_handle);
233 g_warning (G_GNUC_PRETTY_FUNCTION
234 ": error looking up socket handle 0x%x", handle);
235 WSASetLastError(WSAENOTSOCK);
236 return(INVALID_SOCKET);
240 fd=accept(socket_private_handle->fd, addr, addrlen);
242 while (fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
247 g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
251 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
252 WSASetLastError (errnum);
254 return(INVALID_SOCKET);
257 new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
258 if(new_handle==_WAPI_HANDLE_INVALID) {
259 g_warning (G_GNUC_PRETTY_FUNCTION
260 ": error creating socket handle");
261 return(INVALID_SOCKET);
264 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
266 thr_ret = _wapi_handle_lock_handle (new_handle);
267 g_assert (thr_ret == 0);
269 ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
270 (gpointer *)&new_socket_private_handle);
272 g_warning (G_GNUC_PRETTY_FUNCTION
273 ": error looking up socket handle 0x%x", handle);
276 ret = GPOINTER_TO_UINT (new_handle);
278 new_socket_private_handle->fd=fd;
281 g_message(G_GNUC_PRETTY_FUNCTION
282 ": returning newly accepted socket handle %p with fd %d",
283 new_handle, new_socket_private_handle->fd);
287 thr_ret = _wapi_handle_unlock_handle (new_handle);
288 g_assert (thr_ret == 0);
289 pthread_cleanup_pop (0);
294 int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
296 struct _WapiHandlePrivate_socket *socket_private_handle;
300 if(startup_count==0) {
301 WSASetLastError(WSANOTINITIALISED);
302 return(SOCKET_ERROR);
305 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
306 NULL, (gpointer *)&socket_private_handle);
308 g_warning (G_GNUC_PRETTY_FUNCTION
309 ": error looking up socket handle 0x%x", handle);
310 WSASetLastError(WSAENOTSOCK);
311 return(SOCKET_ERROR);
314 ret=bind(socket_private_handle->fd, my_addr, addrlen);
318 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
321 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
322 WSASetLastError (errnum);
324 return(SOCKET_ERROR);
329 int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
332 struct _WapiHandlePrivate_socket *socket_private_handle;
337 if(startup_count==0) {
338 WSASetLastError(WSANOTINITIALISED);
339 return(SOCKET_ERROR);
342 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
343 NULL, (gpointer *)&socket_private_handle);
345 g_warning (G_GNUC_PRETTY_FUNCTION
346 ": error looking up socket handle 0x%x", handle);
347 WSASetLastError(WSAENOTSOCK);
348 return(SOCKET_ERROR);
352 ret=connect(socket_private_handle->fd, serv_addr, addrlen);
354 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
356 if(ret==-1 && errno==EACCES) {
357 /* Try setting SO_BROADCAST and connecting again, but
358 * keep the original errno
364 ret=setsockopt (socket_private_handle->fd, SOL_SOCKET,
365 SO_BROADCAST, &true, sizeof(true));
368 ret=connect (socket_private_handle->fd, serv_addr, addrlen);
370 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
372 } else if (ret==-1) {
378 g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
381 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
382 WSASetLastError (errnum);
384 return(SOCKET_ERROR);
389 int _wapi_getpeername(guint32 handle, struct sockaddr *name,
392 struct _WapiHandlePrivate_socket *socket_private_handle;
396 if(startup_count==0) {
397 WSASetLastError(WSANOTINITIALISED);
398 return(SOCKET_ERROR);
401 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
402 NULL, (gpointer *)&socket_private_handle);
404 g_warning (G_GNUC_PRETTY_FUNCTION
405 ": error looking up socket handle 0x%x", handle);
406 WSASetLastError(WSAENOTSOCK);
407 return(SOCKET_ERROR);
410 ret=getpeername(socket_private_handle->fd, name, namelen);
414 g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
418 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
419 WSASetLastError (errnum);
421 return(SOCKET_ERROR);
427 int _wapi_getsockname(guint32 handle, struct sockaddr *name,
430 struct _WapiHandlePrivate_socket *socket_private_handle;
434 if(startup_count==0) {
435 WSASetLastError(WSANOTINITIALISED);
436 return(SOCKET_ERROR);
439 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
440 NULL, (gpointer *)&socket_private_handle);
442 g_warning (G_GNUC_PRETTY_FUNCTION
443 ": error looking up socket handle 0x%x", handle);
444 WSASetLastError(WSAENOTSOCK);
445 return(SOCKET_ERROR);
448 ret=getsockname(socket_private_handle->fd, name, namelen);
452 g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
456 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
457 WSASetLastError (errnum);
459 return(SOCKET_ERROR);
465 int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval,
468 struct _WapiHandlePrivate_socket *socket_private_handle;
472 if(startup_count==0) {
473 WSASetLastError(WSANOTINITIALISED);
474 return(SOCKET_ERROR);
477 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
478 NULL, (gpointer *)&socket_private_handle);
480 g_warning (G_GNUC_PRETTY_FUNCTION
481 ": error looking up socket handle 0x%x", handle);
482 WSASetLastError(WSAENOTSOCK);
483 return(SOCKET_ERROR);
486 ret=getsockopt(socket_private_handle->fd, level, optname, optval,
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 handle, int backlog)
506 struct _WapiHandlePrivate_socket *socket_private_handle;
510 if(startup_count==0) {
511 WSASetLastError(WSANOTINITIALISED);
512 return(SOCKET_ERROR);
515 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
516 NULL, (gpointer *)&socket_private_handle);
518 g_warning (G_GNUC_PRETTY_FUNCTION
519 ": error looking up socket handle 0x%x", handle);
520 WSASetLastError(WSAENOTSOCK);
521 return(SOCKET_ERROR);
524 ret=listen(socket_private_handle->fd, backlog);
528 g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
532 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
533 WSASetLastError (errnum);
535 return(SOCKET_ERROR);
541 int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags)
543 return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0));
546 int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags,
547 struct sockaddr *from, socklen_t *fromlen)
549 #ifndef HAVE_MSG_NOSIGNAL
550 void (*old_sigpipe)(int); // old SIGPIPE handler
552 struct _WapiHandlePrivate_socket *socket_private_handle;
556 if(startup_count==0) {
557 WSASetLastError(WSANOTINITIALISED);
558 return(SOCKET_ERROR);
561 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
562 NULL, (gpointer *)&socket_private_handle);
564 g_warning (G_GNUC_PRETTY_FUNCTION
565 ": error looking up socket handle 0x%x", handle);
566 WSASetLastError(WSAENOTSOCK);
567 return(SOCKET_ERROR);
570 #ifdef HAVE_MSG_NOSIGNAL
572 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
575 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
577 old_sigpipe = signal(SIGPIPE, SIG_IGN);
579 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from,
582 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
583 signal(SIGPIPE, old_sigpipe);
589 g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
593 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
594 WSASetLastError (errnum);
596 return(SOCKET_ERROR);
601 int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags)
603 #ifndef HAVE_MSG_NOSIGNAL
604 void (*old_sigpipe)(int); // old SIGPIPE handler
606 struct _WapiHandlePrivate_socket *socket_private_handle;
610 if(startup_count==0) {
611 WSASetLastError(WSANOTINITIALISED);
612 return(SOCKET_ERROR);
615 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
616 NULL, (gpointer *)&socket_private_handle);
618 g_warning (G_GNUC_PRETTY_FUNCTION
619 ": error looking up socket handle 0x%x", handle);
620 WSASetLastError(WSAENOTSOCK);
621 return(SOCKET_ERROR);
624 #ifdef HAVE_MSG_NOSIGNAL
626 ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL);
628 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
630 old_sigpipe = signal(SIGPIPE, SIG_IGN);
632 ret=send(socket_private_handle->fd, msg, len, send_flags);
634 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
635 signal(SIGPIPE, old_sigpipe);
640 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
644 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
645 WSASetLastError (errnum);
647 return(SOCKET_ERROR);
652 int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags,
653 const struct sockaddr *to, socklen_t tolen)
655 #ifndef HAVE_MSG_NOSIGNAL
656 void (*old_sigpipe)(int); // old SIGPIPE handler
658 struct _WapiHandlePrivate_socket *socket_private_handle;
662 if(startup_count==0) {
663 WSASetLastError(WSANOTINITIALISED);
664 return(SOCKET_ERROR);
667 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
668 NULL, (gpointer *)&socket_private_handle);
670 g_warning (G_GNUC_PRETTY_FUNCTION
671 ": error looking up socket handle 0x%x", handle);
672 WSASetLastError(WSAENOTSOCK);
673 return(SOCKET_ERROR);
676 #ifdef HAVE_MSG_NOSIGNAL
678 ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
680 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
682 old_sigpipe = signal(SIGPIPE, SIG_IGN);
684 ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen);
686 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
687 signal(SIGPIPE, old_sigpipe);
692 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
696 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
697 WSASetLastError (errnum);
699 return(SOCKET_ERROR);
704 int _wapi_setsockopt(guint32 handle, int level, int optname,
705 const void *optval, socklen_t optlen)
707 struct _WapiHandlePrivate_socket *socket_private_handle;
711 if(startup_count==0) {
712 WSASetLastError(WSANOTINITIALISED);
713 return(SOCKET_ERROR);
716 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
717 NULL, (gpointer *)&socket_private_handle);
719 g_warning (G_GNUC_PRETTY_FUNCTION
720 ": error looking up socket handle 0x%x", handle);
721 WSASetLastError(WSAENOTSOCK);
722 return(SOCKET_ERROR);
725 ret=setsockopt(socket_private_handle->fd, level, optname, optval,
730 g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
734 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
735 WSASetLastError (errnum);
737 return(SOCKET_ERROR);
743 int _wapi_shutdown(guint32 handle, int how)
745 struct _WapiHandlePrivate_socket *socket_private_handle;
749 if(startup_count==0) {
750 WSASetLastError(WSANOTINITIALISED);
751 return(SOCKET_ERROR);
754 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
755 NULL, (gpointer *)&socket_private_handle);
757 g_warning (G_GNUC_PRETTY_FUNCTION
758 ": error looking up socket handle 0x%x", handle);
759 WSASetLastError(WSAENOTSOCK);
760 return(SOCKET_ERROR);
763 ret=shutdown(socket_private_handle->fd, how);
767 g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
771 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
772 WSASetLastError (errnum);
774 return(SOCKET_ERROR);
780 guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
782 struct _WapiHandlePrivate_socket *socket_private_handle;
787 guint32 ret = INVALID_SOCKET;
789 fd=socket(domain, type, protocol);
790 if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
791 /* Retry with protocol == 4 (see bug #54565) */
792 fd = socket (AF_INET, SOCK_RAW, 4);
798 g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
800 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
801 WSASetLastError (errnum);
803 return(INVALID_SOCKET);
806 mono_once (&socket_ops_once, socket_ops_init);
808 handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
809 if(handle==_WAPI_HANDLE_INVALID) {
810 g_warning (G_GNUC_PRETTY_FUNCTION
811 ": error creating socket handle");
812 return(INVALID_SOCKET);
815 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
817 thr_ret = _wapi_handle_lock_handle (handle);
818 g_assert (thr_ret == 0);
820 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
821 (gpointer *)&socket_private_handle);
823 g_warning (G_GNUC_PRETTY_FUNCTION
824 ": error looking up socket handle %p", handle);
827 ret = GPOINTER_TO_UINT (handle);
829 socket_private_handle->fd=fd;
832 g_message(G_GNUC_PRETTY_FUNCTION
833 ": returning socket handle %p with fd %d", handle,
834 socket_private_handle->fd);
838 thr_ret = _wapi_handle_unlock_handle (handle);
839 g_assert (thr_ret == 0);
840 pthread_cleanup_pop (0);
845 struct hostent *_wapi_gethostbyname(const char *hostname)
849 if(startup_count==0) {
850 WSASetLastError(WSANOTINITIALISED);
854 he=gethostbyname(hostname);
857 g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
863 WSASetLastError(WSAHOST_NOT_FOUND);
865 #if NO_ADDRESS != NO_DATA
869 WSASetLastError(WSANO_DATA);
872 WSASetLastError(WSANO_RECOVERY);
875 WSASetLastError(WSATRY_AGAIN);
878 g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
887 WSAIoctl (guint32 handle, gint32 command,
888 gchar *input, gint i_len,
889 gchar *output, gint o_len, glong *written,
890 void *unused1, void *unused2)
892 struct _WapiHandlePrivate_socket *socket_private_handle;
895 gchar *buffer = NULL;
897 if(startup_count==0) {
898 WSASetLastError(WSANOTINITIALISED);
899 return(SOCKET_ERROR);
902 ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
903 NULL, (gpointer *)&socket_private_handle);
906 g_warning (G_GNUC_PRETTY_FUNCTION
907 ": error looking up socket handle 0x%x", handle);
908 WSASetLastError (WSAENOTSOCK);
913 buffer = g_memdup (input, i_len);
915 ret = ioctl (socket_private_handle->fd, command, buffer);
919 g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
923 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
924 WSASetLastError (errnum);
930 if (buffer == NULL) {
933 /* We just copy the buffer to the output. Some ioctls
934 * don't even output any data, but, well... */
935 i_len = (i_len > o_len) ? o_len : i_len;
936 memcpy (output, buffer, i_len);
944 int ioctlsocket(guint32 handle, gint32 command, gpointer arg)
946 struct _WapiHandlePrivate_socket *socket_private_handle;
950 if(startup_count==0) {
951 WSASetLastError(WSANOTINITIALISED);
952 return(SOCKET_ERROR);
955 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
956 NULL, (gpointer *)&socket_private_handle);
958 g_warning (G_GNUC_PRETTY_FUNCTION
959 ": error looking up socket handle 0x%x", handle);
960 WSASetLastError(WSAENOTSOCK);
961 return(SOCKET_ERROR);
964 if(command!=FIONBIO &&
966 command!=SIOCATMARK) {
967 /* Not listed in the MSDN specs, but ioctl(2) returns
968 * this if command is invalid
970 WSASetLastError(WSAEINVAL);
971 return(SOCKET_ERROR);
975 /* This works better than ioctl(...FIONBIO...) on Linux (it causes
976 * connect to return EINPROGRESS, but the ioctl doesn't seem to)
978 if(command==FIONBIO) {
979 ret=fcntl(socket_private_handle->fd, F_GETFL, 0);
981 if(*(gboolean *)arg) {
986 ret=fcntl(socket_private_handle->fd, F_SETFL, ret);
989 #endif /* O_NONBLOCK */
991 ret=ioctl(socket_private_handle->fd, command, arg);
996 g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
1000 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
1001 WSASetLastError (errnum);
1003 return(SOCKET_ERROR);
1009 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1010 fd_set *exceptfds, struct timeval *timeout)
1014 if(startup_count==0) {
1015 WSASetLastError(WSANOTINITIALISED);
1016 return(SOCKET_ERROR);
1020 ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
1022 while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
1025 gint errnum = errno;
1027 g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
1030 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
1031 WSASetLastError (errnum);
1033 return(SOCKET_ERROR);
1039 void _wapi_FD_CLR(guint32 handle, fd_set *set)
1041 struct _WapiHandlePrivate_socket *socket_private_handle;
1044 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1045 NULL, (gpointer *)&socket_private_handle);
1047 g_warning (G_GNUC_PRETTY_FUNCTION
1048 ": error looking up socket handle 0x%x", handle);
1049 WSASetLastError(WSAENOTSOCK);
1053 FD_CLR(socket_private_handle->fd, set);
1056 int _wapi_FD_ISSET(guint32 handle, fd_set *set)
1058 struct _WapiHandlePrivate_socket *socket_private_handle;
1061 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1062 NULL, (gpointer *)&socket_private_handle);
1064 g_warning (G_GNUC_PRETTY_FUNCTION
1065 ": error looking up socket handle 0x%x", handle);
1066 WSASetLastError(WSAENOTSOCK);
1070 return(FD_ISSET(socket_private_handle->fd, set));
1073 void _wapi_FD_SET(guint32 handle, fd_set *set)
1075 struct _WapiHandlePrivate_socket *socket_private_handle;
1078 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1079 NULL, (gpointer *)&socket_private_handle);
1081 g_warning (G_GNUC_PRETTY_FUNCTION
1082 ": error looking up socket handle 0x%x", handle);
1083 WSASetLastError(WSAENOTSOCK);
1087 FD_SET(socket_private_handle->fd, set);
1095 SocketAsyncCB callback;
1098 #define SIGPTR(a) a.SIGVAL_PTR
1101 async_notifier (union sigval sig)
1103 notifier_data_t *ndata = SIGPTR (sig);
1107 error = aio_return (ndata->aio);
1109 error = _wapi_get_win32_file_error (error);
1116 ndata->callback (error, numbytes, ndata->ares);
1117 g_free (ndata->aio);
1122 do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
1123 guint32 numbytes, guint32 *out_bytes,
1125 SocketAsyncCB callback)
1127 struct _WapiHandlePrivate_socket *socket_private_handle;
1132 notifier_data_t *ndata;
1134 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
1135 NULL, (gpointer *)&socket_private_handle);
1137 g_warning (G_GNUC_PRETTY_FUNCTION
1138 ": error looking up socket handle 0x%x", (guint) handle);
1139 WSASetLastError (WSAENOTSOCK);
1143 fd = socket_private_handle->fd;
1145 ndata = g_new0 (notifier_data_t, 1);
1146 aio = g_new0 (struct aiocb, 1);
1149 ndata->callback = callback;
1151 aio->aio_fildes = fd;
1152 aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
1153 aio->aio_nbytes = numbytes;
1154 aio->aio_offset = 0;
1155 aio->aio_buf = buffer;
1156 aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
1157 aio->aio_sigevent.sigev_notify_function = async_notifier;
1158 SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
1161 result = aio_read (aio);
1163 result = aio_write (aio);
1167 WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
1171 result = aio_error (aio);
1173 numbytes = aio_return (aio);
1175 WSASetLastError (errno_to_WSA (result, "do_aio_call"));
1180 *out_bytes = numbytes;
1185 gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
1187 guint32 *bytesread, gpointer ares,
1188 SocketAsyncCB callback)
1190 return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
1193 gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
1195 guint32 *byteswritten, gpointer ares,
1196 SocketAsyncCB callback)
1198 return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
1201 #endif /* USE_AIO */