2 * sockets.c: Socket handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
12 #ifndef DISABLE_SOCKETS
18 #include <sys/types.h>
19 #include <sys/socket.h>
23 #ifdef HAVE_SYS_IOCTL_H
24 # include <sys/ioctl.h>
26 #ifdef HAVE_SYS_FILIO_H
27 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
29 #ifdef HAVE_SYS_SOCKIO_H
30 #include <sys/sockio.h> /* defines SIOCATMARK */
35 #ifndef HAVE_MSG_NOSIGNAL
39 #include <mono/io-layer/wapi.h>
40 #include <mono/io-layer/wapi-private.h>
41 #include <mono/io-layer/socket-private.h>
42 #include <mono/io-layer/handles-private.h>
43 #include <mono/io-layer/socket-wrappers.h>
44 #include <mono/utils/mono-poll.h>
45 #include <mono/utils/mono-once.h>
47 #include <netinet/in.h>
48 #include <netinet/tcp.h>
49 #include <arpa/inet.h>
50 #ifdef HAVE_SYS_SENDFILE_H
51 #include <sys/sendfile.h>
58 #define DEBUG(...) g_message(__VA_ARGS__)
63 static guint32 in_cleanup = 0;
65 static void socket_close (gpointer handle, gpointer data);
67 struct _WapiHandleOps _wapi_socket_ops = {
68 socket_close, /* close */
72 NULL, /* special_wait */
76 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
78 static void socket_ops_init (void)
80 /* No capabilities to register */
83 static void socket_close (gpointer handle, gpointer data)
86 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
88 DEBUG ("%s: closing socket handle %p", __func__, handle);
90 /* Shutdown the socket for reading, to interrupt any potential
91 * receives that may be blocking for data. See bug 75705.
93 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
96 ret = close (GPOINTER_TO_UINT(handle));
97 } while (ret == -1 && errno == EINTR &&
98 !_wapi_thread_cur_apc_pending ());
102 DEBUG ("%s: close error: %s", __func__, strerror (errno));
103 errnum = errno_to_WSA (errnum, __func__);
105 WSASetLastError (errnum);
109 socket_handle->saved_error = 0;
113 cleanup_close (gpointer handle, gpointer data)
115 _wapi_handle_ops_close (handle, NULL);
119 void _wapi_cleanup_networking(void)
121 DEBUG ("%s: cleaning up", __func__);
124 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
128 void WSASetLastError(int error)
130 SetLastError (error);
133 int WSAGetLastError(void)
135 return(GetLastError ());
138 int closesocket(guint32 fd)
140 gpointer handle = GUINT_TO_POINTER (fd);
142 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
143 WSASetLastError (WSAENOTSOCK);
147 _wapi_handle_unref (handle);
151 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
153 gpointer handle = GUINT_TO_POINTER (fd);
155 struct _WapiHandle_socket *socket_handle;
156 struct _WapiHandle_socket new_socket_handle = {0};
160 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
161 WSASetLastError (WSAEFAULT);
162 return(INVALID_SOCKET);
165 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
166 WSASetLastError (WSAENOTSOCK);
167 return(INVALID_SOCKET);
170 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
171 (gpointer *)&socket_handle);
173 g_warning ("%s: error looking up socket handle %p",
175 WSASetLastError (WSAENOTSOCK);
176 return(INVALID_SOCKET);
180 new_fd = accept (fd, addr, addrlen);
181 } while (new_fd == -1 && errno == EINTR &&
182 !_wapi_thread_cur_apc_pending());
186 DEBUG ("%s: accept error: %s", __func__, strerror(errno));
188 errnum = errno_to_WSA (errnum, __func__);
189 WSASetLastError (errnum);
191 return(INVALID_SOCKET);
194 if (new_fd >= _wapi_fd_reserve) {
195 DEBUG ("%s: File descriptor is too big", __func__);
197 WSASetLastError (WSASYSCALLFAILURE);
201 return(INVALID_SOCKET);
204 new_socket_handle.domain = socket_handle->domain;
205 new_socket_handle.type = socket_handle->type;
206 new_socket_handle.protocol = socket_handle->protocol;
207 new_socket_handle.still_readable = 1;
209 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
211 if(new_handle == _WAPI_HANDLE_INVALID) {
212 g_warning ("%s: error creating socket handle", __func__);
213 WSASetLastError (ERROR_GEN_FAILURE);
214 return(INVALID_SOCKET);
217 DEBUG ("%s: returning newly accepted socket handle %p with",
218 __func__, new_handle);
223 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
225 gpointer handle = GUINT_TO_POINTER (fd);
228 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
229 WSASetLastError (WSAENOTSOCK);
230 return(SOCKET_ERROR);
233 ret = bind (fd, my_addr, addrlen);
236 DEBUG ("%s: bind error: %s", __func__, strerror(errno));
237 errnum = errno_to_WSA (errnum, __func__);
238 WSASetLastError (errnum);
240 return(SOCKET_ERROR);
245 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
248 gpointer handle = GUINT_TO_POINTER (fd);
249 struct _WapiHandle_socket *socket_handle;
253 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
254 WSASetLastError (WSAENOTSOCK);
255 return(SOCKET_ERROR);
258 if (connect (fd, serv_addr, addrlen) == -1) {
265 if (errno != EINTR) {
266 DEBUG ("%s: connect error: %s", __func__,
269 errnum = errno_to_WSA (errnum, __func__);
270 if (errnum == WSAEINPROGRESS)
271 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
273 WSASetLastError (errnum);
276 * On solaris x86 getsockopt (SO_ERROR) is not set after
277 * connect () fails so we need to save this error.
279 * But don't do this for EWOULDBLOCK (bug 317315)
281 if (errnum != WSAEWOULDBLOCK) {
282 ok = _wapi_lookup_handle (handle,
284 (gpointer *)&socket_handle);
286 /* ECONNRESET means the socket was closed by another thread */
287 /* Async close on mac raises ECONNABORTED. */
288 if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
289 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
291 socket_handle->saved_error = errnum;
294 return(SOCKET_ERROR);
298 fds.events = MONO_POLLOUT;
299 while (mono_poll (&fds, 1, -1) == -1 &&
300 !_wapi_thread_cur_apc_pending ()) {
301 if (errno != EINTR) {
302 errnum = errno_to_WSA (errno, __func__);
304 DEBUG ("%s: connect poll error: %s",
305 __func__, strerror (errno));
307 WSASetLastError (errnum);
308 return(SOCKET_ERROR);
312 len = sizeof(so_error);
313 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
315 errnum = errno_to_WSA (errno, __func__);
317 DEBUG ("%s: connect getsockopt error: %s",
318 __func__, strerror (errno));
320 WSASetLastError (errnum);
321 return(SOCKET_ERROR);
325 errnum = errno_to_WSA (so_error, __func__);
327 /* Need to save this socket error */
328 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
329 (gpointer *)&socket_handle);
331 g_warning ("%s: error looking up socket handle %p", __func__, handle);
333 socket_handle->saved_error = errnum;
336 DEBUG ("%s: connect getsockopt returned error: %s",
337 __func__, strerror (so_error));
339 WSASetLastError (errnum);
340 return(SOCKET_ERROR);
347 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
349 gpointer handle = GUINT_TO_POINTER (fd);
352 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
353 WSASetLastError (WSAENOTSOCK);
354 return(SOCKET_ERROR);
357 ret = getpeername (fd, name, namelen);
360 DEBUG ("%s: getpeername error: %s", __func__,
363 errnum = errno_to_WSA (errnum, __func__);
364 WSASetLastError (errnum);
366 return(SOCKET_ERROR);
372 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
374 gpointer handle = GUINT_TO_POINTER (fd);
377 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
378 WSASetLastError (WSAENOTSOCK);
379 return(SOCKET_ERROR);
382 ret = getsockname (fd, name, namelen);
385 DEBUG ("%s: getsockname error: %s", __func__,
388 errnum = errno_to_WSA (errnum, __func__);
389 WSASetLastError (errnum);
391 return(SOCKET_ERROR);
397 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
400 gpointer handle = GUINT_TO_POINTER (fd);
404 struct _WapiHandle_socket *socket_handle;
407 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
408 WSASetLastError (WSAENOTSOCK);
409 return(SOCKET_ERROR);
413 if (level == SOL_SOCKET &&
414 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
416 *optlen = sizeof (tv);
419 ret = getsockopt (fd, level, optname, tmp_val, optlen);
422 DEBUG ("%s: getsockopt error: %s", __func__,
425 errnum = errno_to_WSA (errnum, __func__);
426 WSASetLastError (errnum);
428 return(SOCKET_ERROR);
431 if (level == SOL_SOCKET &&
432 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
433 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
434 *optlen = sizeof (int);
437 if (optname == SO_ERROR) {
438 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
439 (gpointer *)&socket_handle);
441 g_warning ("%s: error looking up socket handle %p",
444 /* can't extract the last error */
445 *((int *) optval) = errno_to_WSA (*((int *)optval),
448 if (*((int *)optval) != 0) {
449 *((int *) optval) = errno_to_WSA (*((int *)optval),
451 socket_handle->saved_error = *((int *)optval);
453 *((int *)optval) = socket_handle->saved_error;
461 int _wapi_listen(guint32 fd, int backlog)
463 gpointer handle = GUINT_TO_POINTER (fd);
466 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
467 WSASetLastError (WSAENOTSOCK);
468 return(SOCKET_ERROR);
471 ret = listen (fd, backlog);
474 DEBUG ("%s: listen error: %s", __func__, strerror (errno));
476 errnum = errno_to_WSA (errnum, __func__);
477 WSASetLastError (errnum);
479 return(SOCKET_ERROR);
485 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
487 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
490 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
491 struct sockaddr *from, socklen_t *fromlen)
493 gpointer handle = GUINT_TO_POINTER (fd);
494 struct _WapiHandle_socket *socket_handle;
498 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
499 WSASetLastError (WSAENOTSOCK);
500 return(SOCKET_ERROR);
504 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
505 } while (ret == -1 && errno == EINTR &&
506 !_wapi_thread_cur_apc_pending ());
508 if (ret == 0 && len > 0) {
509 /* According to the Linux man page, recvfrom only
510 * returns 0 when the socket has been shut down
511 * cleanly. Turn this into an EINTR to simulate win32
512 * behaviour of returning EINTR when a socket is
513 * closed while the recvfrom is blocking (we use a
514 * shutdown() in socket_close() to trigger this.) See
517 /* Distinguish between the socket being shut down at
518 * the local or remote ends, and reads that request 0
522 /* If this returns FALSE, it means the socket has been
523 * closed locally. If it returns TRUE, but
524 * still_readable != 1 then shutdown
525 * (SHUT_RD|SHUT_RDWR) has been called locally.
527 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
528 (gpointer *)&socket_handle);
529 if (ok == FALSE || socket_handle->still_readable != 1) {
537 DEBUG ("%s: recv error: %s", __func__, strerror(errno));
539 errnum = errno_to_WSA (errnum, __func__);
540 WSASetLastError (errnum);
542 return(SOCKET_ERROR);
548 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
550 gpointer handle = GUINT_TO_POINTER (fd);
551 struct _WapiHandle_socket *socket_handle;
555 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
556 WSASetLastError (WSAENOTSOCK);
557 return(SOCKET_ERROR);
561 ret = recvmsg (fd, msg, recv_flags);
562 } while (ret == -1 && errno == EINTR &&
563 !_wapi_thread_cur_apc_pending ());
566 /* see _wapi_recvfrom */
567 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
568 (gpointer *)&socket_handle);
569 if (ok == FALSE || socket_handle->still_readable != 1) {
577 DEBUG ("%s: recvmsg error: %s", __func__, strerror(errno));
579 errnum = errno_to_WSA (errnum, __func__);
580 WSASetLastError (errnum);
582 return(SOCKET_ERROR);
587 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
589 gpointer handle = GUINT_TO_POINTER (fd);
592 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
593 WSASetLastError (WSAENOTSOCK);
594 return(SOCKET_ERROR);
598 ret = send (fd, msg, len, send_flags);
599 } while (ret == -1 && errno == EINTR &&
600 !_wapi_thread_cur_apc_pending ());
604 DEBUG ("%s: send error: %s", __func__, strerror (errno));
607 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
608 * a blocking socket. See bug #599488 */
609 if (errnum == EAGAIN) {
610 ret = fcntl (fd, F_GETFL, 0);
611 if (ret != -1 && (ret & O_NONBLOCK) == 0)
614 #endif /* O_NONBLOCK */
615 errnum = errno_to_WSA (errnum, __func__);
616 WSASetLastError (errnum);
618 return(SOCKET_ERROR);
623 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
624 const struct sockaddr *to, socklen_t tolen)
626 gpointer handle = GUINT_TO_POINTER (fd);
629 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
630 WSASetLastError (WSAENOTSOCK);
631 return(SOCKET_ERROR);
635 ret = sendto (fd, msg, len, send_flags, to, tolen);
636 } while (ret == -1 && errno == EINTR &&
637 !_wapi_thread_cur_apc_pending ());
641 DEBUG ("%s: send error: %s", __func__, strerror (errno));
643 errnum = errno_to_WSA (errnum, __func__);
644 WSASetLastError (errnum);
646 return(SOCKET_ERROR);
652 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
654 gpointer handle = GUINT_TO_POINTER (fd);
657 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
658 WSASetLastError (WSAENOTSOCK);
659 return(SOCKET_ERROR);
663 ret = sendmsg (fd, msg, send_flags);
664 } while (ret == -1 && errno == EINTR &&
665 !_wapi_thread_cur_apc_pending ());
669 DEBUG ("%s: sendmsg error: %s", __func__, strerror (errno));
671 errnum = errno_to_WSA (errnum, __func__);
672 WSASetLastError (errnum);
674 return(SOCKET_ERROR);
679 int _wapi_setsockopt(guint32 fd, int level, int optname,
680 const void *optval, socklen_t optlen)
682 gpointer handle = GUINT_TO_POINTER (fd);
685 #if defined (__linux__)
686 /* This has its address taken so it cannot be moved to the if block which uses it */
691 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
692 WSASetLastError (WSAENOTSOCK);
693 return(SOCKET_ERROR);
697 if (level == SOL_SOCKET &&
698 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
699 int ms = *((int *) optval);
700 tv.tv_sec = ms / 1000;
701 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
703 optlen = sizeof (tv);
705 #if defined (__linux__)
706 else if (level == SOL_SOCKET &&
707 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
708 /* According to socket(7) the Linux kernel doubles the
709 * buffer sizes "to allow space for bookkeeping
712 bufsize = *((int *) optval);
719 ret = setsockopt (fd, level, optname, tmp_val, optlen);
722 DEBUG ("%s: setsockopt error: %s", __func__,
725 errnum = errno_to_WSA (errnum, __func__);
726 WSASetLastError (errnum);
728 return(SOCKET_ERROR);
731 #if defined (SO_REUSEPORT)
732 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
733 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
735 socklen_t type_len = sizeof (type);
737 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
738 if (type == SOCK_DGRAM || type == SOCK_STREAM)
739 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
747 int _wapi_shutdown(guint32 fd, int how)
749 struct _WapiHandle_socket *socket_handle;
751 gpointer handle = GUINT_TO_POINTER (fd);
754 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
755 WSASetLastError (WSAENOTSOCK);
756 return(SOCKET_ERROR);
759 if (how == SHUT_RD ||
761 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
762 (gpointer *)&socket_handle);
764 g_warning ("%s: error looking up socket handle %p",
766 WSASetLastError (WSAENOTSOCK);
767 return(SOCKET_ERROR);
770 socket_handle->still_readable = 0;
773 ret = shutdown (fd, how);
776 DEBUG ("%s: shutdown error: %s", __func__,
779 errnum = errno_to_WSA (errnum, __func__);
780 WSASetLastError (errnum);
782 return(SOCKET_ERROR);
788 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
789 guint32 unused2, guint32 unused3)
791 struct _WapiHandle_socket socket_handle = {0};
795 socket_handle.domain = domain;
796 socket_handle.type = type;
797 socket_handle.protocol = protocol;
798 socket_handle.still_readable = 1;
800 fd = socket (domain, type, protocol);
801 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
803 /* Retry with protocol == 4 (see bug #54565) */
804 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
805 socket_handle.protocol = 4;
806 fd = socket (AF_INET, SOCK_RAW, 4);
811 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
812 errnum = errno_to_WSA (errnum, __func__);
813 WSASetLastError (errnum);
815 return(INVALID_SOCKET);
818 if (fd >= _wapi_fd_reserve) {
819 DEBUG ("%s: File descriptor is too big (%d >= %d)",
820 __func__, fd, _wapi_fd_reserve);
822 WSASetLastError (WSASYSCALLFAILURE);
825 return(INVALID_SOCKET);
828 /* .net seems to set this by default for SOCK_STREAM, not for
829 * SOCK_DGRAM (see bug #36322)
830 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
832 * It seems winsock has a rather different idea of what
833 * SO_REUSEADDR means. If it's set, then a new socket can be
834 * bound over an existing listening socket. There's a new
835 * windows-specific option called SO_EXCLUSIVEADDRUSE but
836 * using that means the socket MUST be closed properly, or a
837 * denial of service can occur. Luckily for us, winsock
838 * behaves as though any other system would when SO_REUSEADDR
839 * is true, so we don't need to do anything else here. See
841 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
846 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true_,
851 DEBUG ("%s: Error setting SO_REUSEADDR", __func__);
853 errnum = errno_to_WSA (errnum, __func__);
854 WSASetLastError (errnum);
858 return(INVALID_SOCKET);
863 mono_once (&socket_ops_once, socket_ops_init);
865 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
866 if (handle == _WAPI_HANDLE_INVALID) {
867 g_warning ("%s: error creating socket handle", __func__);
868 WSASetLastError (WSASYSCALLFAILURE);
870 return(INVALID_SOCKET);
873 DEBUG ("%s: returning socket handle %p", __func__, handle);
878 static gboolean socket_disconnect (guint32 fd)
880 struct _WapiHandle_socket *socket_handle;
882 gpointer handle = GUINT_TO_POINTER (fd);
885 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
886 (gpointer *)&socket_handle);
888 g_warning ("%s: error looking up socket handle %p", __func__,
890 WSASetLastError (WSAENOTSOCK);
894 newsock = socket (socket_handle->domain, socket_handle->type,
895 socket_handle->protocol);
899 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
901 errnum = errno_to_WSA (errnum, __func__);
902 WSASetLastError (errnum);
907 /* According to Stevens "Advanced Programming in the UNIX
908 * Environment: UNIX File I/O" dup2() is atomic so there
909 * should not be a race condition between the old fd being
910 * closed and the new socket fd being copied over
913 ret = dup2 (newsock, fd);
914 } while (ret == -1 && errno == EAGAIN);
919 DEBUG ("%s: dup2 error: %s", __func__, strerror (errno));
921 errnum = errno_to_WSA (errnum, __func__);
922 WSASetLastError (errnum);
932 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
933 guint32 flags, guint32 reserved)
935 DEBUG ("%s: called on socket %d!", __func__, fd);
938 WSASetLastError (WSAEINVAL);
942 /* We could check the socket type here and fail unless its
943 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
944 * if we really wanted to
947 return(socket_disconnect (fd));
950 #define SF_BUFFER_SIZE 16384
952 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
954 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
955 gint file = GPOINTER_TO_INT (fd);
961 n = fstat (file, &statbuf);
964 errnum = errno_to_WSA (errnum, __func__);
965 WSASetLastError (errnum);
970 res = sendfile (socket, file, NULL, statbuf.st_size);
971 #elif defined(DARWIN)
972 /* TODO: header/tail could be sent in the 5th argument */
973 /* TODO: Might not send the entire file for non-blocking sockets */
974 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
976 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
979 errnum = errno_to_WSA (errnum, __func__);
980 WSASetLastError (errnum);
984 /* Default implementation */
985 gint file = GPOINTER_TO_INT (fd);
989 buffer = g_malloc (SF_BUFFER_SIZE);
992 n = read (file, buffer, SF_BUFFER_SIZE);
993 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
998 return 0; /* We're done reading */
1001 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1002 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1006 gint errnum = errno;
1007 errnum = errno_to_WSA (errnum, __func__);
1008 WSASetLastError (errnum);
1010 return SOCKET_ERROR;
1018 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1019 WapiTransmitFileBuffers *buffers, guint32 flags)
1021 gpointer sock = GUINT_TO_POINTER (socket);
1024 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1025 WSASetLastError (WSAENOTSOCK);
1029 /* Write the header */
1030 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1031 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1032 if (ret == SOCKET_ERROR)
1036 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1037 if (ret == SOCKET_ERROR)
1040 /* Write the tail */
1041 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1042 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1043 if (ret == SOCKET_ERROR)
1047 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1048 closesocket (socket);
1057 } extension_functions[] = {
1058 {WSAID_DISCONNECTEX, wapi_disconnectex},
1059 {WSAID_TRANSMITFILE, TransmitFile},
1064 WSAIoctl (guint32 fd, gint32 command,
1065 gchar *input, gint i_len,
1066 gchar *output, gint o_len, glong *written,
1067 void *unused1, void *unused2)
1069 gpointer handle = GUINT_TO_POINTER (fd);
1071 gchar *buffer = NULL;
1073 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1074 WSASetLastError (WSAENOTSOCK);
1075 return SOCKET_ERROR;
1078 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1080 WapiGuid *guid = (WapiGuid *)input;
1082 if (i_len < sizeof(WapiGuid)) {
1083 /* As far as I can tell, windows doesn't
1084 * actually set an error here...
1086 WSASetLastError (WSAEINVAL);
1087 return(SOCKET_ERROR);
1090 if (o_len < sizeof(gpointer)) {
1092 WSASetLastError (WSAEINVAL);
1093 return(SOCKET_ERROR);
1096 if (output == NULL) {
1098 WSASetLastError (WSAEINVAL);
1099 return(SOCKET_ERROR);
1102 while(extension_functions[i].func != NULL) {
1103 if (!memcmp (guid, &extension_functions[i].guid,
1104 sizeof(WapiGuid))) {
1105 memcpy (output, &extension_functions[i].func,
1107 *written = sizeof(gpointer);
1114 WSASetLastError (WSAEINVAL);
1115 return(SOCKET_ERROR);
1118 if (command == SIO_KEEPALIVE_VALS) {
1120 uint32_t keepalivetime;
1121 uint32_t keepaliveinterval;
1123 if (i_len < (3 * sizeof (uint32_t))) {
1124 WSASetLastError (WSAEINVAL);
1125 return SOCKET_ERROR;
1127 memcpy (&onoff, input, sizeof (uint32_t));
1128 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1129 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1130 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1132 gint errnum = errno;
1133 errnum = errno_to_WSA (errnum, __func__);
1134 WSASetLastError (errnum);
1135 return SOCKET_ERROR;
1138 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1139 /* Values are in ms, but we need s */
1142 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1143 rem = keepalivetime % 1000;
1144 keepalivetime /= 1000;
1145 if (keepalivetime == 0 || rem >= 500)
1147 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1149 rem = keepaliveinterval % 1000;
1150 keepaliveinterval /= 1000;
1151 if (keepaliveinterval == 0 || rem >= 500)
1152 keepaliveinterval++;
1153 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1156 gint errnum = errno;
1157 errnum = errno_to_WSA (errnum, __func__);
1158 WSASetLastError (errnum);
1159 return SOCKET_ERROR;
1168 buffer = (char *)g_memdup (input, i_len);
1171 ret = ioctl (fd, command, buffer);
1173 gint errnum = errno;
1174 DEBUG("%s: WSAIoctl error: %s", __func__,
1177 errnum = errno_to_WSA (errnum, __func__);
1178 WSASetLastError (errnum);
1181 return(SOCKET_ERROR);
1184 if (buffer == NULL) {
1187 /* We just copy the buffer to the output. Some ioctls
1188 * don't even output any data, but, well...
1190 * NB windows returns WSAEFAULT if o_len is too small
1192 i_len = (i_len > o_len) ? o_len : i_len;
1194 if (i_len > 0 && output != NULL) {
1195 memcpy (output, buffer, i_len);
1205 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1206 int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
1208 gpointer handle = GUINT_TO_POINTER (fd);
1211 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1212 WSASetLastError (WSAENOTSOCK);
1213 return(SOCKET_ERROR);
1219 /* This works better than ioctl(...FIONBIO...)
1220 * on Linux (it causes connect to return
1221 * EINPROGRESS, but the ioctl doesn't seem to)
1223 ret = fcntl(fd, F_GETFL, 0);
1225 if (*(gboolean *)arg) {
1230 ret = fcntl(fd, F_SETFL, ret);
1233 #endif /* O_NONBLOCK */
1234 /* Unused in Mono */
1236 ret = ioctl (fd, command, arg);
1241 #if defined (PLATFORM_MACOSX)
1243 // ioctl (fd, FIONREAD, XXX) returns the size of
1244 // the UDP header as well on
1247 // Use getsockopt SO_NREAD instead to get the
1248 // right values for TCP and UDP.
1250 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1251 // be the value of the ip buffer.
1253 socklen_t optlen = sizeof (int);
1254 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1256 ret = ioctl (fd, command, arg);
1261 WSASetLastError (WSAEINVAL);
1262 return(SOCKET_ERROR);
1266 gint errnum = errno;
1267 DEBUG ("%s: ioctl error: %s", __func__, strerror (errno));
1269 errnum = errno_to_WSA (errnum, __func__);
1270 WSASetLastError (errnum);
1272 return(SOCKET_ERROR);
1278 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1279 fd_set *exceptfds, struct timeval *timeout)
1283 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1284 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1285 (writefds && FD_ISSET (maxfd, writefds)) ||
1286 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1292 WSASetLastError (WSAEINVAL);
1293 return(SOCKET_ERROR);
1297 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1299 } while (ret == -1 && errno == EINTR &&
1300 !_wapi_thread_cur_apc_pending ());
1303 gint errnum = errno;
1304 DEBUG ("%s: select error: %s", __func__, strerror (errno));
1305 errnum = errno_to_WSA (errnum, __func__);
1306 WSASetLastError (errnum);
1308 return(SOCKET_ERROR);
1314 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1316 gpointer handle = GUINT_TO_POINTER (fd);
1318 if (fd >= FD_SETSIZE) {
1319 WSASetLastError (WSAEINVAL);
1323 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1324 WSASetLastError (WSAENOTSOCK);
1331 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1333 gpointer handle = GUINT_TO_POINTER (fd);
1335 if (fd >= FD_SETSIZE) {
1336 WSASetLastError (WSAEINVAL);
1340 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1341 WSASetLastError (WSAENOTSOCK);
1345 return(FD_ISSET (fd, set));
1348 void _wapi_FD_SET(guint32 fd, fd_set *set)
1350 gpointer handle = GUINT_TO_POINTER (fd);
1352 if (fd >= FD_SETSIZE) {
1353 WSASetLastError (WSAEINVAL);
1357 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1358 WSASetLastError (WSAENOTSOCK);
1367 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1371 memset (hdr, 0, sizeof (struct msghdr));
1372 hdr->msg_iovlen = count;
1373 hdr->msg_iov = g_new0 (struct iovec, count);
1374 for (i = 0; i < count; i++) {
1375 hdr->msg_iov [i].iov_base = buffers [i].buf;
1376 hdr->msg_iov [i].iov_len = buffers [i].len;
1381 msghdr_iov_free (struct msghdr *hdr)
1383 g_free (hdr->msg_iov);
1386 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1387 guint32 *flags, WapiOverlapped *overlapped,
1388 WapiOverlappedCB *complete)
1393 g_assert (overlapped == NULL);
1394 g_assert (complete == NULL);
1396 wsabuf_to_msghdr (buffers, count, &hdr);
1397 ret = _wapi_recvmsg (fd, &hdr, *flags);
1398 msghdr_iov_free (&hdr);
1400 if(ret == SOCKET_ERROR) {
1405 *flags = hdr.msg_flags;
1410 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1411 guint32 flags, WapiOverlapped *overlapped,
1412 WapiOverlappedCB *complete)
1417 g_assert (overlapped == NULL);
1418 g_assert (complete == NULL);
1420 wsabuf_to_msghdr (buffers, count, &hdr);
1421 ret = _wapi_sendmsg (fd, &hdr, flags);
1422 msghdr_iov_free (&hdr);
1424 if(ret == SOCKET_ERROR)
1431 #endif /* ifndef DISABLE_SOCKETS */