2010-06-01 Geoff Norton <gnorton@novell.com>
[mono.git] / mono / io-layer / sockets.c
blobedb8e3aad1d2852a3cdf0e1bb0e06bbffc9431f4
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_UIO_H
18 # include <sys/uio.h>
19 #endif
20 #ifdef HAVE_SYS_IOCTL_H
21 # include <sys/ioctl.h>
22 #endif
23 #ifdef HAVE_SYS_FILIO_H
24 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
25 #endif
26 #ifdef HAVE_SYS_SOCKIO_H
27 #include <sys/sockio.h> /* defines SIOCATMARK */
28 #endif
29 #include <unistd.h>
30 #include <fcntl.h>
32 #ifndef HAVE_MSG_NOSIGNAL
33 #include <signal.h>
34 #endif
36 #include <mono/io-layer/wapi.h>
37 #include <mono/io-layer/wapi-private.h>
38 #include <mono/io-layer/socket-private.h>
39 #include <mono/io-layer/handles-private.h>
40 #include <mono/io-layer/socket-wrappers.h>
41 #include <mono/utils/mono-poll.h>
43 #include <netinet/in.h>
44 #include <netinet/tcp.h>
45 #include <netdb.h>
46 #include <arpa/inet.h>
47 #ifdef HAVE_SYS_SENDFILE_H
48 #include <sys/sendfile.h>
49 #endif
51 #undef DEBUG
53 static guint32 startup_count=0;
55 static void socket_close (gpointer handle, gpointer data);
57 struct _WapiHandleOps _wapi_socket_ops = {
58 socket_close, /* close */
59 NULL, /* signal */
60 NULL, /* own */
61 NULL, /* is_owned */
62 NULL, /* special_wait */
63 NULL /* prewait */
66 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
68 static void socket_ops_init (void)
70 /* No capabilities to register */
73 static void socket_close (gpointer handle, gpointer data)
75 int ret;
76 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
78 #ifdef DEBUG
79 g_message ("%s: closing socket handle %p", __func__, handle);
80 #endif
82 if (startup_count == 0) {
83 WSASetLastError (WSANOTINITIALISED);
84 return;
87 /* Shutdown the socket for reading, to interrupt any potential
88 * receives that may be blocking for data. See bug 75705.
90 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
92 do {
93 ret = close (GPOINTER_TO_UINT(handle));
94 } while (ret == -1 && errno == EINTR &&
95 !_wapi_thread_cur_apc_pending ());
97 if (ret == -1) {
98 gint errnum = errno;
99 #ifdef DEBUG
100 g_message ("%s: close error: %s", __func__, strerror (errno));
101 #endif
102 errnum = errno_to_WSA (errnum, __func__);
103 WSASetLastError (errnum);
106 socket_handle->saved_error = 0;
109 int WSAStartup(guint32 requested, WapiWSAData *data)
111 if (data == NULL) {
112 return(WSAEFAULT);
115 /* Insist on v2.0+ */
116 if (requested < MAKEWORD(2,0)) {
117 return(WSAVERNOTSUPPORTED);
120 startup_count++;
122 /* I've no idea what is the minor version of the spec I read */
123 data->wHighVersion = MAKEWORD(2,2);
125 data->wVersion = requested < data->wHighVersion? requested:
126 data->wHighVersion;
128 #ifdef DEBUG
129 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
130 #endif
132 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
133 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
135 return(0);
138 static gboolean
139 cleanup_close (gpointer handle, gpointer data)
141 _wapi_handle_ops_close (handle, NULL);
142 return TRUE;
145 int WSACleanup(void)
147 #ifdef DEBUG
148 g_message ("%s: cleaning up", __func__);
149 #endif
151 if (--startup_count) {
152 /* Do nothing */
153 return(0);
156 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
157 return(0);
160 void WSASetLastError(int error)
162 SetLastError (error);
165 int WSAGetLastError(void)
167 return(GetLastError ());
170 int closesocket(guint32 fd)
172 gpointer handle = GUINT_TO_POINTER (fd);
174 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
175 WSASetLastError (WSAENOTSOCK);
176 return(0);
179 _wapi_handle_unref (handle);
180 return(0);
183 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
185 gpointer handle = GUINT_TO_POINTER (fd);
186 gpointer new_handle;
187 struct _WapiHandle_socket *socket_handle;
188 struct _WapiHandle_socket new_socket_handle = {0};
189 gboolean ok;
190 int new_fd;
192 if (startup_count == 0) {
193 WSASetLastError (WSANOTINITIALISED);
194 return(INVALID_SOCKET);
197 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
198 WSASetLastError (WSAEFAULT);
199 return(INVALID_SOCKET);
202 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
203 WSASetLastError (WSAENOTSOCK);
204 return(INVALID_SOCKET);
207 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
208 (gpointer *)&socket_handle);
209 if (ok == FALSE) {
210 g_warning ("%s: error looking up socket handle %p",
211 __func__, handle);
212 WSASetLastError (WSAENOTSOCK);
213 return(INVALID_SOCKET);
216 do {
217 new_fd = accept (fd, addr, addrlen);
218 } while (new_fd == -1 && errno == EINTR &&
219 !_wapi_thread_cur_apc_pending());
221 if (new_fd == -1) {
222 gint errnum = errno;
223 #ifdef DEBUG
224 g_message ("%s: accept error: %s", __func__, strerror(errno));
225 #endif
227 errnum = errno_to_WSA (errnum, __func__);
228 WSASetLastError (errnum);
230 return(INVALID_SOCKET);
233 if (new_fd >= _wapi_fd_reserve) {
234 #ifdef DEBUG
235 g_message ("%s: File descriptor is too big", __func__);
236 #endif
238 WSASetLastError (WSASYSCALLFAILURE);
240 close (new_fd);
242 return(INVALID_SOCKET);
245 new_socket_handle.domain = socket_handle->domain;
246 new_socket_handle.type = socket_handle->type;
247 new_socket_handle.protocol = socket_handle->protocol;
248 new_socket_handle.still_readable = 1;
250 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
251 &new_socket_handle);
252 if(new_handle == _WAPI_HANDLE_INVALID) {
253 g_warning ("%s: error creating socket handle", __func__);
254 WSASetLastError (ERROR_GEN_FAILURE);
255 return(INVALID_SOCKET);
258 #ifdef DEBUG
259 g_message ("%s: returning newly accepted socket handle %p with",
260 __func__, new_handle);
261 #endif
263 return(new_fd);
266 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
268 gpointer handle = GUINT_TO_POINTER (fd);
269 int ret;
271 if (startup_count == 0) {
272 WSASetLastError (WSANOTINITIALISED);
273 return(SOCKET_ERROR);
276 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
277 WSASetLastError (WSAENOTSOCK);
278 return(SOCKET_ERROR);
281 ret = bind (fd, my_addr, addrlen);
282 if (ret == -1) {
283 gint errnum = errno;
284 #ifdef DEBUG
285 g_message ("%s: bind error: %s", __func__, strerror(errno));
286 #endif
287 errnum = errno_to_WSA (errnum, __func__);
288 WSASetLastError (errnum);
290 return(SOCKET_ERROR);
292 return(ret);
295 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
296 socklen_t addrlen)
298 gpointer handle = GUINT_TO_POINTER (fd);
299 struct _WapiHandle_socket *socket_handle;
300 gboolean ok;
301 gint errnum;
303 if (startup_count == 0) {
304 WSASetLastError (WSANOTINITIALISED);
305 return(SOCKET_ERROR);
308 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
309 WSASetLastError (WSAENOTSOCK);
310 return(SOCKET_ERROR);
313 if (connect (fd, serv_addr, addrlen) == -1) {
314 mono_pollfd fds;
315 int so_error;
316 socklen_t len;
318 errnum = errno;
320 if (errno != EINTR) {
321 #ifdef DEBUG
322 g_message ("%s: connect error: %s", __func__,
323 strerror (errnum));
324 #endif
326 errnum = errno_to_WSA (errnum, __func__);
327 if (errnum == WSAEINPROGRESS)
328 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
330 WSASetLastError (errnum);
333 * On solaris x86 getsockopt (SO_ERROR) is not set after
334 * connect () fails so we need to save this error.
336 * But don't do this for EWOULDBLOCK (bug 317315)
338 if (errnum != WSAEWOULDBLOCK) {
339 ok = _wapi_lookup_handle (handle,
340 WAPI_HANDLE_SOCKET,
341 (gpointer *)&socket_handle);
342 if (ok == FALSE) {
343 /* ECONNRESET means the socket was closed by another thread */
344 if (errnum != WSAECONNRESET)
345 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
346 } else {
347 socket_handle->saved_error = errnum;
350 return(SOCKET_ERROR);
353 fds.fd = fd;
354 fds.events = POLLOUT;
355 while (mono_poll (&fds, 1, -1) == -1 &&
356 !_wapi_thread_cur_apc_pending ()) {
357 if (errno != EINTR) {
358 errnum = errno_to_WSA (errno, __func__);
360 #ifdef DEBUG
361 g_message ("%s: connect poll error: %s",
362 __func__, strerror (errno));
363 #endif
365 WSASetLastError (errnum);
366 return(SOCKET_ERROR);
370 len = sizeof(so_error);
371 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
372 &len) == -1) {
373 errnum = errno_to_WSA (errno, __func__);
375 #ifdef DEBUG
376 g_message ("%s: connect getsockopt error: %s",
377 __func__, strerror (errno));
378 #endif
380 WSASetLastError (errnum);
381 return(SOCKET_ERROR);
384 if (so_error != 0) {
385 errnum = errno_to_WSA (so_error, __func__);
387 /* Need to save this socket error */
388 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
389 (gpointer *)&socket_handle);
390 if (ok == FALSE) {
391 g_warning ("%s: error looking up socket handle %p", __func__, handle);
392 } else {
393 socket_handle->saved_error = errnum;
396 #ifdef DEBUG
397 g_message ("%s: connect getsockopt returned error: %s",
398 __func__, strerror (so_error));
399 #endif
401 WSASetLastError (errnum);
402 return(SOCKET_ERROR);
406 return(0);
409 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
411 gpointer handle = GUINT_TO_POINTER (fd);
412 int ret;
414 if (startup_count == 0) {
415 WSASetLastError (WSANOTINITIALISED);
416 return(SOCKET_ERROR);
419 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
420 WSASetLastError (WSAENOTSOCK);
421 return(SOCKET_ERROR);
424 ret = getpeername (fd, name, namelen);
425 if (ret == -1) {
426 gint errnum = errno;
427 #ifdef DEBUG
428 g_message ("%s: getpeername error: %s", __func__,
429 strerror (errno));
430 #endif
432 errnum = errno_to_WSA (errnum, __func__);
433 WSASetLastError (errnum);
435 return(SOCKET_ERROR);
438 return(ret);
441 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
443 gpointer handle = GUINT_TO_POINTER (fd);
444 int ret;
446 if (startup_count == 0) {
447 WSASetLastError (WSANOTINITIALISED);
448 return(SOCKET_ERROR);
451 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
452 WSASetLastError (WSAENOTSOCK);
453 return(SOCKET_ERROR);
456 ret = getsockname (fd, name, namelen);
457 if (ret == -1) {
458 gint errnum = errno;
459 #ifdef DEBUG
460 g_message ("%s: getsockname error: %s", __func__,
461 strerror (errno));
462 #endif
464 errnum = errno_to_WSA (errnum, __func__);
465 WSASetLastError (errnum);
467 return(SOCKET_ERROR);
470 return(ret);
473 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
474 socklen_t *optlen)
476 gpointer handle = GUINT_TO_POINTER (fd);
477 int ret;
478 struct timeval tv;
479 void *tmp_val;
480 struct _WapiHandle_socket *socket_handle;
481 gboolean ok;
483 if (startup_count == 0) {
484 WSASetLastError (WSANOTINITIALISED);
485 return(SOCKET_ERROR);
488 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
489 WSASetLastError (WSAENOTSOCK);
490 return(SOCKET_ERROR);
493 tmp_val = optval;
494 if (level == SOL_SOCKET &&
495 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
496 tmp_val = &tv;
497 *optlen = sizeof (tv);
500 ret = getsockopt (fd, level, optname, tmp_val, optlen);
501 if (ret == -1) {
502 gint errnum = errno;
503 #ifdef DEBUG
504 g_message ("%s: getsockopt error: %s", __func__,
505 strerror (errno));
506 #endif
508 errnum = errno_to_WSA (errnum, __func__);
509 WSASetLastError (errnum);
511 return(SOCKET_ERROR);
514 if (level == SOL_SOCKET &&
515 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
516 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
517 *optlen = sizeof (int);
520 if (optname == SO_ERROR) {
521 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
522 (gpointer *)&socket_handle);
523 if (ok == FALSE) {
524 g_warning ("%s: error looking up socket handle %p",
525 __func__, handle);
527 /* can't extract the last error */
528 *((int *) optval) = errno_to_WSA (*((int *)optval),
529 __func__);
530 } else {
531 if (*((int *)optval) != 0) {
532 *((int *) optval) = errno_to_WSA (*((int *)optval),
533 __func__);
534 socket_handle->saved_error = *((int *)optval);
535 } else {
536 *((int *)optval) = socket_handle->saved_error;
541 return(ret);
544 int _wapi_listen(guint32 fd, int backlog)
546 gpointer handle = GUINT_TO_POINTER (fd);
547 int ret;
549 if (startup_count == 0) {
550 WSASetLastError (WSANOTINITIALISED);
551 return(SOCKET_ERROR);
554 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
555 WSASetLastError (WSAENOTSOCK);
556 return(SOCKET_ERROR);
559 ret = listen (fd, backlog);
560 if (ret == -1) {
561 gint errnum = errno;
562 #ifdef DEBUG
563 g_message ("%s: listen error: %s", __func__, strerror (errno));
564 #endif
566 errnum = errno_to_WSA (errnum, __func__);
567 WSASetLastError (errnum);
569 return(SOCKET_ERROR);
572 return(0);
575 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
577 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
580 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
581 struct sockaddr *from, socklen_t *fromlen)
583 gpointer handle = GUINT_TO_POINTER (fd);
584 struct _WapiHandle_socket *socket_handle;
585 gboolean ok;
586 int ret;
588 if (startup_count == 0) {
589 WSASetLastError (WSANOTINITIALISED);
590 return(SOCKET_ERROR);
593 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
594 WSASetLastError (WSAENOTSOCK);
595 return(SOCKET_ERROR);
598 do {
599 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
600 } while (ret == -1 && errno == EINTR &&
601 !_wapi_thread_cur_apc_pending ());
603 if (ret == 0 && len > 0) {
604 /* According to the Linux man page, recvfrom only
605 * returns 0 when the socket has been shut down
606 * cleanly. Turn this into an EINTR to simulate win32
607 * behaviour of returning EINTR when a socket is
608 * closed while the recvfrom is blocking (we use a
609 * shutdown() in socket_close() to trigger this.) See
610 * bug 75705.
612 /* Distinguish between the socket being shut down at
613 * the local or remote ends, and reads that request 0
614 * bytes to be read
617 /* If this returns FALSE, it means the socket has been
618 * closed locally. If it returns TRUE, but
619 * still_readable != 1 then shutdown
620 * (SHUT_RD|SHUT_RDWR) has been called locally.
622 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
623 (gpointer *)&socket_handle);
624 if (ok == FALSE || socket_handle->still_readable != 1) {
625 ret = -1;
626 errno = EINTR;
630 if (ret == -1) {
631 gint errnum = errno;
632 #ifdef DEBUG
633 g_message ("%s: recv error: %s", __func__, strerror(errno));
634 #endif
636 errnum = errno_to_WSA (errnum, __func__);
637 WSASetLastError (errnum);
639 return(SOCKET_ERROR);
641 return(ret);
644 static int
645 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
647 gpointer handle = GUINT_TO_POINTER (fd);
648 struct _WapiHandle_socket *socket_handle;
649 gboolean ok;
650 int ret;
652 if (startup_count == 0) {
653 WSASetLastError (WSANOTINITIALISED);
654 return(SOCKET_ERROR);
657 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
658 WSASetLastError (WSAENOTSOCK);
659 return(SOCKET_ERROR);
662 do {
663 ret = recvmsg (fd, msg, recv_flags);
664 } while (ret == -1 && errno == EINTR &&
665 !_wapi_thread_cur_apc_pending ());
667 if (ret == 0) {
668 /* see _wapi_recvfrom */
669 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
670 (gpointer *)&socket_handle);
671 if (ok == FALSE || socket_handle->still_readable != 1) {
672 ret = -1;
673 errno = EINTR;
677 if (ret == -1) {
678 gint errnum = errno;
679 #ifdef DEBUG
680 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
681 #endif
683 errnum = errno_to_WSA (errnum, __func__);
684 WSASetLastError (errnum);
686 return(SOCKET_ERROR);
688 return(ret);
691 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
693 gpointer handle = GUINT_TO_POINTER (fd);
694 int ret;
696 if (startup_count == 0) {
697 WSASetLastError (WSANOTINITIALISED);
698 return(SOCKET_ERROR);
701 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
702 WSASetLastError (WSAENOTSOCK);
703 return(SOCKET_ERROR);
706 do {
707 ret = send (fd, msg, len, send_flags);
708 } while (ret == -1 && errno == EINTR &&
709 !_wapi_thread_cur_apc_pending ());
711 if (ret == -1) {
712 gint errnum = errno;
713 #ifdef DEBUG
714 g_message ("%s: send error: %s", __func__, strerror (errno));
715 #endif
717 errnum = errno_to_WSA (errnum, __func__);
718 WSASetLastError (errnum);
720 return(SOCKET_ERROR);
722 return(ret);
725 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
726 const struct sockaddr *to, socklen_t tolen)
728 gpointer handle = GUINT_TO_POINTER (fd);
729 int ret;
731 if (startup_count == 0) {
732 WSASetLastError (WSANOTINITIALISED);
733 return(SOCKET_ERROR);
736 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
737 WSASetLastError (WSAENOTSOCK);
738 return(SOCKET_ERROR);
741 do {
742 ret = sendto (fd, msg, len, send_flags, to, tolen);
743 } while (ret == -1 && errno == EINTR &&
744 !_wapi_thread_cur_apc_pending ());
746 if (ret == -1) {
747 gint errnum = errno;
748 #ifdef DEBUG
749 g_message ("%s: send error: %s", __func__, strerror (errno));
750 #endif
752 errnum = errno_to_WSA (errnum, __func__);
753 WSASetLastError (errnum);
755 return(SOCKET_ERROR);
757 return(ret);
760 static int
761 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
763 gpointer handle = GUINT_TO_POINTER (fd);
764 int ret;
766 if (startup_count == 0) {
767 WSASetLastError (WSANOTINITIALISED);
768 return(SOCKET_ERROR);
771 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
772 WSASetLastError (WSAENOTSOCK);
773 return(SOCKET_ERROR);
776 do {
777 ret = sendmsg (fd, msg, send_flags);
778 } while (ret == -1 && errno == EINTR &&
779 !_wapi_thread_cur_apc_pending ());
781 if (ret == -1) {
782 gint errnum = errno;
783 #ifdef DEBUG
784 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
785 #endif
787 errnum = errno_to_WSA (errnum, __func__);
788 WSASetLastError (errnum);
790 return(SOCKET_ERROR);
792 return(ret);
795 int _wapi_setsockopt(guint32 fd, int level, int optname,
796 const void *optval, socklen_t optlen)
798 gpointer handle = GUINT_TO_POINTER (fd);
799 int ret;
800 const void *tmp_val;
801 struct timeval tv;
803 if (startup_count == 0) {
804 WSASetLastError (WSANOTINITIALISED);
805 return(SOCKET_ERROR);
808 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
809 WSASetLastError (WSAENOTSOCK);
810 return(SOCKET_ERROR);
813 tmp_val = optval;
814 if (level == SOL_SOCKET &&
815 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
816 int ms = *((int *) optval);
817 tv.tv_sec = ms / 1000;
818 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
819 tmp_val = &tv;
820 optlen = sizeof (tv);
821 #if defined (__linux__)
822 } else if (level == SOL_SOCKET &&
823 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
824 /* According to socket(7) the Linux kernel doubles the
825 * buffer sizes "to allow space for bookkeeping
826 * overhead."
828 int bufsize = *((int *) optval);
830 bufsize /= 2;
831 tmp_val = &bufsize;
832 #endif
835 ret = setsockopt (fd, level, optname, tmp_val, optlen);
836 if (ret == -1) {
837 gint errnum = errno;
838 #ifdef DEBUG
839 g_message ("%s: setsockopt error: %s", __func__,
840 strerror (errno));
841 #endif
843 errnum = errno_to_WSA (errnum, __func__);
844 WSASetLastError (errnum);
846 return(SOCKET_ERROR);
849 #if defined (SO_REUSEPORT)
850 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
851 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
852 int type;
853 socklen_t type_len = sizeof (type);
855 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
856 if (type == SOCK_DGRAM)
857 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
860 #endif
862 return(ret);
865 int _wapi_shutdown(guint32 fd, int how)
867 struct _WapiHandle_socket *socket_handle;
868 gboolean ok;
869 gpointer handle = GUINT_TO_POINTER (fd);
870 int ret;
872 if (startup_count == 0) {
873 WSASetLastError (WSANOTINITIALISED);
874 return(SOCKET_ERROR);
877 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
878 WSASetLastError (WSAENOTSOCK);
879 return(SOCKET_ERROR);
882 if (how == SHUT_RD ||
883 how == SHUT_RDWR) {
884 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
885 (gpointer *)&socket_handle);
886 if (ok == FALSE) {
887 g_warning ("%s: error looking up socket handle %p",
888 __func__, handle);
889 WSASetLastError (WSAENOTSOCK);
890 return(SOCKET_ERROR);
893 socket_handle->still_readable = 0;
896 ret = shutdown (fd, how);
897 if (ret == -1) {
898 gint errnum = errno;
899 #ifdef DEBUG
900 g_message ("%s: shutdown error: %s", __func__,
901 strerror (errno));
902 #endif
904 errnum = errno_to_WSA (errnum, __func__);
905 WSASetLastError (errnum);
907 return(SOCKET_ERROR);
910 return(ret);
913 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
914 guint32 unused2, guint32 unused3)
916 struct _WapiHandle_socket socket_handle = {0};
917 gpointer handle;
918 int fd;
920 socket_handle.domain = domain;
921 socket_handle.type = type;
922 socket_handle.protocol = protocol;
923 socket_handle.still_readable = 1;
925 fd = socket (domain, type, protocol);
926 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
927 protocol == 0) {
928 /* Retry with protocol == 4 (see bug #54565) */
929 socket_handle.protocol = 4;
930 fd = socket (AF_INET, SOCK_RAW, 4);
933 if (fd == -1) {
934 gint errnum = errno;
935 #ifdef DEBUG
936 g_message ("%s: socket error: %s", __func__, strerror (errno));
937 #endif
938 errnum = errno_to_WSA (errnum, __func__);
939 WSASetLastError (errnum);
941 return(INVALID_SOCKET);
944 if (fd >= _wapi_fd_reserve) {
945 #ifdef DEBUG
946 g_message ("%s: File descriptor is too big (%d >= %d)",
947 __func__, fd, _wapi_fd_reserve);
948 #endif
950 WSASetLastError (WSASYSCALLFAILURE);
951 close (fd);
953 return(INVALID_SOCKET);
956 /* .net seems to set this by default for SOCK_STREAM, not for
957 * SOCK_DGRAM (see bug #36322)
959 * It seems winsock has a rather different idea of what
960 * SO_REUSEADDR means. If it's set, then a new socket can be
961 * bound over an existing listening socket. There's a new
962 * windows-specific option called SO_EXCLUSIVEADDRUSE but
963 * using that means the socket MUST be closed properly, or a
964 * denial of service can occur. Luckily for us, winsock
965 * behaves as though any other system would when SO_REUSEADDR
966 * is true, so we don't need to do anything else here. See
967 * bug 53992.
970 int ret, true = 1;
972 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
973 sizeof (true));
974 if (ret == -1) {
975 int errnum = errno;
977 #ifdef DEBUG
978 g_message ("%s: Error setting SO_REUSEADDR", __func__);
979 #endif
981 errnum = errno_to_WSA (errnum, __func__);
982 WSASetLastError (errnum);
984 close (fd);
986 return(INVALID_SOCKET);
991 mono_once (&socket_ops_once, socket_ops_init);
993 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
994 if (handle == _WAPI_HANDLE_INVALID) {
995 g_warning ("%s: error creating socket handle", __func__);
996 WSASetLastError (WSASYSCALLFAILURE);
997 close (fd);
998 return(INVALID_SOCKET);
1001 #ifdef DEBUG
1002 g_message ("%s: returning socket handle %p", __func__, handle);
1003 #endif
1005 return(fd);
1008 struct hostent *_wapi_gethostbyname(const char *hostname)
1010 struct hostent *he;
1012 if (startup_count == 0) {
1013 WSASetLastError (WSANOTINITIALISED);
1014 return(NULL);
1017 he = gethostbyname (hostname);
1018 if (he == NULL) {
1019 #ifdef DEBUG
1020 g_message ("%s: gethostbyname error: %s", __func__,
1021 strerror (h_errno));
1022 #endif
1024 switch(h_errno) {
1025 case HOST_NOT_FOUND:
1026 WSASetLastError (WSAHOST_NOT_FOUND);
1027 break;
1028 #if NO_ADDRESS != NO_DATA
1029 case NO_ADDRESS:
1030 #endif
1031 case NO_DATA:
1032 WSASetLastError (WSANO_DATA);
1033 break;
1034 case NO_RECOVERY:
1035 WSASetLastError (WSANO_RECOVERY);
1036 break;
1037 case TRY_AGAIN:
1038 WSASetLastError (WSATRY_AGAIN);
1039 break;
1040 default:
1041 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1042 break;
1046 return(he);
1049 static gboolean socket_disconnect (guint32 fd)
1051 struct _WapiHandle_socket *socket_handle;
1052 gboolean ok;
1053 gpointer handle = GUINT_TO_POINTER (fd);
1054 int newsock, ret;
1056 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1057 (gpointer *)&socket_handle);
1058 if (ok == FALSE) {
1059 g_warning ("%s: error looking up socket handle %p", __func__,
1060 handle);
1061 WSASetLastError (WSAENOTSOCK);
1062 return(FALSE);
1065 newsock = socket (socket_handle->domain, socket_handle->type,
1066 socket_handle->protocol);
1067 if (newsock == -1) {
1068 gint errnum = errno;
1070 #ifdef DEBUG
1071 g_message ("%s: socket error: %s", __func__, strerror (errno));
1072 #endif
1074 errnum = errno_to_WSA (errnum, __func__);
1075 WSASetLastError (errnum);
1077 return(FALSE);
1080 /* According to Stevens "Advanced Programming in the UNIX
1081 * Environment: UNIX File I/O" dup2() is atomic so there
1082 * should not be a race condition between the old fd being
1083 * closed and the new socket fd being copied over
1085 do {
1086 ret = dup2 (newsock, fd);
1087 } while (ret == -1 && errno == EAGAIN);
1089 if (ret == -1) {
1090 gint errnum = errno;
1092 #ifdef DEBUG
1093 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1094 #endif
1096 errnum = errno_to_WSA (errnum, __func__);
1097 WSASetLastError (errnum);
1099 return(FALSE);
1102 close (newsock);
1104 return(TRUE);
1107 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1108 guint32 flags, guint32 reserved)
1110 #ifdef DEBUG
1111 g_message ("%s: called on socket %d!", __func__, fd);
1112 #endif
1114 if (reserved != 0) {
1115 WSASetLastError (WSAEINVAL);
1116 return(FALSE);
1119 /* We could check the socket type here and fail unless its
1120 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1121 * if we really wanted to
1124 return(socket_disconnect (fd));
1127 #define SF_BUFFER_SIZE 16384
1128 static gint
1129 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
1131 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1132 gint file = GPOINTER_TO_INT (fd);
1133 gint n;
1134 gint errnum;
1135 gssize res;
1136 struct stat statbuf;
1138 n = fstat (file, &statbuf);
1139 if (n == -1) {
1140 errnum = errno;
1141 errnum = errno_to_WSA (errnum, __func__);
1142 WSASetLastError (errnum);
1143 return SOCKET_ERROR;
1145 do {
1146 #ifdef __linux__
1147 res = sendfile (socket, file, NULL, statbuf.st_size);
1148 #elif defined(DARWIN)
1149 /* TODO: header/tail could be sent in the 5th argument */
1150 /* TODO: Might not send the entire file for non-blocking sockets */
1151 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
1152 #endif
1153 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
1154 if (res == -1) {
1155 errnum = errno;
1156 errnum = errno_to_WSA (errnum, __func__);
1157 WSASetLastError (errnum);
1158 return SOCKET_ERROR;
1160 #else
1161 /* Default implementation */
1162 gint file = GPOINTER_TO_INT (fd);
1163 gchar *buffer;
1164 gint n;
1166 buffer = g_malloc (SF_BUFFER_SIZE);
1167 do {
1168 do {
1169 n = read (file, buffer, SF_BUFFER_SIZE);
1170 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1171 if (n == -1)
1172 break;
1173 if (n == 0) {
1174 g_free (buffer);
1175 return 0; /* We're done reading */
1177 do {
1178 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1179 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1180 } while (n != -1);
1182 if (n == -1) {
1183 gint errnum = errno;
1184 errnum = errno_to_WSA (errnum, __func__);
1185 WSASetLastError (errnum);
1186 g_free (buffer);
1187 return SOCKET_ERROR;
1189 g_free (buffer);
1190 #endif
1191 return 0;
1194 gboolean
1195 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1196 WapiTransmitFileBuffers *buffers, guint32 flags)
1198 gpointer sock = GUINT_TO_POINTER (socket);
1199 gint ret;
1201 if (startup_count == 0) {
1202 WSASetLastError (WSANOTINITIALISED);
1203 return FALSE;
1206 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1207 WSASetLastError (WSAENOTSOCK);
1208 return FALSE;
1211 /* Write the header */
1212 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1213 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1214 if (ret == SOCKET_ERROR)
1215 return FALSE;
1218 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1219 if (ret == SOCKET_ERROR)
1220 return FALSE;
1222 /* Write the tail */
1223 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1224 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1225 if (ret == SOCKET_ERROR)
1226 return FALSE;
1229 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1230 closesocket (socket);
1232 return TRUE;
1235 static struct
1237 WapiGuid guid;
1238 gpointer func;
1239 } extension_functions[] = {
1240 {WSAID_DISCONNECTEX, wapi_disconnectex},
1241 {WSAID_TRANSMITFILE, TransmitFile},
1242 {{0}, NULL},
1246 WSAIoctl (guint32 fd, gint32 command,
1247 gchar *input, gint i_len,
1248 gchar *output, gint o_len, glong *written,
1249 void *unused1, void *unused2)
1251 gpointer handle = GUINT_TO_POINTER (fd);
1252 int ret;
1253 gchar *buffer = NULL;
1255 if (startup_count == 0) {
1256 WSASetLastError (WSANOTINITIALISED);
1257 return(SOCKET_ERROR);
1260 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1261 WSASetLastError (WSAENOTSOCK);
1262 return SOCKET_ERROR;
1265 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1266 int i = 0;
1267 WapiGuid *guid = (WapiGuid *)input;
1269 if (i_len < sizeof(WapiGuid)) {
1270 /* As far as I can tell, windows doesn't
1271 * actually set an error here...
1273 WSASetLastError (WSAEINVAL);
1274 return(SOCKET_ERROR);
1277 if (o_len < sizeof(gpointer)) {
1278 /* Or here... */
1279 WSASetLastError (WSAEINVAL);
1280 return(SOCKET_ERROR);
1283 if (output == NULL) {
1284 /* Or here */
1285 WSASetLastError (WSAEINVAL);
1286 return(SOCKET_ERROR);
1289 while(extension_functions[i].func != NULL) {
1290 if (!memcmp (guid, &extension_functions[i].guid,
1291 sizeof(WapiGuid))) {
1292 memcpy (output, &extension_functions[i].func,
1293 sizeof(gpointer));
1294 *written = sizeof(gpointer);
1295 return(0);
1298 i++;
1301 WSASetLastError (WSAEINVAL);
1302 return(SOCKET_ERROR);
1305 if (i_len > 0) {
1306 buffer = g_memdup (input, i_len);
1309 ret = ioctl (fd, command, buffer);
1310 if (ret == -1) {
1311 gint errnum = errno;
1312 #ifdef DEBUG
1313 g_message("%s: WSAIoctl error: %s", __func__,
1314 strerror (errno));
1315 #endif
1317 errnum = errno_to_WSA (errnum, __func__);
1318 WSASetLastError (errnum);
1319 g_free (buffer);
1321 return(SOCKET_ERROR);
1324 if (buffer == NULL) {
1325 *written = 0;
1326 } else {
1327 /* We just copy the buffer to the output. Some ioctls
1328 * don't even output any data, but, well...
1330 * NB windows returns WSAEFAULT if o_len is too small
1332 i_len = (i_len > o_len) ? o_len : i_len;
1334 if (i_len > 0 && output != NULL) {
1335 memcpy (output, buffer, i_len);
1338 g_free (buffer);
1339 *written = i_len;
1342 return(0);
1345 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1346 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1348 gpointer handle = GUINT_TO_POINTER (fd);
1349 int ret;
1351 if (startup_count == 0) {
1352 WSASetLastError (WSANOTINITIALISED);
1353 return(SOCKET_ERROR);
1356 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1357 WSASetLastError (WSAENOTSOCK);
1358 return(SOCKET_ERROR);
1361 switch(command){
1362 case FIONBIO:
1363 #ifdef O_NONBLOCK
1364 /* This works better than ioctl(...FIONBIO...)
1365 * on Linux (it causes connect to return
1366 * EINPROGRESS, but the ioctl doesn't seem to)
1368 ret = fcntl(fd, F_GETFL, 0);
1369 if (ret != -1) {
1370 if (*(gboolean *)arg) {
1371 ret |= O_NONBLOCK;
1372 } else {
1373 ret &= ~O_NONBLOCK;
1375 ret = fcntl(fd, F_SETFL, ret);
1377 break;
1378 #endif /* O_NONBLOCK */
1379 /* Unused in Mono */
1380 case SIOCATMARK:
1381 ret = ioctl (fd, command, arg);
1382 break;
1384 case FIONREAD:
1386 #if defined (PLATFORM_MACOSX)
1388 // ioctl (fd, FIONREAD, XXX) returns the size of
1389 // the UDP header as well on
1390 // Darwin.
1392 // Use getsockopt SO_NREAD instead to get the
1393 // right values for TCP and UDP.
1395 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1396 // be the value of the ip buffer.
1398 socklen_t optlen = sizeof (int);
1399 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1400 #else
1401 ret = ioctl (fd, command, arg);
1402 #endif
1403 break;
1405 default:
1406 WSASetLastError (WSAEINVAL);
1407 return(SOCKET_ERROR);
1410 if (ret == -1) {
1411 gint errnum = errno;
1412 #ifdef DEBUG
1413 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1414 #endif
1416 errnum = errno_to_WSA (errnum, __func__);
1417 WSASetLastError (errnum);
1419 return(SOCKET_ERROR);
1422 return(0);
1425 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1426 fd_set *exceptfds, struct timeval *timeout)
1428 int ret, maxfd;
1430 if (startup_count == 0) {
1431 WSASetLastError (WSANOTINITIALISED);
1432 return(SOCKET_ERROR);
1435 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1436 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1437 (writefds && FD_ISSET (maxfd, writefds)) ||
1438 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1439 break;
1443 if (maxfd == -1) {
1444 WSASetLastError (WSAEINVAL);
1445 return(SOCKET_ERROR);
1448 do {
1449 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1450 timeout);
1451 } while (ret == -1 && errno == EINTR &&
1452 !_wapi_thread_cur_apc_pending ());
1454 if (ret == -1) {
1455 gint errnum = errno;
1456 #ifdef DEBUG
1457 g_message ("%s: select error: %s", __func__, strerror (errno));
1458 #endif
1459 errnum = errno_to_WSA (errnum, __func__);
1460 WSASetLastError (errnum);
1462 return(SOCKET_ERROR);
1465 return(ret);
1468 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1470 gpointer handle = GUINT_TO_POINTER (fd);
1472 if (fd >= FD_SETSIZE) {
1473 WSASetLastError (WSAEINVAL);
1474 return;
1477 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1478 WSASetLastError (WSAENOTSOCK);
1479 return;
1482 FD_CLR (fd, set);
1485 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1487 gpointer handle = GUINT_TO_POINTER (fd);
1489 if (fd >= FD_SETSIZE) {
1490 WSASetLastError (WSAEINVAL);
1491 return(0);
1494 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1495 WSASetLastError (WSAENOTSOCK);
1496 return(0);
1499 return(FD_ISSET (fd, set));
1502 void _wapi_FD_SET(guint32 fd, fd_set *set)
1504 gpointer handle = GUINT_TO_POINTER (fd);
1506 if (fd >= FD_SETSIZE) {
1507 WSASetLastError (WSAEINVAL);
1508 return;
1511 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1512 WSASetLastError (WSAENOTSOCK);
1513 return;
1516 FD_SET (fd, set);
1518 #endif
1520 static void
1521 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1523 guint32 i;
1525 memset (hdr, 0, sizeof (struct msghdr));
1526 hdr->msg_iovlen = count;
1527 hdr->msg_iov = g_new0 (struct iovec, count);
1528 for (i = 0; i < count; i++) {
1529 hdr->msg_iov [i].iov_base = buffers [i].buf;
1530 hdr->msg_iov [i].iov_len = buffers [i].len;
1534 static void
1535 msghdr_iov_free (struct msghdr *hdr)
1537 g_free (hdr->msg_iov);
1540 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1541 guint32 *flags, WapiOverlapped *overlapped,
1542 WapiOverlappedCB *complete)
1544 int ret;
1545 struct msghdr hdr;
1547 g_assert (overlapped == NULL);
1548 g_assert (complete == NULL);
1550 wsabuf_to_msghdr (buffers, count, &hdr);
1551 ret = _wapi_recvmsg (fd, &hdr, *flags);
1552 msghdr_iov_free (&hdr);
1554 if(ret == SOCKET_ERROR) {
1555 return(ret);
1558 *received = ret;
1559 *flags = hdr.msg_flags;
1561 return(0);
1564 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1565 guint32 flags, WapiOverlapped *overlapped,
1566 WapiOverlappedCB *complete)
1568 int ret;
1569 struct msghdr hdr;
1571 g_assert (overlapped == NULL);
1572 g_assert (complete == NULL);
1574 wsabuf_to_msghdr (buffers, count, &hdr);
1575 ret = _wapi_sendmsg (fd, &hdr, flags);
1576 msghdr_iov_free (&hdr);
1578 if(ret == SOCKET_ERROR)
1579 return ret;
1581 *sent = ret;
1582 return 0;