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 */
52 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
54 static void socket_ops_init (void)
56 /* No capabilities to register */
59 static void socket_close (gpointer handle, gpointer data G_GNUC_UNUSED)
64 g_message ("%s: closing socket handle %p", __func__, handle);
67 if (startup_count == 0) {
68 WSASetLastError (WSANOTINITIALISED);
73 ret = close (GPOINTER_TO_UINT(handle));
74 } while (ret == -1 && errno == EINTR &&
75 !_wapi_thread_cur_apc_pending ());
80 g_message ("%s: close error: %s", __func__, strerror (errno));
82 errnum = errno_to_WSA (errnum, __func__);
83 WSASetLastError (errnum);
87 int WSAStartup(guint32 requested, WapiWSAData *data)
94 if (requested < MAKEWORD(2,0)) {
95 return(WSAVERNOTSUPPORTED);
100 /* I've no idea what is the minor version of the spec I read */
101 data->wHighVersion = MAKEWORD(2,0);
103 data->wVersion = requested < data->wHighVersion? requested:
107 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
110 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
111 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
117 cleanup_close (gpointer handle, gpointer data)
119 _wapi_handle_ops_close (handle, NULL);
126 g_message ("%s: cleaning up", __func__);
129 if (--startup_count) {
134 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
138 static void error_init(void)
142 ret = pthread_key_create (&error_key, NULL);
146 void WSASetLastError(int error)
150 mono_once (&error_key_once, error_init);
151 ret = pthread_setspecific (error_key, GINT_TO_POINTER(error));
155 int WSAGetLastError(void)
160 mono_once (&error_key_once, error_init);
161 errptr = pthread_getspecific (error_key);
162 err = GPOINTER_TO_INT(errptr);
167 int closesocket(guint32 fd)
169 gpointer handle = GUINT_TO_POINTER (fd);
171 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
172 WSASetLastError (WSAENOTSOCK);
176 _wapi_handle_unref (handle);
180 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
182 gpointer handle = GUINT_TO_POINTER (fd);
186 if (startup_count == 0) {
187 WSASetLastError (WSANOTINITIALISED);
188 return(INVALID_SOCKET);
191 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
192 WSASetLastError (WSAENOTSOCK);
193 return(INVALID_SOCKET);
197 new_fd = accept (fd, addr, addrlen);
198 } while (new_fd == -1 && errno == EINTR &&
199 !_wapi_thread_cur_apc_pending());
204 g_message ("%s: accept error: %s", __func__, strerror(errno));
207 errnum = errno_to_WSA (errnum, __func__);
208 WSASetLastError (errnum);
210 return(INVALID_SOCKET);
213 if (new_fd >= _wapi_fd_reserve) {
215 g_message ("%s: File descriptor is too big", __func__);
218 WSASetLastError (WSASYSCALLFAILURE);
222 return(INVALID_SOCKET);
225 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, NULL);
226 if(new_handle == _WAPI_HANDLE_INVALID) {
227 g_warning ("%s: error creating socket handle", __func__);
228 WSASetLastError (ERROR_GEN_FAILURE);
229 return(INVALID_SOCKET);
233 g_message ("%s: returning newly accepted socket handle %p with",
234 __func__, new_handle);
240 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
242 gpointer handle = GUINT_TO_POINTER (fd);
245 if (startup_count == 0) {
246 WSASetLastError (WSANOTINITIALISED);
247 return(SOCKET_ERROR);
250 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
251 WSASetLastError (WSAENOTSOCK);
252 return(SOCKET_ERROR);
255 ret = bind (fd, my_addr, addrlen);
259 g_message ("%s: bind error: %s", __func__, strerror(errno));
261 errnum = errno_to_WSA (errnum, __func__);
262 WSASetLastError (errnum);
264 return(SOCKET_ERROR);
269 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
272 gpointer handle = GUINT_TO_POINTER (fd);
276 if (startup_count == 0) {
277 WSASetLastError (WSANOTINITIALISED);
278 return(SOCKET_ERROR);
281 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
282 WSASetLastError (WSAENOTSOCK);
283 return(SOCKET_ERROR);
287 ret = connect (fd, serv_addr, addrlen);
288 } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
290 if (ret == -1 && errno == EACCES) {
291 /* Try setting SO_BROADCAST and connecting again, but
292 * keep the original errno
298 ret = setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
302 ret = connect (fd, serv_addr, addrlen);
303 } while (ret==-1 && errno==EINTR &&
304 !_wapi_thread_cur_apc_pending());
306 } else if (ret == -1) {
312 g_message ("%s: connect error: %s", __func__,
315 errnum = errno_to_WSA (errnum, __func__);
316 if (errnum == WSAEINPROGRESS)
317 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
319 WSASetLastError (errnum);
321 return(SOCKET_ERROR);
326 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
328 gpointer handle = GUINT_TO_POINTER (fd);
331 if (startup_count == 0) {
332 WSASetLastError (WSANOTINITIALISED);
333 return(SOCKET_ERROR);
336 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
337 WSASetLastError (WSAENOTSOCK);
338 return(SOCKET_ERROR);
341 ret = getpeername (fd, name, namelen);
345 g_message ("%s: getpeername error: %s", __func__,
349 errnum = errno_to_WSA (errnum, __func__);
350 WSASetLastError (errnum);
352 return(SOCKET_ERROR);
358 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
360 gpointer handle = GUINT_TO_POINTER (fd);
363 if (startup_count == 0) {
364 WSASetLastError (WSANOTINITIALISED);
365 return(SOCKET_ERROR);
368 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
369 WSASetLastError (WSAENOTSOCK);
370 return(SOCKET_ERROR);
373 ret = getsockname (fd, name, namelen);
377 g_message ("%s: getsockname error: %s", __func__,
381 errnum = errno_to_WSA (errnum, __func__);
382 WSASetLastError (errnum);
384 return(SOCKET_ERROR);
390 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
393 gpointer handle = GUINT_TO_POINTER (fd);
398 if (startup_count == 0) {
399 WSASetLastError (WSANOTINITIALISED);
400 return(SOCKET_ERROR);
403 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
404 WSASetLastError (WSAENOTSOCK);
405 return(SOCKET_ERROR);
409 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
411 *optlen = sizeof (tv);
414 ret = getsockopt (fd, level, optname, tmp_val, optlen);
418 g_message ("%s: getsockopt error: %s", __func__,
422 errnum = errno_to_WSA (errnum, __func__);
423 WSASetLastError (errnum);
425 return(SOCKET_ERROR);
428 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
429 *((int *) optval) = tv.tv_sec * 1000 + tv.tv_usec;
430 *optlen = sizeof (int);
433 if (optname == SO_ERROR) {
434 if (*((int *)optval) != 0) {
435 *((int *) optval) = errno_to_WSA (*((int *)optval),
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;
607 optlen = sizeof (tv);
610 ret = setsockopt (fd, level, optname, tmp_val, optlen);
614 g_message ("%s: setsockopt error: %s", __func__,
618 errnum = errno_to_WSA (errnum, __func__);
619 WSASetLastError (errnum);
621 return(SOCKET_ERROR);
627 int _wapi_shutdown(guint32 fd, int how)
629 gpointer handle = GUINT_TO_POINTER (fd);
632 if (startup_count == 0) {
633 WSASetLastError (WSANOTINITIALISED);
634 return(SOCKET_ERROR);
637 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
638 WSASetLastError (WSAENOTSOCK);
639 return(SOCKET_ERROR);
642 ret = shutdown (fd, how);
646 g_message ("%s: shutdown error: %s", __func__,
650 errnum = errno_to_WSA (errnum, __func__);
651 WSASetLastError (errnum);
653 return(SOCKET_ERROR);
659 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
660 guint32 unused2, guint32 unused3)
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 fd = socket (AF_INET, SOCK_RAW, 4);
675 g_message ("%s: socket error: %s", __func__, strerror (errno));
677 errnum = errno_to_WSA (errnum, __func__);
678 WSASetLastError (errnum);
680 return(INVALID_SOCKET);
683 if (fd >= _wapi_fd_reserve) {
685 g_message ("%s: File descriptor is too big", __func__);
688 WSASetLastError (WSASYSCALLFAILURE);
691 return(INVALID_SOCKET);
695 mono_once (&socket_ops_once, socket_ops_init);
697 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, NULL);
698 if (handle == _WAPI_HANDLE_INVALID) {
699 g_warning ("%s: error creating socket handle", __func__);
700 return(INVALID_SOCKET);
704 g_message ("%s: returning socket handle %p", __func__, handle);
710 struct hostent *_wapi_gethostbyname(const char *hostname)
714 if (startup_count == 0) {
715 WSASetLastError (WSANOTINITIALISED);
719 he = gethostbyname (hostname);
722 g_message ("%s: gethostbyname error: %s", __func__,
728 WSASetLastError (WSAHOST_NOT_FOUND);
730 #if NO_ADDRESS != NO_DATA
734 WSASetLastError (WSANO_DATA);
737 WSASetLastError (WSANO_RECOVERY);
740 WSASetLastError (WSATRY_AGAIN);
743 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
752 WSAIoctl (guint32 fd, gint32 command,
753 gchar *input, gint i_len,
754 gchar *output, gint o_len, glong *written,
755 void *unused1, void *unused2)
757 gpointer handle = GUINT_TO_POINTER (fd);
759 gchar *buffer = NULL;
761 if (startup_count == 0) {
762 WSASetLastError (WSANOTINITIALISED);
763 return(SOCKET_ERROR);
766 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
767 WSASetLastError (WSAENOTSOCK);
772 buffer = g_memdup (input, i_len);
775 ret = ioctl (fd, command, buffer);
779 g_message("%s: WSAIoctl error: %s", __func__,
783 errnum = errno_to_WSA (errnum, __func__);
784 WSASetLastError (errnum);
787 return(SOCKET_ERROR);
790 if (buffer == NULL) {
793 /* We just copy the buffer to the output. Some ioctls
794 * don't even output any data, but, well...
796 i_len = (i_len > o_len) ? o_len : i_len;
797 memcpy (output, buffer, i_len);
805 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
807 gpointer handle = GUINT_TO_POINTER (fd);
810 if (startup_count == 0) {
811 WSASetLastError (WSANOTINITIALISED);
812 return(SOCKET_ERROR);
815 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
816 WSASetLastError (WSAENOTSOCK);
817 return(SOCKET_ERROR);
823 /* This works better than ioctl(...FIONBIO...)
824 * on Linux (it causes connect to return
825 * EINPROGRESS, but the ioctl doesn't seem to)
827 ret = fcntl(fd, F_GETFL, 0);
829 if (*(gboolean *)arg) {
834 ret = fcntl(fd, F_SETFL, ret);
837 #endif /* O_NONBLOCK */
840 ret = ioctl (fd, command, arg);
843 WSASetLastError (WSAEINVAL);
844 return(SOCKET_ERROR);
850 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
853 errnum = errno_to_WSA (errnum, __func__);
854 WSASetLastError (errnum);
856 return(SOCKET_ERROR);
862 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
863 fd_set *exceptfds, struct timeval *timeout)
867 if (startup_count == 0) {
868 WSASetLastError (WSANOTINITIALISED);
869 return(SOCKET_ERROR);
873 ret = select(getdtablesize (), readfds, writefds, exceptfds,
875 } while (ret == -1 && errno == EINTR &&
876 !_wapi_thread_cur_apc_pending ());
881 g_message ("%s: select error: %s", __func__, strerror (errno));
883 errnum = errno_to_WSA (errnum, __func__);
884 WSASetLastError (errnum);
886 return(SOCKET_ERROR);
892 void _wapi_FD_CLR(guint32 fd, fd_set *set)
894 gpointer handle = GUINT_TO_POINTER (fd);
896 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
897 WSASetLastError (WSAENOTSOCK);
904 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
906 gpointer handle = GUINT_TO_POINTER (fd);
908 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
909 WSASetLastError (WSAENOTSOCK);
913 return(FD_ISSET (fd, set));
916 void _wapi_FD_SET(guint32 fd, fd_set *set)
918 gpointer handle = GUINT_TO_POINTER (fd);
920 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
921 WSASetLastError (WSAENOTSOCK);