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);
382 if (startup_count == 0) {
383 WSASetLastError (WSANOTINITIALISED);
384 return(SOCKET_ERROR);
387 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
388 WSASetLastError (WSAENOTSOCK);
389 return(SOCKET_ERROR);
393 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
395 *optlen = sizeof (tv);
398 ret = getsockopt (fd, level, optname, tmp_val, optlen);
402 g_message ("%s: getsockopt error: %s", __func__,
406 errnum = errno_to_WSA (errnum, __func__);
407 WSASetLastError (errnum);
409 return(SOCKET_ERROR);
412 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
413 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
414 *optlen = sizeof (int);
417 if (optname == SO_ERROR) {
418 if (*((int *)optval) != 0) {
419 *((int *) optval) = errno_to_WSA (*((int *)optval),
427 int _wapi_listen(guint32 fd, int backlog)
429 gpointer handle = GUINT_TO_POINTER (fd);
432 if (startup_count == 0) {
433 WSASetLastError (WSANOTINITIALISED);
434 return(SOCKET_ERROR);
437 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
438 WSASetLastError (WSAENOTSOCK);
439 return(SOCKET_ERROR);
442 ret = listen (fd, backlog);
446 g_message ("%s: listen error: %s", __func__, strerror (errno));
449 errnum = errno_to_WSA (errnum, __func__);
450 WSASetLastError (errnum);
452 return(SOCKET_ERROR);
458 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
460 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
463 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
464 struct sockaddr *from, socklen_t *fromlen)
466 gpointer handle = GUINT_TO_POINTER (fd);
469 if (startup_count == 0) {
470 WSASetLastError (WSANOTINITIALISED);
471 return(SOCKET_ERROR);
474 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
475 WSASetLastError (WSAENOTSOCK);
476 return(SOCKET_ERROR);
480 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
481 } while (ret == -1 && errno == EINTR &&
482 !_wapi_thread_cur_apc_pending ());
487 g_message ("%s: recv error: %s", __func__, strerror(errno));
490 errnum = errno_to_WSA (errnum, __func__);
491 WSASetLastError (errnum);
493 return(SOCKET_ERROR);
498 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
500 gpointer handle = GUINT_TO_POINTER (fd);
503 if (startup_count == 0) {
504 WSASetLastError (WSANOTINITIALISED);
505 return(SOCKET_ERROR);
508 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
509 WSASetLastError (WSAENOTSOCK);
510 return(SOCKET_ERROR);
514 ret = send (fd, msg, len, send_flags);
515 } while (ret == -1 && errno == EINTR &&
516 !_wapi_thread_cur_apc_pending ());
521 g_message ("%s: send error: %s", __func__, strerror (errno));
524 errnum = errno_to_WSA (errnum, __func__);
525 WSASetLastError (errnum);
527 return(SOCKET_ERROR);
532 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
533 const struct sockaddr *to, socklen_t tolen)
535 gpointer handle = GUINT_TO_POINTER (fd);
538 if (startup_count == 0) {
539 WSASetLastError (WSANOTINITIALISED);
540 return(SOCKET_ERROR);
543 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
544 WSASetLastError (WSAENOTSOCK);
545 return(SOCKET_ERROR);
549 ret = sendto (fd, msg, len, send_flags, to, tolen);
550 } while (ret == -1 && errno == EINTR &&
551 !_wapi_thread_cur_apc_pending ());
556 g_message ("%s: send error: %s", __func__, strerror (errno));
559 errnum = errno_to_WSA (errnum, __func__);
560 WSASetLastError (errnum);
562 return(SOCKET_ERROR);
567 int _wapi_setsockopt(guint32 fd, int level, int optname,
568 const void *optval, socklen_t optlen)
570 gpointer handle = GUINT_TO_POINTER (fd);
575 if (startup_count == 0) {
576 WSASetLastError (WSANOTINITIALISED);
577 return(SOCKET_ERROR);
580 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
581 WSASetLastError (WSAENOTSOCK);
582 return(SOCKET_ERROR);
586 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
587 int ms = *((int *) optval);
588 tv.tv_sec = ms / 1000;
589 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
591 optlen = sizeof (tv);
592 #if defined (__linux__)
593 } else if (optname == SO_SNDBUF || optname == SO_RCVBUF) {
594 /* According to socket(7) the Linux kernel doubles the
595 * buffer sizes "to allow space for bookkeeping
598 int bufsize = *((int *) optval);
605 ret = setsockopt (fd, level, optname, tmp_val, optlen);
609 g_message ("%s: setsockopt error: %s", __func__,
613 errnum = errno_to_WSA (errnum, __func__);
614 WSASetLastError (errnum);
616 return(SOCKET_ERROR);
622 int _wapi_shutdown(guint32 fd, int how)
624 gpointer handle = GUINT_TO_POINTER (fd);
627 if (startup_count == 0) {
628 WSASetLastError (WSANOTINITIALISED);
629 return(SOCKET_ERROR);
632 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
633 WSASetLastError (WSAENOTSOCK);
634 return(SOCKET_ERROR);
637 ret = shutdown (fd, how);
641 g_message ("%s: shutdown error: %s", __func__,
645 errnum = errno_to_WSA (errnum, __func__);
646 WSASetLastError (errnum);
648 return(SOCKET_ERROR);
654 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
655 guint32 unused2, guint32 unused3)
657 struct _WapiHandle_socket socket_handle = {0};
661 socket_handle.domain = domain;
662 socket_handle.type = type;
663 socket_handle.protocol = protocol;
665 fd = socket (domain, type, protocol);
666 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
668 /* Retry with protocol == 4 (see bug #54565) */
669 socket_handle.protocol = 4;
670 fd = socket (AF_INET, SOCK_RAW, 4);
676 g_message ("%s: socket error: %s", __func__, strerror (errno));
678 errnum = errno_to_WSA (errnum, __func__);
679 WSASetLastError (errnum);
681 return(INVALID_SOCKET);
684 if (fd >= _wapi_fd_reserve) {
686 g_message ("%s: File descriptor is too big (%d >= %d)",
687 __func__, fd, _wapi_fd_reserve);
690 WSASetLastError (WSASYSCALLFAILURE);
693 return(INVALID_SOCKET);
697 mono_once (&socket_ops_once, socket_ops_init);
699 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
700 if (handle == _WAPI_HANDLE_INVALID) {
701 g_warning ("%s: error creating socket handle", __func__);
702 return(INVALID_SOCKET);
706 g_message ("%s: returning socket handle %p", __func__, handle);
712 struct hostent *_wapi_gethostbyname(const char *hostname)
716 if (startup_count == 0) {
717 WSASetLastError (WSANOTINITIALISED);
721 he = gethostbyname (hostname);
724 g_message ("%s: gethostbyname error: %s", __func__,
730 WSASetLastError (WSAHOST_NOT_FOUND);
732 #if NO_ADDRESS != NO_DATA
736 WSASetLastError (WSANO_DATA);
739 WSASetLastError (WSANO_RECOVERY);
742 WSASetLastError (WSATRY_AGAIN);
745 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
753 static gboolean socket_disconnect (guint32 fd)
755 struct _WapiHandle_socket *socket_handle;
757 gpointer handle = GUINT_TO_POINTER (fd);
760 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
761 (gpointer *)&socket_handle);
763 g_warning ("%s: error looking up socket handle %p", __func__,
765 WSASetLastError (WSAENOTSOCK);
769 newsock = socket (socket_handle->domain, socket_handle->type,
770 socket_handle->protocol);
775 g_message ("%s: socket error: %s", __func__, strerror (errno));
778 errnum = errno_to_WSA (errnum, __func__);
779 WSASetLastError (errnum);
784 /* According to Stevens "Advanced Programming in the UNIX
785 * Environment: UNIX File I/O" dup2() is atomic so there
786 * should not be a race condition between the old fd being
787 * closed and the new socket fd being copied over
790 ret = dup2 (newsock, fd);
791 } while (ret == -1 && errno == EAGAIN);
797 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
800 errnum = errno_to_WSA (errnum, __func__);
801 WSASetLastError (errnum);
811 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
812 guint32 flags, guint32 reserved)
815 g_message ("%s: called on socket %d!", __func__, fd);
819 WSASetLastError (WSAEINVAL);
823 /* We could check the socket type here and fail unless its
824 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
825 * if we really wanted to
828 return(socket_disconnect (fd));
831 /* NB only supports NULL file handle, NULL buffers and
832 * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
833 * Shouldn't actually ever need to be called anyway though, because we
834 * have DisconnectEx ().
836 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
837 guint32 num_write, guint32 num_per_send,
838 WapiOverlapped *overlapped,
839 WapiTransmitFileBuffers *buffers,
840 WapiTransmitFileFlags flags)
843 g_message ("%s: called on socket %d!", __func__, fd);
846 g_assert (file == NULL);
847 g_assert (overlapped == NULL);
848 g_assert (buffers == NULL);
849 g_assert (num_write == 0);
850 g_assert (num_per_send == 0);
851 g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
853 return(socket_disconnect (fd));
860 } extension_functions[] = {
861 {WSAID_DISCONNECTEX, wapi_disconnectex},
862 {WSAID_TRANSMITFILE, wapi_transmitfile},
867 WSAIoctl (guint32 fd, gint32 command,
868 gchar *input, gint i_len,
869 gchar *output, gint o_len, glong *written,
870 void *unused1, void *unused2)
872 gpointer handle = GUINT_TO_POINTER (fd);
874 gchar *buffer = NULL;
876 if (startup_count == 0) {
877 WSASetLastError (WSANOTINITIALISED);
878 return(SOCKET_ERROR);
881 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
882 WSASetLastError (WSAENOTSOCK);
886 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
888 WapiGuid *guid = (WapiGuid *)input;
890 if (i_len < sizeof(WapiGuid)) {
891 /* As far as I can tell, windows doesn't
892 * actually set an error here...
894 WSASetLastError (WSAEINVAL);
895 return(SOCKET_ERROR);
898 if (o_len < sizeof(gpointer)) {
900 WSASetLastError (WSAEINVAL);
901 return(SOCKET_ERROR);
904 if (output == NULL) {
906 WSASetLastError (WSAEINVAL);
907 return(SOCKET_ERROR);
910 while(extension_functions[i].func != NULL) {
911 if (!memcmp (guid, &extension_functions[i].guid,
913 memcpy (output, &extension_functions[i].func,
915 *written = sizeof(gpointer);
922 WSASetLastError (WSAEINVAL);
923 return(SOCKET_ERROR);
927 buffer = g_memdup (input, i_len);
930 ret = ioctl (fd, command, buffer);
934 g_message("%s: WSAIoctl error: %s", __func__,
938 errnum = errno_to_WSA (errnum, __func__);
939 WSASetLastError (errnum);
942 return(SOCKET_ERROR);
945 if (buffer == NULL) {
948 /* We just copy the buffer to the output. Some ioctls
949 * don't even output any data, but, well...
951 * NB windows returns WSAEFAULT if o_len is too small
953 i_len = (i_len > o_len) ? o_len : i_len;
955 if (i_len > 0 && output != NULL) {
956 memcpy (output, buffer, i_len);
966 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
968 gpointer handle = GUINT_TO_POINTER (fd);
971 if (startup_count == 0) {
972 WSASetLastError (WSANOTINITIALISED);
973 return(SOCKET_ERROR);
976 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
977 WSASetLastError (WSAENOTSOCK);
978 return(SOCKET_ERROR);
984 /* This works better than ioctl(...FIONBIO...)
985 * on Linux (it causes connect to return
986 * EINPROGRESS, but the ioctl doesn't seem to)
988 ret = fcntl(fd, F_GETFL, 0);
990 if (*(gboolean *)arg) {
995 ret = fcntl(fd, F_SETFL, ret);
998 #endif /* O_NONBLOCK */
1001 ret = ioctl (fd, command, arg);
1004 WSASetLastError (WSAEINVAL);
1005 return(SOCKET_ERROR);
1009 gint errnum = errno;
1011 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1014 errnum = errno_to_WSA (errnum, __func__);
1015 WSASetLastError (errnum);
1017 return(SOCKET_ERROR);
1023 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1024 fd_set *exceptfds, struct timeval *timeout)
1028 if (startup_count == 0) {
1029 WSASetLastError (WSANOTINITIALISED);
1030 return(SOCKET_ERROR);
1033 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1034 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1035 (writefds && FD_ISSET (maxfd, writefds)) ||
1036 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1042 WSASetLastError (WSAEINVAL);
1043 return(SOCKET_ERROR);
1047 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1049 } while (ret == -1 && errno == EINTR &&
1050 !_wapi_thread_cur_apc_pending ());
1053 gint errnum = errno;
1055 g_message ("%s: select error: %s", __func__, strerror (errno));
1057 errnum = errno_to_WSA (errnum, __func__);
1058 WSASetLastError (errnum);
1060 return(SOCKET_ERROR);
1066 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1068 gpointer handle = GUINT_TO_POINTER (fd);
1070 if (fd >= FD_SETSIZE) {
1071 WSASetLastError (WSAEINVAL);
1075 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1076 WSASetLastError (WSAENOTSOCK);
1083 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1085 gpointer handle = GUINT_TO_POINTER (fd);
1087 if (fd >= FD_SETSIZE) {
1088 WSASetLastError (WSAEINVAL);
1092 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1093 WSASetLastError (WSAENOTSOCK);
1097 return(FD_ISSET (fd, set));
1100 void _wapi_FD_SET(guint32 fd, fd_set *set)
1102 gpointer handle = GUINT_TO_POINTER (fd);
1104 if (fd >= FD_SETSIZE) {
1105 WSASetLastError (WSAEINVAL);
1109 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1110 WSASetLastError (WSAENOTSOCK);