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,0);
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());
292 if (ret == -1 && errno == EACCES) {
293 /* Try setting SO_BROADCAST and connecting again, but
294 * keep the original errno
300 ret = setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
304 ret = connect (fd, serv_addr, addrlen);
305 } while (ret==-1 && errno==EINTR &&
306 !_wapi_thread_cur_apc_pending());
308 } else if (ret == -1) {
314 g_message ("%s: connect error: %s", __func__,
317 errnum = errno_to_WSA (errnum, __func__);
318 if (errnum == WSAEINPROGRESS)
319 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
321 WSASetLastError (errnum);
323 return(SOCKET_ERROR);
328 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
330 gpointer handle = GUINT_TO_POINTER (fd);
333 if (startup_count == 0) {
334 WSASetLastError (WSANOTINITIALISED);
335 return(SOCKET_ERROR);
338 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
339 WSASetLastError (WSAENOTSOCK);
340 return(SOCKET_ERROR);
343 ret = getpeername (fd, name, namelen);
347 g_message ("%s: getpeername error: %s", __func__,
351 errnum = errno_to_WSA (errnum, __func__);
352 WSASetLastError (errnum);
354 return(SOCKET_ERROR);
360 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
362 gpointer handle = GUINT_TO_POINTER (fd);
365 if (startup_count == 0) {
366 WSASetLastError (WSANOTINITIALISED);
367 return(SOCKET_ERROR);
370 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
371 WSASetLastError (WSAENOTSOCK);
372 return(SOCKET_ERROR);
375 ret = getsockname (fd, name, namelen);
379 g_message ("%s: getsockname error: %s", __func__,
383 errnum = errno_to_WSA (errnum, __func__);
384 WSASetLastError (errnum);
386 return(SOCKET_ERROR);
392 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
395 gpointer handle = GUINT_TO_POINTER (fd);
400 if (startup_count == 0) {
401 WSASetLastError (WSANOTINITIALISED);
402 return(SOCKET_ERROR);
405 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
406 WSASetLastError (WSAENOTSOCK);
407 return(SOCKET_ERROR);
411 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
413 *optlen = sizeof (tv);
416 ret = getsockopt (fd, level, optname, tmp_val, optlen);
420 g_message ("%s: getsockopt error: %s", __func__,
424 errnum = errno_to_WSA (errnum, __func__);
425 WSASetLastError (errnum);
427 return(SOCKET_ERROR);
430 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
431 *((int *) optval) = tv.tv_sec * 1000 + tv.tv_usec;
432 *optlen = sizeof (int);
435 if (optname == SO_ERROR) {
436 if (*((int *)optval) != 0) {
437 *((int *) optval) = errno_to_WSA (*((int *)optval),
445 int _wapi_listen(guint32 fd, int backlog)
447 gpointer handle = GUINT_TO_POINTER (fd);
450 if (startup_count == 0) {
451 WSASetLastError (WSANOTINITIALISED);
452 return(SOCKET_ERROR);
455 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
456 WSASetLastError (WSAENOTSOCK);
457 return(SOCKET_ERROR);
460 ret = listen (fd, backlog);
464 g_message ("%s: listen error: %s", __func__, strerror (errno));
467 errnum = errno_to_WSA (errnum, __func__);
468 WSASetLastError (errnum);
470 return(SOCKET_ERROR);
476 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
478 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
481 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
482 struct sockaddr *from, socklen_t *fromlen)
484 gpointer handle = GUINT_TO_POINTER (fd);
487 if (startup_count == 0) {
488 WSASetLastError (WSANOTINITIALISED);
489 return(SOCKET_ERROR);
492 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
493 WSASetLastError (WSAENOTSOCK);
494 return(SOCKET_ERROR);
498 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
499 } while (ret == -1 && errno == EINTR &&
500 !_wapi_thread_cur_apc_pending ());
505 g_message ("%s: recv error: %s", __func__, strerror(errno));
508 errnum = errno_to_WSA (errnum, __func__);
509 WSASetLastError (errnum);
511 return(SOCKET_ERROR);
516 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
518 gpointer handle = GUINT_TO_POINTER (fd);
521 if (startup_count == 0) {
522 WSASetLastError (WSANOTINITIALISED);
523 return(SOCKET_ERROR);
526 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
527 WSASetLastError (WSAENOTSOCK);
528 return(SOCKET_ERROR);
532 ret = send (fd, msg, len, send_flags);
533 } while (ret == -1 && errno == EINTR &&
534 !_wapi_thread_cur_apc_pending ());
539 g_message ("%s: send error: %s", __func__, strerror (errno));
542 errnum = errno_to_WSA (errnum, __func__);
543 WSASetLastError (errnum);
545 return(SOCKET_ERROR);
550 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
551 const struct sockaddr *to, socklen_t tolen)
553 gpointer handle = GUINT_TO_POINTER (fd);
556 if (startup_count == 0) {
557 WSASetLastError (WSANOTINITIALISED);
558 return(SOCKET_ERROR);
561 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
562 WSASetLastError (WSAENOTSOCK);
563 return(SOCKET_ERROR);
567 ret = sendto (fd, msg, len, send_flags, to, tolen);
568 } while (ret == -1 && errno == EINTR &&
569 !_wapi_thread_cur_apc_pending ());
574 g_message ("%s: send error: %s", __func__, strerror (errno));
577 errnum = errno_to_WSA (errnum, __func__);
578 WSASetLastError (errnum);
580 return(SOCKET_ERROR);
585 int _wapi_setsockopt(guint32 fd, int level, int optname,
586 const void *optval, socklen_t optlen)
588 gpointer handle = GUINT_TO_POINTER (fd);
593 if (startup_count == 0) {
594 WSASetLastError (WSANOTINITIALISED);
595 return(SOCKET_ERROR);
598 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
599 WSASetLastError (WSAENOTSOCK);
600 return(SOCKET_ERROR);
604 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
605 int ms = *((int *) optval);
606 tv.tv_sec = ms / 1000;
607 tv.tv_usec = ms % 1000;
609 optlen = sizeof (tv);
612 ret = setsockopt (fd, level, optname, tmp_val, optlen);
616 g_message ("%s: setsockopt error: %s", __func__,
620 errnum = errno_to_WSA (errnum, __func__);
621 WSASetLastError (errnum);
623 return(SOCKET_ERROR);
629 int _wapi_shutdown(guint32 fd, int how)
631 gpointer handle = GUINT_TO_POINTER (fd);
634 if (startup_count == 0) {
635 WSASetLastError (WSANOTINITIALISED);
636 return(SOCKET_ERROR);
639 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
640 WSASetLastError (WSAENOTSOCK);
641 return(SOCKET_ERROR);
644 ret = shutdown (fd, how);
648 g_message ("%s: shutdown error: %s", __func__,
652 errnum = errno_to_WSA (errnum, __func__);
653 WSASetLastError (errnum);
655 return(SOCKET_ERROR);
661 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
662 guint32 unused2, guint32 unused3)
667 fd = socket (domain, type, protocol);
668 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
670 /* Retry with protocol == 4 (see bug #54565) */
671 fd = socket (AF_INET, SOCK_RAW, 4);
677 g_message ("%s: socket error: %s", __func__, strerror (errno));
679 errnum = errno_to_WSA (errnum, __func__);
680 WSASetLastError (errnum);
682 return(INVALID_SOCKET);
685 if (fd >= _wapi_fd_reserve) {
687 g_message ("%s: File descriptor is too big", __func__);
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, NULL);
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);
754 WSAIoctl (guint32 fd, gint32 command,
755 gchar *input, gint i_len,
756 gchar *output, gint o_len, glong *written,
757 void *unused1, void *unused2)
759 gpointer handle = GUINT_TO_POINTER (fd);
761 gchar *buffer = NULL;
763 if (startup_count == 0) {
764 WSASetLastError (WSANOTINITIALISED);
765 return(SOCKET_ERROR);
768 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
769 WSASetLastError (WSAENOTSOCK);
774 buffer = g_memdup (input, i_len);
777 ret = ioctl (fd, command, buffer);
781 g_message("%s: WSAIoctl error: %s", __func__,
785 errnum = errno_to_WSA (errnum, __func__);
786 WSASetLastError (errnum);
789 return(SOCKET_ERROR);
792 if (buffer == NULL) {
795 /* We just copy the buffer to the output. Some ioctls
796 * don't even output any data, but, well...
798 * NB windows returns WSAEFAULT if o_len is too small
800 i_len = (i_len > o_len) ? o_len : i_len;
802 if (i_len > 0 && output != NULL) {
803 memcpy (output, buffer, i_len);
813 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
815 gpointer handle = GUINT_TO_POINTER (fd);
818 if (startup_count == 0) {
819 WSASetLastError (WSANOTINITIALISED);
820 return(SOCKET_ERROR);
823 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
824 WSASetLastError (WSAENOTSOCK);
825 return(SOCKET_ERROR);
831 /* This works better than ioctl(...FIONBIO...)
832 * on Linux (it causes connect to return
833 * EINPROGRESS, but the ioctl doesn't seem to)
835 ret = fcntl(fd, F_GETFL, 0);
837 if (*(gboolean *)arg) {
842 ret = fcntl(fd, F_SETFL, ret);
845 #endif /* O_NONBLOCK */
848 ret = ioctl (fd, command, arg);
851 WSASetLastError (WSAEINVAL);
852 return(SOCKET_ERROR);
858 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
861 errnum = errno_to_WSA (errnum, __func__);
862 WSASetLastError (errnum);
864 return(SOCKET_ERROR);
870 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
871 fd_set *exceptfds, struct timeval *timeout)
875 if (startup_count == 0) {
876 WSASetLastError (WSANOTINITIALISED);
877 return(SOCKET_ERROR);
881 ret = select(getdtablesize (), readfds, writefds, exceptfds,
883 } while (ret == -1 && errno == EINTR &&
884 !_wapi_thread_cur_apc_pending ());
889 g_message ("%s: select error: %s", __func__, strerror (errno));
891 errnum = errno_to_WSA (errnum, __func__);
892 WSASetLastError (errnum);
894 return(SOCKET_ERROR);
900 void _wapi_FD_CLR(guint32 fd, fd_set *set)
902 gpointer handle = GUINT_TO_POINTER (fd);
904 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
905 WSASetLastError (WSAENOTSOCK);
912 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
914 gpointer handle = GUINT_TO_POINTER (fd);
916 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
917 WSASetLastError (WSAENOTSOCK);
921 return(FD_ISSET (fd, set));
924 void _wapi_FD_SET(guint32 fd, fd_set *set)
926 gpointer handle = GUINT_TO_POINTER (fd);
928 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
929 WSASetLastError (WSAENOTSOCK);