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 pthread_key_t error_key;
41 static mono_once_t error_key_once=MONO_ONCE_INIT;
43 static void socket_close (gpointer handle, gpointer data);
45 struct _WapiHandleOps _wapi_socket_ops = {
46 socket_close, /* close */
50 NULL, /* special_wait */
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 (gpointer handle, gpointer data G_GNUC_UNUSED)
66 g_message ("%s: closing socket handle %p", __func__, handle);
69 if (startup_count == 0) {
70 WSASetLastError (WSANOTINITIALISED);
75 ret = close (GPOINTER_TO_UINT(handle));
76 } while (ret == -1 && errno == EINTR &&
77 !_wapi_thread_cur_apc_pending ());
82 g_message ("%s: close error: %s", __func__, strerror (errno));
84 errnum = errno_to_WSA (errnum, __func__);
85 WSASetLastError (errnum);
89 int WSAStartup(guint32 requested, WapiWSAData *data)
96 if (requested < MAKEWORD(2,0)) {
97 return(WSAVERNOTSUPPORTED);
102 /* I've no idea what is the minor version of the spec I read */
103 data->wHighVersion = MAKEWORD(2,2);
105 data->wVersion = requested < data->wHighVersion? requested:
109 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
112 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
113 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
119 cleanup_close (gpointer handle, gpointer data)
121 _wapi_handle_ops_close (handle, NULL);
128 g_message ("%s: cleaning up", __func__);
131 if (--startup_count) {
136 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
140 static void error_init(void)
144 ret = pthread_key_create (&error_key, NULL);
148 void WSASetLastError(int error)
152 mono_once (&error_key_once, error_init);
153 ret = pthread_setspecific (error_key, GINT_TO_POINTER(error));
157 int WSAGetLastError(void)
162 mono_once (&error_key_once, error_init);
163 errptr = pthread_getspecific (error_key);
164 err = GPOINTER_TO_INT(errptr);
169 int closesocket(guint32 fd)
171 gpointer handle = GUINT_TO_POINTER (fd);
173 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
174 WSASetLastError (WSAENOTSOCK);
178 _wapi_handle_unref (handle);
182 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
184 gpointer handle = GUINT_TO_POINTER (fd);
188 if (startup_count == 0) {
189 WSASetLastError (WSANOTINITIALISED);
190 return(INVALID_SOCKET);
193 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
194 WSASetLastError (WSAENOTSOCK);
195 return(INVALID_SOCKET);
199 new_fd = accept (fd, addr, addrlen);
200 } while (new_fd == -1 && errno == EINTR &&
201 !_wapi_thread_cur_apc_pending());
206 g_message ("%s: accept error: %s", __func__, strerror(errno));
209 errnum = errno_to_WSA (errnum, __func__);
210 WSASetLastError (errnum);
212 return(INVALID_SOCKET);
215 if (new_fd >= _wapi_fd_reserve) {
217 g_message ("%s: File descriptor is too big", __func__);
220 WSASetLastError (WSASYSCALLFAILURE);
224 return(INVALID_SOCKET);
227 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, NULL);
228 if(new_handle == _WAPI_HANDLE_INVALID) {
229 g_warning ("%s: error creating socket handle", __func__);
230 WSASetLastError (ERROR_GEN_FAILURE);
231 return(INVALID_SOCKET);
235 g_message ("%s: returning newly accepted socket handle %p with",
236 __func__, new_handle);
242 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
244 gpointer handle = GUINT_TO_POINTER (fd);
247 if (startup_count == 0) {
248 WSASetLastError (WSANOTINITIALISED);
249 return(SOCKET_ERROR);
252 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
253 WSASetLastError (WSAENOTSOCK);
254 return(SOCKET_ERROR);
257 ret = bind (fd, my_addr, addrlen);
261 g_message ("%s: bind error: %s", __func__, strerror(errno));
263 errnum = errno_to_WSA (errnum, __func__);
264 WSASetLastError (errnum);
266 return(SOCKET_ERROR);
271 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
274 gpointer handle = GUINT_TO_POINTER (fd);
278 if (startup_count == 0) {
279 WSASetLastError (WSANOTINITIALISED);
280 return(SOCKET_ERROR);
283 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
284 WSASetLastError (WSAENOTSOCK);
285 return(SOCKET_ERROR);
289 ret = connect (fd, serv_addr, addrlen);
290 } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
296 g_message ("%s: connect error: %s", __func__,
299 errnum = errno_to_WSA (errnum, __func__);
300 if (errnum == WSAEINPROGRESS)
301 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
303 WSASetLastError (errnum);
305 return(SOCKET_ERROR);
310 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
312 gpointer handle = GUINT_TO_POINTER (fd);
315 if (startup_count == 0) {
316 WSASetLastError (WSANOTINITIALISED);
317 return(SOCKET_ERROR);
320 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
321 WSASetLastError (WSAENOTSOCK);
322 return(SOCKET_ERROR);
325 ret = getpeername (fd, name, namelen);
329 g_message ("%s: getpeername error: %s", __func__,
333 errnum = errno_to_WSA (errnum, __func__);
334 WSASetLastError (errnum);
336 return(SOCKET_ERROR);
342 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
344 gpointer handle = GUINT_TO_POINTER (fd);
347 if (startup_count == 0) {
348 WSASetLastError (WSANOTINITIALISED);
349 return(SOCKET_ERROR);
352 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
353 WSASetLastError (WSAENOTSOCK);
354 return(SOCKET_ERROR);
357 ret = getsockname (fd, name, namelen);
361 g_message ("%s: getsockname error: %s", __func__,
365 errnum = errno_to_WSA (errnum, __func__);
366 WSASetLastError (errnum);
368 return(SOCKET_ERROR);
374 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
377 gpointer handle = GUINT_TO_POINTER (fd);
381 struct _WapiHandle_socket *socket_handle;
384 if (startup_count == 0) {
385 WSASetLastError (WSANOTINITIALISED);
386 return(SOCKET_ERROR);
389 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
390 WSASetLastError (WSAENOTSOCK);
391 return(SOCKET_ERROR);
395 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
397 *optlen = sizeof (tv);
400 ret = getsockopt (fd, level, optname, tmp_val, optlen);
404 g_message ("%s: getsockopt error: %s", __func__,
408 errnum = errno_to_WSA (errnum, __func__);
409 WSASetLastError (errnum);
411 return(SOCKET_ERROR);
414 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
415 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
416 *optlen = sizeof (int);
419 if (optname == SO_ERROR) {
420 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
421 (gpointer *)&socket_handle);
423 g_warning ("%s: error looking up socket handle %p",
426 /* can't extract the last error */
427 *((int *) optval) = errno_to_WSA (*((int *)optval),
430 if (*((int *)optval) != 0) {
431 *((int *) optval) = errno_to_WSA (*((int *)optval),
433 socket_handle->saved_error = *((int *)optval);
435 *((int *)optval) = socket_handle->saved_error;
443 int _wapi_listen(guint32 fd, int backlog)
445 gpointer handle = GUINT_TO_POINTER (fd);
448 if (startup_count == 0) {
449 WSASetLastError (WSANOTINITIALISED);
450 return(SOCKET_ERROR);
453 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
454 WSASetLastError (WSAENOTSOCK);
455 return(SOCKET_ERROR);
458 ret = listen (fd, backlog);
462 g_message ("%s: listen error: %s", __func__, strerror (errno));
465 errnum = errno_to_WSA (errnum, __func__);
466 WSASetLastError (errnum);
468 return(SOCKET_ERROR);
474 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
476 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
479 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
480 struct sockaddr *from, socklen_t *fromlen)
482 gpointer handle = GUINT_TO_POINTER (fd);
485 if (startup_count == 0) {
486 WSASetLastError (WSANOTINITIALISED);
487 return(SOCKET_ERROR);
490 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
491 WSASetLastError (WSAENOTSOCK);
492 return(SOCKET_ERROR);
496 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
497 } while (ret == -1 && errno == EINTR &&
498 !_wapi_thread_cur_apc_pending ());
503 g_message ("%s: recv error: %s", __func__, strerror(errno));
506 errnum = errno_to_WSA (errnum, __func__);
507 WSASetLastError (errnum);
509 return(SOCKET_ERROR);
514 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
516 gpointer handle = GUINT_TO_POINTER (fd);
519 if (startup_count == 0) {
520 WSASetLastError (WSANOTINITIALISED);
521 return(SOCKET_ERROR);
524 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
525 WSASetLastError (WSAENOTSOCK);
526 return(SOCKET_ERROR);
530 ret = send (fd, msg, len, send_flags);
531 } while (ret == -1 && errno == EINTR &&
532 !_wapi_thread_cur_apc_pending ());
537 g_message ("%s: send error: %s", __func__, strerror (errno));
540 errnum = errno_to_WSA (errnum, __func__);
541 WSASetLastError (errnum);
543 return(SOCKET_ERROR);
548 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
549 const struct sockaddr *to, socklen_t tolen)
551 gpointer handle = GUINT_TO_POINTER (fd);
554 if (startup_count == 0) {
555 WSASetLastError (WSANOTINITIALISED);
556 return(SOCKET_ERROR);
559 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
560 WSASetLastError (WSAENOTSOCK);
561 return(SOCKET_ERROR);
565 ret = sendto (fd, msg, len, send_flags, to, tolen);
566 } while (ret == -1 && errno == EINTR &&
567 !_wapi_thread_cur_apc_pending ());
572 g_message ("%s: send error: %s", __func__, strerror (errno));
575 errnum = errno_to_WSA (errnum, __func__);
576 WSASetLastError (errnum);
578 return(SOCKET_ERROR);
583 int _wapi_setsockopt(guint32 fd, int level, int optname,
584 const void *optval, socklen_t optlen)
586 gpointer handle = GUINT_TO_POINTER (fd);
591 if (startup_count == 0) {
592 WSASetLastError (WSANOTINITIALISED);
593 return(SOCKET_ERROR);
596 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
597 WSASetLastError (WSAENOTSOCK);
598 return(SOCKET_ERROR);
602 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
603 int ms = *((int *) optval);
604 tv.tv_sec = ms / 1000;
605 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
607 optlen = sizeof (tv);
608 #if defined (__linux__)
609 } else if (optname == SO_SNDBUF || optname == SO_RCVBUF) {
610 /* According to socket(7) the Linux kernel doubles the
611 * buffer sizes "to allow space for bookkeeping
614 int bufsize = *((int *) optval);
621 ret = setsockopt (fd, level, optname, tmp_val, optlen);
625 g_message ("%s: setsockopt error: %s", __func__,
629 errnum = errno_to_WSA (errnum, __func__);
630 WSASetLastError (errnum);
632 return(SOCKET_ERROR);
638 int _wapi_shutdown(guint32 fd, int how)
640 gpointer handle = GUINT_TO_POINTER (fd);
643 if (startup_count == 0) {
644 WSASetLastError (WSANOTINITIALISED);
645 return(SOCKET_ERROR);
648 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
649 WSASetLastError (WSAENOTSOCK);
650 return(SOCKET_ERROR);
653 ret = shutdown (fd, how);
657 g_message ("%s: shutdown error: %s", __func__,
661 errnum = errno_to_WSA (errnum, __func__);
662 WSASetLastError (errnum);
664 return(SOCKET_ERROR);
670 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
671 guint32 unused2, guint32 unused3)
673 struct _WapiHandle_socket socket_handle = {0};
677 socket_handle.domain = domain;
678 socket_handle.type = type;
679 socket_handle.protocol = protocol;
681 fd = socket (domain, type, protocol);
682 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
684 /* Retry with protocol == 4 (see bug #54565) */
685 socket_handle.protocol = 4;
686 fd = socket (AF_INET, SOCK_RAW, 4);
692 g_message ("%s: socket error: %s", __func__, strerror (errno));
694 errnum = errno_to_WSA (errnum, __func__);
695 WSASetLastError (errnum);
697 return(INVALID_SOCKET);
700 if (fd >= _wapi_fd_reserve) {
702 g_message ("%s: File descriptor is too big (%d >= %d)",
703 __func__, fd, _wapi_fd_reserve);
706 WSASetLastError (WSASYSCALLFAILURE);
709 return(INVALID_SOCKET);
713 mono_once (&socket_ops_once, socket_ops_init);
715 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
716 if (handle == _WAPI_HANDLE_INVALID) {
717 g_warning ("%s: error creating socket handle", __func__);
718 return(INVALID_SOCKET);
722 g_message ("%s: returning socket handle %p", __func__, handle);
728 struct hostent *_wapi_gethostbyname(const char *hostname)
732 if (startup_count == 0) {
733 WSASetLastError (WSANOTINITIALISED);
737 he = gethostbyname (hostname);
740 g_message ("%s: gethostbyname error: %s", __func__,
746 WSASetLastError (WSAHOST_NOT_FOUND);
748 #if NO_ADDRESS != NO_DATA
752 WSASetLastError (WSANO_DATA);
755 WSASetLastError (WSANO_RECOVERY);
758 WSASetLastError (WSATRY_AGAIN);
761 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
769 static gboolean socket_disconnect (guint32 fd)
771 struct _WapiHandle_socket *socket_handle;
773 gpointer handle = GUINT_TO_POINTER (fd);
776 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
777 (gpointer *)&socket_handle);
779 g_warning ("%s: error looking up socket handle %p", __func__,
781 WSASetLastError (WSAENOTSOCK);
785 newsock = socket (socket_handle->domain, socket_handle->type,
786 socket_handle->protocol);
791 g_message ("%s: socket error: %s", __func__, strerror (errno));
794 errnum = errno_to_WSA (errnum, __func__);
795 WSASetLastError (errnum);
800 /* According to Stevens "Advanced Programming in the UNIX
801 * Environment: UNIX File I/O" dup2() is atomic so there
802 * should not be a race condition between the old fd being
803 * closed and the new socket fd being copied over
806 ret = dup2 (newsock, fd);
807 } while (ret == -1 && errno == EAGAIN);
813 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
816 errnum = errno_to_WSA (errnum, __func__);
817 WSASetLastError (errnum);
827 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
828 guint32 flags, guint32 reserved)
831 g_message ("%s: called on socket %d!", __func__, fd);
835 WSASetLastError (WSAEINVAL);
839 /* We could check the socket type here and fail unless its
840 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
841 * if we really wanted to
844 return(socket_disconnect (fd));
847 /* NB only supports NULL file handle, NULL buffers and
848 * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
849 * Shouldn't actually ever need to be called anyway though, because we
850 * have DisconnectEx ().
852 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
853 guint32 num_write, guint32 num_per_send,
854 WapiOverlapped *overlapped,
855 WapiTransmitFileBuffers *buffers,
856 WapiTransmitFileFlags flags)
859 g_message ("%s: called on socket %d!", __func__, fd);
862 g_assert (file == NULL);
863 g_assert (overlapped == NULL);
864 g_assert (buffers == NULL);
865 g_assert (num_write == 0);
866 g_assert (num_per_send == 0);
867 g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
869 return(socket_disconnect (fd));
876 } extension_functions[] = {
877 {WSAID_DISCONNECTEX, wapi_disconnectex},
878 {WSAID_TRANSMITFILE, wapi_transmitfile},
883 WSAIoctl (guint32 fd, gint32 command,
884 gchar *input, gint i_len,
885 gchar *output, gint o_len, glong *written,
886 void *unused1, void *unused2)
888 gpointer handle = GUINT_TO_POINTER (fd);
890 gchar *buffer = NULL;
892 if (startup_count == 0) {
893 WSASetLastError (WSANOTINITIALISED);
894 return(SOCKET_ERROR);
897 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
898 WSASetLastError (WSAENOTSOCK);
902 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
904 WapiGuid *guid = (WapiGuid *)input;
906 if (i_len < sizeof(WapiGuid)) {
907 /* As far as I can tell, windows doesn't
908 * actually set an error here...
910 WSASetLastError (WSAEINVAL);
911 return(SOCKET_ERROR);
914 if (o_len < sizeof(gpointer)) {
916 WSASetLastError (WSAEINVAL);
917 return(SOCKET_ERROR);
920 if (output == NULL) {
922 WSASetLastError (WSAEINVAL);
923 return(SOCKET_ERROR);
926 while(extension_functions[i].func != NULL) {
927 if (!memcmp (guid, &extension_functions[i].guid,
929 memcpy (output, &extension_functions[i].func,
931 *written = sizeof(gpointer);
938 WSASetLastError (WSAEINVAL);
939 return(SOCKET_ERROR);
943 buffer = g_memdup (input, i_len);
946 ret = ioctl (fd, command, buffer);
950 g_message("%s: WSAIoctl error: %s", __func__,
954 errnum = errno_to_WSA (errnum, __func__);
955 WSASetLastError (errnum);
958 return(SOCKET_ERROR);
961 if (buffer == NULL) {
964 /* We just copy the buffer to the output. Some ioctls
965 * don't even output any data, but, well...
967 * NB windows returns WSAEFAULT if o_len is too small
969 i_len = (i_len > o_len) ? o_len : i_len;
971 if (i_len > 0 && output != NULL) {
972 memcpy (output, buffer, i_len);
982 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
984 gpointer handle = GUINT_TO_POINTER (fd);
987 if (startup_count == 0) {
988 WSASetLastError (WSANOTINITIALISED);
989 return(SOCKET_ERROR);
992 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
993 WSASetLastError (WSAENOTSOCK);
994 return(SOCKET_ERROR);
1000 /* This works better than ioctl(...FIONBIO...)
1001 * on Linux (it causes connect to return
1002 * EINPROGRESS, but the ioctl doesn't seem to)
1004 ret = fcntl(fd, F_GETFL, 0);
1006 if (*(gboolean *)arg) {
1011 ret = fcntl(fd, F_SETFL, ret);
1014 #endif /* O_NONBLOCK */
1017 ret = ioctl (fd, command, arg);
1020 WSASetLastError (WSAEINVAL);
1021 return(SOCKET_ERROR);
1025 gint errnum = errno;
1027 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1030 errnum = errno_to_WSA (errnum, __func__);
1031 WSASetLastError (errnum);
1033 return(SOCKET_ERROR);
1039 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1040 fd_set *exceptfds, struct timeval *timeout)
1044 if (startup_count == 0) {
1045 WSASetLastError (WSANOTINITIALISED);
1046 return(SOCKET_ERROR);
1049 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1050 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1051 (writefds && FD_ISSET (maxfd, writefds)) ||
1052 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1058 WSASetLastError (WSAEINVAL);
1059 return(SOCKET_ERROR);
1063 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1065 } while (ret == -1 && errno == EINTR &&
1066 !_wapi_thread_cur_apc_pending ());
1069 gint errnum = errno;
1071 g_message ("%s: select error: %s", __func__, strerror (errno));
1073 errnum = errno_to_WSA (errnum, __func__);
1074 WSASetLastError (errnum);
1076 return(SOCKET_ERROR);
1082 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1084 gpointer handle = GUINT_TO_POINTER (fd);
1086 if (fd >= FD_SETSIZE) {
1087 WSASetLastError (WSAEINVAL);
1091 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1092 WSASetLastError (WSAENOTSOCK);
1099 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1101 gpointer handle = GUINT_TO_POINTER (fd);
1103 if (fd >= FD_SETSIZE) {
1104 WSASetLastError (WSAEINVAL);
1108 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1109 WSASetLastError (WSAENOTSOCK);
1113 return(FD_ISSET (fd, set));
1116 void _wapi_FD_SET(guint32 fd, fd_set *set)
1118 gpointer handle = GUINT_TO_POINTER (fd);
1120 if (fd >= FD_SETSIZE) {
1121 WSASetLastError (WSAEINVAL);
1125 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1126 WSASetLastError (WSAENOTSOCK);