2010-02-13 Jb Evain <jbevain@novell.com>
[mono-project.git] / mono / io-layer / sockets.c
blob16dcb16892f85e5b97427f34e3ca2abdbed4b01c
1 /*
2 * sockets.c: Socket handles
4 * Author:
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
8 */
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #ifdef HAVE_SYS_IOCTL_H
18 # include <sys/ioctl.h>
19 #endif
20 #include <sys/poll.h>
21 #ifdef HAVE_SYS_FILIO_H
22 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
23 #endif
24 #ifdef HAVE_SYS_SOCKIO_H
25 #include <sys/sockio.h> /* defines SIOCATMARK */
26 #endif
27 #include <unistd.h>
28 #include <fcntl.h>
30 #ifndef HAVE_MSG_NOSIGNAL
31 #include <signal.h>
32 #endif
34 #include <mono/io-layer/wapi.h>
35 #include <mono/io-layer/wapi-private.h>
36 #include <mono/io-layer/socket-private.h>
37 #include <mono/io-layer/handles-private.h>
38 #include <mono/io-layer/socket-wrappers.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 #include <netdb.h>
43 #include <arpa/inet.h>
44 #ifdef HAVE_SYS_SENDFILE_H
45 #include <sys/sendfile.h>
46 #endif
48 #undef DEBUG
50 static guint32 startup_count=0;
52 static void socket_close (gpointer handle, gpointer data);
54 struct _WapiHandleOps _wapi_socket_ops = {
55 socket_close, /* close */
56 NULL, /* signal */
57 NULL, /* own */
58 NULL, /* is_owned */
59 NULL, /* special_wait */
60 NULL /* prewait */
63 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
65 static void socket_ops_init (void)
67 /* No capabilities to register */
70 static void socket_close (gpointer handle, gpointer data)
72 int ret;
73 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
75 #ifdef DEBUG
76 g_message ("%s: closing socket handle %p", __func__, handle);
77 #endif
79 if (startup_count == 0) {
80 WSASetLastError (WSANOTINITIALISED);
81 return;
84 /* Shutdown the socket for reading, to interrupt any potential
85 * receives that may be blocking for data. See bug 75705.
87 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
89 do {
90 ret = close (GPOINTER_TO_UINT(handle));
91 } while (ret == -1 && errno == EINTR &&
92 !_wapi_thread_cur_apc_pending ());
94 if (ret == -1) {
95 gint errnum = errno;
96 #ifdef DEBUG
97 g_message ("%s: close error: %s", __func__, strerror (errno));
98 #endif
99 errnum = errno_to_WSA (errnum, __func__);
100 WSASetLastError (errnum);
103 socket_handle->saved_error = 0;
106 int WSAStartup(guint32 requested, WapiWSAData *data)
108 if (data == NULL) {
109 return(WSAEFAULT);
112 /* Insist on v2.0+ */
113 if (requested < MAKEWORD(2,0)) {
114 return(WSAVERNOTSUPPORTED);
117 startup_count++;
119 /* I've no idea what is the minor version of the spec I read */
120 data->wHighVersion = MAKEWORD(2,2);
122 data->wVersion = requested < data->wHighVersion? requested:
123 data->wHighVersion;
125 #ifdef DEBUG
126 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
127 #endif
129 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
130 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
132 return(0);
135 static gboolean
136 cleanup_close (gpointer handle, gpointer data)
138 _wapi_handle_ops_close (handle, NULL);
139 return TRUE;
142 int WSACleanup(void)
144 #ifdef DEBUG
145 g_message ("%s: cleaning up", __func__);
146 #endif
148 if (--startup_count) {
149 /* Do nothing */
150 return(0);
153 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
154 return(0);
157 void WSASetLastError(int error)
159 SetLastError (error);
162 int WSAGetLastError(void)
164 return(GetLastError ());
167 int closesocket(guint32 fd)
169 gpointer handle = GUINT_TO_POINTER (fd);
171 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
172 WSASetLastError (WSAENOTSOCK);
173 return(0);
176 _wapi_handle_unref (handle);
177 return(0);
180 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
182 gpointer handle = GUINT_TO_POINTER (fd);
183 gpointer new_handle;
184 struct _WapiHandle_socket *socket_handle;
185 struct _WapiHandle_socket new_socket_handle = {0};
186 gboolean ok;
187 int new_fd;
189 if (startup_count == 0) {
190 WSASetLastError (WSANOTINITIALISED);
191 return(INVALID_SOCKET);
194 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
195 WSASetLastError (WSAEFAULT);
196 return(INVALID_SOCKET);
199 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
200 WSASetLastError (WSAENOTSOCK);
201 return(INVALID_SOCKET);
204 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
205 (gpointer *)&socket_handle);
206 if (ok == FALSE) {
207 g_warning ("%s: error looking up socket handle %p",
208 __func__, handle);
209 WSASetLastError (WSAENOTSOCK);
210 return(INVALID_SOCKET);
213 do {
214 new_fd = accept (fd, addr, addrlen);
215 } while (new_fd == -1 && errno == EINTR &&
216 !_wapi_thread_cur_apc_pending());
218 if (new_fd == -1) {
219 gint errnum = errno;
220 #ifdef DEBUG
221 g_message ("%s: accept error: %s", __func__, strerror(errno));
222 #endif
224 errnum = errno_to_WSA (errnum, __func__);
225 WSASetLastError (errnum);
227 return(INVALID_SOCKET);
230 if (new_fd >= _wapi_fd_reserve) {
231 #ifdef DEBUG
232 g_message ("%s: File descriptor is too big", __func__);
233 #endif
235 WSASetLastError (WSASYSCALLFAILURE);
237 close (new_fd);
239 return(INVALID_SOCKET);
242 new_socket_handle.domain = socket_handle->domain;
243 new_socket_handle.type = socket_handle->type;
244 new_socket_handle.protocol = socket_handle->protocol;
245 new_socket_handle.still_readable = 1;
247 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
248 &new_socket_handle);
249 if(new_handle == _WAPI_HANDLE_INVALID) {
250 g_warning ("%s: error creating socket handle", __func__);
251 WSASetLastError (ERROR_GEN_FAILURE);
252 return(INVALID_SOCKET);
255 #ifdef DEBUG
256 g_message ("%s: returning newly accepted socket handle %p with",
257 __func__, new_handle);
258 #endif
260 return(new_fd);
263 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
265 gpointer handle = GUINT_TO_POINTER (fd);
266 int ret;
268 if (startup_count == 0) {
269 WSASetLastError (WSANOTINITIALISED);
270 return(SOCKET_ERROR);
273 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
274 WSASetLastError (WSAENOTSOCK);
275 return(SOCKET_ERROR);
278 ret = bind (fd, my_addr, addrlen);
279 if (ret == -1) {
280 gint errnum = errno;
281 #ifdef DEBUG
282 g_message ("%s: bind error: %s", __func__, strerror(errno));
283 #endif
284 errnum = errno_to_WSA (errnum, __func__);
285 WSASetLastError (errnum);
287 return(SOCKET_ERROR);
289 return(ret);
292 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
293 socklen_t addrlen)
295 gpointer handle = GUINT_TO_POINTER (fd);
296 struct _WapiHandle_socket *socket_handle;
297 gboolean ok;
298 gint errnum;
300 if (startup_count == 0) {
301 WSASetLastError (WSANOTINITIALISED);
302 return(SOCKET_ERROR);
305 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
306 WSASetLastError (WSAENOTSOCK);
307 return(SOCKET_ERROR);
310 if (connect (fd, serv_addr, addrlen) == -1) {
311 struct pollfd fds;
312 int so_error;
313 socklen_t len;
315 errnum = errno;
317 if (errno != EINTR) {
318 #ifdef DEBUG
319 g_message ("%s: connect error: %s", __func__,
320 strerror (errnum));
321 #endif
323 errnum = errno_to_WSA (errnum, __func__);
324 if (errnum == WSAEINPROGRESS)
325 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
327 WSASetLastError (errnum);
330 * On solaris x86 getsockopt (SO_ERROR) is not set after
331 * connect () fails so we need to save this error.
333 * But don't do this for EWOULDBLOCK (bug 317315)
335 if (errnum != WSAEWOULDBLOCK) {
336 ok = _wapi_lookup_handle (handle,
337 WAPI_HANDLE_SOCKET,
338 (gpointer *)&socket_handle);
339 if (ok == FALSE) {
340 /* ECONNRESET means the socket was closed by another thread */
341 if (errnum != WSAECONNRESET)
342 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
343 } else {
344 socket_handle->saved_error = errnum;
347 return(SOCKET_ERROR);
350 fds.fd = fd;
351 fds.events = POLLOUT;
352 while (poll (&fds, 1, -1) == -1 &&
353 !_wapi_thread_cur_apc_pending ()) {
354 if (errno != EINTR) {
355 errnum = errno_to_WSA (errno, __func__);
357 #ifdef DEBUG
358 g_message ("%s: connect poll error: %s",
359 __func__, strerror (errno));
360 #endif
362 WSASetLastError (errnum);
363 return(SOCKET_ERROR);
367 len = sizeof(so_error);
368 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
369 &len) == -1) {
370 errnum = errno_to_WSA (errno, __func__);
372 #ifdef DEBUG
373 g_message ("%s: connect getsockopt error: %s",
374 __func__, strerror (errno));
375 #endif
377 WSASetLastError (errnum);
378 return(SOCKET_ERROR);
381 if (so_error != 0) {
382 errnum = errno_to_WSA (so_error, __func__);
384 /* Need to save this socket error */
385 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
386 (gpointer *)&socket_handle);
387 if (ok == FALSE) {
388 g_warning ("%s: error looking up socket handle %p", __func__, handle);
389 } else {
390 socket_handle->saved_error = errnum;
393 #ifdef DEBUG
394 g_message ("%s: connect getsockopt returned error: %s",
395 __func__, strerror (so_error));
396 #endif
398 WSASetLastError (errnum);
399 return(SOCKET_ERROR);
403 return(0);
406 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
408 gpointer handle = GUINT_TO_POINTER (fd);
409 int ret;
411 if (startup_count == 0) {
412 WSASetLastError (WSANOTINITIALISED);
413 return(SOCKET_ERROR);
416 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
417 WSASetLastError (WSAENOTSOCK);
418 return(SOCKET_ERROR);
421 ret = getpeername (fd, name, namelen);
422 if (ret == -1) {
423 gint errnum = errno;
424 #ifdef DEBUG
425 g_message ("%s: getpeername error: %s", __func__,
426 strerror (errno));
427 #endif
429 errnum = errno_to_WSA (errnum, __func__);
430 WSASetLastError (errnum);
432 return(SOCKET_ERROR);
435 return(ret);
438 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
440 gpointer handle = GUINT_TO_POINTER (fd);
441 int ret;
443 if (startup_count == 0) {
444 WSASetLastError (WSANOTINITIALISED);
445 return(SOCKET_ERROR);
448 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
449 WSASetLastError (WSAENOTSOCK);
450 return(SOCKET_ERROR);
453 ret = getsockname (fd, name, namelen);
454 if (ret == -1) {
455 gint errnum = errno;
456 #ifdef DEBUG
457 g_message ("%s: getsockname error: %s", __func__,
458 strerror (errno));
459 #endif
461 errnum = errno_to_WSA (errnum, __func__);
462 WSASetLastError (errnum);
464 return(SOCKET_ERROR);
467 return(ret);
470 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
471 socklen_t *optlen)
473 gpointer handle = GUINT_TO_POINTER (fd);
474 int ret;
475 struct timeval tv;
476 void *tmp_val;
477 struct _WapiHandle_socket *socket_handle;
478 gboolean ok;
480 if (startup_count == 0) {
481 WSASetLastError (WSANOTINITIALISED);
482 return(SOCKET_ERROR);
485 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
486 WSASetLastError (WSAENOTSOCK);
487 return(SOCKET_ERROR);
490 tmp_val = optval;
491 if (level == SOL_SOCKET &&
492 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
493 tmp_val = &tv;
494 *optlen = sizeof (tv);
497 ret = getsockopt (fd, level, optname, tmp_val, optlen);
498 if (ret == -1) {
499 gint errnum = errno;
500 #ifdef DEBUG
501 g_message ("%s: getsockopt error: %s", __func__,
502 strerror (errno));
503 #endif
505 errnum = errno_to_WSA (errnum, __func__);
506 WSASetLastError (errnum);
508 return(SOCKET_ERROR);
511 if (level == SOL_SOCKET &&
512 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
513 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
514 *optlen = sizeof (int);
517 if (optname == SO_ERROR) {
518 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
519 (gpointer *)&socket_handle);
520 if (ok == FALSE) {
521 g_warning ("%s: error looking up socket handle %p",
522 __func__, handle);
524 /* can't extract the last error */
525 *((int *) optval) = errno_to_WSA (*((int *)optval),
526 __func__);
527 } else {
528 if (*((int *)optval) != 0) {
529 *((int *) optval) = errno_to_WSA (*((int *)optval),
530 __func__);
531 socket_handle->saved_error = *((int *)optval);
532 } else {
533 *((int *)optval) = socket_handle->saved_error;
538 return(ret);
541 int _wapi_listen(guint32 fd, int backlog)
543 gpointer handle = GUINT_TO_POINTER (fd);
544 int ret;
546 if (startup_count == 0) {
547 WSASetLastError (WSANOTINITIALISED);
548 return(SOCKET_ERROR);
551 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
552 WSASetLastError (WSAENOTSOCK);
553 return(SOCKET_ERROR);
556 ret = listen (fd, backlog);
557 if (ret == -1) {
558 gint errnum = errno;
559 #ifdef DEBUG
560 g_message ("%s: listen error: %s", __func__, strerror (errno));
561 #endif
563 errnum = errno_to_WSA (errnum, __func__);
564 WSASetLastError (errnum);
566 return(SOCKET_ERROR);
569 return(0);
572 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
574 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
577 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
578 struct sockaddr *from, socklen_t *fromlen)
580 gpointer handle = GUINT_TO_POINTER (fd);
581 struct _WapiHandle_socket *socket_handle;
582 gboolean ok;
583 int ret;
585 if (startup_count == 0) {
586 WSASetLastError (WSANOTINITIALISED);
587 return(SOCKET_ERROR);
590 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
591 WSASetLastError (WSAENOTSOCK);
592 return(SOCKET_ERROR);
595 do {
596 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
597 } while (ret == -1 && errno == EINTR &&
598 !_wapi_thread_cur_apc_pending ());
600 if (ret == 0 && len > 0) {
601 /* According to the Linux man page, recvfrom only
602 * returns 0 when the socket has been shut down
603 * cleanly. Turn this into an EINTR to simulate win32
604 * behaviour of returning EINTR when a socket is
605 * closed while the recvfrom is blocking (we use a
606 * shutdown() in socket_close() to trigger this.) See
607 * bug 75705.
609 /* Distinguish between the socket being shut down at
610 * the local or remote ends, and reads that request 0
611 * bytes to be read
614 /* If this returns FALSE, it means the socket has been
615 * closed locally. If it returns TRUE, but
616 * still_readable != 1 then shutdown
617 * (SHUT_RD|SHUT_RDWR) has been called locally.
619 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
620 (gpointer *)&socket_handle);
621 if (ok == FALSE || socket_handle->still_readable != 1) {
622 ret = -1;
623 errno = EINTR;
627 if (ret == -1) {
628 gint errnum = errno;
629 #ifdef DEBUG
630 g_message ("%s: recv error: %s", __func__, strerror(errno));
631 #endif
633 errnum = errno_to_WSA (errnum, __func__);
634 WSASetLastError (errnum);
636 return(SOCKET_ERROR);
638 return(ret);
641 static int
642 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
644 gpointer handle = GUINT_TO_POINTER (fd);
645 struct _WapiHandle_socket *socket_handle;
646 gboolean ok;
647 int ret;
649 if (startup_count == 0) {
650 WSASetLastError (WSANOTINITIALISED);
651 return(SOCKET_ERROR);
654 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
655 WSASetLastError (WSAENOTSOCK);
656 return(SOCKET_ERROR);
659 do {
660 ret = recvmsg (fd, msg, recv_flags);
661 } while (ret == -1 && errno == EINTR &&
662 !_wapi_thread_cur_apc_pending ());
664 if (ret == 0) {
665 /* see _wapi_recvfrom */
666 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
667 (gpointer *)&socket_handle);
668 if (ok == FALSE || socket_handle->still_readable != 1) {
669 ret = -1;
670 errno = EINTR;
674 if (ret == -1) {
675 gint errnum = errno;
676 #ifdef DEBUG
677 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
678 #endif
680 errnum = errno_to_WSA (errnum, __func__);
681 WSASetLastError (errnum);
683 return(SOCKET_ERROR);
685 return(ret);
688 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
690 gpointer handle = GUINT_TO_POINTER (fd);
691 int ret;
693 if (startup_count == 0) {
694 WSASetLastError (WSANOTINITIALISED);
695 return(SOCKET_ERROR);
698 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
699 WSASetLastError (WSAENOTSOCK);
700 return(SOCKET_ERROR);
703 do {
704 ret = send (fd, msg, len, send_flags);
705 } while (ret == -1 && errno == EINTR &&
706 !_wapi_thread_cur_apc_pending ());
708 if (ret == -1) {
709 gint errnum = errno;
710 #ifdef DEBUG
711 g_message ("%s: send error: %s", __func__, strerror (errno));
712 #endif
714 errnum = errno_to_WSA (errnum, __func__);
715 WSASetLastError (errnum);
717 return(SOCKET_ERROR);
719 return(ret);
722 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
723 const struct sockaddr *to, socklen_t tolen)
725 gpointer handle = GUINT_TO_POINTER (fd);
726 int ret;
728 if (startup_count == 0) {
729 WSASetLastError (WSANOTINITIALISED);
730 return(SOCKET_ERROR);
733 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
734 WSASetLastError (WSAENOTSOCK);
735 return(SOCKET_ERROR);
738 do {
739 ret = sendto (fd, msg, len, send_flags, to, tolen);
740 } while (ret == -1 && errno == EINTR &&
741 !_wapi_thread_cur_apc_pending ());
743 if (ret == -1) {
744 gint errnum = errno;
745 #ifdef DEBUG
746 g_message ("%s: send error: %s", __func__, strerror (errno));
747 #endif
749 errnum = errno_to_WSA (errnum, __func__);
750 WSASetLastError (errnum);
752 return(SOCKET_ERROR);
754 return(ret);
757 static int
758 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
760 gpointer handle = GUINT_TO_POINTER (fd);
761 int ret;
763 if (startup_count == 0) {
764 WSASetLastError (WSANOTINITIALISED);
765 return(SOCKET_ERROR);
768 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
769 WSASetLastError (WSAENOTSOCK);
770 return(SOCKET_ERROR);
773 do {
774 ret = sendmsg (fd, msg, send_flags);
775 } while (ret == -1 && errno == EINTR &&
776 !_wapi_thread_cur_apc_pending ());
778 if (ret == -1) {
779 gint errnum = errno;
780 #ifdef DEBUG
781 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
782 #endif
784 errnum = errno_to_WSA (errnum, __func__);
785 WSASetLastError (errnum);
787 return(SOCKET_ERROR);
789 return(ret);
792 int _wapi_setsockopt(guint32 fd, int level, int optname,
793 const void *optval, socklen_t optlen)
795 gpointer handle = GUINT_TO_POINTER (fd);
796 int ret;
797 const void *tmp_val;
798 struct timeval tv;
800 if (startup_count == 0) {
801 WSASetLastError (WSANOTINITIALISED);
802 return(SOCKET_ERROR);
805 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
806 WSASetLastError (WSAENOTSOCK);
807 return(SOCKET_ERROR);
810 tmp_val = optval;
811 if (level == SOL_SOCKET &&
812 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
813 int ms = *((int *) optval);
814 tv.tv_sec = ms / 1000;
815 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
816 tmp_val = &tv;
817 optlen = sizeof (tv);
818 #if defined (__linux__)
819 } else if (level == SOL_SOCKET &&
820 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
821 /* According to socket(7) the Linux kernel doubles the
822 * buffer sizes "to allow space for bookkeeping
823 * overhead."
825 int bufsize = *((int *) optval);
827 bufsize /= 2;
828 tmp_val = &bufsize;
829 #endif
832 ret = setsockopt (fd, level, optname, tmp_val, optlen);
833 if (ret == -1) {
834 gint errnum = errno;
835 #ifdef DEBUG
836 g_message ("%s: setsockopt error: %s", __func__,
837 strerror (errno));
838 #endif
840 errnum = errno_to_WSA (errnum, __func__);
841 WSASetLastError (errnum);
843 return(SOCKET_ERROR);
846 #if defined (SO_REUSEPORT)
847 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
848 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
849 int type;
850 socklen_t type_len = sizeof (type);
852 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
853 if (type == SOCK_DGRAM)
854 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
857 #endif
859 return(ret);
862 int _wapi_shutdown(guint32 fd, int how)
864 struct _WapiHandle_socket *socket_handle;
865 gboolean ok;
866 gpointer handle = GUINT_TO_POINTER (fd);
867 int ret;
869 if (startup_count == 0) {
870 WSASetLastError (WSANOTINITIALISED);
871 return(SOCKET_ERROR);
874 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
875 WSASetLastError (WSAENOTSOCK);
876 return(SOCKET_ERROR);
879 if (how == SHUT_RD ||
880 how == SHUT_RDWR) {
881 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
882 (gpointer *)&socket_handle);
883 if (ok == FALSE) {
884 g_warning ("%s: error looking up socket handle %p",
885 __func__, handle);
886 WSASetLastError (WSAENOTSOCK);
887 return(SOCKET_ERROR);
890 socket_handle->still_readable = 0;
893 ret = shutdown (fd, how);
894 if (ret == -1) {
895 gint errnum = errno;
896 #ifdef DEBUG
897 g_message ("%s: shutdown error: %s", __func__,
898 strerror (errno));
899 #endif
901 errnum = errno_to_WSA (errnum, __func__);
902 WSASetLastError (errnum);
904 return(SOCKET_ERROR);
907 return(ret);
910 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
911 guint32 unused2, guint32 unused3)
913 struct _WapiHandle_socket socket_handle = {0};
914 gpointer handle;
915 int fd;
917 socket_handle.domain = domain;
918 socket_handle.type = type;
919 socket_handle.protocol = protocol;
920 socket_handle.still_readable = 1;
922 fd = socket (domain, type, protocol);
923 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
924 protocol == 0) {
925 /* Retry with protocol == 4 (see bug #54565) */
926 socket_handle.protocol = 4;
927 fd = socket (AF_INET, SOCK_RAW, 4);
930 if (fd == -1) {
931 gint errnum = errno;
932 #ifdef DEBUG
933 g_message ("%s: socket error: %s", __func__, strerror (errno));
934 #endif
935 errnum = errno_to_WSA (errnum, __func__);
936 WSASetLastError (errnum);
938 return(INVALID_SOCKET);
941 if (fd >= _wapi_fd_reserve) {
942 #ifdef DEBUG
943 g_message ("%s: File descriptor is too big (%d >= %d)",
944 __func__, fd, _wapi_fd_reserve);
945 #endif
947 WSASetLastError (WSASYSCALLFAILURE);
948 close (fd);
950 return(INVALID_SOCKET);
953 /* .net seems to set this by default for SOCK_STREAM, not for
954 * SOCK_DGRAM (see bug #36322)
956 * It seems winsock has a rather different idea of what
957 * SO_REUSEADDR means. If it's set, then a new socket can be
958 * bound over an existing listening socket. There's a new
959 * windows-specific option called SO_EXCLUSIVEADDRUSE but
960 * using that means the socket MUST be closed properly, or a
961 * denial of service can occur. Luckily for us, winsock
962 * behaves as though any other system would when SO_REUSEADDR
963 * is true, so we don't need to do anything else here. See
964 * bug 53992.
967 int ret, true = 1;
969 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
970 sizeof (true));
971 if (ret == -1) {
972 int errnum = errno;
974 #ifdef DEBUG
975 g_message ("%s: Error setting SO_REUSEADDR", __func__);
976 #endif
978 errnum = errno_to_WSA (errnum, __func__);
979 WSASetLastError (errnum);
981 close (fd);
983 return(INVALID_SOCKET);
988 mono_once (&socket_ops_once, socket_ops_init);
990 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
991 if (handle == _WAPI_HANDLE_INVALID) {
992 g_warning ("%s: error creating socket handle", __func__);
993 WSASetLastError (WSASYSCALLFAILURE);
994 close (fd);
995 return(INVALID_SOCKET);
998 #ifdef DEBUG
999 g_message ("%s: returning socket handle %p", __func__, handle);
1000 #endif
1002 return(fd);
1005 struct hostent *_wapi_gethostbyname(const char *hostname)
1007 struct hostent *he;
1009 if (startup_count == 0) {
1010 WSASetLastError (WSANOTINITIALISED);
1011 return(NULL);
1014 he = gethostbyname (hostname);
1015 if (he == NULL) {
1016 #ifdef DEBUG
1017 g_message ("%s: gethostbyname error: %s", __func__,
1018 strerror (h_errno));
1019 #endif
1021 switch(h_errno) {
1022 case HOST_NOT_FOUND:
1023 WSASetLastError (WSAHOST_NOT_FOUND);
1024 break;
1025 #if NO_ADDRESS != NO_DATA
1026 case NO_ADDRESS:
1027 #endif
1028 case NO_DATA:
1029 WSASetLastError (WSANO_DATA);
1030 break;
1031 case NO_RECOVERY:
1032 WSASetLastError (WSANO_RECOVERY);
1033 break;
1034 case TRY_AGAIN:
1035 WSASetLastError (WSATRY_AGAIN);
1036 break;
1037 default:
1038 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1039 break;
1043 return(he);
1046 static gboolean socket_disconnect (guint32 fd)
1048 struct _WapiHandle_socket *socket_handle;
1049 gboolean ok;
1050 gpointer handle = GUINT_TO_POINTER (fd);
1051 int newsock, ret;
1053 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1054 (gpointer *)&socket_handle);
1055 if (ok == FALSE) {
1056 g_warning ("%s: error looking up socket handle %p", __func__,
1057 handle);
1058 WSASetLastError (WSAENOTSOCK);
1059 return(FALSE);
1062 newsock = socket (socket_handle->domain, socket_handle->type,
1063 socket_handle->protocol);
1064 if (newsock == -1) {
1065 gint errnum = errno;
1067 #ifdef DEBUG
1068 g_message ("%s: socket error: %s", __func__, strerror (errno));
1069 #endif
1071 errnum = errno_to_WSA (errnum, __func__);
1072 WSASetLastError (errnum);
1074 return(FALSE);
1077 /* According to Stevens "Advanced Programming in the UNIX
1078 * Environment: UNIX File I/O" dup2() is atomic so there
1079 * should not be a race condition between the old fd being
1080 * closed and the new socket fd being copied over
1082 do {
1083 ret = dup2 (newsock, fd);
1084 } while (ret == -1 && errno == EAGAIN);
1086 if (ret == -1) {
1087 gint errnum = errno;
1089 #ifdef DEBUG
1090 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1091 #endif
1093 errnum = errno_to_WSA (errnum, __func__);
1094 WSASetLastError (errnum);
1096 return(FALSE);
1099 close (newsock);
1101 return(TRUE);
1104 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1105 guint32 flags, guint32 reserved)
1107 #ifdef DEBUG
1108 g_message ("%s: called on socket %d!", __func__, fd);
1109 #endif
1111 if (reserved != 0) {
1112 WSASetLastError (WSAEINVAL);
1113 return(FALSE);
1116 /* We could check the socket type here and fail unless its
1117 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1118 * if we really wanted to
1121 return(socket_disconnect (fd));
1124 #define SF_BUFFER_SIZE 16384
1125 static gint
1126 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1128 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1129 gint file = GPOINTER_TO_INT (fd);
1130 gint n;
1131 gint errnum;
1132 gssize res;
1133 struct stat statbuf;
1135 n = fstat (file, &statbuf);
1136 if (n == -1) {
1137 errnum = errno;
1138 errnum = errno_to_WSA (errnum, __func__);
1139 WSASetLastError (errnum);
1140 return SOCKET_ERROR;
1142 do {
1143 #ifdef __linux__
1144 res = sendfile (socket, file, NULL, statbuf.st_size);
1145 #elif defined(DARWIN)
1146 /* TODO: header/tail could be sent in the 5th argument */
1147 /* TODO: Might not send the entire file for non-blocking sockets */
1148 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1149 #endif
1150 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1151 if (res == -1) {
1152 errnum = errno;
1153 errnum = errno_to_WSA (errnum, __func__);
1154 WSASetLastError (errnum);
1155 return SOCKET_ERROR;
1157 #else
1158 /* Default implementation */
1159 gint file = GPOINTER_TO_INT (fd);
1160 gchar *buffer;
1161 gint n;
1163 buffer = g_malloc (SF_BUFFER_SIZE);
1164 do {
1165 do {
1166 n = read (file, buffer, SF_BUFFER_SIZE);
1167 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1168 if (n == -1)
1169 break;
1170 if (n == 0) {
1171 g_free (buffer);
1172 return 0; /* We're done reading */
1174 do {
1175 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1176 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1177 } while (n != -1);
1179 if (n == -1) {
1180 gint errnum = errno;
1181 errnum = errno_to_WSA (errnum, __func__);
1182 WSASetLastError (errnum);
1183 g_free (buffer);
1184 return SOCKET_ERROR;
1186 g_free (buffer);
1187 #endif
1188 return 0;
1191 gboolean
1192 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1193 WapiTransmitFileBuffers *buffers, guint32 flags)
1195 gpointer sock = GUINT_TO_POINTER (socket);
1196 gint ret;
1198 if (startup_count == 0) {
1199 WSASetLastError (WSANOTINITIALISED);
1200 return FALSE;
1203 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1204 WSASetLastError (WSAENOTSOCK);
1205 return FALSE;
1208 /* Write the header */
1209 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1210 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1211 if (ret == SOCKET_ERROR)
1212 return FALSE;
1215 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1216 if (ret == SOCKET_ERROR)
1217 return FALSE;
1219 /* Write the tail */
1220 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1221 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1222 if (ret == SOCKET_ERROR)
1223 return FALSE;
1226 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1227 closesocket (socket);
1229 return TRUE;
1232 static struct
1234 WapiGuid guid;
1235 gpointer func;
1236 } extension_functions[] = {
1237 {WSAID_DISCONNECTEX, wapi_disconnectex},
1238 {WSAID_TRANSMITFILE, TransmitFile},
1239 {{0}, NULL},
1243 WSAIoctl (guint32 fd, gint32 command,
1244 gchar *input, gint i_len,
1245 gchar *output, gint o_len, glong *written,
1246 void *unused1, void *unused2)
1248 gpointer handle = GUINT_TO_POINTER (fd);
1249 int ret;
1250 gchar *buffer = NULL;
1252 if (startup_count == 0) {
1253 WSASetLastError (WSANOTINITIALISED);
1254 return(SOCKET_ERROR);
1257 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1258 WSASetLastError (WSAENOTSOCK);
1259 return SOCKET_ERROR;
1262 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1263 int i = 0;
1264 WapiGuid *guid = (WapiGuid *)input;
1266 if (i_len < sizeof(WapiGuid)) {
1267 /* As far as I can tell, windows doesn't
1268 * actually set an error here...
1270 WSASetLastError (WSAEINVAL);
1271 return(SOCKET_ERROR);
1274 if (o_len < sizeof(gpointer)) {
1275 /* Or here... */
1276 WSASetLastError (WSAEINVAL);
1277 return(SOCKET_ERROR);
1280 if (output == NULL) {
1281 /* Or here */
1282 WSASetLastError (WSAEINVAL);
1283 return(SOCKET_ERROR);
1286 while(extension_functions[i].func != NULL) {
1287 if (!memcmp (guid, &extension_functions[i].guid,
1288 sizeof(WapiGuid))) {
1289 memcpy (output, &extension_functions[i].func,
1290 sizeof(gpointer));
1291 *written = sizeof(gpointer);
1292 return(0);
1295 i++;
1298 WSASetLastError (WSAEINVAL);
1299 return(SOCKET_ERROR);
1302 if (i_len > 0) {
1303 buffer = g_memdup (input, i_len);
1306 ret = ioctl (fd, command, buffer);
1307 if (ret == -1) {
1308 gint errnum = errno;
1309 #ifdef DEBUG
1310 g_message("%s: WSAIoctl error: %s", __func__,
1311 strerror (errno));
1312 #endif
1314 errnum = errno_to_WSA (errnum, __func__);
1315 WSASetLastError (errnum);
1316 g_free (buffer);
1318 return(SOCKET_ERROR);
1321 if (buffer == NULL) {
1322 *written = 0;
1323 } else {
1324 /* We just copy the buffer to the output. Some ioctls
1325 * don't even output any data, but, well...
1327 * NB windows returns WSAEFAULT if o_len is too small
1329 i_len = (i_len > o_len) ? o_len : i_len;
1331 if (i_len > 0 && output != NULL) {
1332 memcpy (output, buffer, i_len);
1335 g_free (buffer);
1336 *written = i_len;
1339 return(0);
1342 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1343 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1345 gpointer handle = GUINT_TO_POINTER (fd);
1346 int ret;
1348 if (startup_count == 0) {
1349 WSASetLastError (WSANOTINITIALISED);
1350 return(SOCKET_ERROR);
1353 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1354 WSASetLastError (WSAENOTSOCK);
1355 return(SOCKET_ERROR);
1358 switch(command){
1359 case FIONBIO:
1360 #ifdef O_NONBLOCK
1361 /* This works better than ioctl(...FIONBIO...)
1362 * on Linux (it causes connect to return
1363 * EINPROGRESS, but the ioctl doesn't seem to)
1365 ret = fcntl(fd, F_GETFL, 0);
1366 if (ret != -1) {
1367 if (*(gboolean *)arg) {
1368 ret |= O_NONBLOCK;
1369 } else {
1370 ret &= ~O_NONBLOCK;
1372 ret = fcntl(fd, F_SETFL, ret);
1374 break;
1375 #endif /* O_NONBLOCK */
1376 /* Unused in Mono */
1377 case SIOCATMARK:
1378 ret = ioctl (fd, command, arg);
1379 break;
1381 case FIONREAD:
1383 #if defined (PLATFORM_MACOSX)
1385 // ioctl (fd, FIONREAD, XXX) returns the size of
1386 // the UDP header as well on
1387 // Darwin.
1389 // Use getsockopt SO_NREAD instead to get the
1390 // right values for TCP and UDP.
1392 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1393 // be the value of the ip buffer.
1395 socklen_t optlen = sizeof (int);
1396 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1397 #else
1398 ret = ioctl (fd, command, arg);
1399 #endif
1400 break;
1402 default:
1403 WSASetLastError (WSAEINVAL);
1404 return(SOCKET_ERROR);
1407 if (ret == -1) {
1408 gint errnum = errno;
1409 #ifdef DEBUG
1410 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1411 #endif
1413 errnum = errno_to_WSA (errnum, __func__);
1414 WSASetLastError (errnum);
1416 return(SOCKET_ERROR);
1419 return(0);
1422 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1423 fd_set *exceptfds, struct timeval *timeout)
1425 int ret, maxfd;
1427 if (startup_count == 0) {
1428 WSASetLastError (WSANOTINITIALISED);
1429 return(SOCKET_ERROR);
1432 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1433 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1434 (writefds && FD_ISSET (maxfd, writefds)) ||
1435 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1436 break;
1440 if (maxfd == -1) {
1441 WSASetLastError (WSAEINVAL);
1442 return(SOCKET_ERROR);
1445 do {
1446 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1447 timeout);
1448 } while (ret == -1 && errno == EINTR &&
1449 !_wapi_thread_cur_apc_pending ());
1451 if (ret == -1) {
1452 gint errnum = errno;
1453 #ifdef DEBUG
1454 g_message ("%s: select error: %s", __func__, strerror (errno));
1455 #endif
1456 errnum = errno_to_WSA (errnum, __func__);
1457 WSASetLastError (errnum);
1459 return(SOCKET_ERROR);
1462 return(ret);
1465 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1467 gpointer handle = GUINT_TO_POINTER (fd);
1469 if (fd >= FD_SETSIZE) {
1470 WSASetLastError (WSAEINVAL);
1471 return;
1474 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1475 WSASetLastError (WSAENOTSOCK);
1476 return;
1479 FD_CLR (fd, set);
1482 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1484 gpointer handle = GUINT_TO_POINTER (fd);
1486 if (fd >= FD_SETSIZE) {
1487 WSASetLastError (WSAEINVAL);
1488 return(0);
1491 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1492 WSASetLastError (WSAENOTSOCK);
1493 return(0);
1496 return(FD_ISSET (fd, set));
1499 void _wapi_FD_SET(guint32 fd, fd_set *set)
1501 gpointer handle = GUINT_TO_POINTER (fd);
1503 if (fd >= FD_SETSIZE) {
1504 WSASetLastError (WSAEINVAL);
1505 return;
1508 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1509 WSASetLastError (WSAENOTSOCK);
1510 return;
1513 FD_SET (fd, set);
1515 #endif
1517 static void
1518 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1520 guint32 i;
1522 memset (hdr, 0, sizeof (struct msghdr));
1523 hdr->msg_iovlen = count;
1524 hdr->msg_iov = g_new0 (struct iovec, count);
1525 for (i = 0; i < count; i++) {
1526 hdr->msg_iov [i].iov_base = buffers [i].buf;
1527 hdr->msg_iov [i].iov_len = buffers [i].len;
1531 static void
1532 msghdr_iov_free (struct msghdr *hdr)
1534 g_free (hdr->msg_iov);
1537 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1538 guint32 *flags, WapiOverlapped *overlapped,
1539 WapiOverlappedCB *complete)
1541 int ret;
1542 struct msghdr hdr;
1544 g_assert (overlapped == NULL);
1545 g_assert (complete == NULL);
1547 wsabuf_to_msghdr (buffers, count, &hdr);
1548 ret = _wapi_recvmsg (fd, &hdr, *flags);
1549 msghdr_iov_free (&hdr);
1551 if(ret == SOCKET_ERROR) {
1552 return(ret);
1555 *received = ret;
1556 *flags = hdr.msg_flags;
1558 return(0);
1561 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1562 guint32 flags, WapiOverlapped *overlapped,
1563 WapiOverlappedCB *complete)
1565 int ret;
1566 struct msghdr hdr;
1568 g_assert (overlapped == NULL);
1569 g_assert (complete == NULL);
1571 wsabuf_to_msghdr (buffers, count, &hdr);
1572 ret = _wapi_sendmsg (fd, &hdr, flags);
1573 msghdr_iov_free (&hdr);
1575 if(ret == SOCKET_ERROR)
1576 return ret;
1578 *sent = ret;
1579 return 0;