From e343ad0cfd404c92761cd6e0f683ccd46402897b Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 19 Jan 2017 09:25:55 -0500 Subject: [PATCH] [io-layer] Extract socket (#4241) * [socket] Extract win32 and unix specific code from w32socket.c * [socket] Extract WSAGetLastError and WSASetLastError * [socket] Extract closesocket * [socket] Extract iocltsocket * [socket] Extract socket-wrappers.h functions * [socket] Extract w32handle operations * [socket] Extract WSAIoctl * [socket] Do not use mono_w32socket_ioctl for disconnect * [socket] Extract errno_to_WSA * [socket] Remove redundant mono_w32handle_get_type/mono_w32handle_lookup * [socket] Inline _wapi_* functions * [socket] Make disconnect not rely on mono_w32socket_ioctl * [socket] Remove unused parameters to mono_w32socket_transmit_file * [socket] Refactor calls to mono_w32socket_convert_error * [socket] Remove dead code --- mono/io-layer/Makefile.am | 5 - mono/io-layer/error.c | 125 -- mono/io-layer/error.h | 1 - mono/io-layer/socket-private.h | 30 - mono/io-layer/socket-wrappers.h | 91 - mono/io-layer/sockets.c | 1457 ----------------- mono/io-layer/sockets.h | 100 -- mono/io-layer/uglify.h | 12 - mono/io-layer/wapi-private.h | 1 - mono/io-layer/wapi-remap.h | 6 - mono/io-layer/wapi.c | 2 - mono/io-layer/wapi.h | 1 - mono/metadata/Makefile.am | 10 +- mono/metadata/appdomain.c | 2 +- mono/metadata/icall.c | 2 +- mono/metadata/socket-io-windows-internals.h | 27 - mono/metadata/socket-io.h | 197 --- mono/metadata/threadpool-io.c | 1 + mono/metadata/threadpool-io.h | 1 - mono/metadata/threadpool-worker-default.c | 1 + mono/metadata/threadpool.c | 1 + mono/metadata/w32socket-internals.h | 151 ++ mono/metadata/w32socket-unix.c | 1331 +++++++++++++++ ...{socket-io-windows.c => w32socket-win32.c} | 142 +- mono/metadata/{socket-io.c => w32socket.c} | 425 ++--- mono/metadata/w32socket.h | 281 ++++ mono/mini/debugger-agent.c | 2 +- mono/mini/driver.c | 1 - msvc/libmonoruntime.vcxproj | 8 +- msvc/libmonoruntime.vcxproj.filters | 8 +- msvc/pedump.vcxproj | 2 +- msvc/pedump.vcxproj.filters | 2 +- 32 files changed, 2066 insertions(+), 2360 deletions(-) delete mode 100644 mono/io-layer/socket-private.h delete mode 100644 mono/io-layer/socket-wrappers.h delete mode 100644 mono/io-layer/sockets.c delete mode 100644 mono/io-layer/sockets.h delete mode 100644 mono/metadata/socket-io-windows-internals.h delete mode 100644 mono/metadata/socket-io.h create mode 100644 mono/metadata/w32socket-internals.h create mode 100644 mono/metadata/w32socket-unix.c rename mono/metadata/{socket-io-windows.c => w32socket-win32.c} (61%) rename mono/metadata/{socket-io.c => w32socket.c} (85%) create mode 100644 mono/metadata/w32socket.h diff --git a/mono/io-layer/Makefile.am b/mono/io-layer/Makefile.am index c0f5119c006..2247a51a71c 100644 --- a/mono/io-layer/Makefile.am +++ b/mono/io-layer/Makefile.am @@ -16,7 +16,6 @@ OTHER_H = \ io-trace.h \ io-layer.h \ io-portability.h \ - sockets.h \ uglify.h \ wapi.h \ wapi-remap.h @@ -32,10 +31,6 @@ OTHER_SRC = \ io-layer.h \ locking.c \ posix.c \ - sockets.c \ - sockets.h \ - socket-private.h \ - socket-wrappers.h \ uglify.h \ wapi_glob.h \ wapi_glob.c \ diff --git a/mono/io-layer/error.c b/mono/io-layer/error.c index bc884c3d8d9..5b1b22d6dcd 100644 --- a/mono/io-layer/error.c +++ b/mono/io-layer/error.c @@ -81,131 +81,6 @@ void SetLastError(guint32 code) g_assert (ret == 0); } -guint32 -errno_to_WSA (guint32 code, const gchar *function_name) -{ - gint result = -1; - char *sys_error; - gchar *msg; - - switch (code) { - case 0: result = ERROR_SUCCESS; break; - case EACCES: result = WSAEACCES; break; -#ifdef EADDRINUSE - case EADDRINUSE: result = WSAEADDRINUSE; break; -#endif -#ifdef EAFNOSUPPORT - case EAFNOSUPPORT: result = WSAEAFNOSUPPORT; break; -#endif -#if EAGAIN != EWOULDBLOCK - case EAGAIN: result = WSAEWOULDBLOCK; break; -#endif -#ifdef EALREADY - case EALREADY: result = WSAEALREADY; break; -#endif - case EBADF: result = WSAENOTSOCK; break; -#ifdef ECONNABORTED - case ECONNABORTED: result = WSAENETDOWN; break; -#endif -#ifdef ECONNREFUSED - case ECONNREFUSED: result = WSAECONNREFUSED; break; -#endif -#ifdef ECONNRESET - case ECONNRESET: result = WSAECONNRESET; break; -#endif - case EFAULT: result = WSAEFAULT; break; -#ifdef EHOSTUNREACH - case EHOSTUNREACH: result = WSAEHOSTUNREACH; break; -#endif -#ifdef EINPROGRESS - case EINPROGRESS: result = WSAEINPROGRESS; break; -#endif - case EINTR: result = WSAEINTR; break; - case EINVAL: result = WSAEINVAL; break; - /*FIXME: case EIO: result = WSAE????; break; */ -#ifdef EISCONN - case EISCONN: result = WSAEISCONN; break; -#endif - /* FIXME: case ELOOP: result = WSA????; break; */ - case EMFILE: result = WSAEMFILE; break; -#ifdef EMSGSIZE - case EMSGSIZE: result = WSAEMSGSIZE; break; -#endif - /* FIXME: case ENAMETOOLONG: result = WSAEACCES; break; */ -#ifdef ENETUNREACH - case ENETUNREACH: result = WSAENETUNREACH; break; -#endif -#ifdef ENOBUFS - case ENOBUFS: result = WSAENOBUFS; break; /* not documented */ -#endif - /* case ENOENT: result = WSAE????; break; */ - case ENOMEM: result = WSAENOBUFS; break; -#ifdef ENOPROTOOPT - case ENOPROTOOPT: result = WSAENOPROTOOPT; break; -#endif -#ifdef ENOSR - case ENOSR: result = WSAENETDOWN; break; -#endif -#ifdef ENOTCONN - case ENOTCONN: result = WSAENOTCONN; break; -#endif - /*FIXME: case ENOTDIR: result = WSAE????; break; */ -#ifdef ENOTSOCK - case ENOTSOCK: result = WSAENOTSOCK; break; -#endif - case ENOTTY: result = WSAENOTSOCK; break; -#ifdef EOPNOTSUPP - case EOPNOTSUPP: result = WSAEOPNOTSUPP; break; -#endif - case EPERM: result = WSAEACCES; break; - case EPIPE: result = WSAESHUTDOWN; break; -#ifdef EPROTONOSUPPORT - case EPROTONOSUPPORT: result = WSAEPROTONOSUPPORT; break; -#endif -#if ERESTARTSYS - case ERESTARTSYS: result = WSAENETDOWN; break; -#endif - /*FIXME: case EROFS: result = WSAE????; break; */ -#ifdef ESOCKTNOSUPPORT - case ESOCKTNOSUPPORT: result = WSAESOCKTNOSUPPORT; break; -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: result = WSAETIMEDOUT; break; -#endif -#ifdef EWOULDBLOCK - case EWOULDBLOCK: result = WSAEWOULDBLOCK; break; -#endif -#ifdef EADDRNOTAVAIL - case EADDRNOTAVAIL: result = WSAEADDRNOTAVAIL; break; -#endif - /* This might happen with unix sockets */ - case ENOENT: result = WSAECONNREFUSED; break; -#ifdef EDESTADDRREQ - case EDESTADDRREQ: result = WSAEDESTADDRREQ; break; -#endif -#ifdef EHOSTDOWN - case EHOSTDOWN: result = WSAEHOSTDOWN; break; -#endif -#ifdef ENETDOWN - case ENETDOWN: result = WSAENETDOWN; break; -#endif - case ENODEV: result = WSAENETDOWN; break; - default: - sys_error = strerror (code); - msg = g_locale_to_utf8 (sys_error, strlen (sys_error), NULL, NULL, NULL); - if (function_name == NULL) - function_name = __func__; - - g_warning ("%s: Need to translate %d [%s] into winsock error", - function_name, code, msg); - - g_free (msg); - result = WSASYSCALLFAILURE; - } - - return result; -} - gint _wapi_get_win32_file_error (gint err) { diff --git a/mono/io-layer/error.h b/mono/io-layer/error.h index 7271d71bb1c..d4ffe1e9235 100644 --- a/mono/io-layer/error.h +++ b/mono/io-layer/error.h @@ -81,7 +81,6 @@ G_BEGIN_DECLS guint32 GetLastError (void); void SetLastError (guint32 code); -guint32 errno_to_WSA (guint32 code, const char *function_name); gint _wapi_get_win32_file_error (gint err); void _wapi_error_cleanup (void); diff --git a/mono/io-layer/socket-private.h b/mono/io-layer/socket-private.h deleted file mode 100644 index 31bbfe33c89..00000000000 --- a/mono/io-layer/socket-private.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * socket-private.h: Private definitions for socket handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_SOCKET_PRIVATE_H_ -#define _WAPI_SOCKET_PRIVATE_H_ - -#include -#include - -#include "wapi-private.h" - -struct _WapiHandle_socket -{ - int domain; - int type; - int protocol; - int saved_error; - int still_readable; -}; - -void -_wapi_socket_init (void); - -#endif /* _WAPI_SOCKET_PRIVATE_H_ */ diff --git a/mono/io-layer/socket-wrappers.h b/mono/io-layer/socket-wrappers.h deleted file mode 100644 index a532ce9f3ba..00000000000 --- a/mono/io-layer/socket-wrappers.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Special header file to be included only in selected C files. - * We need to use the _wapi_ equivalents of the socket API when - * working with io-layer handles. On windows we define the wrappers to use - * the normal win32 functions. - */ - -#include -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif - -#ifndef HAVE_SOCKLEN_T -#define socklen_t int -#endif - -#ifdef HOST_WIN32 -#define _wapi_accept accept -#define _wapi_bind bind -#define _wapi_connect connect -#define _wapi_getpeername getpeername -#define _wapi_getsockname getsockname -#define _wapi_getsockopt getsockopt -#define _wapi_listen listen -#define _wapi_recv recv -#define _wapi_recvfrom recvfrom -#define _wapi_send send -#define _wapi_sendto sendto -#define _wapi_setsockopt setsockopt -#define _wapi_shutdown shutdown -#define _wapi_socket WSASocket -#define _wapi_select select - -/* No need to wrap FD_ZERO because it doesnt involve file - * descriptors -*/ -#define _wapi_FD_CLR FD_CLR -#define _wapi_FD_ISSET FD_ISSET -#define _wapi_FD_SET FD_SET - -#define _wapi_cleanup_networking() ; -#else - -#define WSA_FLAG_OVERLAPPED 0x01 - -extern guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, - socklen_t *addrlen); -extern int _wapi_bind(guint32 handle, struct sockaddr *my_addr, - socklen_t addrlen); -extern int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, - socklen_t addrlen); -extern int _wapi_getpeername(guint32 handle, struct sockaddr *name, - socklen_t *namelen); -extern int _wapi_getsockname(guint32 handle, struct sockaddr *name, - socklen_t *namelen); -extern int _wapi_getsockopt(guint32 handle, int level, int optname, - void *optval, socklen_t *optlen); -extern int _wapi_listen(guint32 handle, int backlog); -extern int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags); -extern int _wapi_recvfrom(guint32 handle, void *buf, size_t len, - int recv_flags, struct sockaddr *from, - socklen_t *fromlen); -extern int _wapi_send(guint32 handle, const void *msg, size_t len, - int send_flags); -extern int _wapi_sendto(guint32 handle, const void *msg, size_t len, - int send_flags, const struct sockaddr *to, - socklen_t tolen); -extern int _wapi_setsockopt(guint32 handle, int level, int optname, - const void *optval, socklen_t optlen); -extern int _wapi_shutdown(guint32 handle, int how); -extern guint32 _wapi_socket(int domain, int type, int protocol, void *unused, - guint32 unused2, guint32 flags); - -#ifdef HAVE_SYS_SELECT_H -extern int _wapi_select(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout); - -extern void _wapi_FD_CLR(guint32 handle, fd_set *set); -extern int _wapi_FD_ISSET(guint32 handle, fd_set *set); -extern void _wapi_FD_SET(guint32 handle, fd_set *set); -#endif - -extern void _wapi_cleanup_networking (void); -#endif /* HOST_WIN32 */ - diff --git a/mono/io-layer/sockets.c b/mono/io-layer/sockets.c deleted file mode 100644 index d98ac677a2e..00000000000 --- a/mono/io-layer/sockets.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * sockets.c: Socket handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#include - -#ifndef DISABLE_SOCKETS - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_UIO_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_SYS_FILIO_H -#include /* defines FIONBIO and FIONREAD */ -#endif -#ifdef HAVE_SYS_SOCKIO_H -#include /* defines SIOCATMARK */ -#endif -#include -#include - -#ifndef HAVE_MSG_NOSIGNAL -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef HAVE_SYS_SENDFILE_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif - -static guint32 in_cleanup = 0; - -static void socket_close (gpointer handle, gpointer data); -static void socket_details (gpointer data); -static const gchar* socket_typename (void); -static gsize socket_typesize (void); - -static MonoW32HandleOps _wapi_socket_ops = { - socket_close, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - socket_details, /* details */ - socket_typename, /* typename */ - socket_typesize, /* typesize */ -}; - -void -_wapi_socket_init (void) -{ - mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &_wapi_socket_ops); -} - -static void socket_close (gpointer handle, gpointer data) -{ - int ret; - struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data; - MonoThreadInfo *info = mono_thread_info_current (); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle); - - /* Shutdown the socket for reading, to interrupt any potential - * receives that may be blocking for data. See bug 75705. - */ - shutdown (GPOINTER_TO_UINT (handle), SHUT_RD); - - do { - ret = close (GPOINTER_TO_UINT(handle)); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, strerror (errno)); - errnum = errno_to_WSA (errnum, __func__); - if (!in_cleanup) - WSASetLastError (errnum); - } - - if (!in_cleanup) - socket_handle->saved_error = 0; -} - -static void socket_details (gpointer data) -{ - /* FIXME: do something */ -} - -static const gchar* socket_typename (void) -{ - return "Socket"; -} - -static gsize socket_typesize (void) -{ - return sizeof (struct _WapiHandle_socket); -} - -static gboolean -cleanup_close (gpointer handle, gpointer data, gpointer user_data) -{ - if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET) - mono_w32handle_force_close (handle, data); - - return FALSE; -} - -void _wapi_cleanup_networking(void) -{ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__); - - in_cleanup = 1; - mono_w32handle_foreach (cleanup_close, NULL); - in_cleanup = 0; -} - -void WSASetLastError(int error) -{ - SetLastError (error); -} - -int WSAGetLastError(void) -{ - return(GetLastError ()); -} - -int closesocket(guint32 fd) -{ - gpointer handle = GUINT_TO_POINTER (fd); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(0); - } - - mono_w32handle_unref (handle); - return(0); -} - -guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - gpointer new_handle; - struct _WapiHandle_socket *socket_handle; - struct _WapiHandle_socket new_socket_handle = {0}; - gboolean ok; - int new_fd; - MonoThreadInfo *info = mono_thread_info_current (); - - if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { - WSASetLastError (WSAEFAULT); - return(INVALID_SOCKET); - } - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(INVALID_SOCKET); - } - - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up socket handle %p", - __func__, handle); - WSASetLastError (WSAENOTSOCK); - return(INVALID_SOCKET); - } - - do { - new_fd = accept (fd, addr, addrlen); - } while (new_fd == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (new_fd == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, strerror(errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(INVALID_SOCKET); - } - - if (new_fd >= mono_w32handle_fd_reserve) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); - - WSASetLastError (WSASYSCALLFAILURE); - - close (new_fd); - - return(INVALID_SOCKET); - } - - new_socket_handle.domain = socket_handle->domain; - new_socket_handle.type = socket_handle->type; - new_socket_handle.protocol = socket_handle->protocol; - new_socket_handle.still_readable = 1; - - new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, - &new_socket_handle); - if(new_handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating socket handle", __func__); - WSASetLastError (ERROR_GEN_FAILURE); - return(INVALID_SOCKET); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with", - __func__, new_handle); - - return(new_fd); -} - -int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - ret = bind (fd, my_addr, addrlen); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, strerror(errno)); - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, - socklen_t addrlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - struct _WapiHandle_socket *socket_handle; - gboolean ok; - gint errnum; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - if (connect (fd, serv_addr, addrlen) == -1) { - mono_pollfd fds; - int so_error; - socklen_t len; - - errnum = errno; - - if (errno != EINTR) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__, - strerror (errnum)); - - errnum = errno_to_WSA (errnum, __func__); - if (errnum == WSAEINPROGRESS) - errnum = WSAEWOULDBLOCK; /* see bug #73053 */ - - WSASetLastError (errnum); - - /* - * On solaris x86 getsockopt (SO_ERROR) is not set after - * connect () fails so we need to save this error. - * - * But don't do this for EWOULDBLOCK (bug 317315) - */ - if (errnum != WSAEWOULDBLOCK) { - ok = mono_w32handle_lookup (handle, - MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - /* ECONNRESET means the socket was closed by another thread */ - /* Async close on mac raises ECONNABORTED. */ - if (errnum != WSAECONNRESET && errnum != WSAENETDOWN) - g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum); - } else { - socket_handle->saved_error = errnum; - } - } - return(SOCKET_ERROR); - } - - fds.fd = fd; - fds.events = MONO_POLLOUT; - while (mono_poll (&fds, 1, -1) == -1 && - !mono_thread_info_is_interrupt_state (info)) { - if (errno != EINTR) { - errnum = errno_to_WSA (errno, __func__); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", - __func__, strerror (errno)); - - WSASetLastError (errnum); - return(SOCKET_ERROR); - } - } - - len = sizeof(so_error); - if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error, - &len) == -1) { - errnum = errno_to_WSA (errno, __func__); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", - __func__, strerror (errno)); - - WSASetLastError (errnum); - return(SOCKET_ERROR); - } - - if (so_error != 0) { - errnum = errno_to_WSA (so_error, __func__); - - /* Need to save this socket error */ - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up socket handle %p", __func__, handle); - } else { - socket_handle->saved_error = errnum; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s", - __func__, strerror (so_error)); - - WSASetLastError (errnum); - return(SOCKET_ERROR); - } - } - - return(0); -} - -int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - ret = getpeername (fd, name, namelen); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(ret); -} - -int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - ret = getsockname (fd, name, namelen); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(ret); -} - -int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, - socklen_t *optlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - struct timeval tv; - void *tmp_val; - struct _WapiHandle_socket *socket_handle; - gboolean ok; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - tmp_val = optval; - if (level == SOL_SOCKET && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { - tmp_val = &tv; - *optlen = sizeof (tv); - } - - ret = getsockopt (fd, level, optname, tmp_val, optlen); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - if (level == SOL_SOCKET && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { - *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro - *optlen = sizeof (int); - } - - if (optname == SO_ERROR) { - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up socket handle %p", - __func__, handle); - - /* can't extract the last error */ - *((int *) optval) = errno_to_WSA (*((int *)optval), - __func__); - } else { - if (*((int *)optval) != 0) { - *((int *) optval) = errno_to_WSA (*((int *)optval), - __func__); - socket_handle->saved_error = *((int *)optval); - } else { - *((int *)optval) = socket_handle->saved_error; - } - } - } - - return(ret); -} - -int _wapi_listen(guint32 fd, int backlog) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - ret = listen (fd, backlog); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(0); -} - -int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags) -{ - return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0)); -} - -int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, - struct sockaddr *from, socklen_t *fromlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - struct _WapiHandle_socket *socket_handle; - gboolean ok; - int ret; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - do { - ret = recvfrom (fd, buf, len, recv_flags, from, fromlen); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == 0 && len > 0) { - /* According to the Linux man page, recvfrom only - * returns 0 when the socket has been shut down - * cleanly. Turn this into an EINTR to simulate win32 - * behaviour of returning EINTR when a socket is - * closed while the recvfrom is blocking (we use a - * shutdown() in socket_close() to trigger this.) See - * bug 75705. - */ - /* Distinguish between the socket being shut down at - * the local or remote ends, and reads that request 0 - * bytes to be read - */ - - /* If this returns FALSE, it means the socket has been - * closed locally. If it returns TRUE, but - * still_readable != 1 then shutdown - * (SHUT_RD|SHUT_RDWR) has been called locally. - */ - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE || socket_handle->still_readable != 1) { - ret = -1; - errno = EINTR; - } - } - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, strerror(errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -static int -_wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags) -{ - gpointer handle = GUINT_TO_POINTER (fd); - struct _WapiHandle_socket *socket_handle; - gboolean ok; - int ret; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - do { - ret = recvmsg (fd, msg, recv_flags); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == 0) { - /* see _wapi_recvfrom */ - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE || socket_handle->still_readable != 1) { - ret = -1; - errno = EINTR; - } - } - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, strerror(errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - do { - ret = send (fd, msg, len, send_flags); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno)); - -#ifdef O_NONBLOCK - /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on - * a blocking socket. See bug #599488 */ - if (errnum == EAGAIN) { - ret = fcntl (fd, F_GETFL, 0); - if (ret != -1 && (ret & O_NONBLOCK) == 0) - errnum = ETIMEDOUT; - } -#endif /* O_NONBLOCK */ - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags, - const struct sockaddr *to, socklen_t tolen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - do { - ret = sendto (fd, msg, len, send_flags, to, tolen); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -static int -_wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - MonoThreadInfo *info = mono_thread_info_current (); - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - do { - ret = sendmsg (fd, msg, send_flags); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - return(ret); -} - -int _wapi_setsockopt(guint32 fd, int level, int optname, - const void *optval, socklen_t optlen) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - const void *tmp_val; -#if defined (__linux__) - /* This has its address taken so it cannot be moved to the if block which uses it */ - int bufsize = 0; -#endif - struct timeval tv; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - tmp_val = optval; - if (level == SOL_SOCKET && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { - int ms = *((int *) optval); - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; // micro from milli - tmp_val = &tv; - optlen = sizeof (tv); - } -#if defined (__linux__) - else if (level == SOL_SOCKET && - (optname == SO_SNDBUF || optname == SO_RCVBUF)) { - /* According to socket(7) the Linux kernel doubles the - * buffer sizes "to allow space for bookkeeping - * overhead." - */ - bufsize = *((int *) optval); - - bufsize /= 2; - tmp_val = &bufsize; - } -#endif - - ret = setsockopt (fd, level, optname, tmp_val, optlen); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - -#if defined (SO_REUSEPORT) - /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */ - if (level == SOL_SOCKET && optname == SO_REUSEADDR) { - int type; - socklen_t type_len = sizeof (type); - - if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) { - if (type == SOCK_DGRAM || type == SOCK_STREAM) - setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen); - } - } -#endif - - return(ret); -} - -int _wapi_shutdown(guint32 fd, int how) -{ - struct _WapiHandle_socket *socket_handle; - gboolean ok; - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - if (how == SHUT_RD || - how == SHUT_RDWR) { - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up socket handle %p", - __func__, handle); - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - socket_handle->still_readable = 0; - } - - ret = shutdown (fd, how); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(ret); -} - -guint32 _wapi_socket(int domain, int type, int protocol, void *unused, - guint32 unused2, guint32 unused3) -{ - struct _WapiHandle_socket socket_handle = {0}; - gpointer handle; - int fd; - - socket_handle.domain = domain; - socket_handle.type = type; - socket_handle.protocol = protocol; - socket_handle.still_readable = 1; - - fd = socket (domain, type, protocol); - if (fd == -1 && domain == AF_INET && type == SOCK_RAW && - protocol == 0) { - /* Retry with protocol == 4 (see bug #54565) */ - // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565 - socket_handle.protocol = 4; - fd = socket (AF_INET, SOCK_RAW, 4); - } - - if (fd == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno)); - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(INVALID_SOCKET); - } - - if (fd >= mono_w32handle_fd_reserve) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)", - __func__, fd, mono_w32handle_fd_reserve); - - WSASetLastError (WSASYSCALLFAILURE); - close (fd); - - return(INVALID_SOCKET); - } - - /* .net seems to set this by default for SOCK_STREAM, not for - * SOCK_DGRAM (see bug #36322) - * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322 - * - * It seems winsock has a rather different idea of what - * SO_REUSEADDR means. If it's set, then a new socket can be - * bound over an existing listening socket. There's a new - * windows-specific option called SO_EXCLUSIVEADDRUSE but - * using that means the socket MUST be closed properly, or a - * denial of service can occur. Luckily for us, winsock - * behaves as though any other system would when SO_REUSEADDR - * is true, so we don't need to do anything else here. See - * bug 53992. - * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992 - */ - { - int ret, true_ = 1; - - ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true_, - sizeof (true_)); - if (ret == -1) { - int errnum = errno; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - close (fd); - - return(INVALID_SOCKET); - } - } - - - handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, fd, &socket_handle); - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating socket handle", __func__); - WSASetLastError (WSASYSCALLFAILURE); - close (fd); - return(INVALID_SOCKET); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle); - - return(fd); -} - -static gboolean socket_disconnect (guint32 fd) -{ - struct _WapiHandle_socket *socket_handle; - gboolean ok; - gpointer handle = GUINT_TO_POINTER (fd); - int newsock, ret; - - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, - (gpointer *)&socket_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up socket handle %p", __func__, - handle); - WSASetLastError (WSAENOTSOCK); - return(FALSE); - } - - newsock = socket (socket_handle->domain, socket_handle->type, - socket_handle->protocol); - if (newsock == -1) { - gint errnum = errno; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(FALSE); - } - - /* According to Stevens "Advanced Programming in the UNIX - * Environment: UNIX File I/O" dup2() is atomic so there - * should not be a race condition between the old fd being - * closed and the new socket fd being copied over - */ - do { - ret = dup2 (newsock, fd); - } while (ret == -1 && errno == EAGAIN); - - if (ret == -1) { - gint errnum = errno; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(FALSE); - } - - close (newsock); - - return(TRUE); -} - -static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped, - guint32 flags, guint32 reserved) -{ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, fd); - - if (reserved != 0) { - WSASetLastError (WSAEINVAL); - return(FALSE); - } - - /* We could check the socket type here and fail unless its - * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn) - * if we really wanted to - */ - - return(socket_disconnect (fd)); -} - -#define SF_BUFFER_SIZE 16384 -static gint -wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags) -{ - MonoThreadInfo *info = mono_thread_info_current (); -#if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) - gint file = GPOINTER_TO_INT (fd); - gint n; - gint errnum; - gssize res; - struct stat statbuf; - - n = fstat (file, &statbuf); - if (n == -1) { - errnum = errno; - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - return SOCKET_ERROR; - } - do { -#ifdef __linux__ - res = sendfile (socket, file, NULL, statbuf.st_size); -#elif defined(DARWIN) - /* TODO: header/tail could be sent in the 5th argument */ - /* TODO: Might not send the entire file for non-blocking sockets */ - res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0); -#endif - } while (res != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - if (res == -1) { - errnum = errno; - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - return SOCKET_ERROR; - } -#else - /* Default implementation */ - gint file = GPOINTER_TO_INT (fd); - gchar *buffer; - gint n; - - buffer = g_malloc (SF_BUFFER_SIZE); - do { - do { - n = read (file, buffer, SF_BUFFER_SIZE); - } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - if (n == -1) - break; - if (n == 0) { - g_free (buffer); - return 0; /* We're done reading */ - } - do { - n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */ - } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - } while (n != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - - if (n == -1) { - gint errnum = errno; - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - g_free (buffer); - return SOCKET_ERROR; - } - g_free (buffer); -#endif - return 0; -} - -gboolean -TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol, - WapiTransmitFileBuffers *buffers, guint32 flags) -{ - gpointer sock = GUINT_TO_POINTER (socket); - gint ret; - - if (mono_w32handle_get_type (sock) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return FALSE; - } - - /* Write the header */ - if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) { - ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0); - if (ret == SOCKET_ERROR) - return FALSE; - } - - ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags); - if (ret == SOCKET_ERROR) - return FALSE; - - /* Write the tail */ - if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) { - ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0); - if (ret == SOCKET_ERROR) - return FALSE; - } - - if ((flags & TF_DISCONNECT) == TF_DISCONNECT) - closesocket (socket); - - return TRUE; -} - -static struct -{ - WapiGuid guid; - gpointer func; -} extension_functions[] = { - {WSAID_DISCONNECTEX, wapi_disconnectex}, - {WSAID_TRANSMITFILE, TransmitFile}, - {{0}, NULL}, -}; - -int -WSAIoctl (guint32 fd, gint32 command, - gchar *input, gint i_len, - gchar *output, gint o_len, glong *written, - void *unused1, void *unused2) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - gchar *buffer = NULL; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return SOCKET_ERROR; - } - - if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) { - int i = 0; - WapiGuid *guid = (WapiGuid *)input; - - if (i_len < sizeof(WapiGuid)) { - /* As far as I can tell, windows doesn't - * actually set an error here... - */ - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - if (o_len < sizeof(gpointer)) { - /* Or here... */ - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - if (output == NULL) { - /* Or here */ - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - while(extension_functions[i].func != NULL) { - if (!memcmp (guid, &extension_functions[i].guid, - sizeof(WapiGuid))) { - memcpy (output, &extension_functions[i].func, - sizeof(gpointer)); - *written = sizeof(gpointer); - return(0); - } - - i++; - } - - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - if (command == SIO_KEEPALIVE_VALS) { - uint32_t onoff; - uint32_t keepalivetime; - uint32_t keepaliveinterval; - - if (i_len < (3 * sizeof (uint32_t))) { - WSASetLastError (WSAEINVAL); - return SOCKET_ERROR; - } - memcpy (&onoff, input, sizeof (uint32_t)); - memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t)); - memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t)); - ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t)); - if (ret < 0) { - gint errnum = errno; - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - return SOCKET_ERROR; - } - if (onoff != 0) { -#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) - /* Values are in ms, but we need s */ - uint32_t rem; - - /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */ - rem = keepalivetime % 1000; - keepalivetime /= 1000; - if (keepalivetime == 0 || rem >= 500) - keepalivetime++; - ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t)); - if (ret == 0) { - rem = keepaliveinterval % 1000; - keepaliveinterval /= 1000; - if (keepaliveinterval == 0 || rem >= 500) - keepaliveinterval++; - ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t)); - } - if (ret != 0) { - gint errnum = errno; - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - return SOCKET_ERROR; - } - return 0; -#endif - } - return 0; - } - - if (i_len > 0) { - buffer = (char *)g_memdup (input, i_len); - } - - ret = ioctl (fd, command, buffer); - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, - strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - g_free (buffer); - - return(SOCKET_ERROR); - } - - if (buffer == NULL) { - *written = 0; - } else { - /* We just copy the buffer to the output. Some ioctls - * don't even output any data, but, well... - * - * NB windows returns WSAEFAULT if o_len is too small - */ - i_len = (i_len > o_len) ? o_len : i_len; - - if (i_len > 0 && output != NULL) { - memcpy (output, buffer, i_len); - } - - g_free (buffer); - *written = i_len; - } - - return(0); -} - -#ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET -int ioctlsocket(guint32 fd, unsigned long command, gpointer arg) -{ - gpointer handle = GUINT_TO_POINTER (fd); - int ret; - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(SOCKET_ERROR); - } - - switch(command){ - case FIONBIO: -#ifdef O_NONBLOCK - /* This works better than ioctl(...FIONBIO...) - * on Linux (it causes connect to return - * EINPROGRESS, but the ioctl doesn't seem to) - */ - ret = fcntl(fd, F_GETFL, 0); - if (ret != -1) { - if (*(gboolean *)arg) { - ret |= O_NONBLOCK; - } else { - ret &= ~O_NONBLOCK; - } - ret = fcntl(fd, F_SETFL, ret); - } - break; -#endif /* O_NONBLOCK */ - /* Unused in Mono */ - case SIOCATMARK: - ret = ioctl (fd, command, arg); - break; - - case FIONREAD: - { -#if defined (PLATFORM_MACOSX) - - // ioctl (fd, FIONREAD, XXX) returns the size of - // the UDP header as well on - // Darwin. - // - // Use getsockopt SO_NREAD instead to get the - // right values for TCP and UDP. - // - // ai_canonname can be null in some cases on darwin, where the runtime assumes it will - // be the value of the ip buffer. - - socklen_t optlen = sizeof (int); - ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen); -#else - ret = ioctl (fd, command, arg); -#endif - break; - } - default: - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, strerror (errno)); - - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(0); -} - -int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ - int ret, maxfd; - MonoThreadInfo *info = mono_thread_info_current (); - - for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) { - if ((readfds && FD_ISSET (maxfd, readfds)) || - (writefds && FD_ISSET (maxfd, writefds)) || - (exceptfds && FD_ISSET (maxfd, exceptfds))) { - break; - } - } - - if (maxfd == -1) { - WSASetLastError (WSAEINVAL); - return(SOCKET_ERROR); - } - - do { - ret = select(maxfd + 1, readfds, writefds, exceptfds, - timeout); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); - - if (ret == -1) { - gint errnum = errno; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: select error: %s", __func__, strerror (errno)); - errnum = errno_to_WSA (errnum, __func__); - WSASetLastError (errnum); - - return(SOCKET_ERROR); - } - - return(ret); -} - -void _wapi_FD_CLR(guint32 fd, fd_set *set) -{ - gpointer handle = GUINT_TO_POINTER (fd); - - if (fd >= FD_SETSIZE) { - WSASetLastError (WSAEINVAL); - return; - } - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return; - } - - FD_CLR (fd, set); -} - -int _wapi_FD_ISSET(guint32 fd, fd_set *set) -{ - gpointer handle = GUINT_TO_POINTER (fd); - - if (fd >= FD_SETSIZE) { - WSASetLastError (WSAEINVAL); - return(0); - } - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return(0); - } - - return(FD_ISSET (fd, set)); -} - -void _wapi_FD_SET(guint32 fd, fd_set *set) -{ - gpointer handle = GUINT_TO_POINTER (fd); - - if (fd >= FD_SETSIZE) { - WSASetLastError (WSAEINVAL); - return; - } - - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - WSASetLastError (WSAENOTSOCK); - return; - } - - FD_SET (fd, set); -} -#endif - -static void -wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr) -{ - guint32 i; - - memset (hdr, 0, sizeof (struct msghdr)); - hdr->msg_iovlen = count; - hdr->msg_iov = g_new0 (struct iovec, count); - for (i = 0; i < count; i++) { - hdr->msg_iov [i].iov_base = buffers [i].buf; - hdr->msg_iov [i].iov_len = buffers [i].len; - } -} - -static void -msghdr_iov_free (struct msghdr *hdr) -{ - g_free (hdr->msg_iov); -} - -int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received, - guint32 *flags, WapiOverlapped *overlapped, - WapiOverlappedCB *complete) -{ - int ret; - struct msghdr hdr; - - g_assert (overlapped == NULL); - g_assert (complete == NULL); - - wsabuf_to_msghdr (buffers, count, &hdr); - ret = _wapi_recvmsg (fd, &hdr, *flags); - msghdr_iov_free (&hdr); - - if(ret == SOCKET_ERROR) { - return(ret); - } - - *received = ret; - *flags = hdr.msg_flags; - - return(0); -} - -int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent, - guint32 flags, WapiOverlapped *overlapped, - WapiOverlappedCB *complete) -{ - int ret; - struct msghdr hdr; - - g_assert (overlapped == NULL); - g_assert (complete == NULL); - - wsabuf_to_msghdr (buffers, count, &hdr); - ret = _wapi_sendmsg (fd, &hdr, flags); - msghdr_iov_free (&hdr); - - if(ret == SOCKET_ERROR) - return ret; - - *sent = ret; - return 0; -} - -#endif /* ifndef DISABLE_SOCKETS */ diff --git a/mono/io-layer/sockets.h b/mono/io-layer/sockets.h deleted file mode 100644 index d634ae956ec..00000000000 --- a/mono/io-layer/sockets.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * sockets.h: Socket handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_SOCKETS_H_ -#define _WAPI_SOCKETS_H_ - -#include "mono/io-layer/wapi.h" - -G_BEGIN_DECLS - -#define WSADESCRIPTION_LEN 256 -#define WSASYS_STATUS_LEN 128 - -typedef struct -{ - guint16 wVersion; - guint16 wHighVersion; - char szDescription[WSADESCRIPTION_LEN+1]; - char szSystemStatus[WSASYS_STATUS_LEN+1]; - guint16 iMaxSockets; - guint16 iMaxUdpDg; - guchar *lpVendorInfo; -} WapiWSAData; - -#define INVALID_SOCKET (guint32)(~0) -#define SOCKET_ERROR -1 - -#define WSAID_DISCONNECTEX {0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} -#define WSAID_TRANSMITFILE {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} - -typedef struct -{ - guint32 Data1; - guint16 Data2; - guint16 Data3; - guint8 Data4[8]; -} WapiGuid; - -typedef struct -{ - gpointer Head; - guint32 HeadLength; - gpointer Tail; - guint32 TailLength; -} WapiTransmitFileBuffers; - -typedef enum { - TF_USE_DEFAULT_WORKER = 0, - TF_DISCONNECT = 0x01, - TF_REUSE_SOCKET = 0x02, - TF_WRITE_BEHIND = 0x04, - TF_USE_SYSTEM_THREAD = 0x10, - TF_USE_KERNEL_APC = 0x20 -} WapiTransmitFileFlags; - -typedef struct -{ - guint32 len; - gpointer buf; -} WapiWSABuf; - -/* If we need to support more WSAIoctl commands then define these - * using the bitfield flags method - */ -#define SIO_GET_EXTENSION_FUNCTION_POINTER 0xC8000006 -#define SIO_KEEPALIVE_VALS 0x98000004 - -typedef gboolean (*WapiDisconnectExFn)(guint32, WapiOverlapped *, guint32, - guint32); -typedef gboolean (*WapiTransmitFileFn)(guint32, gpointer, guint32, guint32, - WapiOverlapped *, - WapiTransmitFileBuffers *, - WapiTransmitFileFlags); - -extern void WSASetLastError(int error); -extern int WSAGetLastError(void); -extern int closesocket(guint32 handle); - -extern int ioctlsocket(guint32 handle, unsigned long command, gpointer arg); -extern int WSAIoctl (guint32 handle, gint32 command, - gchar *input, gint i_len, - gchar *output, gint o_len, glong *written, - void *unused1, void *unused2); -extern int WSARecv (guint32 handle, WapiWSABuf *buffers, guint32 count, - guint32 *received, guint32 *flags, - WapiOverlapped *overlapped, WapiOverlappedCB *complete); -extern int WSASend (guint32 handle, WapiWSABuf *buffers, guint32 count, - guint32 *sent, guint32 flags, - WapiOverlapped *overlapped, WapiOverlappedCB *complete); - -gboolean TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol, - WapiTransmitFileBuffers *tb, guint32 flags); -G_END_DECLS -#endif /* _WAPI_SOCKETS_H_ */ diff --git a/mono/io-layer/uglify.h b/mono/io-layer/uglify.h index fdadebc1207..0335d0a7200 100644 --- a/mono/io-layer/uglify.h +++ b/mono/io-layer/uglify.h @@ -40,7 +40,6 @@ typedef gconstpointer LPCVOID; typedef gpointer HANDLE; typedef gpointer *LPHANDLE; -typedef guint32 SOCKET; typedef gpointer HMODULE; typedef gpointer HINSTANCE; typedef gpointer HWND; @@ -54,21 +53,10 @@ typedef WapiFileTime FILETIME; typedef WapiFileTime *LPFILETIME; typedef WapiSystemTime SYSTEMTIME; typedef WapiSystemTime *LPSYSTEMTIME; -typedef WapiWSAData WSADATA; -typedef WapiWSAData *LDWSADATA; -typedef WapiWSABuf WSABUF; -typedef WapiWSABuf *LPWSABUF; typedef WapiFindData WIN32_FIND_DATA; typedef WapiFindData *LPWIN32_FIND_DATA; typedef WapiFileAttributesData WIN32_FILE_ATTRIBUTE_DATA; typedef WapiGetFileExInfoLevels GET_FILEEX_INFO_LEVELS; -typedef WapiTransmitFileBuffers TRANSMIT_FILE_BUFFERS; -typedef WapiTransmitFileBuffers *PTRANSMIT_FILE_BUFFERS; -typedef WapiTransmitFileBuffers *LPTRANSMIT_FILE_BUFFERS; -typedef WapiDisconnectExFn LPFN_DISCONNECTEX; -typedef WapiTransmitFileFn LPFN_TRANSMITFILE; -typedef WapiGuid GUID; -typedef WapiGuid *LPGUID; #define CONST const #define VOID void diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h index 9be764c1521..f39d4e4fab4 100644 --- a/mono/io-layer/wapi-private.h +++ b/mono/io-layer/wapi-private.h @@ -25,7 +25,6 @@ extern gboolean _wapi_has_shut_down; #include -#include #include struct _WapiHandle_shared_ref diff --git a/mono/io-layer/wapi-remap.h b/mono/io-layer/wapi-remap.h index e8426c4da83..7cc3b89ff38 100644 --- a/mono/io-layer/wapi-remap.h +++ b/mono/io-layer/wapi-remap.h @@ -14,7 +14,6 @@ #define GetLastError wapi_GetLastError #define SetLastError wapi_SetLastError -#define TransmitFile wapi_TransmitFile #define CloseHandle wapi_CloseHandle #define CreateFile wapi_CreateFile #define DeleteFile wapi_DeleteFile @@ -51,11 +50,6 @@ #define GetVolumeInformation wapi_GetVolumeInformation #define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser #define RevertToSelf wapi_RevertToSelf -#define WSASetLastError wapi_WSASetLastError -#define WSAGetLastError wapi_WSAGetLastError -#define WSAIoctl wapi_WSAIoctl -#define WSARecv wapi_WSARecv -#define WSASend wapi_WSASend #define GetSystemInfo wapi_GetSystemInfo #endif /* __WAPI_REMAP_H__ */ diff --git a/mono/io-layer/wapi.c b/mono/io-layer/wapi.c index fc9c00ccd90..d4da229603e 100644 --- a/mono/io-layer/wapi.c +++ b/mono/io-layer/wapi.c @@ -3,7 +3,6 @@ #include "io-trace.h" #include "io.h" -#include "socket-private.h" #include "mono/utils/mono-lazy-init.h" #include "mono/metadata/w32handle.h" @@ -14,7 +13,6 @@ void wapi_init (void) { _wapi_io_init (); - _wapi_socket_init (); } void diff --git a/mono/io-layer/wapi.h b/mono/io-layer/wapi.h index 65c98a4a584..fb0bf4fbce9 100644 --- a/mono/io-layer/wapi.h +++ b/mono/io-layer/wapi.h @@ -18,7 +18,6 @@ #include #include #include -#include G_BEGIN_DECLS diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 92b99cd28bc..5deda477e2d 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -16,7 +16,7 @@ win32_sources = \ w32event-win32.c \ w32process-win32.c \ w32process-win32-internals.h \ - socket-io-windows.c + w32socket-win32.c platform_sources = $(win32_sources) @@ -48,7 +48,8 @@ unix_sources = \ w32process-unix-osx.c \ w32process-unix-bsd.c \ w32process-unix-haiku.c \ - w32process-unix-default.c + w32process-unix-default.c \ + w32socket-unix.c platform_sources = $(unix_sources) endif @@ -205,8 +206,9 @@ common_sources = \ opcodes.c \ property-bag.h \ property-bag.c \ - socket-io.c \ - socket-io.h \ + w32socket.c \ + w32socket.h \ + w32socket-internals.h \ w32process.c \ w32process.h \ w32process-internals.h \ diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index cd8df1cb063..74323ab37b3 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #include #include #include diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 3d772e9a092..322f77805ab 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/mono/metadata/socket-io-windows-internals.h b/mono/metadata/socket-io-windows-internals.h deleted file mode 100644 index b76f9cbd43e..00000000000 --- a/mono/metadata/socket-io-windows-internals.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -* socket-io-windows-internals.h: Windows specific socket code. -* -* Copyright 2016 Microsoft -* Licensed under the MIT license. See LICENSE file in the project root for full license information. -*/ -#ifndef __MONO_METADATA_SOCKET_IO_WINDOWS_INTERNALS_H__ -#define __MONO_METADATA_SOCKET_IO_WINDOWS_INTERNALS_H__ - -#include -#include -#include - -SOCKET alertable_accept (SOCKET s, struct sockaddr *addr, int *addrlen, gboolean blocking); -int alertable_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking); -int alertable_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking); -int alertable_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen, gboolean blocking); -int alertable_WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, gboolean blocking); -int alertable_send (SOCKET s, char *buf, int len, int flags, gboolean blocking); -int alertable_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking); -int alertable_WSASend (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, DWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, gboolean blocking); - -#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) -BOOL alertable_TransmitFile (SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwReserved, gboolean blocking); -#endif - -#endif // __MONO_METADATA_SOCKET_IO_WINDOWS_INTERNALS_H__ diff --git a/mono/metadata/socket-io.h b/mono/metadata/socket-io.h deleted file mode 100644 index 7a8c9361ad6..00000000000 --- a/mono/metadata/socket-io.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * socket-io.h: Socket IO internal calls - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2001 Ximian, Inc. - */ - -#ifndef _MONO_METADATA_SOCKET_H_ -#define _MONO_METADATA_SOCKET_H_ - -#include -#include - -#include -#include - -/* This is a copy of System.Net.Sockets.SocketType */ -typedef enum { - SocketType_Stream=1, - SocketType_Dgram=2, - SocketType_Raw=3, - SocketType_Rdm=4, - SocketType_Seqpacket=5, - SocketType_Unknown=-1 -} MonoSocketType; - -/* This is a copy of System.Net.Sockets.AddressFamily */ -typedef enum { - AddressFamily_Unknown=-1, - AddressFamily_Unspecified=0, - AddressFamily_Unix=1, - AddressFamily_InterNetwork=2, - AddressFamily_ImpLink=3, - AddressFamily_Pup=4, - AddressFamily_Chaos=5, - AddressFamily_NS=6, - AddressFamily_Ipx=6, - AddressFamily_Iso=7, - AddressFamily_Osi=7, - AddressFamily_Ecma=8, - AddressFamily_DataKit=9, - AddressFamily_Ccitt=10, - AddressFamily_Sna=11, - AddressFamily_DecNet=12, - AddressFamily_DataLink=13, - AddressFamily_Lat=14, - AddressFamily_HyperChannel=15, - AddressFamily_AppleTalk=16, - AddressFamily_NetBios=17, - AddressFamily_VoiceView=18, - AddressFamily_FireFox=19, - AddressFamily_Banyan=21, - AddressFamily_Atm=22, - AddressFamily_InterNetworkV6=23, - AddressFamily_Cluster=24, - AddressFamily_Ieee12844=25, - AddressFamily_Irda=26, - AddressFamily_NetworkDesigners=28 -} MonoAddressFamily; - -/* This is a copy of System.Net.Sockets.ProtocolType */ -typedef enum { - ProtocolType_IP=0, - ProtocolType_Icmp=1, - ProtocolType_Igmp=2, - ProtocolType_Ggp=3, - ProtocolType_Tcp=6, - ProtocolType_Pup=12, - ProtocolType_Udp=17, - ProtocolType_Idp=22, - ProtocolType_IPv6=41, - ProtocolType_ND=77, - ProtocolType_Raw=255, - ProtocolType_Unspecified=0, - ProtocolType_Ipx=1000, - ProtocolType_Spx=1256, - ProtocolType_SpxII=1257, - ProtocolType_Unknown=-1 -} MonoProtocolType; - -/* This is a copy of System.Net.Sockets.SocketOptionLevel */ -typedef enum { - SocketOptionLevel_Socket=65535, - SocketOptionLevel_IP=0, - SocketOptionLevel_IPv6=41, - SocketOptionLevel_Tcp=6, - SocketOptionLevel_Udp=17 -} MonoSocketOptionLevel; - -/* This is a copy of System.Net.Sockets.SocketOptionName */ -typedef enum { - SocketOptionName_Debug=1, - SocketOptionName_AcceptConnection=2, - SocketOptionName_ReuseAddress=4, - SocketOptionName_KeepAlive=8, - SocketOptionName_DontRoute=16, - SocketOptionName_IPProtectionLevel = 23, - SocketOptionName_IPv6Only = 27, - SocketOptionName_Broadcast=32, - SocketOptionName_UseLoopback=64, - SocketOptionName_Linger=128, - SocketOptionName_OutOfBandInline=256, - SocketOptionName_DontLinger= -129, - SocketOptionName_ExclusiveAddressUse= -5, - SocketOptionName_SendBuffer= 4097, - SocketOptionName_ReceiveBuffer=4098, - SocketOptionName_SendLowWater=4099, - SocketOptionName_ReceiveLowWater=4100, - SocketOptionName_SendTimeout=4101, - SocketOptionName_ReceiveTimeout=4102, - SocketOptionName_Error=4103, - SocketOptionName_Type=4104, - SocketOptionName_MaxConnections=2147483647, - SocketOptionName_IPOptions=1, - SocketOptionName_HeaderIncluded=2, - SocketOptionName_TypeOfService=3, - SocketOptionName_IpTimeToLive=4, - SocketOptionName_MulticastInterface=9, - SocketOptionName_MulticastTimeToLive=10, - SocketOptionName_MulticastLoopback=11, - SocketOptionName_AddMembership=12, - SocketOptionName_DropMembership=13, - SocketOptionName_DontFragment=14, - SocketOptionName_AddSourceMembership=15, - SocketOptionName_DropSourceMembership=16, - SocketOptionName_BlockSource=17, - SocketOptionName_UnblockSource=18, - SocketOptionName_PacketInformation=19, - SocketOptionName_NoDelay=1, - SocketOptionName_BsdUrgent=2, - SocketOptionName_Expedited=2, - SocketOptionName_NoChecksum=1, - SocketOptionName_ChecksumCoverage=20, - SocketOptionName_HopLimit=21, - - /* This is Mono-specific, keep it in sync with - * Mono.Posix/PeerCred.cs - */ - SocketOptionName_PeerCred=10001 -} MonoSocketOptionName; - -/* This is a copy of System.Net.Sockets.SocketFlags */ -typedef enum { - SocketFlags_None = 0x0000, - SocketFlags_OutOfBand = 0x0001, - SocketFlags_MaxIOVectorLength = 0x0010, - SocketFlags_Peek = 0x0002, - SocketFlags_DontRoute = 0x0004, - SocketFlags_Partial = 0x8000 -} MonoSocketFlags; - -typedef struct -{ - MonoObject obj; - gint pid; - gint uid; - gint gid; -} MonoPeerCredData; - -extern gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock, gint32 *error); -extern gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void); -extern gint32 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock, gboolean block, gint32 *error); -extern gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock, gint32 *error, gboolean blocking); -extern void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog, gint32 *error); -extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock, gint32 af, gint32 *error); -extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock, gint32 af, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoObject *sockaddr, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_Receive_array_internal(SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_Send_array_internal(SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error, gboolean blocking); -extern gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *error, gboolean blocking); -extern void ves_icall_System_Net_Sockets_Socket_Select_internal(MonoArray **sockets, gint32 timeout, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock, gint32 how, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal(SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error); -extern int ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *error); -extern MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint); -extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint); -extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name); -extern MonoBoolean ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, gint timeout, gint32 *error); -extern void ves_icall_System_Net_Sockets_Socket_Disconnect_internal(SOCKET sock, MonoBoolean reuse, gint32 *error); -extern gboolean ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags, gint32 *error, gboolean blocking); -void icall_cancel_blocking_socket_operation (MonoThread *thread); -extern gboolean ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto); - -extern void mono_network_init(void); -extern void mono_network_cleanup(void); - -#endif /* _MONO_METADATA_SOCKET_H_ */ diff --git a/mono/metadata/threadpool-io.c b/mono/metadata/threadpool-io.c index 00b7e466933..4b59150832a 100644 --- a/mono/metadata/threadpool-io.c +++ b/mono/metadata/threadpool-io.c @@ -29,6 +29,7 @@ #include #include #include +#include typedef struct { gboolean (*init) (gint wakeup_pipe_fd); diff --git a/mono/metadata/threadpool-io.h b/mono/metadata/threadpool-io.h index 0936ee016cd..c7de70f2715 100644 --- a/mono/metadata/threadpool-io.h +++ b/mono/metadata/threadpool-io.h @@ -6,7 +6,6 @@ #include #include -#include typedef struct _MonoIOSelectorJob MonoIOSelectorJob; diff --git a/mono/metadata/threadpool-worker-default.c b/mono/metadata/threadpool-worker-default.c index fa8f850ea66..f78ccf68b2a 100644 --- a/mono/metadata/threadpool-worker-default.c +++ b/mono/metadata/threadpool-worker-default.c @@ -33,6 +33,7 @@ #include #include #include +#include #define CPU_USAGE_LOW 80 #define CPU_USAGE_HIGH 95 diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c index 84165e226b1..21738485349 100644 --- a/mono/metadata/threadpool.c +++ b/mono/metadata/threadpool.c @@ -45,6 +45,7 @@ #include #include #include +#include typedef struct { MonoDomain *domain; diff --git a/mono/metadata/w32socket-internals.h b/mono/metadata/w32socket-internals.h new file mode 100644 index 00000000000..dd4c61129d0 --- /dev/null +++ b/mono/metadata/w32socket-internals.h @@ -0,0 +1,151 @@ +/* +* w32socket-internals.h +* +* Copyright 2016 Microsoft +* Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#ifndef __MONO_METADATA_W32SOCKET_INTERNALS_H__ +#define __MONO_METADATA_W32SOCKET_INTERNALS_H__ + +#include +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include + +#ifndef HAVE_SOCKLEN_T +#define socklen_t int +#endif + +#ifndef HOST_WIN32 + +#define TF_DISCONNECT 0x01 +#define TF_REUSE_SOCKET 0x02 + +typedef struct { + guint32 len; + gpointer buf; +} WSABUF; + +typedef struct { + guint32 Internal; + guint32 InternalHigh; + guint32 Offset; + guint32 OffsetHigh; + gpointer hEvent; + gpointer handle1; + gpointer handle2; +} OVERLAPPED; + +typedef struct { + gpointer Head; + guint32 HeadLength; + gpointer Tail; + guint32 TailLength; +} TRANSMIT_FILE_BUFFERS; + +typedef struct { + guint32 Data1; + guint16 Data2; + guint16 Data3; + guint8 Data4[8]; +} GUID; + +typedef BOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET, OVERLAPPED*, guint32, guint32); +typedef BOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET, HANDLE, guint32, guint32, OVERLAPPED*, TRANSMIT_FILE_BUFFERS*, guint32); + +#endif + +void +mono_w32socket_initialize (void); + +void +mono_w32socket_cleanup (void); + +SOCKET +mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking); + +int +mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking); + +int +mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking); + +int +mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking); + +int +mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking); + +int +mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking); + +int +mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking); + +int +mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking); + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) + +BOOL +mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking); + +#endif + +#ifndef HOST_WIN32 + +SOCKET +mono_w32socket_socket (int domain, int type, int protocol); + +gint +mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen); + +gint +mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen); + +gint +mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen); + +gint +mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen); + +gint +mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen); + +gint +mono_w32socket_listen (SOCKET sock, gint backlog); + +gint +mono_w32socket_shutdown (SOCKET sock, gint how); + +gint +mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written); + +#endif /* HOST_WIN32 */ + +gint +mono_w32socket_disconnect (SOCKET sock, gboolean reuse); + +gint +mono_w32socket_set_blocking (SOCKET socket, gboolean blocking); + +gint +mono_w32socket_get_available (SOCKET socket, guint64 *amount); + +void +mono_w32socket_set_last_error (gint32 error); + +gint32 +mono_w32socket_get_last_error (void); + +gint32 +mono_w32socket_convert_error (gint error); + +#endif // __MONO_METADATA_W32SOCKET_INTERNALS_H__ diff --git a/mono/metadata/w32socket-unix.c b/mono/metadata/w32socket-unix.c new file mode 100644 index 00000000000..4b3d863e746 --- /dev/null +++ b/mono/metadata/w32socket-unix.c @@ -0,0 +1,1331 @@ +/* + * w32socket-unix.c: Unix specific socket code. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include +#include + +#include +#include +#include +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#include +#include +#ifdef HAVE_NETDB_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_UIO_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_FILIO_H +#include /* defines FIONBIO and FIONREAD */ +#endif +#ifdef HAVE_SYS_SOCKIO_H +#include /* defines SIOCATMARK */ +#endif +#ifndef HAVE_MSG_NOSIGNAL +#include +#endif +#ifdef HAVE_SYS_SENDFILE_H +#include +#endif + +#include "w32socket.h" +#include "w32socket-internals.h" +#include "w32handle.h" +#include "utils/mono-logger-internals.h" +#include "utils/mono-poll.h" + +typedef struct { + int domain; + int type; + int protocol; + int saved_error; + int still_readable; +} MonoW32HandleSocket; + +static guint32 in_cleanup = 0; + +static void +socket_close (gpointer handle, gpointer data) +{ + int ret; + MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data; + MonoThreadInfo *info = mono_thread_info_current (); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle); + + /* Shutdown the socket for reading, to interrupt any potential + * receives that may be blocking for data. See bug 75705. */ + shutdown (GPOINTER_TO_UINT (handle), SHUT_RD); + + do { + ret = close (GPOINTER_TO_UINT(handle)); + } while (ret == -1 && errno == EINTR && + !mono_thread_info_is_interrupt_state (info)); + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno)); + if (!in_cleanup) + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + } + + if (!in_cleanup) + socket_handle->saved_error = 0; +} + +static void +socket_details (gpointer data) +{ + /* FIXME: do something */ +} + +static const gchar* +socket_typename (void) +{ + return "Socket"; +} + +static gsize +socket_typesize (void) +{ + return sizeof (MonoW32HandleSocket); +} + +static MonoW32HandleOps ops = { + socket_close, /* close */ + NULL, /* signal */ + NULL, /* own */ + NULL, /* is_owned */ + NULL, /* special_wait */ + NULL, /* prewait */ + socket_details, /* details */ + socket_typename, /* typename */ + socket_typesize, /* typesize */ +}; + +void +mono_w32socket_initialize (void) +{ + mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &ops); +} + +static gboolean +cleanup_close (gpointer handle, gpointer data, gpointer user_data) +{ + if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET) + mono_w32handle_force_close (handle, data); + + return FALSE; +} + +void +mono_w32socket_cleanup (void) +{ + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__); + + in_cleanup = 1; + mono_w32handle_foreach (cleanup_close, NULL); + in_cleanup = 0; +} + +SOCKET +mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) +{ + gpointer handle; + gpointer new_handle; + MonoW32HandleSocket *socket_handle; + MonoW32HandleSocket new_socket_handle; + SOCKET new_fd; + MonoThreadInfo *info; + + if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { + mono_w32socket_set_last_error (WSAEFAULT); + return INVALID_SOCKET; + } + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return INVALID_SOCKET; + } + + info = mono_thread_info_current (); + + do { + new_fd = accept (sock, addr, addrlen); + } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + if (new_fd == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return INVALID_SOCKET; + } + + if (new_fd >= mono_w32handle_fd_reserve) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); + + mono_w32socket_set_last_error (WSASYSCALLFAILURE); + + close (new_fd); + + return INVALID_SOCKET; + } + + new_socket_handle.domain = socket_handle->domain; + new_socket_handle.type = socket_handle->type; + new_socket_handle.protocol = socket_handle->protocol; + new_socket_handle.still_readable = 1; + + new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, + &new_socket_handle); + if(new_handle == INVALID_HANDLE_VALUE) { + g_warning ("%s: error creating socket handle", __func__); + mono_w32socket_set_last_error (ERROR_GEN_FAILURE); + return INVALID_SOCKET; + } + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with", + __func__, new_handle); + + return new_fd; +} + +int +mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking) +{ + gpointer handle; + MonoW32HandleSocket *socket_handle; + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (connect (sock, addr, addrlen) == -1) { + MonoThreadInfo *info; + mono_pollfd fds; + gint errnum, so_error; + socklen_t len; + + errnum = errno; + + if (errno != EINTR) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__, + g_strerror (errnum)); + + errnum = mono_w32socket_convert_error (errnum); + if (errnum == WSAEINPROGRESS) + errnum = WSAEWOULDBLOCK; /* see bug #73053 */ + + mono_w32socket_set_last_error (errnum); + + /* + * On solaris x86 getsockopt (SO_ERROR) is not set after + * connect () fails so we need to save this error. + * + * But don't do this for EWOULDBLOCK (bug 317315) + */ + if (errnum != WSAEWOULDBLOCK) { + /* ECONNRESET means the socket was closed by another thread */ + /* Async close on mac raises ECONNABORTED. */ + socket_handle->saved_error = errnum; + } + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + fds.fd = sock; + fds.events = MONO_POLLOUT; + while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) { + if (errno != EINTR) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + } + + len = sizeof(so_error); + if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + if (so_error != 0) { + gint errnum = mono_w32socket_convert_error (so_error); + + /* Need to save this socket error */ + socket_handle->saved_error = errnum; + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s", + __func__, g_strerror (so_error)); + + mono_w32socket_set_last_error (errnum); + return SOCKET_ERROR; + } + } + + return 0; +} + +int +mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking) +{ + return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking); +} + +int +mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking) +{ + gpointer handle; + MonoW32HandleSocket *socket_handle; + int ret; + MonoThreadInfo *info; + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + do { + ret = recvfrom (sock, buf, len, flags, from, fromlen); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + if (ret == 0 && len > 0) { + /* According to the Linux man page, recvfrom only + * returns 0 when the socket has been shut down + * cleanly. Turn this into an EINTR to simulate win32 + * behaviour of returning EINTR when a socket is + * closed while the recvfrom is blocking (we use a + * shutdown() in socket_close() to trigger this.) See + * bug 75705. + */ + /* Distinguish between the socket being shut down at + * the local or remote ends, and reads that request 0 + * bytes to be read + */ + + /* If this returns FALSE, it means the socket has been + * closed locally. If it returns TRUE, but + * still_readable != 1 then shutdown + * (SHUT_RD|SHUT_RDWR) has been called locally. + */ + if (socket_handle->still_readable != 1) { + ret = -1; + errno = EINTR; + } + } + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + return ret; +} + +static void +wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr) +{ + guint32 i; + + memset (hdr, 0, sizeof (struct msghdr)); + hdr->msg_iovlen = count; + hdr->msg_iov = g_new0 (struct iovec, count); + for (i = 0; i < count; i++) { + hdr->msg_iov [i].iov_base = buffers [i].buf; + hdr->msg_iov [i].iov_len = buffers [i].len; + } +} + +static void +msghdr_iov_free (struct msghdr *hdr) +{ + g_free (hdr->msg_iov); +} + +int +mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking) +{ + MonoW32HandleSocket *socket_handle; + MonoThreadInfo *info; + gpointer handle; + gint ret; + struct msghdr hdr; + + g_assert (overlapped == NULL); + g_assert (complete == NULL); + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + wsabuf_to_msghdr (buffers, count, &hdr); + + do { + ret = recvmsg (sock, &hdr, *flags); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + msghdr_iov_free (&hdr); + + if (ret == 0) { + /* see mono_w32socket_recvfrom */ + if (socket_handle->still_readable != 1) { + ret = -1; + errno = EINTR; + } + } + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + *received = ret; + *flags = hdr.msg_flags; + + return 0; +} + +int +mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking) +{ + gpointer handle; + int ret; + MonoThreadInfo *info; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + do { + ret = send (sock, buf, len, flags); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno)); + +#ifdef O_NONBLOCK + /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on + * a blocking socket. See bug #599488 */ + if (errnum == EAGAIN) { + ret = fcntl (sock, F_GETFL, 0); + if (ret != -1 && (ret & O_NONBLOCK) == 0) + errnum = ETIMEDOUT; + } +#endif /* O_NONBLOCK */ + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + return ret; +} + +int +mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) +{ + gpointer handle; + int ret; + MonoThreadInfo *info; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + do { + ret = sendto (sock, buf, len, flags, to, tolen); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + return ret; +} + +int +mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking) +{ + struct msghdr hdr; + MonoThreadInfo *info; + gpointer handle; + gint ret; + + g_assert (overlapped == NULL); + g_assert (complete == NULL); + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + info = mono_thread_info_current (); + + wsabuf_to_msghdr (buffers, count, &hdr); + + do { + ret = sendmsg (sock, &hdr, flags); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + msghdr_iov_free (&hdr); + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + *sent = ret; + return 0; +} + +#define SF_BUFFER_SIZE 16384 + +BOOL +mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking) +{ + MonoThreadInfo *info; + gpointer handle; + gint file; + gssize ret; +#if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) + struct stat statbuf; +#else + gchar *buffer; +#endif + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return FALSE; + } + + /* Write the header */ + if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) { + ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE); + if (ret == SOCKET_ERROR) + return FALSE; + } + + info = mono_thread_info_current (); + + file = GPOINTER_TO_INT (file_handle); + +#if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) + ret = fstat (file, &statbuf); + if (ret == -1) { + gint errnum = errno; + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + do { +#ifdef __linux__ + ret = sendfile (sock, file, NULL, statbuf.st_size); +#elif defined(DARWIN) + /* TODO: header/tail could be sent in the 5th argument */ + /* TODO: Might not send the entire file for non-blocking sockets */ + ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0); +#endif + } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); +#else + buffer = g_malloc (SF_BUFFER_SIZE); + + do { + do { + ret = read (file, buffer, SF_BUFFER_SIZE); + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + if (ret == -1 || ret == 0) + break; + + do { + ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */ + } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + + g_free (buffer); +#endif + + if (ret == -1) { + gint errnum = errno; + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return FALSE; + } + + /* Write the tail */ + if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) { + ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE); + if (ret == SOCKET_ERROR) + return FALSE; + } + + if ((flags & TF_DISCONNECT) == TF_DISCONNECT) + CloseHandle (handle); + + return TRUE; +} + +SOCKET +mono_w32socket_socket (int domain, int type, int protocol) +{ + MonoW32HandleSocket socket_handle = {0}; + gpointer handle; + SOCKET sock; + + socket_handle.domain = domain; + socket_handle.type = type; + socket_handle.protocol = protocol; + socket_handle.still_readable = 1; + + sock = socket (domain, type, protocol); + if (sock == -1 && domain == AF_INET && type == SOCK_RAW && + protocol == 0) { + /* Retry with protocol == 4 (see bug #54565) */ + // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565 + socket_handle.protocol = 4; + sock = socket (AF_INET, SOCK_RAW, 4); + } + + if (sock == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return INVALID_SOCKET; + } + + if (sock >= mono_w32handle_fd_reserve) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)", + __func__, sock, mono_w32handle_fd_reserve); + + mono_w32socket_set_last_error (WSASYSCALLFAILURE); + close (sock); + + return INVALID_SOCKET; + } + + /* .net seems to set this by default for SOCK_STREAM, not for + * SOCK_DGRAM (see bug #36322) + * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322 + * + * It seems winsock has a rather different idea of what + * SO_REUSEADDR means. If it's set, then a new socket can be + * bound over an existing listening socket. There's a new + * windows-specific option called SO_EXCLUSIVEADDRUSE but + * using that means the socket MUST be closed properly, or a + * denial of service can occur. Luckily for us, winsock + * behaves as though any other system would when SO_REUSEADDR + * is true, so we don't need to do anything else here. See + * bug 53992. + * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992 + */ + { + int ret, true_ = 1; + + ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_)); + if (ret == -1) { + close (sock); + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return INVALID_SOCKET; + } + } + + + handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, sock, &socket_handle); + if (handle == INVALID_HANDLE_VALUE) { + g_warning ("%s: error creating socket handle", __func__); + mono_w32socket_set_last_error (WSASYSCALLFAILURE); + close (sock); + return INVALID_SOCKET; + } + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle); + + return sock; +} + +gint +mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen) +{ + gpointer handle; + int ret; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + ret = bind (sock, addr, addrlen); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +gint +mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + gpointer handle; + gint ret; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + ret = getpeername (sock, name, namelen); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +gint +mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + gpointer handle; + gint ret; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + ret = getsockname (sock, name, namelen); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +gint +mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) +{ + gpointer handle; + gint ret; + struct timeval tv; + gpointer tmp_val; + MonoW32HandleSocket *socket_handle; + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + tmp_val = optval; + if (level == SOL_SOCKET && + (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { + tmp_val = &tv; + *optlen = sizeof (tv); + } + + ret = getsockopt (sock, level, optname, tmp_val, optlen); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { + *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro + *optlen = sizeof (int); + } + + if (optname == SO_ERROR) { + if (*((int *)optval) != 0) { + *((int *) optval) = mono_w32socket_convert_error (*((int *)optval)); + socket_handle->saved_error = *((int *)optval); + } else { + *((int *)optval) = socket_handle->saved_error; + } + } + + return 0; +} + +gint +mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen) +{ + gpointer handle; + gint ret; + gpointer tmp_val; +#if defined (__linux__) + /* This has its address taken so it cannot be moved to the if block which uses it */ + gint bufsize = 0; +#endif + struct timeval tv; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + tmp_val = optval; + if (level == SOL_SOCKET && + (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { + int ms = *((int *) optval); + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; // micro from milli + tmp_val = &tv; + optlen = sizeof (tv); + } +#if defined (__linux__) + else if (level == SOL_SOCKET && + (optname == SO_SNDBUF || optname == SO_RCVBUF)) { + /* According to socket(7) the Linux kernel doubles the + * buffer sizes "to allow space for bookkeeping + * overhead." + */ + bufsize = *((int *) optval); + + bufsize /= 2; + tmp_val = &bufsize; + } +#endif + + ret = setsockopt (sock, level, optname, tmp_val, optlen); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + +#if defined (SO_REUSEPORT) + /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */ + if (level == SOL_SOCKET && optname == SO_REUSEADDR) { + int type; + socklen_t type_len = sizeof (type); + + if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) { + if (type == SOCK_DGRAM || type == SOCK_STREAM) + setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen); + } + } +#endif + + return ret; +} + +gint +mono_w32socket_listen (SOCKET sock, gint backlog) +{ + gpointer handle; + gint ret; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + ret = listen (sock, backlog); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +gint +mono_w32socket_shutdown (SOCKET sock, gint how) +{ + MonoW32HandleSocket *socket_handle; + gpointer handle; + gint ret; + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (how == SHUT_RD || how == SHUT_RDWR) + socket_handle->still_readable = 0; + + ret = shutdown (sock, how); + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return ret; +} + +gint +mono_w32socket_disconnect (SOCKET sock, gboolean reuse) +{ + MonoW32HandleSocket *socket_handle; + gpointer handle; + SOCKET newsock; + gint ret; + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock); + + /* We could check the socket type here and fail unless its + * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn) + * if we really wanted to */ + + handle = GUINT_TO_POINTER (sock); + if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol); + if (newsock == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + /* According to Stevens "Advanced Programming in the UNIX + * Environment: UNIX File I/O" dup2() is atomic so there + * should not be a race condition between the old fd being + * closed and the new socket fd being copied over */ + do { + ret = dup2 (newsock, sock); + } while (ret == -1 && errno == EAGAIN); + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + close (newsock); + + return 0; +} + +static gboolean +extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved) +{ + return mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0; +} + +static gboolean +extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send, + OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags) +{ + return mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE); +} + +static struct { + GUID guid; + gpointer func; +} extension_functions[] = { + { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, extension_disconect }, + { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, extension_transmit_file }, + { {0} , NULL }, +}; + +gint +mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written) +{ + gpointer handle; + gint ret; + gchar *buffer; + + handle = GUINT_TO_POINTER (sock); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) { + gint i; + GUID *guid; + + if (inputlen < sizeof(GUID)) { + /* As far as I can tell, windows doesn't + * actually set an error here... + */ + mono_w32socket_set_last_error (WSAEINVAL); + return SOCKET_ERROR; + } + + if (outputlen < sizeof(gpointer)) { + /* Or here... */ + mono_w32socket_set_last_error (WSAEINVAL); + return SOCKET_ERROR; + } + + if (output == NULL) { + /* Or here */ + mono_w32socket_set_last_error (WSAEINVAL); + return SOCKET_ERROR; + } + + guid = (GUID*) input; + for (i = 0; extension_functions[i].func; i++) { + if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) { + memcpy (output, &extension_functions[i].func, sizeof(gpointer)); + *written = sizeof(gpointer); + return 0; + } + } + + mono_w32socket_set_last_error (WSAEINVAL); + return SOCKET_ERROR; + } + + if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) { + guint32 onoff; + + if (inputlen < 3 * sizeof (guint32)) { + mono_w32socket_set_last_error (WSAEINVAL); + return SOCKET_ERROR; + } + + onoff = *((guint32*) input); + + ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32)); + if (ret < 0) { + mono_w32socket_set_last_error (mono_w32socket_convert_error (errno)); + return SOCKET_ERROR; + } + +#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) + if (onoff != 0) { + /* Values are in ms, but we need s */ + guint32 keepalivetime, keepaliveinterval, rem; + + keepalivetime = *(((guint32*) input) + 1); + keepaliveinterval = *(((guint32*) input) + 2); + + /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */ + rem = keepalivetime % 1000; + keepalivetime /= 1000; + if (keepalivetime == 0 || rem >= 500) + keepalivetime++; + ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32)); + if (ret == 0) { + rem = keepaliveinterval % 1000; + keepaliveinterval /= 1000; + if (keepaliveinterval == 0 || rem >= 500) + keepaliveinterval++; + ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32)); + } + if (ret != 0) { + mono_w32socket_set_last_error (mono_w32socket_convert_error (errno)); + return SOCKET_ERROR; + } + + return 0; + } +#endif + + return 0; + } + + buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL; + + ret = ioctl (sock, command, buffer); + if (ret == -1) { + g_free (buffer); + + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + if (!buffer) { + *written = 0; + return 0; + } + + /* We just copy the buffer to the output. Some ioctls + * don't even output any data, but, well... + * + * NB windows returns WSAEFAULT if outputlen is too small */ + inputlen = (inputlen > outputlen) ? outputlen : inputlen; + + if (inputlen > 0 && output != NULL) + memcpy (output, buffer, inputlen); + + g_free (buffer); + *written = inputlen; + + return 0; +} + +gint +mono_w32socket_set_blocking (SOCKET socket, gboolean blocking) +{ + gint ret; + gpointer handle; + + handle = GINT_TO_POINTER (socket); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + +#ifdef O_NONBLOCK + /* This works better than ioctl(...FIONBIO...) + * on Linux (it causes connect to return + * EINPROGRESS, but the ioctl doesn't seem to) */ + ret = fcntl (socket, F_GETFL, 0); + if (ret != -1) + ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK))); +#endif /* O_NONBLOCK */ + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +gint +mono_w32socket_get_available (SOCKET socket, guint64 *amount) +{ + gint ret; + gpointer handle; + + handle = GINT_TO_POINTER (socket); + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { + mono_w32socket_set_last_error (WSAENOTSOCK); + return SOCKET_ERROR; + } + +#if defined (PLATFORM_MACOSX) + // ioctl (socket, FIONREAD, XXX) returns the size of + // the UDP header as well on Darwin. + // + // Use getsockopt SO_NREAD instead to get the + // right values for TCP and UDP. + // + // ai_canonname can be null in some cases on darwin, + // where the runtime assumes it will be the value of + // the ip buffer. + + socklen_t optlen = sizeof (int); + ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen); +#else + ret = ioctl (socket, FIONREAD, (gulong*) amount); +#endif + + if (ret == -1) { + gint errnum = errno; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + return SOCKET_ERROR; + } + + return 0; +} + +void +mono_w32socket_set_last_error (gint32 error) +{ + SetLastError (error); +} + +gint32 +mono_w32socket_get_last_error (void) +{ + return GetLastError (); +} + +gint32 +mono_w32socket_convert_error (gint error) +{ + switch (error) { + case 0: return ERROR_SUCCESS; + case EACCES: return WSAEACCES; +#ifdef EADDRINUSE + case EADDRINUSE: return WSAEADDRINUSE; +#endif +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: return WSAEAFNOSUPPORT; +#endif +#if EAGAIN != EWOULDBLOCK + case EAGAIN: return WSAEWOULDBLOCK; +#endif +#ifdef EALREADY + case EALREADY: return WSAEALREADY; +#endif + case EBADF: return WSAENOTSOCK; +#ifdef ECONNABORTED + case ECONNABORTED: return WSAENETDOWN; +#endif +#ifdef ECONNREFUSED + case ECONNREFUSED: return WSAECONNREFUSED; +#endif +#ifdef ECONNRESET + case ECONNRESET: return WSAECONNRESET; +#endif + case EFAULT: return WSAEFAULT; +#ifdef EHOSTUNREACH + case EHOSTUNREACH: return WSAEHOSTUNREACH; +#endif +#ifdef EINPROGRESS + case EINPROGRESS: return WSAEINPROGRESS; +#endif + case EINTR: return WSAEINTR; + case EINVAL: return WSAEINVAL; + /*FIXME: case EIO: return WSAE????; */ +#ifdef EISCONN + case EISCONN: return WSAEISCONN; +#endif + /* FIXME: case ELOOP: return WSA????; */ + case EMFILE: return WSAEMFILE; +#ifdef EMSGSIZE + case EMSGSIZE: return WSAEMSGSIZE; +#endif + /* FIXME: case ENAMETOOLONG: return WSAEACCES; */ +#ifdef ENETUNREACH + case ENETUNREACH: return WSAENETUNREACH; +#endif +#ifdef ENOBUFS + case ENOBUFS: return WSAENOBUFS; /* not documented */ +#endif + /* case ENOENT: return WSAE????; */ + case ENOMEM: return WSAENOBUFS; +#ifdef ENOPROTOOPT + case ENOPROTOOPT: return WSAENOPROTOOPT; +#endif +#ifdef ENOSR + case ENOSR: return WSAENETDOWN; +#endif +#ifdef ENOTCONN + case ENOTCONN: return WSAENOTCONN; +#endif + /*FIXME: case ENOTDIR: return WSAE????; */ +#ifdef ENOTSOCK + case ENOTSOCK: return WSAENOTSOCK; +#endif + case ENOTTY: return WSAENOTSOCK; +#ifdef EOPNOTSUPP + case EOPNOTSUPP: return WSAEOPNOTSUPP; +#endif + case EPERM: return WSAEACCES; + case EPIPE: return WSAESHUTDOWN; +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; +#endif +#if ERESTARTSYS + case ERESTARTSYS: return WSAENETDOWN; +#endif + /*FIXME: case EROFS: return WSAE????; */ +#ifdef ESOCKTNOSUPPORT + case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: return WSAETIMEDOUT; +#endif +#ifdef EWOULDBLOCK + case EWOULDBLOCK: return WSAEWOULDBLOCK; +#endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; +#endif + /* This might happen with unix sockets */ + case ENOENT: return WSAECONNREFUSED; +#ifdef EDESTADDRREQ + case EDESTADDRREQ: return WSAEDESTADDRREQ; +#endif +#ifdef EHOSTDOWN + case EHOSTDOWN: return WSAEHOSTDOWN; +#endif +#ifdef ENETDOWN + case ENETDOWN: return WSAENETDOWN; +#endif + case ENODEV: return WSAENETDOWN; + default: + g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error)); + } +} + +gboolean +ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto) +{ +#if defined (SO_REUSEPORT) + return TRUE; +#else +#ifdef __linux__ + /* Linux always supports double binding for UDP, even on older kernels. */ + if (proto == ProtocolType_Udp) + return TRUE; +#endif + return FALSE; +#endif +} diff --git a/mono/metadata/socket-io-windows.c b/mono/metadata/w32socket-win32.c similarity index 61% rename from mono/metadata/socket-io-windows.c rename to mono/metadata/w32socket-win32.c index 125dbeb9c4d..9a2d4522167 100644 --- a/mono/metadata/socket-io-windows.c +++ b/mono/metadata/w32socket-win32.c @@ -1,16 +1,38 @@ /* -* socket-io-windows.c: Windows specific socket code. -* -* Copyright 2016 Microsoft -* Licensed under the MIT license. See LICENSE file in the project root for full license information. -*/ + * w32socket-win32.c: Windows specific socket code. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + #include #include -#include "mono/metadata/socket-io-windows-internals.h" +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#include + +#include "w32socket.h" +#include "w32socket-internals.h" #define LOGDEBUG(...) +void +mono_w32socket_initialize (void) +{ +} + +void +mono_w32socket_cleanup (void) +{ +} + static gboolean set_blocking (SOCKET sock, gboolean block) { u_long non_block = block ? 0 : 1; @@ -108,14 +130,17 @@ static gboolean alertable_socket_wait (SOCKET sock, int event_bit) blocking ? "blocking" : "non-blocking", sock, ret, _saved_error)); \ WSASetLastError (_saved_error); -SOCKET alertable_accept (SOCKET s, struct sockaddr *addr, int *addrlen, gboolean blocking) +SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) { + MonoInternalThread *curthread = mono_thread_internal_current (); SOCKET newsock = INVALID_SOCKET; + curthread->interrupt_on_stop = (gpointer)TRUE; ALERTABLE_SOCKET_CALL (FD_ACCEPT_BIT, blocking, TRUE, newsock, accept, s, addr, addrlen); + curthread->interrupt_on_stop = (gpointer)FALSE; return newsock; } -int alertable_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking) +int mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_CONNECT_BIT, blocking, FALSE, ret, connect, s, name, namelen); @@ -123,42 +148,45 @@ int alertable_connect (SOCKET s, const struct sockaddr *name, int namelen, gbool return ret; } -int alertable_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking) +int mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking) { + MonoInternalThread *curthread = mono_thread_internal_current (); int ret = SOCKET_ERROR; + curthread->interrupt_on_stop = (gpointer)TRUE; ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recv, s, buf, len, flags); + curthread->interrupt_on_stop = (gpointer)FALSE; return ret; } -int alertable_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen, gboolean blocking) +int mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recvfrom, s, buf, len, flags, from, fromlen); return ret; } -int alertable_WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, gboolean blocking) +int mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, WSARecv, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine); return ret; } -int alertable_send (SOCKET s, char *buf, int len, int flags, gboolean blocking) +int mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, send, s, buf, len, flags); return ret; } -int alertable_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) +int mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, sendto, s, buf, len, flags, to, tolen); return ret; } -int alertable_WSASend (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, DWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, gboolean blocking) +int mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking) { int ret = SOCKET_ERROR; ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine); @@ -166,18 +194,17 @@ int alertable_WSASend (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWOR } #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) -BOOL alertable_TransmitFile (SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwReserved, gboolean blocking) +BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking) { LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket)); int error = 0; if (blocking) { - g_assert (lpOverlapped == NULL); OVERLAPPED overlapped = { 0 }; overlapped.hEvent = WSACreateEvent (); if (overlapped.hEvent == WSA_INVALID_EVENT) return FALSE; - if (!TransmitFile (hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, &overlapped, lpTransmitBuffers, dwReserved)) { + if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) { error = WSAGetLastError (); if (error == WSA_IO_PENDING) { error = 0; @@ -195,7 +222,7 @@ BOOL alertable_TransmitFile (SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesT } WSACloseEvent (overlapped.hEvent); } else { - if (!TransmitFile (hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, lpOverlapped, lpTransmitBuffers, dwReserved)) { + if (!TransmitFile (hSocket, hFile, 0, 0, NULL, lpTransmitBuffers, dwReserved)) { error = WSAGetLastError (); } } @@ -207,3 +234,82 @@ BOOL alertable_TransmitFile (SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesT return error == 0; } #endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */ + +gint +mono_w32socket_disconnect (SOCKET sock, gboolean reuse) +{ + LPFN_DISCONNECTEX disconnect; + LPFN_TRANSMITFILE transmit_file; + DWORD output_bytes; + gint ret; + + /* Use the SIO_GET_EXTENSION_FUNCTION_POINTER to determine + * the address of the disconnect method without taking + * a hard dependency on a single provider + * + * For an explanation of why this is done, you can read the + * article at http://www.codeproject.com/internet/jbsocketserver3.asp + * + * I _think_ the extension function pointers need to be looked + * up for each socket. + * + * FIXME: check the best way to store pointers to functions in + * managed objects that still works on 64bit platforms. */ + + GUID disconnect_guid = WSAID_DISCONNECTEX; + ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnect_guid, sizeof (GUID), &disconnect, sizeof (LPFN_DISCONNECTEX), &output_bytes, NULL, NULL); + if (ret == 0) { + if (!disconnect (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0)) + return WSAGetLastError (); + + return 0; + } + + GUID transmit_file_guid = WSAID_TRANSMITFILE; + ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmit_file_guid, sizeof (GUID), &transmit_file, sizeof (LPFN_TRANSMITFILE), &output_bytes, NULL, NULL); + if (ret == 0) { + if (!transmit_file (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0))) + return WSAGetLastError (); + + return 0; + } + + return ERROR_NOT_SUPPORTED; +} + +gint +mono_w32socket_set_blocking (SOCKET sock, gboolean blocking) +{ + gulong nonblocking_long = !blocking; + return ioctlsocket (sock, FIONBIO, &nonblocking_long); +} + +gint +mono_w32socket_get_available (SOCKET sock, guint64 *amount) +{ + return ioctlsocket (sock, FIONREAD, (int*) amount); +} + +void +mono_w32socket_set_last_error (gint32 error) +{ + WSASetLastError (error); +} + +gint32 +mono_w32socket_get_last_error (void) +{ + return WSAGetLastError (); +} + +gint32 +mono_w32socket_convert_error (gint error) +{ + return (error > 0 && error < WSABASEERR) ? error + WSABASEERR : error; +} + +gboolean +ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto) +{ + return TRUE; +} diff --git a/mono/metadata/socket-io.c b/mono/metadata/w32socket.c similarity index 85% rename from mono/metadata/socket-io.c rename to mono/metadata/w32socket.c index 606eff3692d..9d45ddac921 100644 --- a/mono/metadata/socket-io.c +++ b/mono/metadata/w32socket.c @@ -47,7 +47,6 @@ #include #include -#include #include #include #include @@ -63,6 +62,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_SYS_TIME_H @@ -97,14 +98,67 @@ #include #endif -#include "mono/io-layer/socket-wrappers.h" -#ifdef HOST_WIN32 -#include "mono/metadata/socket-io-windows-internals.h" -#endif - #define LOGDEBUG(...) /* define LOGDEBUG(...) g_message(__VA_ARGS__) */ +#ifdef HOST_WIN32 + +static SOCKET +mono_w32socket_socket (int domain, int type, int protocol) +{ + return WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); +} + +static gint +mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen) +{ + return bind (sock, addr, addrlen); +} + +static gint +mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + return getpeername (sock, name, namelen); +} + +static gint +mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + return getsockname (sock, name, namelen); +} + +static gint +mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) +{ + return getsockopt (sock, level, optname, optval, optlen); +} + +static gint +mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen) +{ + return setsockopt (sock, level, optname, optval, optlen); +} + +static gint +mono_w32socket_listen (SOCKET sock, gint backlog) +{ + return listen (sock, backlog); +} + +static gint +mono_w32socket_shutdown (SOCKET sock, gint how) +{ + return shutdown (sock, how); +} + +static gint +mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written) +{ + return WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL); +} + +#endif /* HOST_WIN32 */ + static void abort_syscall (gpointer data) { @@ -623,11 +677,10 @@ ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint3 return NULL; } - sock = _wapi_socket (sock_family, sock_type, sock_proto, - NULL, 0, WSA_FLAG_OVERLAPPED); + sock = mono_w32socket_socket (sock_family, sock_type, sock_proto); if (sock == INVALID_SOCKET) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); return NULL; } @@ -638,7 +691,7 @@ ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint3 * file) is really an IntPtr which needs to be converted to a guint32. */ void -ves_icall_System_Net_Sockets_Socket_Close_internal (SOCKET sock, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror) { LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock)); @@ -649,30 +702,30 @@ ves_icall_System_Net_Sockets_Socket_Close_internal (SOCKET sock, gint32 *werror) mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock)); MONO_ENTER_GC_SAFE; - closesocket (sock); + CloseHandle (GINT_TO_POINTER (sock)); MONO_EXIT_GC_SAFE; } gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void) { - LOGDEBUG (g_message("%s: returning %d", __func__, WSAGetLastError ())); + LOGDEBUG (g_message("%s: returning %d", __func__, mono_w32socket_get_last_error ())); - return WSAGetLastError (); + return mono_w32socket_get_last_error (); } gint32 -ves_icall_System_Net_Sockets_Socket_Available_internal (SOCKET sock, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *werror) { int ret; - int amount; + guint64 amount; *werror = 0; /* FIXME: this might require amount to be unsigned long. */ - ret = ioctlsocket (sock, FIONREAD, &amount); + ret = mono_w32socket_get_available (sock, &amount); if (ret == SOCKET_ERROR) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); return 0; } @@ -680,25 +733,19 @@ ves_icall_System_Net_Sockets_Socket_Available_internal (SOCKET sock, gint32 *wer } void -ves_icall_System_Net_Sockets_Socket_Blocking_internal (SOCKET sock, gboolean block, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *werror) { int ret; *werror = 0; - /* - * block == TRUE/FALSE means we will block/not block. - * But the ioctlsocket call takes TRUE/FALSE for non-block/block - */ - block = !block; - - ret = ioctlsocket (sock, FIONBIO, (gulong *)&block); + ret = mono_w32socket_set_blocking (sock, block); if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); } gpointer -ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror, gboolean blocking) { gboolean interrupted; SOCKET newsock; @@ -712,22 +759,11 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - { - MonoInternalThread *curthread = mono_thread_internal_current (); - curthread->interrupt_on_stop = (gpointer)TRUE; - newsock = alertable_accept (sock, NULL, 0, blocking); - curthread->interrupt_on_stop = (gpointer)FALSE; - } -#else - newsock = _wapi_accept (sock, NULL, 0); -#endif - + newsock = mono_w32socket_accept (sock, NULL, 0, blocking); MONO_EXIT_GC_SAFE; if (newsock == INVALID_SOCKET) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -740,7 +776,7 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror } void -ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog, gint32 *werror) { int ret; @@ -748,12 +784,12 @@ ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog MONO_ENTER_GC_SAFE; - ret = _wapi_listen (sock, backlog); + ret = mono_w32socket_listen (sock, backlog); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); } // Check whether it's ::ffff::0:0. @@ -926,7 +962,7 @@ get_sockaddr_size (int family) } MonoObject* -ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock, gint32 af, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *werror) { gchar *sa; socklen_t salen; @@ -945,12 +981,12 @@ ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock, gint32 MONO_ENTER_GC_SAFE; - ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen); + ret = mono_w32socket_getsockname (sock, (struct sockaddr *)sa, &salen); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); if (salen > 128) g_free (sa); return NULL; @@ -967,7 +1003,7 @@ ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock, gint32 } MonoObject* -ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (SOCKET sock, gint32 af, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *werror) { gchar *sa; socklen_t salen; @@ -987,12 +1023,12 @@ ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (SOCKET sock, gint32 MONO_ENTER_GC_SAFE; - ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen); + ret = mono_w32socket_getpeername (sock, (struct sockaddr *)sa, &salen); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); if (salen > 128) g_free (sa); return NULL; @@ -1131,7 +1167,7 @@ create_sockaddr_from_object (MonoObject *saddr_obj, socklen_t *sa_size, gint32 * } void -ves_icall_System_Net_Sockets_Socket_Bind_internal (SOCKET sock, MonoObject *sockaddr, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObject *sockaddr, gint32 *werror) { MonoError error; struct sockaddr *sa; @@ -1150,10 +1186,10 @@ ves_icall_System_Net_Sockets_Socket_Bind_internal (SOCKET sock, MonoObject *sock LOGDEBUG (g_message("%s: binding to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port))); - ret = _wapi_bind (sock, sa, sa_size); + ret = mono_w32socket_bind (sock, sa, sa_size); if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); g_free (sa); } @@ -1165,7 +1201,7 @@ enum { }; MonoBoolean -ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, +ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint timeout, gint32 *werror) { MonoInternalThread *thread = mono_thread_internal_current (); @@ -1241,11 +1277,7 @@ ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, } while (ret == -1 && errno == EINTR); if (ret == -1) { -#ifdef HOST_WIN32 - *werror = (errno > 0 && errno < WSABASEERR) ? errno + WSABASEERR : errno; -#else - *werror = errno_to_WSA (errno, __func__); -#endif + *werror = mono_w32socket_convert_error (errno); g_free (pfds); return FALSE; } @@ -1255,7 +1287,7 @@ ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, } void -ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *sockaddr, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObject *sockaddr, gint32 *werror, gboolean blocking) { MonoError error; struct sockaddr *sa; @@ -1282,17 +1314,11 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *s } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_connect (sock, sa, sa_size, blocking); -#else - ret = _wapi_connect (sock, sa, sa_size); -#endif - + ret = mono_w32socket_connect (sock, sa, sa_size, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1302,72 +1328,14 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *s } #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) -/* These #defines from mswsock.h from wine. Defining them here allows - * us to build this file on a mingw box that doesn't know the magic - * numbers, but still run on a newer windows box that does. - */ -#ifndef WSAID_DISCONNECTEX -#define WSAID_DISCONNECTEX {0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} -typedef BOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET, LPOVERLAPPED, DWORD, DWORD); -#endif - -#ifndef WSAID_TRANSMITFILE -#define WSAID_TRANSMITFILE {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} -typedef BOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET, HANDLE, DWORD, DWORD, LPOVERLAPPED, LPTRANSMIT_FILE_BUFFERS, DWORD); -#endif void -ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolean reuse, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror) { - int ret; - glong output_bytes = 0; - GUID disco_guid = WSAID_DISCONNECTEX; - GUID trans_guid = WSAID_TRANSMITFILE; - LPFN_DISCONNECTEX _wapi_disconnectex = NULL; - LPFN_TRANSMITFILE _wapi_transmitfile = NULL; gboolean interrupted; - *werror = 0; - LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__, sock, reuse)); - MONO_ENTER_GC_SAFE; - - /* I _think_ the extension function pointers need to be looked - * up for each socket. FIXME: check the best way to store - * pointers to functions in managed objects that still works - * on 64bit platforms. - */ - ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (gchar *)&disco_guid, sizeof (GUID), - (gchar *)&_wapi_disconnectex, sizeof (void *), &output_bytes, NULL, NULL); - - MONO_EXIT_GC_SAFE; - - if (ret != 0) { - /* make sure that WSAIoctl didn't put crap in the - * output pointer - */ - _wapi_disconnectex = NULL; - - MONO_ENTER_GC_SAFE; - - /* - * Use the SIO_GET_EXTENSION_FUNCTION_POINTER to - * determine the address of the disconnect method without - * taking a hard dependency on a single provider - * - * For an explanation of why this is done, you can read - * the article at http://www.codeproject.com/internet/jbsocketserver3.asp - */ - ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (gchar *)&trans_guid, sizeof(GUID), - (gchar *)&_wapi_transmitfile, sizeof(void *), &output_bytes, NULL, NULL); - - MONO_EXIT_GC_SAFE; - - if (ret != 0) - _wapi_transmitfile = NULL; - } - mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted); if (interrupted) { *werror = WSAEINTR; @@ -1375,17 +1343,7 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolea } MONO_ENTER_GC_SAFE; - - if (_wapi_disconnectex != NULL) { - if (!_wapi_disconnectex (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0)) - *werror = WSAGetLastError (); - } else if (_wapi_transmitfile != NULL) { - if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0))) - *werror = WSAGetLastError (); - } else { - *werror = ERROR_NOT_SUPPORTED; - } - + *werror = mono_w32socket_disconnect (sock, reuse); MONO_EXIT_GC_SAFE; mono_thread_info_uninstall_interrupt (&interrupted); @@ -1395,10 +1353,10 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolea #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */ gint32 -ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking) { int ret; - guchar *buf; + gchar *buf; gint32 alen; int recvflags = 0; gboolean interrupted; @@ -1410,7 +1368,7 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *bu if (offset > alen - count) return 0; - buf = mono_array_addr (buffer, guchar, offset); + buf = mono_array_addr (buffer, gchar, offset); recvflags = convert_socketflags (flags); if (recvflags == -1) { @@ -1423,21 +1381,11 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *bu return 0; MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - { - curthread->interrupt_on_stop = (gpointer)TRUE; - ret = alertable_recv (sock, buf, count, recvflags, blocking); - curthread->interrupt_on_stop = (gpointer)FALSE; - } -#else - ret = _wapi_recv (sock, buf, count, recvflags); -#endif - + ret = mono_w32socket_recv (sock, buf, count, recvflags, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1450,13 +1398,13 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *bu } gint32 -ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking) { int ret, count; gboolean interrupted; - DWORD recv; + guint32 recv; WSABUF *wsabufs; - DWORD recvflags = 0; + guint32 recvflags = 0; *werror = 0; @@ -1476,17 +1424,11 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArr } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_WSARecv (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking); -#else - ret = WSARecv (sock, wsabufs, count, &recv, &recvflags, NULL, NULL); -#endif - + ret = mono_w32socket_recvbuffers (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1499,11 +1441,11 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArr } gint32 -ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *werror, gboolean blocking) { MonoError error; int ret; - guchar *buf; + gchar *buf; gint32 alen; int recvflags = 0; struct sockaddr *sa; @@ -1524,7 +1466,7 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray return 0; } - buf = mono_array_addr (buffer, guchar, offset); + buf = mono_array_addr (buffer, gchar, offset); recvflags = convert_socketflags (flags); if (recvflags == -1) { @@ -1540,17 +1482,11 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking); -#else - ret = _wapi_recvfrom (sock, buf, count, recvflags, sa, &sa_size); -#endif - + ret = mono_w32socket_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); @@ -1583,10 +1519,10 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray } gint32 -ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking) { int ret; - guchar *buf; + gchar *buf; gint32 alen; int sendflags = 0; gboolean interrupted; @@ -1599,7 +1535,7 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffe LOGDEBUG (g_message("%s: alen: %d", __func__, alen)); - buf = mono_array_addr (buffer, guchar, offset); + buf = mono_array_addr (buffer, gchar, offset); LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count)); @@ -1616,17 +1552,11 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffe } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_send (sock, buf, count, sendflags, blocking); -#else - ret = _wapi_send (sock, buf, count, sendflags); -#endif - + ret = mono_w32socket_send (sock, buf, count, sendflags, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1639,12 +1569,12 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffe } gint32 -ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking) { int ret, count; - DWORD sent; + guint32 sent; WSABUF *wsabufs; - DWORD sendflags = 0; + guint32 sendflags = 0; gboolean interrupted; *werror = 0; @@ -1665,17 +1595,11 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_WSASend (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking); -#else - ret = WSASend (sock, wsabufs, count, &sent, sendflags, NULL, NULL); -#endif - + ret = mono_w32socket_sendbuffers (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1688,11 +1612,11 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray } gint32 -ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *werror, gboolean blocking) { MonoError error; int ret; - guchar *buf; + gchar *buf; gint32 alen; int sendflags = 0; struct sockaddr *sa; @@ -1716,7 +1640,7 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock, MonoArray *buf LOGDEBUG (g_message ("%s: alen: %d", __func__, alen)); - buf = mono_array_addr (buffer, guchar, offset); + buf = mono_array_addr (buffer, gchar, offset); LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count)); @@ -1735,17 +1659,11 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock, MonoArray *buf } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_sendto (sock, buf, count, sendflags, sa, sa_size, blocking); -#else - ret = _wapi_sendto (sock, buf, count, sendflags, sa, sa_size); -#endif - + ret = mono_w32socket_sendto (sock, buf, count, sendflags, sa, sa_size, blocking); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) @@ -1867,11 +1785,7 @@ ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 } while (ret == -1 && errno == EINTR); if (ret == -1) { -#ifdef HOST_WIN32 - *werror = (errno > 0 && errno < WSABASEERR) ? errno + WSABASEERR : errno; -#else - *werror = errno_to_WSA (errno, __func__); -#endif + *werror = mono_w32socket_convert_error (errno); g_free (pfds); return; } @@ -1927,7 +1841,7 @@ int_to_object (MonoDomain *domain, int val, MonoError *error) } void -ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *werror) { int system_level = 0; int system_name = 0; @@ -1984,28 +1898,28 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, g switch (name) { case SocketOptionName_Linger: case SocketOptionName_DontLinger: - ret = _wapi_getsockopt (sock, system_level, system_name, &linger, &lingersize); + ret = mono_w32socket_getsockopt (sock, system_level, system_name, &linger, &lingersize); break; case SocketOptionName_SendTimeout: case SocketOptionName_ReceiveTimeout: - ret = _wapi_getsockopt (sock, system_level, system_name, (char *)&time_ms, &time_ms_size); + ret = mono_w32socket_getsockopt (sock, system_level, system_name, (char *)&time_ms, &time_ms_size); break; #ifdef SO_PEERCRED case SocketOptionName_PeerCred: - ret = _wapi_getsockopt (sock, system_level, system_name, &cred, &credsize); + ret = mono_w32socket_getsockopt (sock, system_level, system_name, &cred, &credsize); break; #endif default: - ret = _wapi_getsockopt (sock, system_level, system_name, &val, &valsize); + ret = mono_w32socket_getsockopt (sock, system_level, system_name, &val, &valsize); } MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); return; } @@ -2092,7 +2006,7 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, g } void -ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *werror) { int system_level = 0; int system_name = 0; @@ -2116,12 +2030,12 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (SOCKET sock, g MONO_ENTER_GC_SAFE; - ret = _wapi_getsockopt (sock, system_level, system_name, buf, &valsize); + ret = mono_w32socket_getsockopt (sock, system_level, system_name, buf, &valsize); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); } #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ) @@ -2205,7 +2119,7 @@ get_local_interface_id (int family) #endif /* defined(__APPLE__) || defined(__FreeBSD__) */ void -ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *werror) { struct linger linger; int system_level = 0; @@ -2253,8 +2167,7 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 linger.l_linger = *(guint32 *)(((char *)obj_val) + field->offset); valsize = sizeof (linger); - ret = _wapi_setsockopt (sock, system_level, - system_name, &linger, valsize); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, valsize); break; case SocketOptionName_AddMembership: case SocketOptionName_DropMembership: @@ -2293,9 +2206,7 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 mreq6.ipv6mr_interface = get_local_interface_id (AF_INET6); #endif - ret = _wapi_setsockopt (sock, system_level, - system_name, &mreq6, - sizeof (mreq6)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq6, sizeof (mreq6)); } else if (system_level == sol_ip) { #ifdef HAVE_STRUCT_IP_MREQN struct ip_mreqn mreq = {{0}}; @@ -2330,9 +2241,7 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 mreq.imr_interface = ipaddress_to_struct_in_addr (address); #endif /* HAVE_STRUCT_IP_MREQN */ - ret = _wapi_setsockopt (sock, system_level, - system_name, &mreq, - sizeof (mreq)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq, sizeof (mreq)); } break; } @@ -2351,13 +2260,13 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 if (valsize == 1) { linger.l_onoff = (*buf) ? 0 : 1; linger.l_linger = 0; - ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); } else { *werror = WSAEINVAL; } break; default: - ret = _wapi_setsockopt (sock, system_level, system_name, buf, valsize); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, buf, valsize); break; } } else { @@ -2366,7 +2275,7 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 case SocketOptionName_DontLinger: linger.l_onoff = !int_val; linger.l_linger = 0; - ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); break; case SocketOptionName_MulticastInterface: #ifndef HOST_WIN32 @@ -2376,14 +2285,14 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 /* int_val is interface index */ struct ip_mreqn mreq = {{0}}; mreq.imr_ifindex = int_val; - ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &mreq, sizeof (mreq)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, (char *) &mreq, sizeof (mreq)); break; } int_val = GUINT32_TO_BE (int_val); #endif /* HAVE_STRUCT_IP_MREQN */ #endif /* HOST_WIN32 */ /* int_val is in_addr */ - ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val)); break; case SocketOptionName_DontFragment: #ifdef HAVE_IP_MTU_DISCOVER @@ -2396,16 +2305,16 @@ ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint3 #endif default: - ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val)); + ret = mono_w32socket_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val)); } } if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); } void -ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *werror) { int ret; gboolean interrupted; @@ -2421,12 +2330,12 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how, MONO_ENTER_GC_SAFE; /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */ - ret = _wapi_shutdown (sock, how); + ret = mono_w32socket_shutdown (sock, how); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) { @@ -2436,7 +2345,7 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how, } gint -ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *werror) +ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *werror) { glong output_bytes = 0; gchar *i_buffer, *o_buffer; @@ -2467,12 +2376,12 @@ ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code MONO_ENTER_GC_SAFE; - ret = WSAIoctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes, NULL, NULL); + ret = mono_w32socket_ioctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes); MONO_EXIT_GC_SAFE; if (ret == SOCKET_ERROR) { - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); return -1; } @@ -2716,7 +2625,7 @@ ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name) #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) gboolean -ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags, gint32 *werror, gboolean blocking) +ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags, gint32 *werror, gboolean blocking) { HANDLE file; gboolean ret; @@ -2753,17 +2662,11 @@ ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString * } MONO_ENTER_GC_SAFE; - -#ifdef HOST_WIN32 - ret = alertable_TransmitFile (sock, file, 0, 0, NULL, &buffers, flags, blocking); -#else - ret = TransmitFile (sock, file, 0, 0, NULL, &buffers, flags); -#endif - + ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking); MONO_EXIT_GC_SAFE; if (!ret) - *werror = WSAGetLastError (); + *werror = mono_w32socket_get_last_error (); mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) { @@ -2785,31 +2688,17 @@ ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString * } #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */ -gboolean -ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto) -{ -#if defined (SO_REUSEPORT) || defined (HOST_WIN32) - return TRUE; -#else -#ifdef __linux__ - /* Linux always supports double binding for UDP, even on older kernels. */ - if (proto == ProtocolType_Udp) - return TRUE; -#endif - return FALSE; -#endif -} - void mono_network_init (void) { mono_networking_init (); + mono_w32socket_initialize (); } void mono_network_cleanup (void) { - _wapi_cleanup_networking (); + mono_w32socket_cleanup (); mono_networking_shutdown (); } diff --git a/mono/metadata/w32socket.h b/mono/metadata/w32socket.h new file mode 100644 index 00000000000..dade775479a --- /dev/null +++ b/mono/metadata/w32socket.h @@ -0,0 +1,281 @@ +/* + * w32socket.h: System.Net.Sockets.Socket support + * + * Author: + * Dick Porter (dick@ximian.com) + * + * (C) 2001 Ximian, Inc. + */ + +#ifndef _MONO_METADATA_W32SOCKET_H_ +#define _MONO_METADATA_W32SOCKET_H_ + +#include +#include + +#include + +#define INVALID_SOCKET ((SOCKET)(guint32)(~0)) +#define SOCKET_ERROR (-1) + +#ifndef HOST_WIN32 +typedef gint SOCKET; +#endif + +/* This is a copy of System.Net.Sockets.SocketType */ +typedef enum { + SocketType_Stream=1, + SocketType_Dgram=2, + SocketType_Raw=3, + SocketType_Rdm=4, + SocketType_Seqpacket=5, + SocketType_Unknown=-1 +} MonoSocketType; + +/* This is a copy of System.Net.Sockets.AddressFamily */ +typedef enum { + AddressFamily_Unknown=-1, + AddressFamily_Unspecified=0, + AddressFamily_Unix=1, + AddressFamily_InterNetwork=2, + AddressFamily_ImpLink=3, + AddressFamily_Pup=4, + AddressFamily_Chaos=5, + AddressFamily_NS=6, + AddressFamily_Ipx=6, + AddressFamily_Iso=7, + AddressFamily_Osi=7, + AddressFamily_Ecma=8, + AddressFamily_DataKit=9, + AddressFamily_Ccitt=10, + AddressFamily_Sna=11, + AddressFamily_DecNet=12, + AddressFamily_DataLink=13, + AddressFamily_Lat=14, + AddressFamily_HyperChannel=15, + AddressFamily_AppleTalk=16, + AddressFamily_NetBios=17, + AddressFamily_VoiceView=18, + AddressFamily_FireFox=19, + AddressFamily_Banyan=21, + AddressFamily_Atm=22, + AddressFamily_InterNetworkV6=23, + AddressFamily_Cluster=24, + AddressFamily_Ieee12844=25, + AddressFamily_Irda=26, + AddressFamily_NetworkDesigners=28 +} MonoAddressFamily; + +/* This is a copy of System.Net.Sockets.ProtocolType */ +typedef enum { + ProtocolType_IP=0, + ProtocolType_Icmp=1, + ProtocolType_Igmp=2, + ProtocolType_Ggp=3, + ProtocolType_Tcp=6, + ProtocolType_Pup=12, + ProtocolType_Udp=17, + ProtocolType_Idp=22, + ProtocolType_IPv6=41, + ProtocolType_ND=77, + ProtocolType_Raw=255, + ProtocolType_Unspecified=0, + ProtocolType_Ipx=1000, + ProtocolType_Spx=1256, + ProtocolType_SpxII=1257, + ProtocolType_Unknown=-1 +} MonoProtocolType; + +/* This is a copy of System.Net.Sockets.SocketOptionLevel */ +typedef enum { + SocketOptionLevel_Socket=65535, + SocketOptionLevel_IP=0, + SocketOptionLevel_IPv6=41, + SocketOptionLevel_Tcp=6, + SocketOptionLevel_Udp=17 +} MonoSocketOptionLevel; + +/* This is a copy of System.Net.Sockets.SocketOptionName */ +typedef enum { + SocketOptionName_Debug=1, + SocketOptionName_AcceptConnection=2, + SocketOptionName_ReuseAddress=4, + SocketOptionName_KeepAlive=8, + SocketOptionName_DontRoute=16, + SocketOptionName_IPProtectionLevel = 23, + SocketOptionName_IPv6Only = 27, + SocketOptionName_Broadcast=32, + SocketOptionName_UseLoopback=64, + SocketOptionName_Linger=128, + SocketOptionName_OutOfBandInline=256, + SocketOptionName_DontLinger= -129, + SocketOptionName_ExclusiveAddressUse= -5, + SocketOptionName_SendBuffer= 4097, + SocketOptionName_ReceiveBuffer=4098, + SocketOptionName_SendLowWater=4099, + SocketOptionName_ReceiveLowWater=4100, + SocketOptionName_SendTimeout=4101, + SocketOptionName_ReceiveTimeout=4102, + SocketOptionName_Error=4103, + SocketOptionName_Type=4104, + SocketOptionName_MaxConnections=2147483647, + SocketOptionName_IPOptions=1, + SocketOptionName_HeaderIncluded=2, + SocketOptionName_TypeOfService=3, + SocketOptionName_IpTimeToLive=4, + SocketOptionName_MulticastInterface=9, + SocketOptionName_MulticastTimeToLive=10, + SocketOptionName_MulticastLoopback=11, + SocketOptionName_AddMembership=12, + SocketOptionName_DropMembership=13, + SocketOptionName_DontFragment=14, + SocketOptionName_AddSourceMembership=15, + SocketOptionName_DropSourceMembership=16, + SocketOptionName_BlockSource=17, + SocketOptionName_UnblockSource=18, + SocketOptionName_PacketInformation=19, + SocketOptionName_NoDelay=1, + SocketOptionName_BsdUrgent=2, + SocketOptionName_Expedited=2, + SocketOptionName_NoChecksum=1, + SocketOptionName_ChecksumCoverage=20, + SocketOptionName_HopLimit=21, + + /* This is Mono-specific, keep it in sync with + * Mono.Posix/PeerCred.cs + */ + SocketOptionName_PeerCred=10001 +} MonoSocketOptionName; + +/* This is a copy of System.Net.Sockets.SocketFlags */ +typedef enum { + SocketFlags_None = 0x0000, + SocketFlags_OutOfBand = 0x0001, + SocketFlags_MaxIOVectorLength = 0x0010, + SocketFlags_Peek = 0x0002, + SocketFlags_DontRoute = 0x0004, + SocketFlags_Partial = 0x8000 +} MonoSocketFlags; + +typedef struct +{ + MonoObject obj; + gint pid; + gint uid; + gint gid; +} MonoPeerCredData; + +gpointer +ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, + gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *error); + +gint32 +ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void); + +gint32 +ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *error); + +gpointer +ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *error, gboolean blocking); + +void +ves_icall_System_Net_Sockets_Socket_Listen_internal (gsize sock, guint32 backlog, gint32 *error); + +MonoObject* +ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *error); + +MonoObject* +ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObject *sockaddr, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObject *sockaddr, gint32 *error, gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, + gint32 flags, gint32 *error, gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *error, + gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, + gint32 flags, MonoObject **sockaddr, gint32 *error, gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, + gint32 flags, gint32 *error, gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *error, + gboolean blocking); + +gint32 +ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, + gint32 flags, MonoObject *sockaddr, gint32 *error, gboolean blocking); + +void +ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gint32 level, gint32 name, + MonoObject **obj_val, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gint32 level, gint32 name, + MonoArray **byte_val, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock, gint32 level, gint32 name, + MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error); + +int +ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, MonoArray *input, MonoArray *output, + gint32 *error); + +MonoBoolean +ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases, + MonoArray **h_addr_list, gint32 hint); + +MonoBoolean +ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases, + MonoArray **h_addr_list, gint32 hint); + +MonoBoolean +ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name); + +MonoBoolean +ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint timeout, gint32 *error); + +void +ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *error); + +gboolean +ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoString *filename, MonoArray *pre_buffer, + MonoArray *post_buffer, gint flags, gint32 *error, gboolean blocking); + +void +icall_cancel_blocking_socket_operation (MonoThread *thread); + +gboolean +ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto); + +void +mono_network_init(void); + +void +mono_network_cleanup(void); + +#endif /* _MONO_METADATA_W32SOCKET_H_ */ diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 0e95ae85f20..ce2656126b6 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -59,11 +59,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/mono/mini/driver.c b/mono/mini/driver.c index da2033e5e8c..40de446bc05 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/msvc/libmonoruntime.vcxproj b/msvc/libmonoruntime.vcxproj index f0e8db4e9a8..6c94d1ff21e 100644 --- a/msvc/libmonoruntime.vcxproj +++ b/msvc/libmonoruntime.vcxproj @@ -28,7 +28,7 @@ - + @@ -100,7 +100,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -199,7 +199,7 @@ - + diff --git a/msvc/libmonoruntime.vcxproj.filters b/msvc/libmonoruntime.vcxproj.filters index 1154e5e8fc7..8de9920a9ea 100644 --- a/msvc/libmonoruntime.vcxproj.filters +++ b/msvc/libmonoruntime.vcxproj.filters @@ -154,7 +154,7 @@ Source Files - + Source Files @@ -247,7 +247,7 @@ Source Files - + Source Files @@ -456,7 +456,7 @@ Header Files - + Header Files @@ -525,7 +525,7 @@ Header Files - + Header Files diff --git a/msvc/pedump.vcxproj b/msvc/pedump.vcxproj index ad0d476fd93..e997a22ae4b 100644 --- a/msvc/pedump.vcxproj +++ b/msvc/pedump.vcxproj @@ -234,7 +234,7 @@ - + diff --git a/msvc/pedump.vcxproj.filters b/msvc/pedump.vcxproj.filters index 72a54e16255..c7f55c9b0d1 100644 --- a/msvc/pedump.vcxproj.filters +++ b/msvc/pedump.vcxproj.filters @@ -79,7 +79,7 @@ Source Files - + Source Files -- 2.25.1