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>
46 #include <netinet/in.h>
47 #include <netinet/tcp.h>
48 #include <arpa/inet.h>
49 #ifdef HAVE_SYS_SENDFILE_H
50 #include <sys/sendfile.h>
57 #define DEBUG(...) g_message(__VA_ARGS__)
62 static guint32 in_cleanup = 0;
64 static void socket_close (gpointer handle, gpointer data);
66 struct _WapiHandleOps _wapi_socket_ops = {
67 socket_close, /* close */
71 NULL, /* special_wait */
75 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
77 static void socket_ops_init (void)
79 /* No capabilities to register */
82 static void socket_close (gpointer handle, gpointer data)
85 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
87 DEBUG ("%s: closing socket handle %p", __func__, handle);
89 /* Shutdown the socket for reading, to interrupt any potential
90 * receives that may be blocking for data. See bug 75705.
92 shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
95 ret = close (GPOINTER_TO_UINT(handle));
96 } while (ret == -1 && errno == EINTR &&
97 !_wapi_thread_cur_apc_pending ());
101 DEBUG ("%s: close error: %s", __func__, strerror (errno));
102 errnum = errno_to_WSA (errnum, __func__);
104 WSASetLastError (errnum);
108 socket_handle->saved_error = 0;
112 cleanup_close (gpointer handle, gpointer data)
114 _wapi_handle_ops_close (handle, NULL);
118 void _wapi_cleanup_networking(void)
120 DEBUG ("%s: cleaning up", __func__);
123 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
127 void WSASetLastError(int error)
129 SetLastError (error);
132 int WSAGetLastError(void)
134 return(GetLastError ());
137 int closesocket(guint32 fd)
139 gpointer handle = GUINT_TO_POINTER (fd);
141 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
142 WSASetLastError (WSAENOTSOCK);
146 _wapi_handle_unref (handle);
150 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
152 gpointer handle = GUINT_TO_POINTER (fd);
154 struct _WapiHandle_socket *socket_handle;
155 struct _WapiHandle_socket new_socket_handle = {0};
159 if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
160 WSASetLastError (WSAEFAULT);
161 return(INVALID_SOCKET);
164 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
165 WSASetLastError (WSAENOTSOCK);
166 return(INVALID_SOCKET);
169 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
170 (gpointer *)&socket_handle);
172 g_warning ("%s: error looking up socket handle %p",
174 WSASetLastError (WSAENOTSOCK);
175 return(INVALID_SOCKET);
179 new_fd = accept (fd, addr, addrlen);
180 } while (new_fd == -1 && errno == EINTR &&
181 !_wapi_thread_cur_apc_pending());
185 DEBUG ("%s: accept error: %s", __func__, strerror(errno));
187 errnum = errno_to_WSA (errnum, __func__);
188 WSASetLastError (errnum);
190 return(INVALID_SOCKET);
193 if (new_fd >= _wapi_fd_reserve) {
194 DEBUG ("%s: File descriptor is too big", __func__);
196 WSASetLastError (WSASYSCALLFAILURE);
200 return(INVALID_SOCKET);
203 new_socket_handle.domain = socket_handle->domain;
204 new_socket_handle.type = socket_handle->type;
205 new_socket_handle.protocol = socket_handle->protocol;
206 new_socket_handle.still_readable = 1;
208 new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
210 if(new_handle == _WAPI_HANDLE_INVALID) {
211 g_warning ("%s: error creating socket handle", __func__);
212 WSASetLastError (ERROR_GEN_FAILURE);
213 return(INVALID_SOCKET);
216 DEBUG ("%s: returning newly accepted socket handle %p with",
217 __func__, new_handle);
222 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
224 gpointer handle = GUINT_TO_POINTER (fd);
227 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
228 WSASetLastError (WSAENOTSOCK);
229 return(SOCKET_ERROR);
232 ret = bind (fd, my_addr, addrlen);
235 DEBUG ("%s: bind error: %s", __func__, strerror(errno));
236 errnum = errno_to_WSA (errnum, __func__);
237 WSASetLastError (errnum);
239 return(SOCKET_ERROR);
244 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
247 gpointer handle = GUINT_TO_POINTER (fd);
248 struct _WapiHandle_socket *socket_handle;
252 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
253 WSASetLastError (WSAENOTSOCK);
254 return(SOCKET_ERROR);
257 if (connect (fd, serv_addr, addrlen) == -1) {
264 if (errno != EINTR) {
265 DEBUG ("%s: connect error: %s", __func__,
268 errnum = errno_to_WSA (errnum, __func__);
269 if (errnum == WSAEINPROGRESS)
270 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
272 WSASetLastError (errnum);
275 * On solaris x86 getsockopt (SO_ERROR) is not set after
276 * connect () fails so we need to save this error.
278 * But don't do this for EWOULDBLOCK (bug 317315)
280 if (errnum != WSAEWOULDBLOCK) {
281 ok = _wapi_lookup_handle (handle,
283 (gpointer *)&socket_handle);
285 /* ECONNRESET means the socket was closed by another thread */
286 /* Async close on mac raises ECONNABORTED. */
287 if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
288 g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
290 socket_handle->saved_error = errnum;
293 return(SOCKET_ERROR);
297 fds.events = MONO_POLLOUT;
298 while (mono_poll (&fds, 1, -1) == -1 &&
299 !_wapi_thread_cur_apc_pending ()) {
300 if (errno != EINTR) {
301 errnum = errno_to_WSA (errno, __func__);
303 DEBUG ("%s: connect poll error: %s",
304 __func__, strerror (errno));
306 WSASetLastError (errnum);
307 return(SOCKET_ERROR);
311 len = sizeof(so_error);
312 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
314 errnum = errno_to_WSA (errno, __func__);
316 DEBUG ("%s: connect getsockopt error: %s",
317 __func__, strerror (errno));
319 WSASetLastError (errnum);
320 return(SOCKET_ERROR);
324 errnum = errno_to_WSA (so_error, __func__);
326 /* Need to save this socket error */
327 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
328 (gpointer *)&socket_handle);
330 g_warning ("%s: error looking up socket handle %p", __func__, handle);
332 socket_handle->saved_error = errnum;
335 DEBUG ("%s: connect getsockopt returned error: %s",
336 __func__, strerror (so_error));
338 WSASetLastError (errnum);
339 return(SOCKET_ERROR);
346 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
348 gpointer handle = GUINT_TO_POINTER (fd);
351 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
352 WSASetLastError (WSAENOTSOCK);
353 return(SOCKET_ERROR);
356 ret = getpeername (fd, name, namelen);
359 DEBUG ("%s: getpeername error: %s", __func__,
362 errnum = errno_to_WSA (errnum, __func__);
363 WSASetLastError (errnum);
365 return(SOCKET_ERROR);
371 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
373 gpointer handle = GUINT_TO_POINTER (fd);
376 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
377 WSASetLastError (WSAENOTSOCK);
378 return(SOCKET_ERROR);
381 ret = getsockname (fd, name, namelen);
384 DEBUG ("%s: getsockname error: %s", __func__,
387 errnum = errno_to_WSA (errnum, __func__);
388 WSASetLastError (errnum);
390 return(SOCKET_ERROR);
396 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
399 gpointer handle = GUINT_TO_POINTER (fd);
403 struct _WapiHandle_socket *socket_handle;
406 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
407 WSASetLastError (WSAENOTSOCK);
408 return(SOCKET_ERROR);
412 if (level == SOL_SOCKET &&
413 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
415 *optlen = sizeof (tv);
418 ret = getsockopt (fd, level, optname, tmp_val, optlen);
421 DEBUG ("%s: getsockopt error: %s", __func__,
424 errnum = errno_to_WSA (errnum, __func__);
425 WSASetLastError (errnum);
427 return(SOCKET_ERROR);
430 if (level == SOL_SOCKET &&
431 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
432 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro
433 *optlen = sizeof (int);
436 if (optname == SO_ERROR) {
437 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
438 (gpointer *)&socket_handle);
440 g_warning ("%s: error looking up socket handle %p",
443 /* can't extract the last error */
444 *((int *) optval) = errno_to_WSA (*((int *)optval),
447 if (*((int *)optval) != 0) {
448 *((int *) optval) = errno_to_WSA (*((int *)optval),
450 socket_handle->saved_error = *((int *)optval);
452 *((int *)optval) = socket_handle->saved_error;
460 int _wapi_listen(guint32 fd, int backlog)
462 gpointer handle = GUINT_TO_POINTER (fd);
465 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
466 WSASetLastError (WSAENOTSOCK);
467 return(SOCKET_ERROR);
470 ret = listen (fd, backlog);
473 DEBUG ("%s: listen error: %s", __func__, strerror (errno));
475 errnum = errno_to_WSA (errnum, __func__);
476 WSASetLastError (errnum);
478 return(SOCKET_ERROR);
484 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
486 return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
489 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
490 struct sockaddr *from, socklen_t *fromlen)
492 gpointer handle = GUINT_TO_POINTER (fd);
493 struct _WapiHandle_socket *socket_handle;
497 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
498 WSASetLastError (WSAENOTSOCK);
499 return(SOCKET_ERROR);
503 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
504 } while (ret == -1 && errno == EINTR &&
505 !_wapi_thread_cur_apc_pending ());
507 if (ret == 0 && len > 0) {
508 /* According to the Linux man page, recvfrom only
509 * returns 0 when the socket has been shut down
510 * cleanly. Turn this into an EINTR to simulate win32
511 * behaviour of returning EINTR when a socket is
512 * closed while the recvfrom is blocking (we use a
513 * shutdown() in socket_close() to trigger this.) See
516 /* Distinguish between the socket being shut down at
517 * the local or remote ends, and reads that request 0
521 /* If this returns FALSE, it means the socket has been
522 * closed locally. If it returns TRUE, but
523 * still_readable != 1 then shutdown
524 * (SHUT_RD|SHUT_RDWR) has been called locally.
526 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
527 (gpointer *)&socket_handle);
528 if (ok == FALSE || socket_handle->still_readable != 1) {
536 DEBUG ("%s: recv error: %s", __func__, strerror(errno));
538 errnum = errno_to_WSA (errnum, __func__);
539 WSASetLastError (errnum);
541 return(SOCKET_ERROR);
547 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
549 gpointer handle = GUINT_TO_POINTER (fd);
550 struct _WapiHandle_socket *socket_handle;
554 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
555 WSASetLastError (WSAENOTSOCK);
556 return(SOCKET_ERROR);
560 ret = recvmsg (fd, msg, recv_flags);
561 } while (ret == -1 && errno == EINTR &&
562 !_wapi_thread_cur_apc_pending ());
565 /* see _wapi_recvfrom */
566 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
567 (gpointer *)&socket_handle);
568 if (ok == FALSE || socket_handle->still_readable != 1) {
576 DEBUG ("%s: recvmsg error: %s", __func__, strerror(errno));
578 errnum = errno_to_WSA (errnum, __func__);
579 WSASetLastError (errnum);
581 return(SOCKET_ERROR);
586 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
588 gpointer handle = GUINT_TO_POINTER (fd);
591 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
592 WSASetLastError (WSAENOTSOCK);
593 return(SOCKET_ERROR);
597 ret = send (fd, msg, len, send_flags);
598 } while (ret == -1 && errno == EINTR &&
599 !_wapi_thread_cur_apc_pending ());
603 DEBUG ("%s: send error: %s", __func__, strerror (errno));
606 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
607 * a blocking socket. See bug #599488 */
608 if (errnum == EAGAIN) {
609 ret = fcntl (fd, F_GETFL, 0);
610 if (ret != -1 && (ret & O_NONBLOCK) == 0)
613 #endif /* O_NONBLOCK */
614 errnum = errno_to_WSA (errnum, __func__);
615 WSASetLastError (errnum);
617 return(SOCKET_ERROR);
622 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
623 const struct sockaddr *to, socklen_t tolen)
625 gpointer handle = GUINT_TO_POINTER (fd);
628 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
629 WSASetLastError (WSAENOTSOCK);
630 return(SOCKET_ERROR);
634 ret = sendto (fd, msg, len, send_flags, to, tolen);
635 } while (ret == -1 && errno == EINTR &&
636 !_wapi_thread_cur_apc_pending ());
640 DEBUG ("%s: send error: %s", __func__, strerror (errno));
642 errnum = errno_to_WSA (errnum, __func__);
643 WSASetLastError (errnum);
645 return(SOCKET_ERROR);
651 _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags)
653 gpointer handle = GUINT_TO_POINTER (fd);
656 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
657 WSASetLastError (WSAENOTSOCK);
658 return(SOCKET_ERROR);
662 ret = sendmsg (fd, msg, send_flags);
663 } while (ret == -1 && errno == EINTR &&
664 !_wapi_thread_cur_apc_pending ());
668 DEBUG ("%s: sendmsg error: %s", __func__, strerror (errno));
670 errnum = errno_to_WSA (errnum, __func__);
671 WSASetLastError (errnum);
673 return(SOCKET_ERROR);
678 int _wapi_setsockopt(guint32 fd, int level, int optname,
679 const void *optval, socklen_t optlen)
681 gpointer handle = GUINT_TO_POINTER (fd);
684 #if defined (__linux__)
685 /* This has its address taken so it cannot be moved to the if block which uses it */
690 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
691 WSASetLastError (WSAENOTSOCK);
692 return(SOCKET_ERROR);
696 if (level == SOL_SOCKET &&
697 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
698 int ms = *((int *) optval);
699 tv.tv_sec = ms / 1000;
700 tv.tv_usec = (ms % 1000) * 1000; // micro from milli
702 optlen = sizeof (tv);
704 #if defined (__linux__)
705 else if (level == SOL_SOCKET &&
706 (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
707 /* According to socket(7) the Linux kernel doubles the
708 * buffer sizes "to allow space for bookkeeping
711 bufsize = *((int *) optval);
718 ret = setsockopt (fd, level, optname, tmp_val, optlen);
721 DEBUG ("%s: setsockopt error: %s", __func__,
724 errnum = errno_to_WSA (errnum, __func__);
725 WSASetLastError (errnum);
727 return(SOCKET_ERROR);
730 #if defined (SO_REUSEPORT)
731 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
732 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
734 socklen_t type_len = sizeof (type);
736 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
737 if (type == SOCK_DGRAM || type == SOCK_STREAM)
738 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
746 int _wapi_shutdown(guint32 fd, int how)
748 struct _WapiHandle_socket *socket_handle;
750 gpointer handle = GUINT_TO_POINTER (fd);
753 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
754 WSASetLastError (WSAENOTSOCK);
755 return(SOCKET_ERROR);
758 if (how == SHUT_RD ||
760 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
761 (gpointer *)&socket_handle);
763 g_warning ("%s: error looking up socket handle %p",
765 WSASetLastError (WSAENOTSOCK);
766 return(SOCKET_ERROR);
769 socket_handle->still_readable = 0;
772 ret = shutdown (fd, how);
775 DEBUG ("%s: shutdown error: %s", __func__,
778 errnum = errno_to_WSA (errnum, __func__);
779 WSASetLastError (errnum);
781 return(SOCKET_ERROR);
787 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
788 guint32 unused2, guint32 unused3)
790 struct _WapiHandle_socket socket_handle = {0};
794 socket_handle.domain = domain;
795 socket_handle.type = type;
796 socket_handle.protocol = protocol;
797 socket_handle.still_readable = 1;
799 fd = socket (domain, type, protocol);
800 if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
802 /* Retry with protocol == 4 (see bug #54565) */
803 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
804 socket_handle.protocol = 4;
805 fd = socket (AF_INET, SOCK_RAW, 4);
810 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
811 errnum = errno_to_WSA (errnum, __func__);
812 WSASetLastError (errnum);
814 return(INVALID_SOCKET);
817 if (fd >= _wapi_fd_reserve) {
818 DEBUG ("%s: File descriptor is too big (%d >= %d)",
819 __func__, fd, _wapi_fd_reserve);
821 WSASetLastError (WSASYSCALLFAILURE);
824 return(INVALID_SOCKET);
827 /* .net seems to set this by default for SOCK_STREAM, not for
828 * SOCK_DGRAM (see bug #36322)
829 * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
831 * It seems winsock has a rather different idea of what
832 * SO_REUSEADDR means. If it's set, then a new socket can be
833 * bound over an existing listening socket. There's a new
834 * windows-specific option called SO_EXCLUSIVEADDRUSE but
835 * using that means the socket MUST be closed properly, or a
836 * denial of service can occur. Luckily for us, winsock
837 * behaves as though any other system would when SO_REUSEADDR
838 * is true, so we don't need to do anything else here. See
840 * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
845 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
850 DEBUG ("%s: Error setting SO_REUSEADDR", __func__);
852 errnum = errno_to_WSA (errnum, __func__);
853 WSASetLastError (errnum);
857 return(INVALID_SOCKET);
862 mono_once (&socket_ops_once, socket_ops_init);
864 handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
865 if (handle == _WAPI_HANDLE_INVALID) {
866 g_warning ("%s: error creating socket handle", __func__);
867 WSASetLastError (WSASYSCALLFAILURE);
869 return(INVALID_SOCKET);
872 DEBUG ("%s: returning socket handle %p", __func__, handle);
877 static gboolean socket_disconnect (guint32 fd)
879 struct _WapiHandle_socket *socket_handle;
881 gpointer handle = GUINT_TO_POINTER (fd);
884 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
885 (gpointer *)&socket_handle);
887 g_warning ("%s: error looking up socket handle %p", __func__,
889 WSASetLastError (WSAENOTSOCK);
893 newsock = socket (socket_handle->domain, socket_handle->type,
894 socket_handle->protocol);
898 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
900 errnum = errno_to_WSA (errnum, __func__);
901 WSASetLastError (errnum);
906 /* According to Stevens "Advanced Programming in the UNIX
907 * Environment: UNIX File I/O" dup2() is atomic so there
908 * should not be a race condition between the old fd being
909 * closed and the new socket fd being copied over
912 ret = dup2 (newsock, fd);
913 } while (ret == -1 && errno == EAGAIN);
918 DEBUG ("%s: dup2 error: %s", __func__, strerror (errno));
920 errnum = errno_to_WSA (errnum, __func__);
921 WSASetLastError (errnum);
931 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
932 guint32 flags, guint32 reserved)
934 DEBUG ("%s: called on socket %d!", __func__, fd);
937 WSASetLastError (WSAEINVAL);
941 /* We could check the socket type here and fail unless its
942 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
943 * if we really wanted to
946 return(socket_disconnect (fd));
949 #define SF_BUFFER_SIZE 16384
951 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
953 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
954 gint file = GPOINTER_TO_INT (fd);
960 n = fstat (file, &statbuf);
963 errnum = errno_to_WSA (errnum, __func__);
964 WSASetLastError (errnum);
969 res = sendfile (socket, file, NULL, statbuf.st_size);
970 #elif defined(DARWIN)
971 /* TODO: header/tail could be sent in the 5th argument */
972 /* TODO: Might not send the entire file for non-blocking sockets */
973 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
975 } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
978 errnum = errno_to_WSA (errnum, __func__);
979 WSASetLastError (errnum);
983 /* Default implementation */
984 gint file = GPOINTER_TO_INT (fd);
988 buffer = g_malloc (SF_BUFFER_SIZE);
991 n = read (file, buffer, SF_BUFFER_SIZE);
992 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
997 return 0; /* We're done reading */
1000 n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1001 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1005 gint errnum = errno;
1006 errnum = errno_to_WSA (errnum, __func__);
1007 WSASetLastError (errnum);
1009 return SOCKET_ERROR;
1017 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1018 WapiTransmitFileBuffers *buffers, guint32 flags)
1020 gpointer sock = GUINT_TO_POINTER (socket);
1023 if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1024 WSASetLastError (WSAENOTSOCK);
1028 /* Write the header */
1029 if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1030 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1031 if (ret == SOCKET_ERROR)
1035 ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1036 if (ret == SOCKET_ERROR)
1039 /* Write the tail */
1040 if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1041 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1042 if (ret == SOCKET_ERROR)
1046 if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1047 closesocket (socket);
1056 } extension_functions[] = {
1057 {WSAID_DISCONNECTEX, wapi_disconnectex},
1058 {WSAID_TRANSMITFILE, TransmitFile},
1063 WSAIoctl (guint32 fd, gint32 command,
1064 gchar *input, gint i_len,
1065 gchar *output, gint o_len, glong *written,
1066 void *unused1, void *unused2)
1068 gpointer handle = GUINT_TO_POINTER (fd);
1070 gchar *buffer = NULL;
1072 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1073 WSASetLastError (WSAENOTSOCK);
1074 return SOCKET_ERROR;
1077 if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1079 WapiGuid *guid = (WapiGuid *)input;
1081 if (i_len < sizeof(WapiGuid)) {
1082 /* As far as I can tell, windows doesn't
1083 * actually set an error here...
1085 WSASetLastError (WSAEINVAL);
1086 return(SOCKET_ERROR);
1089 if (o_len < sizeof(gpointer)) {
1091 WSASetLastError (WSAEINVAL);
1092 return(SOCKET_ERROR);
1095 if (output == NULL) {
1097 WSASetLastError (WSAEINVAL);
1098 return(SOCKET_ERROR);
1101 while(extension_functions[i].func != NULL) {
1102 if (!memcmp (guid, &extension_functions[i].guid,
1103 sizeof(WapiGuid))) {
1104 memcpy (output, &extension_functions[i].func,
1106 *written = sizeof(gpointer);
1113 WSASetLastError (WSAEINVAL);
1114 return(SOCKET_ERROR);
1117 if (command == SIO_KEEPALIVE_VALS) {
1119 uint32_t keepalivetime;
1120 uint32_t keepaliveinterval;
1122 if (i_len < (3 * sizeof (uint32_t))) {
1123 WSASetLastError (WSAEINVAL);
1124 return SOCKET_ERROR;
1126 memcpy (&onoff, input, sizeof (uint32_t));
1127 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1128 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1129 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1131 gint errnum = errno;
1132 errnum = errno_to_WSA (errnum, __func__);
1133 WSASetLastError (errnum);
1134 return SOCKET_ERROR;
1137 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1138 /* Values are in ms, but we need s */
1141 /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1142 rem = keepalivetime % 1000;
1143 keepalivetime /= 1000;
1144 if (keepalivetime == 0 || rem >= 500)
1146 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1148 rem = keepaliveinterval % 1000;
1149 keepaliveinterval /= 1000;
1150 if (keepaliveinterval == 0 || rem >= 500)
1151 keepaliveinterval++;
1152 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1155 gint errnum = errno;
1156 errnum = errno_to_WSA (errnum, __func__);
1157 WSASetLastError (errnum);
1158 return SOCKET_ERROR;
1167 buffer = g_memdup (input, i_len);
1170 ret = ioctl (fd, command, buffer);
1172 gint errnum = errno;
1173 DEBUG("%s: WSAIoctl error: %s", __func__,
1176 errnum = errno_to_WSA (errnum, __func__);
1177 WSASetLastError (errnum);
1180 return(SOCKET_ERROR);
1183 if (buffer == NULL) {
1186 /* We just copy the buffer to the output. Some ioctls
1187 * don't even output any data, but, well...
1189 * NB windows returns WSAEFAULT if o_len is too small
1191 i_len = (i_len > o_len) ? o_len : i_len;
1193 if (i_len > 0 && output != NULL) {
1194 memcpy (output, buffer, i_len);
1204 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1205 int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
1207 gpointer handle = GUINT_TO_POINTER (fd);
1210 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1211 WSASetLastError (WSAENOTSOCK);
1212 return(SOCKET_ERROR);
1218 /* This works better than ioctl(...FIONBIO...)
1219 * on Linux (it causes connect to return
1220 * EINPROGRESS, but the ioctl doesn't seem to)
1222 ret = fcntl(fd, F_GETFL, 0);
1224 if (*(gboolean *)arg) {
1229 ret = fcntl(fd, F_SETFL, ret);
1232 #endif /* O_NONBLOCK */
1233 /* Unused in Mono */
1235 ret = ioctl (fd, command, arg);
1240 #if defined (PLATFORM_MACOSX)
1242 // ioctl (fd, FIONREAD, XXX) returns the size of
1243 // the UDP header as well on
1246 // Use getsockopt SO_NREAD instead to get the
1247 // right values for TCP and UDP.
1249 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1250 // be the value of the ip buffer.
1252 socklen_t optlen = sizeof (int);
1253 ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1255 ret = ioctl (fd, command, arg);
1260 WSASetLastError (WSAEINVAL);
1261 return(SOCKET_ERROR);
1265 gint errnum = errno;
1266 DEBUG ("%s: ioctl error: %s", __func__, strerror (errno));
1268 errnum = errno_to_WSA (errnum, __func__);
1269 WSASetLastError (errnum);
1271 return(SOCKET_ERROR);
1277 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1278 fd_set *exceptfds, struct timeval *timeout)
1282 for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1283 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1284 (writefds && FD_ISSET (maxfd, writefds)) ||
1285 (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1291 WSASetLastError (WSAEINVAL);
1292 return(SOCKET_ERROR);
1296 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1298 } while (ret == -1 && errno == EINTR &&
1299 !_wapi_thread_cur_apc_pending ());
1302 gint errnum = errno;
1303 DEBUG ("%s: select error: %s", __func__, strerror (errno));
1304 errnum = errno_to_WSA (errnum, __func__);
1305 WSASetLastError (errnum);
1307 return(SOCKET_ERROR);
1313 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1315 gpointer handle = GUINT_TO_POINTER (fd);
1317 if (fd >= FD_SETSIZE) {
1318 WSASetLastError (WSAEINVAL);
1322 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1323 WSASetLastError (WSAENOTSOCK);
1330 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1332 gpointer handle = GUINT_TO_POINTER (fd);
1334 if (fd >= FD_SETSIZE) {
1335 WSASetLastError (WSAEINVAL);
1339 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1340 WSASetLastError (WSAENOTSOCK);
1344 return(FD_ISSET (fd, set));
1347 void _wapi_FD_SET(guint32 fd, fd_set *set)
1349 gpointer handle = GUINT_TO_POINTER (fd);
1351 if (fd >= FD_SETSIZE) {
1352 WSASetLastError (WSAEINVAL);
1356 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1357 WSASetLastError (WSAENOTSOCK);
1366 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1370 memset (hdr, 0, sizeof (struct msghdr));
1371 hdr->msg_iovlen = count;
1372 hdr->msg_iov = g_new0 (struct iovec, count);
1373 for (i = 0; i < count; i++) {
1374 hdr->msg_iov [i].iov_base = buffers [i].buf;
1375 hdr->msg_iov [i].iov_len = buffers [i].len;
1380 msghdr_iov_free (struct msghdr *hdr)
1382 g_free (hdr->msg_iov);
1385 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1386 guint32 *flags, WapiOverlapped *overlapped,
1387 WapiOverlappedCB *complete)
1392 g_assert (overlapped == NULL);
1393 g_assert (complete == NULL);
1395 wsabuf_to_msghdr (buffers, count, &hdr);
1396 ret = _wapi_recvmsg (fd, &hdr, *flags);
1397 msghdr_iov_free (&hdr);
1399 if(ret == SOCKET_ERROR) {
1404 *flags = hdr.msg_flags;
1409 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1410 guint32 flags, WapiOverlapped *overlapped,
1411 WapiOverlappedCB *complete)
1416 g_assert (overlapped == NULL);
1417 g_assert (complete == NULL);
1419 wsabuf_to_msghdr (buffers, count, &hdr);
1420 ret = _wapi_sendmsg (fd, &hdr, flags);
1421 msghdr_iov_free (&hdr);
1423 if(ret == SOCKET_ERROR)
1430 #endif /* ifndef DISABLE_SOCKETS */