[io-layer] Extract socket (#4241)
authorLudovic Henry <ludovic@xamarin.com>
Thu, 19 Jan 2017 14:25:55 +0000 (09:25 -0500)
committerGitHub <noreply@github.com>
Thu, 19 Jan 2017 14:25:55 +0000 (09:25 -0500)
* [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

34 files changed:
mono/io-layer/Makefile.am
mono/io-layer/error.c
mono/io-layer/error.h
mono/io-layer/socket-private.h [deleted file]
mono/io-layer/socket-wrappers.h [deleted file]
mono/io-layer/sockets.c [deleted file]
mono/io-layer/sockets.h [deleted file]
mono/io-layer/uglify.h
mono/io-layer/wapi-private.h
mono/io-layer/wapi-remap.h
mono/io-layer/wapi.c
mono/io-layer/wapi.h
mono/metadata/Makefile.am
mono/metadata/appdomain.c
mono/metadata/icall.c
mono/metadata/socket-io-windows-internals.h [deleted file]
mono/metadata/socket-io-windows.c [deleted file]
mono/metadata/socket-io.c [deleted file]
mono/metadata/socket-io.h [deleted file]
mono/metadata/threadpool-io.c
mono/metadata/threadpool-io.h
mono/metadata/threadpool-worker-default.c
mono/metadata/threadpool.c
mono/metadata/w32socket-internals.h [new file with mode: 0644]
mono/metadata/w32socket-unix.c [new file with mode: 0644]
mono/metadata/w32socket-win32.c [new file with mode: 0644]
mono/metadata/w32socket.c [new file with mode: 0644]
mono/metadata/w32socket.h [new file with mode: 0644]
mono/mini/debugger-agent.c
mono/mini/driver.c
msvc/libmonoruntime.vcxproj
msvc/libmonoruntime.vcxproj.filters
msvc/pedump.vcxproj
msvc/pedump.vcxproj.filters

index c0f5119c0060460b2c9ccff48e65996254731ced..2247a51a71c391abbdef66445a3230cb040dcfe7 100644 (file)
@@ -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             \
index bc884c3d8d9f14f8f97385b51ff70fae3f3bc713..5b1b22d6dcd08d7cd3871e3ce99c52310f6cc7cf 100644 (file)
@@ -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)
 {
index 7271d71bb1c93a72f33017a4f9989d7771c1d186..d4ffe1e92359b9d7d01b7b4f0547ccc45c963c78 100644 (file)
@@ -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 (file)
index 31bbfe3..0000000
+++ /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 <config.h>
-#include <glib.h>
-
-#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 (file)
index a532ce9..0000000
+++ /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 <config.h>
-#ifdef HAVE_SYS_SELECT_H
-#  include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#  include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#  include <sys/socket.h>
-#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 (file)
index d98ac67..0000000
+++ /dev/null
@@ -1,1457 +0,0 @@
-/*
- * sockets.c:  Socket handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-
-#ifndef DISABLE_SOCKETS
-
-#include <glib.h>
-#include <pthread.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#ifdef HAVE_SYS_UIO_H
-#  include <sys/uio.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#  include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
-#endif
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>    /* defines SIOCATMARK */
-#endif
-#include <unistd.h>
-#include <fcntl.h>
-
-#ifndef HAVE_MSG_NOSIGNAL
-#include <signal.h>
-#endif
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/socket-private.h>
-#include <mono/io-layer/socket-wrappers.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-poll.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#ifdef HAVE_SYS_SENDFILE_H
-#include <sys/sendfile.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#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 (file)
index d634ae9..0000000
+++ /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_ */
index fdadebc120790a595741d4c3a679bf8e23bd164c..0335d0a72000811f028501478e65cdf4b930dbd4 100644 (file)
@@ -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
index 9be764c15218771e3bb46150829b67b85286ca1d..f39d4e4fab4ddf2b4ca6e9bcb7685c42e7dfc0a5 100644 (file)
@@ -25,7 +25,6 @@
 extern gboolean _wapi_has_shut_down;
 
 #include <mono/io-layer/io-private.h>
-#include <mono/io-layer/socket-private.h>
 #include <mono/metadata/w32handle.h>
 
 struct _WapiHandle_shared_ref
index e8426c4da830a792456cf52eede2f13fb9fb725d..7cc3b89ff380dc094993a8b58c983d5881740c49 100644 (file)
@@ -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
 #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__ */
index fc9c00ccd909b7462b40556820b8848a2e666e5b..d4da229603e49264010aa78f072d525d308dd690 100644 (file)
@@ -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
index 65c98a4a584053360610b627e044d9715968baeb..fb0bf4fbce951609667fcddafd9692ca8e024ad7 100644 (file)
@@ -18,7 +18,6 @@
 #include <mono/io-layer/io.h>
 #include <mono/io-layer/io-portability.h>
 #include <mono/io-layer/error.h>
-#include <mono/io-layer/sockets.h>
 
 G_BEGIN_DECLS
 
index 92b99cd28bcef469592a7e8c8c4ff21c1caae7cb..5deda477e2d9a083748b77e8fb56e6f37100c9fb 100644 (file)
@@ -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          \
index cd8df1cb0632d0bd136d42a648b42d17d42e07dd..74323ab37b36e9a6fc94a85a049c4c2910d3ce3e 100644 (file)
@@ -43,7 +43,6 @@
 #include <mono/metadata/exception-internals.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/threadpool.h>
-#include <mono/metadata/socket-io.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/mono-gc.h>
@@ -60,6 +59,7 @@
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/reflection-internals.h>
 #include <mono/metadata/abi-details.h>
+#include <mono/metadata/w32socket.h>
 #include <mono/utils/mono-uri.h>
 #include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-path.h>
index 3d772e9a09200d6d3be7b140961a2ca359bd5379..322f77805abe1a15e84d59d892e0b9161923da9b 100644 (file)
@@ -49,7 +49,7 @@
 #include <mono/metadata/file-io.h>
 #include <mono/metadata/console-io.h>
 #include <mono/metadata/mono-route.h>
-#include <mono/metadata/socket-io.h>
+#include <mono/metadata/w32socket.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/metadata-internals.h>
diff --git a/mono/metadata/socket-io-windows-internals.h b/mono/metadata/socket-io-windows-internals.h
deleted file mode 100644 (file)
index b76f9cb..0000000
+++ /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 <config.h>
-#include <glib.h>
-#include <mono/io-layer/io-layer.h>
-
-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-windows.c b/mono/metadata/socket-io-windows.c
deleted file mode 100644 (file)
index 125dbeb..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
-* 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.
-*/
-#include <config.h>
-#include <glib.h>
-
-#include "mono/metadata/socket-io-windows-internals.h"
-
-#define LOGDEBUG(...)  
-
-static gboolean set_blocking (SOCKET sock, gboolean block)
-{
-       u_long non_block = block ? 0 : 1;
-       return ioctlsocket (sock, FIONBIO, &non_block) != SOCKET_ERROR;
-}
-
-static DWORD get_socket_timeout (SOCKET sock, int optname)
-{
-       DWORD timeout = 0;
-       int optlen = sizeof (DWORD);
-       if (getsockopt (sock, SOL_SOCKET, optname, (char *)&timeout, &optlen) == SOCKET_ERROR) {
-               WSASetLastError (0);
-               return WSA_INFINITE;
-       }
-       if (timeout == 0)
-               timeout = WSA_INFINITE; // 0 means infinite
-       return timeout;
-}
-
-/*
-* Performs an alertable wait for the specified event (FD_ACCEPT_BIT,
-* FD_CONNECT_BIT, FD_READ_BIT, FD_WRITE_BIT) on the specified socket.
-* Returns TRUE if the event is fired without errors. Calls WSASetLastError()
-* with WSAEINTR and returns FALSE if the thread is alerted. If the event is
-* fired but with an error WSASetLastError() is called to set the error and the
-* function returns FALSE.
-*/
-static gboolean alertable_socket_wait (SOCKET sock, int event_bit)
-{
-       static char *EVENT_NAMES[] = { "FD_READ", "FD_WRITE", NULL /*FD_OOB*/, "FD_ACCEPT", "FD_CONNECT", "FD_CLOSE" };
-       gboolean success = FALSE;
-       int error = -1;
-       DWORD timeout = WSA_INFINITE;
-       if (event_bit == FD_READ_BIT || event_bit == FD_WRITE_BIT) {
-               timeout = get_socket_timeout (sock, event_bit == FD_READ_BIT ? SO_RCVTIMEO : SO_SNDTIMEO);
-       }
-       WSASetLastError (0);
-       WSAEVENT event = WSACreateEvent ();
-       if (event != WSA_INVALID_EVENT) {
-               if (WSAEventSelect (sock, event, (1 << event_bit) | FD_CLOSE) != SOCKET_ERROR) {
-                       LOGDEBUG (g_message ("%06d - Calling WSAWaitForMultipleEvents () on socket %d", GetCurrentThreadId (), sock));
-                       DWORD ret = WSAWaitForMultipleEvents (1, &event, TRUE, timeout, TRUE);
-                       if (ret == WSA_WAIT_IO_COMPLETION) {
-                               LOGDEBUG (g_message ("%06d - WSAWaitForMultipleEvents () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), sock));
-                               error = WSAEINTR;
-                       } else if (ret == WSA_WAIT_TIMEOUT) {
-                               error = WSAETIMEDOUT;
-                       } else {
-                               g_assert (ret == WSA_WAIT_EVENT_0);
-                               WSANETWORKEVENTS ne = { 0 };
-                               if (WSAEnumNetworkEvents (sock, event, &ne) != SOCKET_ERROR) {
-                                       if (ne.lNetworkEvents & (1 << event_bit) && ne.iErrorCode[event_bit]) {
-                                               LOGDEBUG (g_message ("%06d - %s error %d on socket %d", GetCurrentThreadId (), EVENT_NAMES[event_bit], ne.iErrorCode[event_bit], sock));
-                                               error = ne.iErrorCode[event_bit];
-                                       } else if (ne.lNetworkEvents & FD_CLOSE_BIT && ne.iErrorCode[FD_CLOSE_BIT]) {
-                                               LOGDEBUG (g_message ("%06d - FD_CLOSE error %d on socket %d", GetCurrentThreadId (), ne.iErrorCode[FD_CLOSE_BIT], sock));
-                                               error = ne.iErrorCode[FD_CLOSE_BIT];
-                                       } else {
-                                               LOGDEBUG (g_message ("%06d - WSAEnumNetworkEvents () finished successfully on socket %d", GetCurrentThreadId (), sock));
-                                               success = TRUE;
-                                               error = 0;
-                                       }
-                               }
-                       }
-                       WSAEventSelect (sock, NULL, 0);
-               }
-               WSACloseEvent (event);
-       }
-       if (error != -1) {
-               WSASetLastError (error);
-       }
-       return success;
-}
-
-#define ALERTABLE_SOCKET_CALL(event_bit, blocking, repeat, ret, op, sock, ...) \
-       LOGDEBUG (g_message ("%06d - Performing %s " #op " () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", sock)); \
-       if (blocking) { \
-               if (set_blocking(sock, FALSE)) { \
-                       while (-1 == (int) (ret = op (sock, __VA_ARGS__))) { \
-                               int _error = WSAGetLastError ();\
-                               if (_error != WSAEWOULDBLOCK && _error != WSA_IO_PENDING) \
-                                       break; \
-                               if (!alertable_socket_wait (sock, event_bit) || !repeat) \
-                                       break; \
-                       } \
-                       int _saved_error = WSAGetLastError (); \
-                       set_blocking (sock, TRUE); \
-                       WSASetLastError (_saved_error); \
-               } \
-       } else { \
-               ret = op (sock, __VA_ARGS__); \
-       } \
-       int _saved_error = WSAGetLastError (); \
-       LOGDEBUG (g_message ("%06d - Finished %s " #op " () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \
-               blocking ? "blocking" : "non-blocking", sock, ret, _saved_error)); \
-       WSASetLastError (_saved_error);
-
-SOCKET alertable_accept (SOCKET s, struct sockaddr *addr, int *addrlen, gboolean blocking)
-{
-       SOCKET newsock = INVALID_SOCKET;
-       ALERTABLE_SOCKET_CALL (FD_ACCEPT_BIT, blocking, TRUE, newsock, accept, s, addr, addrlen);
-       return newsock;
-}
-
-int alertable_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);
-       ret = WSAGetLastError () != 0 ? SOCKET_ERROR : 0;
-       return ret;
-}
-
-int alertable_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking)
-{
-       int ret = SOCKET_ERROR;
-       ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recv, s, buf, len, flags);
-       return ret;
-}
-
-int alertable_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *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 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 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 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 ret = SOCKET_ERROR;
-       ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
-       return ret;
-}
-
-#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)
-{
-       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)) {
-                       error = WSAGetLastError ();
-                       if (error == WSA_IO_PENDING) {
-                               error = 0;
-                               // NOTE: .NET's Socket.SendFile() doesn't honor the Socket's SendTimeout so we shouldn't either
-                               DWORD ret = WaitForSingleObjectEx (overlapped.hEvent, INFINITE, TRUE);
-                               if (ret == WAIT_IO_COMPLETION) {
-                                       LOGDEBUG (g_message ("%06d - WaitForSingleObjectEx () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), hSocket));
-                                       error = WSAEINTR;
-                               } else if (ret == WAIT_TIMEOUT) {
-                                       error = WSAETIMEDOUT;
-                               } else if (ret != WAIT_OBJECT_0) {
-                                       error = GetLastError ();
-                               }
-                       }
-               }
-               WSACloseEvent (overlapped.hEvent);
-       } else {
-               if (!TransmitFile (hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, lpOverlapped, lpTransmitBuffers, dwReserved)) {
-                       error = WSAGetLastError ();
-               }
-       }
-
-       LOGDEBUG (g_message ("%06d - Finished %s TransmitFile () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \
-               blocking ? "blocking" : "non-blocking", hSocket, error == 0, error));
-       WSASetLastError (error);
-
-       return error == 0;
-}
-#endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
diff --git a/mono/metadata/socket-io.c b/mono/metadata/socket-io.c
deleted file mode 100644 (file)
index 606eff3..0000000
+++ /dev/null
@@ -1,2827 +0,0 @@
-/*
- * socket-io.c: Socket IO internal calls
- *
- * Authors:
- *     Dick Porter (dick@ximian.com)
- *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- *
- * This file has been re-licensed under the MIT License:
- * http://opensource.org/licenses/MIT
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#ifndef DISABLE_SOCKETS
-
-#if defined(__APPLE__) || defined(__FreeBSD__)
-#define __APPLE_USE_RFC_3542
-#endif
-
-#include <glib.h>
-#include <string.h>
-#include <stdlib.h>
-#ifdef HOST_WIN32
-#include <ws2tcpip.h>
-#else
-#include <sys/socket.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-
-#include <sys/types.h>
-
-#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
-#include <mono/metadata/socket-io.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/file-io.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/threads-types.h>
-#include <mono/metadata/threadpool-io.h>
-#include <mono/utils/mono-poll.h>
-/* FIXME change this code to not mess so much with the internals */
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/domain-internals.h>
-#include <mono/utils/mono-threads.h>
-#include <mono/utils/mono-memory-model.h>
-#include <mono/utils/networking.h>
-#include <mono/metadata/w32handle.h>
-
-#include <time.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
-#endif
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>    /* defines SIOCATMARK */
-#endif
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-
-#ifdef HAVE_GETIFADDRS
-// <net/if.h> must be included before <ifaddrs.h>
-#include <ifaddrs.h>
-#endif
-
-#if defined(_MSC_VER) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
-#include <MSWSock.h>
-#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__)  */
-
-static void
-abort_syscall (gpointer data)
-{
-       mono_thread_info_abort_socket_syscall_for_close ((MonoNativeThreadId) (gsize) data);
-}
-
-static gint32
-convert_family (MonoAddressFamily mono_family)
-{
-       switch (mono_family) {
-       case AddressFamily_Unknown:
-       case AddressFamily_ImpLink:
-       case AddressFamily_Pup:
-       case AddressFamily_Chaos:
-       case AddressFamily_Iso:
-       case AddressFamily_Ecma:
-       case AddressFamily_DataKit:
-       case AddressFamily_Ccitt:
-       case AddressFamily_DataLink:
-       case AddressFamily_Lat:
-       case AddressFamily_HyperChannel:
-       case AddressFamily_NetBios:
-       case AddressFamily_VoiceView:
-       case AddressFamily_FireFox:
-       case AddressFamily_Banyan:
-       case AddressFamily_Atm:
-       case AddressFamily_Cluster:
-       case AddressFamily_Ieee12844:
-       case AddressFamily_NetworkDesigners:
-               g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
-               return -1;
-       case AddressFamily_Unspecified:
-               return AF_UNSPEC;
-       case AddressFamily_Unix:
-               return AF_UNIX;
-       case AddressFamily_InterNetwork:
-               return AF_INET;
-       case AddressFamily_AppleTalk:
-               return AF_APPLETALK;
-       case AddressFamily_InterNetworkV6:
-               return AF_INET6;
-       case AddressFamily_DecNet:
-#ifdef AF_DECnet
-               return AF_DECnet;
-#else
-               return -1;
-#endif
-       case AddressFamily_Ipx:
-#ifdef AF_IPX
-               return AF_IPX;
-#else
-               return -1;
-#endif
-       case AddressFamily_Sna:
-#ifdef AF_SNA
-               return AF_SNA;
-#else
-               return -1;
-#endif
-       case AddressFamily_Irda:
-#ifdef AF_IRDA
-               return AF_IRDA;
-#else
-               return -1;
-#endif
-       default:
-               g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
-               return -1;
-       }
-}
-
-static MonoAddressFamily
-convert_to_mono_family (guint16 af_family)
-{
-       switch (af_family) {
-       case AF_UNSPEC:
-               return AddressFamily_Unspecified;
-       case AF_UNIX:
-               return AddressFamily_Unix;
-       case AF_INET:
-               return AddressFamily_InterNetwork;
-#ifdef AF_IPX
-       case AF_IPX:
-               return AddressFamily_Ipx;
-#endif
-#ifdef AF_SNA
-       case AF_SNA:
-               return AddressFamily_Sna;
-#endif
-#ifdef AF_DECnet
-       case AF_DECnet:
-               return AddressFamily_DecNet;
-#endif
-       case AF_APPLETALK:
-               return AddressFamily_AppleTalk;
-       case AF_INET6:
-               return AddressFamily_InterNetworkV6;
-#ifdef AF_IRDA
-       case AF_IRDA:
-               return AddressFamily_Irda;
-#endif
-       default:
-               g_warning ("unknown address family 0x%x", af_family);
-               return AddressFamily_Unknown;
-       }
-}
-
-static gint32
-convert_type (MonoSocketType mono_type)
-{
-       switch (mono_type) {
-       case SocketType_Stream:
-               return SOCK_STREAM;
-       case SocketType_Dgram:
-               return SOCK_DGRAM;
-       case SocketType_Raw:
-               return SOCK_RAW;
-       case SocketType_Rdm:
-#ifdef SOCK_RDM
-               return SOCK_RDM;
-#else
-               return -1;
-#endif
-       case SocketType_Seqpacket:
-               return SOCK_SEQPACKET;
-       case SocketType_Unknown:
-               g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
-               return -1;
-       default:
-               g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
-               return -1;
-       }
-}
-
-static gint32
-convert_proto (MonoProtocolType mono_proto)
-{
-       switch (mono_proto) {
-       case ProtocolType_IP:
-       case ProtocolType_IPv6:
-       case ProtocolType_Icmp:
-       case ProtocolType_Igmp:
-       case ProtocolType_Ggp:
-       case ProtocolType_Tcp:
-       case ProtocolType_Pup:
-       case ProtocolType_Udp:
-       case ProtocolType_Idp:
-               /* These protocols are known (on my system at least) */
-               return mono_proto;
-       case ProtocolType_ND:
-       case ProtocolType_Raw:
-       case ProtocolType_Ipx:
-       case ProtocolType_Spx:
-       case ProtocolType_SpxII:
-       case ProtocolType_Unknown:
-               /* These protocols arent */
-               g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
-               return -1;
-       default:
-               return -1;
-       }
-}
-
-/* Convert MonoSocketFlags */
-static gint32
-convert_socketflags (gint32 sflags)
-{
-       gint32 flags = 0;
-
-       if (!sflags)
-               /* SocketFlags.None */
-               return 0;
-
-       if (sflags & ~(SocketFlags_OutOfBand | SocketFlags_MaxIOVectorLength | SocketFlags_Peek | 
-                       SocketFlags_DontRoute | SocketFlags_Partial))
-               /* Contains invalid flag values */
-               return -1;
-
-       if (sflags & SocketFlags_OutOfBand)
-               flags |= MSG_OOB;
-       if (sflags & SocketFlags_Peek)
-               flags |= MSG_PEEK;
-       if (sflags & SocketFlags_DontRoute)
-               flags |= MSG_DONTROUTE;
-
-       /* Ignore Partial - see bug 349688.  Don't return -1, because
-        * according to the comment in that bug ms runtime doesn't for
-        * UDP sockets (this means we will silently ignore it for TCP
-        * too)
-        */
-#ifdef MSG_MORE
-       if (sflags & SocketFlags_Partial)
-               flags |= MSG_MORE;
-#endif
-#if 0
-       /* Don't do anything for MaxIOVectorLength */
-       if (sflags & SocketFlags_MaxIOVectorLength)
-               return -1;      
-#endif
-       return flags;
-}
-
-/*
- * Returns:
- *    0 on success (mapped mono_level and mono_name to system_level and system_name
- *   -1 on error
- *   -2 on non-fatal error (ie, must ignore)
- */
-static gint32
-convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level, MonoSocketOptionName mono_name, int *system_level, int *system_name)
-{
-       switch (mono_level) {
-       case SocketOptionLevel_Socket:
-               *system_level = SOL_SOCKET;
-               
-               switch (mono_name) {
-               case SocketOptionName_DontLinger:
-                       /* This is SO_LINGER, because the setsockopt
-                        * internal call maps DontLinger to SO_LINGER
-                        * with l_onoff=0
-                        */
-                       *system_name = SO_LINGER;
-                       break;
-               case SocketOptionName_Debug:
-                       *system_name = SO_DEBUG;
-                       break;
-#ifdef SO_ACCEPTCONN
-               case SocketOptionName_AcceptConnection:
-                       *system_name = SO_ACCEPTCONN;
-                       break;
-#endif
-               case SocketOptionName_ReuseAddress:
-                       *system_name = SO_REUSEADDR;
-                       break;
-               case SocketOptionName_KeepAlive:
-                       *system_name = SO_KEEPALIVE;
-                       break;
-               case SocketOptionName_DontRoute:
-                       *system_name = SO_DONTROUTE;
-                       break;
-               case SocketOptionName_Broadcast:
-                       *system_name = SO_BROADCAST;
-                       break;
-               case SocketOptionName_Linger:
-                       *system_name = SO_LINGER;
-                       break;
-               case SocketOptionName_OutOfBandInline:
-                       *system_name = SO_OOBINLINE;
-                       break;
-               case SocketOptionName_SendBuffer:
-                       *system_name = SO_SNDBUF;
-                       break;
-               case SocketOptionName_ReceiveBuffer:
-                       *system_name = SO_RCVBUF;
-                       break;
-               case SocketOptionName_SendLowWater:
-                       *system_name = SO_SNDLOWAT;
-                       break;
-               case SocketOptionName_ReceiveLowWater:
-                       *system_name = SO_RCVLOWAT;
-                       break;
-               case SocketOptionName_SendTimeout:
-                       *system_name = SO_SNDTIMEO;
-                       break;
-               case SocketOptionName_ReceiveTimeout:
-                       *system_name = SO_RCVTIMEO;
-                       break;
-               case SocketOptionName_Error:
-                       *system_name = SO_ERROR;
-                       break;
-               case SocketOptionName_Type:
-                       *system_name = SO_TYPE;
-                       break;
-#ifdef SO_PEERCRED
-               case SocketOptionName_PeerCred:
-                       *system_name = SO_PEERCRED;
-                       break;
-#endif
-               case SocketOptionName_ExclusiveAddressUse:
-#ifdef SO_EXCLUSIVEADDRUSE
-                       *system_name = SO_EXCLUSIVEADDRUSE;
-                       break;
-#endif
-               case SocketOptionName_UseLoopback:
-#ifdef SO_USELOOPBACK
-                       *system_name = SO_USELOOPBACK;
-                       break;
-#endif
-               case SocketOptionName_MaxConnections:
-#ifdef SO_MAXCONN
-                       *system_name = SO_MAXCONN;
-                       break;
-#elif defined(SOMAXCONN)
-                       *system_name = SOMAXCONN;
-                       break;
-#endif
-               default:
-                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
-                       return -1;
-               }
-               break;
-               
-       case SocketOptionLevel_IP:
-               *system_level = mono_networking_get_ip_protocol ();
-               
-               switch (mono_name) {
-               case SocketOptionName_IPOptions:
-                       *system_name = IP_OPTIONS;
-                       break;
-#ifdef IP_HDRINCL
-               case SocketOptionName_HeaderIncluded:
-                       *system_name = IP_HDRINCL;
-                       break;
-#endif
-#ifdef IP_TOS
-               case SocketOptionName_TypeOfService:
-                       *system_name = IP_TOS;
-                       break;
-#endif
-#ifdef IP_TTL
-               case SocketOptionName_IpTimeToLive:
-                       *system_name = IP_TTL;
-                       break;
-#endif
-               case SocketOptionName_MulticastInterface:
-                       *system_name = IP_MULTICAST_IF;
-                       break;
-               case SocketOptionName_MulticastTimeToLive:
-                       *system_name = IP_MULTICAST_TTL;
-                       break;
-               case SocketOptionName_MulticastLoopback:
-                       *system_name = IP_MULTICAST_LOOP;
-                       break;
-               case SocketOptionName_AddMembership:
-                       *system_name = IP_ADD_MEMBERSHIP;
-                       break;
-               case SocketOptionName_DropMembership:
-                       *system_name = IP_DROP_MEMBERSHIP;
-                       break;
-#ifdef HAVE_IP_PKTINFO
-               case SocketOptionName_PacketInformation:
-                       *system_name = IP_PKTINFO;
-                       break;
-#endif /* HAVE_IP_PKTINFO */
-
-               case SocketOptionName_DontFragment:
-#ifdef HAVE_IP_DONTFRAGMENT
-                       *system_name = IP_DONTFRAGMENT;
-                       break;
-#elif defined HAVE_IP_MTU_DISCOVER
-                       /* Not quite the same */
-                       *system_name = IP_MTU_DISCOVER;
-                       break;
-#else
-                       /* If the flag is not available on this system, we can ignore this error */
-                       return -2;
-#endif /* HAVE_IP_DONTFRAGMENT */
-               case SocketOptionName_AddSourceMembership:
-               case SocketOptionName_DropSourceMembership:
-               case SocketOptionName_BlockSource:
-               case SocketOptionName_UnblockSource:
-                       /* Can't figure out how to map these, so fall
-                        * through
-                        */
-               default:
-                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
-                       return -1;
-               }
-               break;
-
-       case SocketOptionLevel_IPv6:
-               *system_level = mono_networking_get_ipv6_protocol ();
-
-               switch (mono_name) {
-               case SocketOptionName_IpTimeToLive:
-               case SocketOptionName_HopLimit:
-                       *system_name = IPV6_UNICAST_HOPS;
-                       break;
-               case SocketOptionName_MulticastInterface:
-                       *system_name = IPV6_MULTICAST_IF;
-                       break;
-               case SocketOptionName_MulticastTimeToLive:
-                       *system_name = IPV6_MULTICAST_HOPS;
-                       break;
-               case SocketOptionName_MulticastLoopback:
-                       *system_name = IPV6_MULTICAST_LOOP;
-                       break;
-               case SocketOptionName_AddMembership:
-                       *system_name = IPV6_JOIN_GROUP;
-                       break;
-               case SocketOptionName_DropMembership:
-                       *system_name = IPV6_LEAVE_GROUP;
-                       break;
-               case SocketOptionName_IPv6Only:
-#ifdef IPV6_V6ONLY
-                       *system_name = IPV6_V6ONLY;
-#else
-                       return -1;
-#endif
-                       break;
-               case SocketOptionName_PacketInformation:
-#ifdef HAVE_IPV6_PKTINFO
-                       *system_name = IPV6_PKTINFO;
-#endif
-                       break;
-               case SocketOptionName_HeaderIncluded:
-               case SocketOptionName_IPOptions:
-               case SocketOptionName_TypeOfService:
-               case SocketOptionName_DontFragment:
-               case SocketOptionName_AddSourceMembership:
-               case SocketOptionName_DropSourceMembership:
-               case SocketOptionName_BlockSource:
-               case SocketOptionName_UnblockSource:
-                       /* Can't figure out how to map these, so fall
-                        * through
-                        */
-               default:
-                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name);
-                       return -1;
-               }
-               break;  /* SocketOptionLevel_IPv6 */
-               
-       case SocketOptionLevel_Tcp:
-               *system_level = mono_networking_get_tcp_protocol ();
-               
-               switch (mono_name) {
-               case SocketOptionName_NoDelay:
-                       *system_name = TCP_NODELAY;
-                       break;
-#if 0
-                       /* The documentation is talking complete
-                        * bollocks here: rfc-1222 is titled
-                        * 'Advancing the NSFNET Routing Architecture'
-                        * and doesn't mention either of the words
-                        * "expedite" or "urgent".
-                        */
-               case SocketOptionName_BsdUrgent:
-               case SocketOptionName_Expedited:
-#endif
-               default:
-                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
-                       return -1;
-               }
-               break;
-               
-       case SocketOptionLevel_Udp:
-               g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
-
-               switch(mono_name) {
-               case SocketOptionName_NoChecksum:
-               case SocketOptionName_ChecksumCoverage:
-               default:
-                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
-                       return -1;
-               }
-               return -1;
-               break;
-
-       default:
-               g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
-               return -1;
-       }
-
-       return 0;
-}
-
-static MonoImage*
-get_socket_assembly (void)
-{
-       MonoDomain *domain = mono_domain_get ();
-       
-       if (domain->socket_assembly == NULL) {
-               MonoImage *socket_assembly;
-
-               socket_assembly = mono_image_loaded ("System");
-               if (!socket_assembly) {
-                       MonoAssembly *sa = mono_assembly_open ("System.dll", NULL);
-               
-                       if (!sa) {
-                               g_assert_not_reached ();
-                       } else {
-                               socket_assembly = mono_assembly_get_image (sa);
-                       }
-               }
-               mono_atomic_store_release (&domain->socket_assembly, socket_assembly);
-       }
-       
-       return domain->socket_assembly;
-}
-
-gpointer
-ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, gint32 *werror)
-{
-       SOCKET sock;
-       gint32 sock_family;
-       gint32 sock_proto;
-       gint32 sock_type;
-       
-       *werror = 0;
-       
-       sock_family = convert_family ((MonoAddressFamily)family);
-       if (sock_family == -1) {
-               *werror = WSAEAFNOSUPPORT;
-               return NULL;
-       }
-
-       sock_proto = convert_proto ((MonoProtocolType)proto);
-       if (sock_proto == -1) {
-               *werror = WSAEPROTONOSUPPORT;
-               return NULL;
-       }
-       
-       sock_type = convert_type ((MonoSocketType)type);
-       if (sock_type == -1) {
-               *werror = WSAESOCKTNOSUPPORT;
-               return NULL;
-       }
-       
-       sock = _wapi_socket (sock_family, sock_type, sock_proto,
-                            NULL, 0, WSA_FLAG_OVERLAPPED);
-
-       if (sock == INVALID_SOCKET) {
-               *werror = WSAGetLastError ();
-               return NULL;
-       }
-
-       return GUINT_TO_POINTER (sock);
-}
-
-/* FIXME: the SOCKET parameter (here and in other functions in this
- * 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)
-{
-       LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock));
-
-       *werror = 0;
-
-       /* Clear any pending work item from this socket if the underlying
-        * polling system does not notify when the socket is closed */
-       mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock));
-
-       MONO_ENTER_GC_SAFE;
-       closesocket (sock);
-       MONO_EXIT_GC_SAFE;
-}
-
-gint32
-ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void)
-{
-       LOGDEBUG (g_message("%s: returning %d", __func__, WSAGetLastError ()));
-
-       return WSAGetLastError ();
-}
-
-gint32
-ves_icall_System_Net_Sockets_Socket_Available_internal (SOCKET sock, gint32 *werror)
-{
-       int ret;
-       int amount;
-       
-       *werror = 0;
-
-       /* FIXME: this might require amount to be unsigned long. */
-       ret = ioctlsocket (sock, FIONREAD, &amount);
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
-               return 0;
-       }
-       
-       return amount;
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_Blocking_internal (SOCKET 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);
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-}
-
-gpointer
-ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror, gboolean blocking)
-{
-       gboolean interrupted;
-       SOCKET newsock;
-
-       *werror = 0;
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return NULL;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (newsock == INVALID_SOCKET)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror)
-               return NULL;
-       
-       return GUINT_TO_POINTER (newsock);
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog, gint32 *werror)
-{
-       int ret;
-       
-       *werror = 0;
-
-       MONO_ENTER_GC_SAFE;
-
-       ret = _wapi_listen (sock, backlog);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-}
-
-// Check whether it's ::ffff::0:0.
-static gboolean
-is_ipv4_mapped_any (const struct in6_addr *addr)
-{
-       int i;
-       
-       for (i = 0; i < 10; i++) {
-               if (addr->s6_addr [i])
-                       return FALSE;
-       }
-       if ((addr->s6_addr [10] != 0xff) || (addr->s6_addr [11] != 0xff))
-               return FALSE;
-       for (i = 12; i < 16; i++) {
-               if (addr->s6_addr [i])
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-static MonoObject*
-create_object_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error)
-{
-       MonoDomain *domain = mono_domain_get ();
-       MonoObject *sockaddr_obj;
-       MonoArray *data;
-       MonoAddressFamily family;
-
-       mono_error_init (error);
-
-       /* Build a System.Net.SocketAddress object instance */
-       if (!domain->sockaddr_class)
-               domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
-       sockaddr_obj = mono_object_new_checked (domain, domain->sockaddr_class, error);
-       return_val_if_nok (error, NULL);
-       
-       /* Locate the SocketAddress data buffer in the object */
-       if (!domain->sockaddr_data_field) {
-               domain->sockaddr_data_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Buffer");
-               g_assert (domain->sockaddr_data_field);
-       }
-
-       /* Locate the SocketAddress data buffer length in the object */
-       if (!domain->sockaddr_data_length_field) {
-               domain->sockaddr_data_length_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Size");
-               g_assert (domain->sockaddr_data_length_field);
-       }
-
-       /* May be the +2 here is too conservative, as sa_len returns
-        * the length of the entire sockaddr_in/in6, including
-        * sizeof (unsigned short) of the family */
-       /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
-       data = mono_array_new_cached (domain, mono_get_byte_class (), sa_size + 2, error);
-       return_val_if_nok (error, NULL);
-
-       /* The data buffer is laid out as follows:
-        * bytes 0 and 1 are the address family
-        * bytes 2 and 3 are the port info
-        * the rest is the address info
-        */
-               
-       family = convert_to_mono_family (saddr->sa_family);
-       if (family == AddressFamily_Unknown) {
-               *werror = WSAEAFNOSUPPORT;
-               return NULL;
-       }
-
-       mono_array_set (data, guint8, 0, family & 0x0FF);
-       mono_array_set (data, guint8, 1, (family >> 8) & 0x0FF);
-       
-       if (saddr->sa_family == AF_INET) {
-               struct sockaddr_in *sa_in = (struct sockaddr_in *)saddr;
-               guint16 port = ntohs (sa_in->sin_port);
-               guint32 address = ntohl (sa_in->sin_addr.s_addr);
-               int buffer_size = 8;
-               
-               if (sa_size < buffer_size) {
-                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
-                       return NULL;
-               }
-               
-               mono_array_set (data, guint8, 2, (port>>8) & 0xff);
-               mono_array_set (data, guint8, 3, (port) & 0xff);
-               mono_array_set (data, guint8, 4, (address>>24) & 0xff);
-               mono_array_set (data, guint8, 5, (address>>16) & 0xff);
-               mono_array_set (data, guint8, 6, (address>>8) & 0xff);
-               mono_array_set (data, guint8, 7, (address) & 0xff);
-       
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
-
-               return sockaddr_obj;
-       } else if (saddr->sa_family == AF_INET6) {
-               struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)saddr;
-               int i;
-               int buffer_size = 28;
-
-               guint16 port = ntohs (sa_in->sin6_port);
-
-               if (sa_size < buffer_size) {
-                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
-                       return NULL;
-               }
-
-               mono_array_set (data, guint8, 2, (port>>8) & 0xff);
-               mono_array_set (data, guint8, 3, (port) & 0xff);
-               
-               if (is_ipv4_mapped_any (&sa_in->sin6_addr)) {
-                       // Map ::ffff:0:0 to :: (bug #5502)
-                       for (i = 0; i < 16; i++)
-                               mono_array_set (data, guint8, 8 + i, 0);
-               } else {
-                       for (i = 0; i < 16; i++) {
-                               mono_array_set (data, guint8, 8 + i,
-                                                               sa_in->sin6_addr.s6_addr [i]);
-                       }
-               }
-
-               mono_array_set (data, guint8, 24, sa_in->sin6_scope_id & 0xff);
-               mono_array_set (data, guint8, 25,
-                                               (sa_in->sin6_scope_id >> 8) & 0xff);
-               mono_array_set (data, guint8, 26,
-                                               (sa_in->sin6_scope_id >> 16) & 0xff);
-               mono_array_set (data, guint8, 27,
-                                               (sa_in->sin6_scope_id >> 24) & 0xff);
-
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
-
-               return sockaddr_obj;
-       }
-#ifdef HAVE_SYS_UN_H
-       else if (saddr->sa_family == AF_UNIX) {
-               int i;
-               int buffer_size = sa_size + 2;
-
-               for (i = 0; i < sa_size; i++)
-                       mono_array_set (data, guint8, i + 2, saddr->sa_data [i]);
-               
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
-               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
-
-               return sockaddr_obj;
-       }
-#endif
-       else {
-               *werror = WSAEAFNOSUPPORT;
-               return NULL;
-       }
-}
-
-static int
-get_sockaddr_size (int family)
-{
-       int size;
-
-       size = 0;
-       if (family == AF_INET) {
-               size = sizeof (struct sockaddr_in);
-       } else if (family == AF_INET6) {
-               size = sizeof (struct sockaddr_in6);
-       }
-#ifdef HAVE_SYS_UN_H
-       else if (family == AF_UNIX) {
-               size = sizeof (struct sockaddr_un);
-       }
-#endif
-       return size;
-}
-
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock, gint32 af, gint32 *werror)
-{
-       gchar *sa;
-       socklen_t salen;
-       int ret;
-       MonoObject *result;
-       MonoError error;
-       
-       *werror = 0;
-       
-       salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af));
-       if (salen == 0) {
-               *werror = WSAEAFNOSUPPORT;
-               return NULL;
-       }
-       sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
-
-       MONO_ENTER_GC_SAFE;
-
-       ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen);
-
-       MONO_EXIT_GC_SAFE;
-       
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
-               if (salen > 128)
-                       g_free (sa);
-               return NULL;
-       }
-       
-       LOGDEBUG (g_message("%s: bound to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
-
-       result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
-       if (salen > 128)
-               g_free (sa);
-       if (!mono_error_ok (&error))
-               mono_error_set_pending_exception (&error);
-       return result;
-}
-
-MonoObject*
-ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (SOCKET sock, gint32 af, gint32 *werror)
-{
-       gchar *sa;
-       socklen_t salen;
-       int ret;
-       MonoObject *result;
-       MonoError error;
-       
-       *werror = 0;
-       
-       salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af));
-       if (salen == 0) {
-               *werror = WSAEAFNOSUPPORT;
-               return NULL;
-       }
-       sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
-       /* Note: linux returns just 2 for AF_UNIX. Always. */
-
-       MONO_ENTER_GC_SAFE;
-
-       ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
-               if (salen > 128)
-                       g_free (sa);
-               return NULL;
-       }
-       
-       LOGDEBUG (g_message("%s: connected to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
-
-       result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
-       if (salen > 128)
-               g_free (sa);
-       if (!mono_error_ok (&error))
-               mono_error_set_pending_exception (&error);
-       return result;
-}
-
-static struct sockaddr*
-create_sockaddr_from_object (MonoObject *saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error)
-{
-       MonoDomain *domain = mono_domain_get ();
-       MonoArray *data;
-       gint32 family;
-       int len;
-
-       mono_error_init (error);
-
-       if (!domain->sockaddr_class)
-               domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
-
-       /* Locate the SocketAddress data buffer in the object */
-       if (!domain->sockaddr_data_field) {
-               domain->sockaddr_data_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Buffer");
-               g_assert (domain->sockaddr_data_field);
-       }
-
-       /* Locate the SocketAddress data buffer length in the object */
-       if (!domain->sockaddr_data_length_field) {
-               domain->sockaddr_data_length_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Size");
-               g_assert (domain->sockaddr_data_length_field);
-       }
-
-       data = *(MonoArray **)(((char *)saddr_obj) + domain->sockaddr_data_field->offset);
-
-       /* The data buffer is laid out as follows:
-        * byte 0 is the address family low byte
-        * byte 1 is the address family high byte
-        * INET:
-        *      bytes 2 and 3 are the port info
-        *      the rest is the address info
-        * UNIX:
-        *      the rest is the file name
-        */
-       len = *(int *)(((char *)saddr_obj) + domain->sockaddr_data_length_field->offset);
-       g_assert (len >= 2);
-
-       family = convert_family ((MonoAddressFamily)(mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8)));
-       if (family == AF_INET) {
-               struct sockaddr_in *sa;
-               guint16 port;
-               guint32 address;
-               
-               if (len < 8) {
-                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
-                       return NULL;
-               }
-
-               sa = g_new0 (struct sockaddr_in, 1);
-               port = (mono_array_get (data, guint8, 2) << 8) +
-                       mono_array_get (data, guint8, 3);
-               address = (mono_array_get (data, guint8, 4) << 24) +
-                       (mono_array_get (data, guint8, 5) << 16 ) +
-                       (mono_array_get (data, guint8, 6) << 8) +
-                       mono_array_get (data, guint8, 7);
-
-               sa->sin_family = family;
-               sa->sin_addr.s_addr = htonl (address);
-               sa->sin_port = htons (port);
-
-               *sa_size = sizeof (struct sockaddr_in);
-               return (struct sockaddr *)sa;
-       } else if (family == AF_INET6) {
-               struct sockaddr_in6 *sa;
-               int i;
-               guint16 port;
-               guint32 scopeid;
-               
-               if (len < 28) {
-                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
-                       return NULL;
-               }
-
-               sa = g_new0 (struct sockaddr_in6, 1);
-               port = mono_array_get (data, guint8, 3) +
-                       (mono_array_get (data, guint8, 2) << 8);
-               scopeid = mono_array_get (data, guint8, 24) + 
-                       (mono_array_get (data, guint8, 25) << 8) + 
-                       (mono_array_get (data, guint8, 26) << 16) + 
-                       (mono_array_get (data, guint8, 27) << 24);
-
-               sa->sin6_family = family;
-               sa->sin6_port = htons (port);
-               sa->sin6_scope_id = scopeid;
-
-               for (i = 0; i < 16; i++)
-                       sa->sin6_addr.s6_addr [i] = mono_array_get (data, guint8, 8 + i);
-
-               *sa_size = sizeof (struct sockaddr_in6);
-               return (struct sockaddr *)sa;
-       }
-#ifdef HAVE_SYS_UN_H
-       else if (family == AF_UNIX) {
-               struct sockaddr_un *sock_un;
-               int i;
-
-               /* Need a byte for the '\0' terminator/prefix, and the first
-                * two bytes hold the SocketAddress family
-                */
-               if (len - 2 >= sizeof (sock_un->sun_path)) {
-                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
-                       return NULL;
-               }
-               
-               sock_un = g_new0 (struct sockaddr_un, 1);
-
-               sock_un->sun_family = family;
-               for (i = 0; i < len - 2; i++)
-                       sock_un->sun_path [i] = mono_array_get (data, guint8, i + 2);
-               
-               *sa_size = len;
-               return (struct sockaddr *)sock_un;
-       }
-#endif
-       else {
-               *werror = WSAEAFNOSUPPORT;
-               return 0;
-       }
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_Bind_internal (SOCKET sock, MonoObject *sockaddr, gint32 *werror)
-{
-       MonoError error;
-       struct sockaddr *sa;
-       socklen_t sa_size;
-       int ret;
-       
-       *werror = 0;
-       
-       sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
-       if (*werror != 0)
-               return;
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return;
-       }
-
-       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);
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       g_free (sa);
-}
-
-enum {
-       SelectModeRead,
-       SelectModeWrite,
-       SelectModeError
-};
-
-MonoBoolean
-ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode,
-                                                                                                  gint timeout, gint32 *werror)
-{
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       mono_pollfd *pfds;
-       int ret;
-       gboolean interrupted;
-       time_t start;
-
-       *werror = 0;
-
-       pfds = g_new0 (mono_pollfd, 1);
-       pfds->fd = GPOINTER_TO_INT (sock);
-
-       switch (mode) {
-       case SelectModeRead:
-               pfds->events = MONO_POLLIN;
-               break;
-       case SelectModeWrite:
-               pfds->events = MONO_POLLOUT;
-               break;
-       default:
-               pfds->events = MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL;
-               break;
-       }
-
-       timeout = (timeout >= 0) ? (timeout / 1000) : -1;
-       start = time (NULL);
-
-       do {
-               mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-               if (interrupted) {
-                       g_free (pfds);
-                       *werror = WSAEINTR;
-                       return FALSE;
-               }
-
-               MONO_ENTER_GC_SAFE;
-
-               ret = mono_poll (pfds, 1, timeout);
-
-               MONO_EXIT_GC_SAFE;
-
-               mono_thread_info_uninstall_interrupt (&interrupted);
-               if (interrupted) {
-                       g_free (pfds);
-                       *werror = WSAEINTR;
-                       return FALSE;
-               }
-
-               if (timeout > 0 && ret < 0) {
-                       int err = errno;
-                       int sec = time (NULL) - start;
-                       
-                       timeout -= sec * 1000;
-                       if (timeout < 0) {
-                               timeout = 0;
-                       }
-                       
-                       errno = err;
-               }
-
-               if (ret == -1 && errno == EINTR) {
-                       if (mono_thread_test_state (thread, (MonoThreadState)(ThreadState_AbortRequested | ThreadState_StopRequested))) {
-                               g_free (pfds);
-                               return FALSE;
-                       }
-
-                       /* Suspend requested? */
-                       mono_thread_interruption_checkpoint ();
-
-                       errno = EINTR;
-               }
-       } 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
-               g_free (pfds);
-               return FALSE;
-       }
-
-       g_free (pfds);
-       return ret != 0;
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *sockaddr, gint32 *werror, gboolean blocking)
-{
-       MonoError error;
-       struct sockaddr *sa;
-       socklen_t sa_size;
-       int ret;
-       gboolean interrupted;
-
-       *werror = 0;
-
-       sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
-       if (*werror != 0)
-               return;
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return;
-       }
-
-       LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return;
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-#ifdef HOST_WIN32
-       ret = alertable_connect (sock, sa, sa_size, blocking);
-#else
-       ret = _wapi_connect (sock, sa, sa_size);
-#endif
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       g_free (sa);
-}
-
-#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)
-{
-       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;
-               return;
-       }
-
-       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;
-       }
-
-       MONO_EXIT_GC_SAFE;
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-}
-#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)
-{
-       int ret;
-       guchar *buf;
-       gint32 alen;
-       int recvflags = 0;
-       gboolean interrupted;
-       MonoInternalThread* curthread G_GNUC_UNUSED = mono_thread_internal_current ();
-       
-       *werror = 0;
-       
-       alen = mono_array_length (buffer);
-       if (offset > alen - count)
-               return 0;
-       
-       buf = mono_array_addr (buffer, guchar, offset);
-       
-       recvflags = convert_socketflags (flags);
-       if (recvflags == -1) {
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted)
-               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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror)
-               return 0;
-
-       return ret;
-}
-
-gint32
-ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
-{
-       int ret, count;
-       gboolean interrupted;
-       DWORD recv;
-       WSABUF *wsabufs;
-       DWORD recvflags = 0;
-       
-       *werror = 0;
-       
-       wsabufs = mono_array_addr (buffers, WSABUF, 0);
-       count = mono_array_length (buffers);
-       
-       recvflags = convert_socketflags (flags);
-       if (recvflags == -1) {
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return 0;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror)
-               return 0;
-
-       return recv;
-}
-
-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)
-{
-       MonoError error;
-       int ret;
-       guchar *buf;
-       gint32 alen;
-       int recvflags = 0;
-       struct sockaddr *sa;
-       socklen_t sa_size;
-       gboolean interrupted;
-       
-       *werror = 0;
-       
-       alen = mono_array_length (buffer);
-       if (offset > alen - count)
-               return 0;
-
-       sa = create_sockaddr_from_object (*sockaddr, &sa_size, werror, &error);
-       if (*werror != 0)
-               return 0;
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return 0;
-       }
-       
-       buf = mono_array_addr (buffer, guchar, offset);
-       
-       recvflags = convert_socketflags (flags);
-       if (recvflags == -1) {
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               g_free (sa);
-               *werror = WSAEINTR;
-               return 0;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror) {
-               g_free(sa);
-               return 0;
-       }
-
-       /* If we didn't get a socket size, then we're probably a
-        * connected connection-oriented socket and the stack hasn't
-        * returned the remote address. All we can do is return null.
-        */
-       if (sa_size) {
-               *sockaddr = create_object_from_sockaddr (sa, sa_size, werror, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       g_free (sa);
-                       return 0;
-               }
-       } else {
-               *sockaddr = NULL;
-       }
-
-       g_free (sa);
-       
-       return ret;
-}
-
-gint32
-ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking)
-{
-       int ret;
-       guchar *buf;
-       gint32 alen;
-       int sendflags = 0;
-       gboolean interrupted;
-       
-       *werror = 0;
-       
-       alen = mono_array_length (buffer);
-       if (offset > alen - count)
-               return 0;
-
-       LOGDEBUG (g_message("%s: alen: %d", __func__, alen));
-       
-       buf = mono_array_addr (buffer, guchar, offset);
-
-       LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
-
-       sendflags = convert_socketflags (flags);
-       if (sendflags == -1) {
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return 0;
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-#ifdef HOST_WIN32
-       ret = alertable_send (sock, buf, count, sendflags, blocking);
-#else
-       ret = _wapi_send (sock, buf, count, sendflags);
-#endif
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror)
-               return 0;
-
-       return ret;
-}
-
-gint32
-ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
-{
-       int ret, count;
-       DWORD sent;
-       WSABUF *wsabufs;
-       DWORD sendflags = 0;
-       gboolean interrupted;
-       
-       *werror = 0;
-       
-       wsabufs = mono_array_addr (buffers, WSABUF, 0);
-       count = mono_array_length (buffers);
-       
-       sendflags = convert_socketflags (flags);
-       if (sendflags == -1) {
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return 0;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       if (*werror)
-               return 0;
-
-       return sent;
-}
-
-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)
-{
-       MonoError error;
-       int ret;
-       guchar *buf;
-       gint32 alen;
-       int sendflags = 0;
-       struct sockaddr *sa;
-       socklen_t sa_size;
-       gboolean interrupted;
-       
-       *werror = 0;
-       
-       alen = mono_array_length (buffer);
-       if (offset > alen - count) {
-               return 0;
-       }
-
-       sa = create_sockaddr_from_object(sockaddr, &sa_size, werror, &error);
-       if (*werror != 0)
-               return 0;
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               return 0;
-       }
-       
-       LOGDEBUG (g_message ("%s: alen: %d", __func__, alen));
-       
-       buf = mono_array_addr (buffer, guchar, offset);
-
-       LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
-
-       sendflags = convert_socketflags (flags);
-       if (sendflags == -1) {
-               g_free (sa);
-               *werror = WSAEOPNOTSUPP;
-               return 0;
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               g_free (sa);
-               *werror = WSAEINTR;
-               return 0;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted)
-               *werror = WSAEINTR;
-
-       g_free(sa);
-
-       if (*werror)
-               return 0;
-
-       return ret;
-}
-
-static SOCKET
-Socket_to_SOCKET (MonoObject *sockobj)
-{
-       MonoSafeHandle *safe_handle;
-       MonoClassField *field;
-       
-       field = mono_class_get_field_from_name (sockobj->vtable->klass, "m_Handle");
-       safe_handle = ((MonoSafeHandle *)(*(gpointer *)(((char *)sockobj) + field->offset)));
-
-       if (safe_handle == NULL)
-               return -1;
-
-       return (SOCKET)safe_handle->handle;
-}
-
-#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
-
-void
-ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *werror)
-{
-       MonoError error;
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       MonoObject *obj;
-       mono_pollfd *pfds;
-       int nfds, idx;
-       int ret;
-       int i, count;
-       int mode;
-       MonoClass *sock_arr_class;
-       MonoArray *socks;
-       time_t start;
-       uintptr_t socks_size;
-       gboolean interrupted;
-
-       *werror = 0;
-
-       /* *sockets -> READ, null, WRITE, null, ERROR, null */
-       count = mono_array_length (*sockets);
-       nfds = count - 3; /* NULL separators */
-       pfds = g_new0 (mono_pollfd, nfds);
-       mode = idx = 0;
-       for (i = 0; i < count; i++) {
-               obj = mono_array_get (*sockets, MonoObject *, i);
-               if (obj == NULL) {
-                       mode++;
-                       continue;
-               }
-
-               if (idx >= nfds) {
-                       /* The socket array was bogus */
-                       g_free (pfds);
-                       *werror = WSAEFAULT;
-                       return;
-               }
-
-               pfds [idx].fd = Socket_to_SOCKET (obj);
-               pfds [idx].events = (mode == 0) ? MONO_POLLIN : (mode == 1) ? MONO_POLLOUT : POLL_ERRORS;
-               idx++;
-       }
-
-       timeout = (timeout >= 0) ? (timeout / 1000) : -1;
-       start = time (NULL);
-       do {
-               mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-               if (interrupted) {
-                       g_free (pfds);
-                       *werror = WSAEINTR;
-                       return;
-               }
-
-               MONO_ENTER_GC_SAFE;
-
-               ret = mono_poll (pfds, nfds, timeout);
-
-               MONO_EXIT_GC_SAFE;
-
-               mono_thread_info_uninstall_interrupt (&interrupted);
-               if (interrupted) {
-                       g_free (pfds);
-                       *werror = WSAEINTR;
-                       return;
-               }
-
-               if (timeout > 0 && ret < 0) {
-                       int err = errno;
-                       int sec = time (NULL) - start;
-
-                       timeout -= sec * 1000;
-                       if (timeout < 0)
-                               timeout = 0;
-                       errno = err;
-               }
-
-               if (ret == -1 && errno == EINTR) {
-                       if (mono_thread_test_state (thread, (MonoThreadState)(ThreadState_AbortRequested | ThreadState_StopRequested))) {
-                               g_free (pfds);
-                               *sockets = NULL;
-                               return;
-                       }
-
-                       /* Suspend requested? */
-                       mono_thread_interruption_checkpoint ();
-
-                       errno = EINTR;
-               }
-       } 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
-               g_free (pfds);
-               return;
-       }
-
-       if (ret == 0) {
-               g_free (pfds);
-               *sockets = NULL;
-               return;
-       }
-
-       sock_arr_class = ((MonoObject *)*sockets)->vtable->klass;
-       socks_size = ((uintptr_t)ret) + 3; /* space for the NULL delimiters */
-       socks = mono_array_new_full_checked (mono_domain_get (), sock_arr_class, &socks_size, NULL, &error);
-       if (!mono_error_ok (&error)) {
-               mono_error_set_pending_exception (&error);
-               g_free (pfds);
-               return;
-       }
-
-       mode = idx = 0;
-       for (i = 0; i < count && ret > 0; i++) {
-               mono_pollfd *pfd;
-
-               obj = mono_array_get (*sockets, MonoObject *, i);
-               if (obj == NULL) {
-                       mode++;
-                       idx++;
-                       continue;
-               }
-
-               pfd = &pfds [i - mode];
-               if (pfd->revents == 0)
-                       continue;
-
-               ret--;
-               if (mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
-                       mono_array_setref (socks, idx++, obj);
-               } else if (mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
-                       mono_array_setref (socks, idx++, obj);
-               } else if ((pfd->revents & POLL_ERRORS) != 0) {
-                       mono_array_setref (socks, idx++, obj);
-               }
-       }
-
-       *sockets = socks;
-       g_free (pfds);
-}
-
-static MonoObject*
-int_to_object (MonoDomain *domain, int val, MonoError *error)
-{
-       return mono_value_box_checked (domain, mono_get_int32_class (), &val, error);
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *werror)
-{
-       int system_level = 0;
-       int system_name = 0;
-       int ret;
-       int val = 0;
-       socklen_t valsize = sizeof (val);
-       struct linger linger;
-       socklen_t lingersize = sizeof (linger);
-       int time_ms = 0;
-       socklen_t time_ms_size = sizeof (time_ms);
-#ifdef SO_PEERCRED
-#  if defined(__OpenBSD__)
-       struct sockpeercred cred;
-#  else
-       struct ucred cred;
-#  endif
-       socklen_t credsize = sizeof (cred);
-#endif
-       MonoError error;
-       MonoDomain *domain = mono_domain_get ();
-       MonoObject *obj;
-       MonoClass *obj_class;
-       MonoClassField *field;
-       
-       *werror = 0;
-       
-#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
-       if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
-               system_level = SOL_SOCKET;
-               system_name = SO_REUSEADDR;
-               ret = 0;
-       } else
-#endif
-       {
-               ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level, &system_name);
-       }
-
-       if (ret == -1) {
-               *werror = WSAENOPROTOOPT;
-               return;
-       }
-       if (ret == -2) {
-               *obj_val = int_to_object (domain, 0, &error);
-               mono_error_set_pending_exception (&error);
-               return;
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-       /* No need to deal with MulticastOption names here, because
-        * you cant getsockopt AddMembership or DropMembership (the
-        * int getsockopt will error, causing an exception)
-        */
-       switch (name) {
-       case SocketOptionName_Linger:
-       case SocketOptionName_DontLinger:
-               ret = _wapi_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);
-               break;
-
-#ifdef SO_PEERCRED
-       case SocketOptionName_PeerCred: 
-               ret = _wapi_getsockopt (sock, system_level, system_name, &cred, &credsize);
-               break;
-#endif
-
-       default:
-               ret = _wapi_getsockopt (sock, system_level, system_name, &val, &valsize);
-       }
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
-               return;
-       }
-       
-       switch (name) {
-       case SocketOptionName_Linger:
-               /* build a System.Net.Sockets.LingerOption */
-               obj_class = mono_class_load_from_name (get_socket_assembly (),
-                                                                                          "System.Net.Sockets",
-                                                                                          "LingerOption");
-               obj = mono_object_new_checked (domain, obj_class, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return;
-               }
-
-               /* Locate and set the fields "bool enabled" and "int
-                * lingerTime"
-                */
-               field = mono_class_get_field_from_name(obj_class, "enabled");
-               *(guint8 *)(((char *)obj)+field->offset) = linger.l_onoff;
-
-               field = mono_class_get_field_from_name(obj_class, "lingerTime");
-               *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
-               break;
-       case SocketOptionName_DontLinger:
-               /* construct a bool int in val - true if linger is off */
-               obj = int_to_object (domain, !linger.l_onoff, &error);
-               mono_error_set_pending_exception (&error);
-               break;
-       case SocketOptionName_SendTimeout:
-       case SocketOptionName_ReceiveTimeout:
-               obj = int_to_object (domain, time_ms, &error);
-               mono_error_set_pending_exception (&error);
-               break;
-
-#ifdef SO_PEERCRED
-       case SocketOptionName_PeerCred:  {
-               /* 
-                * build a Mono.Posix.PeerCred+PeerCredData if
-                * possible
-                */
-               static MonoImage *mono_posix_image = NULL;
-               MonoPeerCredData *cred_data;
-               
-               if (mono_posix_image == NULL) {
-                       mono_posix_image = mono_image_loaded ("Mono.Posix");
-                       if (!mono_posix_image) {
-                               MonoAssembly *sa = mono_assembly_open ("Mono.Posix.dll", NULL);
-                               if (!sa) {
-                                       *werror = WSAENOPROTOOPT;
-                                       return;
-                               } else {
-                                       mono_posix_image = mono_assembly_get_image (sa);
-                               }
-                       }
-               }
-               
-               obj_class = mono_class_load_from_name (mono_posix_image,
-                                                "Mono.Posix",
-                                                "PeerCredData");
-               obj = mono_object_new_checked (domain, obj_class, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return;
-               }
-               cred_data = (MonoPeerCredData *)obj;
-               cred_data->pid = cred.pid;
-               cred_data->uid = cred.uid;
-               cred_data->gid = cred.gid;
-               break;
-       }
-#endif
-
-       default:
-#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
-               if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse)
-                       val = val ? 0 : 1;
-#endif
-               obj = int_to_object (domain, val, &error);
-               mono_error_set_pending_exception (&error);
-       }
-
-       *obj_val = obj;
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *werror)
-{
-       int system_level = 0;
-       int system_name = 0;
-       int ret;
-       guchar *buf;
-       socklen_t valsize;
-       
-       *werror = 0;
-       
-       ret = convert_sockopt_level_and_name((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level,
-                                                                                &system_name);
-       if (ret == -1) {
-               *werror = WSAENOPROTOOPT;
-               return;
-       }
-       if (ret == -2)
-               return;
-
-       valsize = mono_array_length (*byte_val);
-       buf = mono_array_addr (*byte_val, guchar, 0);
-
-       MONO_ENTER_GC_SAFE;
-
-       ret = _wapi_getsockopt (sock, system_level, system_name, buf, &valsize);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-}
-
-#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
-static struct in_addr
-ipaddress_to_struct_in_addr (MonoObject *ipaddr)
-{
-       struct in_addr inaddr;
-       MonoClassField *field;
-       
-       field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Address");
-
-       /* No idea why .net uses a 64bit type to hold a 32bit value...
-        *
-        * Internal value of IPAddess is in little-endian order
-        */
-       inaddr.s_addr = GUINT_FROM_LE ((guint32)*(guint64 *)(((char *)ipaddr) + field->offset));
-       
-       return inaddr;
-}
-
-static struct in6_addr
-ipaddress_to_struct_in6_addr (MonoObject *ipaddr)
-{
-       struct in6_addr in6addr;
-       MonoClassField *field;
-       MonoArray *data;
-       int i;
-
-       field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Numbers");
-       g_assert (field);
-       data = *(MonoArray **)(((char *)ipaddr) + field->offset);
-
-       for (i = 0; i < 8; i++) {
-               const guint16 s = GUINT16_TO_BE (mono_array_get (data, guint16, i));
-
-/* Solaris/MacOS have only the 8 bit version. */
-#ifndef s6_addr16
-               in6addr.s6_addr[2 * i + 1] = (s >> 8) & 0xff;
-               in6addr.s6_addr[2 * i] = s & 0xff;
-#else
-               in6addr.s6_addr16[i] = s;
-#endif
-       }
-       return in6addr;
-}
-#endif
-
-#if defined(__APPLE__) || defined(__FreeBSD__)
-
-static int
-get_local_interface_id (int family)
-{
-#if !defined(HAVE_GETIFADDRS) || !defined(HAVE_IF_NAMETOINDEX)
-       return 0;
-#else
-       struct ifaddrs *ifap = NULL, *ptr;
-       int idx = 0;
-       
-       if (getifaddrs (&ifap))
-               return 0;
-       
-       for (ptr = ifap; ptr; ptr = ptr->ifa_next) {
-               if (!ptr->ifa_addr || !ptr->ifa_name)
-                       continue;
-               if (ptr->ifa_addr->sa_family != family)
-                       continue;
-               if ((ptr->ifa_flags & IFF_LOOPBACK) != 0)
-                       continue;
-               if ((ptr->ifa_flags & IFF_MULTICAST) == 0)
-                       continue;
-                       
-               idx = if_nametoindex (ptr->ifa_name);
-               break;
-       }
-       
-       freeifaddrs (ifap);
-       return idx;
-#endif
-}
-
-#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)
-{
-       struct linger linger;
-       int system_level = 0;
-       int system_name = 0;
-       int ret;
-       int sol_ip;
-       int sol_ipv6;
-
-       *werror = 0;
-
-       sol_ipv6 = mono_networking_get_ipv6_protocol ();
-       sol_ip = mono_networking_get_ip_protocol ();
-
-       ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level,
-                                                                                 &system_name);
-
-#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
-       if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
-               system_name = SO_REUSEADDR;
-               int_val = int_val ? 0 : 1;
-               ret = 0;
-       }
-#endif
-
-       if (ret == -1) {
-               *werror = WSAENOPROTOOPT;
-               return;
-       }
-       if (ret == -2)
-               return;
-
-       /* Only one of obj_val, byte_val or int_val has data */
-       if (obj_val) {
-               MonoClassField *field;
-               int valsize;
-               
-               switch (name) {
-               case SocketOptionName_Linger:
-                       /* Dig out "bool enabled" and "int lingerTime"
-                        * fields
-                        */
-                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "enabled");
-                       linger.l_onoff = *(guint8 *)(((char *)obj_val) + field->offset);
-                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "lingerTime");
-                       linger.l_linger = *(guint32 *)(((char *)obj_val) + field->offset);
-                       
-                       valsize = sizeof (linger);
-                       ret = _wapi_setsockopt (sock, system_level,
-                                                                       system_name, &linger, valsize);
-                       break;
-               case SocketOptionName_AddMembership:
-               case SocketOptionName_DropMembership:
-#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
-               {
-                       MonoObject *address = NULL;
-
-                       if (system_level == sol_ipv6) {
-                               struct ipv6_mreq mreq6;
-
-                               /*
-                                *      Get group address
-                                */
-                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Group");
-                               g_assert (field);
-                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
-                               
-                               if (address)
-                                       mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
-
-                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Interface");
-                               mreq6.ipv6mr_interface = *(guint64 *)(((char *)obj_val) + field->offset);
-                               
-#if defined(__APPLE__) || defined(__FreeBSD__)
-                               /*
-                               * Bug #5504:
-                               *
-                               * Mac OS Lion doesn't allow ipv6mr_interface = 0.
-                               *
-                               * Tests on Windows and Linux show that the multicast group is only
-                               * joined on one NIC when interface = 0, so we simply use the interface
-                               * id from the first non-loopback interface (this is also what
-                               * Dns.GetHostName (string.Empty) would return).
-                               */
-                               if (!mreq6.ipv6mr_interface)
-                                       mreq6.ipv6mr_interface = get_local_interface_id (AF_INET6);
-#endif
-                                       
-                               ret = _wapi_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}};
-#else
-                               struct ip_mreq mreq = {{0}};
-#endif /* HAVE_STRUCT_IP_MREQN */
-                       
-                               /*
-                                * pain! MulticastOption holds two IPAddress
-                                * members, so I have to dig the value out of
-                                * those :-(
-                                */
-                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
-                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
-
-                               /* address might not be defined and if so, set the address to ADDR_ANY.
-                                */
-                               if (address)
-                                       mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
-
-                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "localAddress");
-                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
-
-#ifdef HAVE_STRUCT_IP_MREQN
-                               if (address)
-                                       mreq.imr_address = ipaddress_to_struct_in_addr (address);
-
-                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "ifIndex");
-                               mreq.imr_ifindex = *(gint32 *)(((char *)obj_val) + field->offset);
-#else
-                               if (address)
-                                       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));
-                       }
-                       break;
-               }
-#endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
-               default:
-                       /* Cause an exception to be thrown */
-                       *werror = WSAEINVAL;
-                       return;
-               }
-       } else if (byte_val!=NULL) {
-               int valsize = mono_array_length (byte_val);
-               guchar *buf = mono_array_addr (byte_val, guchar, 0);
-               
-               switch(name) {
-               case SocketOptionName_DontLinger:
-                       if (valsize == 1) {
-                               linger.l_onoff = (*buf) ? 0 : 1;
-                               linger.l_linger = 0;
-                               ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
-                       } else {
-                               *werror = WSAEINVAL;
-                       }
-                       break;
-               default:
-                       ret = _wapi_setsockopt (sock, system_level, system_name, buf, valsize);
-                       break;
-               }
-       } else {
-               /* ReceiveTimeout/SendTimeout get here */
-               switch (name) {
-               case SocketOptionName_DontLinger:
-                       linger.l_onoff = !int_val;
-                       linger.l_linger = 0;
-                       ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
-                       break;
-               case SocketOptionName_MulticastInterface:
-#ifndef HOST_WIN32
-#ifdef HAVE_STRUCT_IP_MREQN
-                       int_val = GUINT32_FROM_BE (int_val);
-                       if ((int_val & 0xff000000) == 0) {
-                               /* 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));
-                               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));
-                       break;
-               case SocketOptionName_DontFragment:
-#ifdef HAVE_IP_MTU_DISCOVER
-                       /* Fiddle with the value slightly if we're
-                        * turning DF on
-                        */
-                       if (int_val == 1)
-                               int_val = IP_PMTUDISC_DO;
-                       /* Fall through */
-#endif
-                       
-               default:
-                       ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
-               }
-       }
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how, gint32 *werror)
-{
-       int ret;
-       gboolean interrupted;
-
-       *werror = 0;
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return;
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-       /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
-       ret = _wapi_shutdown (sock, how);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-       }
-
-}
-
-gint
-ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *werror)
-{
-       glong output_bytes = 0;
-       gchar *i_buffer, *o_buffer;
-       gint i_len, o_len;
-       gint ret;
-
-       *werror = 0;
-       
-       if ((guint32)code == FIONBIO)
-               /* Invalid command. Must use Socket.Blocking */
-               return -1;
-
-       if (input == NULL) {
-               i_buffer = NULL;
-               i_len = 0;
-       } else {
-               i_buffer = mono_array_addr (input, gchar, 0);
-               i_len = mono_array_length (input);
-       }
-
-       if (output == NULL) {
-               o_buffer = NULL;
-               o_len = 0;
-       } else {
-               o_buffer = mono_array_addr (output, gchar, 0);
-               o_len = mono_array_length (output);
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-       ret = WSAIoctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes, NULL, NULL);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
-               return -1;
-       }
-
-       return (gint)output_bytes;
-}
-
-static gboolean 
-addrinfo_to_IPHostEntry (MonoAddressInfo *info, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gboolean add_local_ips, MonoError *error)
-{
-       gint32 count, i;
-       MonoAddressEntry *ai = NULL;
-       struct in_addr *local_in = NULL;
-       int nlocal_in = 0;
-       struct in6_addr *local_in6 = NULL;
-       int nlocal_in6 = 0;
-       int addr_index;
-       MonoDomain *domain = mono_domain_get ();
-
-       mono_error_init (error);
-       addr_index = 0;
-       *h_aliases = mono_array_new_checked (domain, mono_get_string_class (), 0, error);
-       return_val_if_nok (error, FALSE);
-       if (add_local_ips) {
-               local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in);
-               local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6);
-               if (nlocal_in || nlocal_in6) {
-                       char addr [INET6_ADDRSTRLEN];
-                       *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), nlocal_in + nlocal_in6, error);
-                       if (!is_ok (error))
-                               goto leave;
-                       
-                       if (nlocal_in) {
-                               MonoString *addr_string;
-                               int i;
-
-                               for (i = 0; i < nlocal_in; i++) {
-                                       MonoAddress maddr;
-                                       mono_address_init (&maddr, AF_INET, &local_in [i]);
-                                       if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
-                                               addr_string = mono_string_new (domain, addr);
-                                               mono_array_setref (*h_addr_list, addr_index, addr_string);
-                                               addr_index++;
-                                       }
-                               }
-                       }
-
-                       if (nlocal_in6) {
-                               MonoString *addr_string;
-                               int i;
-
-                               for (i = 0; i < nlocal_in6; i++) {
-                                       MonoAddress maddr;
-                                       mono_address_init (&maddr, AF_INET6, &local_in6 [i]);
-                                       if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
-                                               addr_string = mono_string_new (domain, addr);
-                                               mono_array_setref (*h_addr_list, addr_index, addr_string);
-                                               addr_index++;
-                                       }
-                               }
-                       }
-
-               leave:
-                       g_free (local_in);
-                       g_free (local_in6);
-                       if (info)
-                               mono_free_address_info (info);
-                       return is_ok (error);;
-               }
-
-               g_free (local_in);
-               g_free (local_in6);
-       }
-
-       for (count = 0, ai = info->entries; ai != NULL; ai = ai->next) {
-               if (ai->family != AF_INET && ai->family != AF_INET6)
-                       continue;
-               count++;
-       }
-
-       *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), count, error);
-       if (!is_ok (error))
-               goto leave2;
-
-       for (ai = info->entries, i = 0; ai != NULL; ai = ai->next) {
-               MonoAddress maddr;
-               MonoString *addr_string;
-               char buffer [INET6_ADDRSTRLEN]; /* Max. size for IPv6 */
-
-               if ((ai->family != PF_INET) && (ai->family != PF_INET6))
-                       continue;
-
-               mono_address_init (&maddr, ai->family, &ai->address);
-               if (mono_networking_addr_to_str (&maddr, buffer, sizeof (buffer)))
-                       addr_string = mono_string_new (domain, buffer);
-               else
-                       addr_string = mono_string_new (domain, "");
-
-               mono_array_setref (*h_addr_list, addr_index, addr_string);
-
-               if (!i) {
-                       i++;
-                       if (ai->canonical_name != NULL) {
-                               *h_name = mono_string_new (domain, ai->canonical_name);
-                       } else {
-                               *h_name = mono_string_new (domain, buffer);
-                       }
-               }
-
-               addr_index++;
-       }
-
-leave2:
-       if (info)
-               mono_free_address_info (info);
-
-       return is_ok (error);
-}
-
-MonoBoolean
-ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
-{
-       MonoError error;
-       gboolean add_local_ips = FALSE, add_info_ok = TRUE;
-       gchar this_hostname [256];
-       MonoAddressInfo *info = NULL;
-
-       char *hostname = mono_string_to_utf8_checked (host, &error);
-       if (mono_error_set_pending_exception (&error))
-               return FALSE;
-
-       if (*hostname == '\0') {
-               add_local_ips = TRUE;
-               *h_name = host;
-       }
-
-       if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) {
-               if (!strcmp (hostname, this_hostname)) {
-                       add_local_ips = TRUE;
-                       *h_name = host;
-               }
-       }
-
-#ifdef HOST_WIN32
-       // Win32 APIs already returns local interface addresses for empty hostname ("")
-       // so we never want to add them manually.
-       add_local_ips = FALSE;
-       if (mono_get_address_info(hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info))
-               add_info_ok = FALSE;
-#else
-       if (*hostname && mono_get_address_info (hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info))
-               add_info_ok = FALSE;
-#endif
-
-       g_free(hostname);
-
-       if (add_info_ok) {
-               MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, add_local_ips, &error);
-               mono_error_set_pending_exception (&error);
-               return result;
-       }
-       return FALSE;
-}
-
-MonoBoolean
-ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
-{
-       char *address;
-       struct sockaddr_in saddr;
-       struct sockaddr_in6 saddr6;
-       MonoAddressInfo *info = NULL;
-       MonoError error;
-       gint32 family;
-       gchar hostname [NI_MAXHOST] = { 0 };
-       gboolean ret;
-
-       address = mono_string_to_utf8_checked (addr, &error);
-       if (mono_error_set_pending_exception (&error))
-               return FALSE;
-
-       if (inet_pton (AF_INET, address, &saddr.sin_addr ) == 1) {
-               family = AF_INET;
-               saddr.sin_family = AF_INET;
-       } else if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) == 1) {
-               family = AF_INET6;
-               saddr6.sin6_family = AF_INET6;
-       } else {
-               g_free (address);
-               return FALSE;
-       }
-
-       g_free (address);
-
-       MONO_ENTER_GC_SAFE;
-
-       switch (family) {
-       case AF_INET: {
-#if HAVE_SOCKADDR_IN_SIN_LEN
-               saddr.sin_len = sizeof (saddr);
-#endif
-               ret = getnameinfo ((struct sockaddr*)&saddr, sizeof (saddr), hostname, sizeof (hostname), NULL, 0, 0) == 0;
-               break;
-       }
-       case AF_INET6: {
-#if HAVE_SOCKADDR_IN6_SIN_LEN
-               saddr6.sin6_len = sizeof (saddr6);
-#endif
-               ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof (saddr6), hostname, sizeof (hostname), NULL, 0, 0) == 0;
-               break;
-       }
-       default:
-               g_assert_not_reached ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-
-       if (!ret)
-               return FALSE;
-
-       if (mono_get_address_info (hostname, 0, hint | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info) != 0)
-               return FALSE;
-
-       MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, FALSE, &error);
-       mono_error_set_pending_exception (&error);
-       return result;
-}
-
-MonoBoolean
-ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name)
-{
-       gchar hostname [NI_MAXHOST] = { 0 };
-       int ret;
-
-       ret = gethostname (hostname, sizeof (hostname));
-       if (ret == -1)
-               return FALSE;
-
-       *h_name = mono_string_new (mono_domain_get (), hostname);
-
-       return TRUE;
-}
-
-#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)
-{
-       HANDLE file;
-       gboolean ret;
-       gboolean interrupted;
-       TRANSMIT_FILE_BUFFERS buffers;
-
-       if (filename == NULL)
-               return FALSE;
-
-       /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
-
-       file = ves_icall_System_IO_MonoIO_Open (filename, FileMode_Open, FileAccess_Read, FileShare_Read, 0, werror);
-
-       if (file == INVALID_HANDLE_VALUE) {
-               SetLastError (*werror);
-               return FALSE;
-       }
-
-       memset (&buffers, 0, sizeof (buffers));
-       if (pre_buffer != NULL) {
-               buffers.Head = mono_array_addr (pre_buffer, guchar, 0);
-               buffers.HeadLength = mono_array_length (pre_buffer);
-       }
-       if (post_buffer != NULL) {
-               buffers.Tail = mono_array_addr (post_buffer, guchar, 0);
-               buffers.TailLength = mono_array_length (post_buffer);
-       }
-
-       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
-       if (interrupted) {
-               CloseHandle (file);
-               SetLastError (WSAEINTR);
-               return FALSE;
-       }
-
-       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
-
-       MONO_EXIT_GC_SAFE;
-
-       if (!ret)
-               *werror = WSAGetLastError ();
-
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
-               CloseHandle (file);
-               *werror = WSAEINTR;
-               return FALSE;
-       }
-
-       MONO_ENTER_GC_SAFE;
-
-       CloseHandle (file);
-
-       MONO_EXIT_GC_SAFE;
-
-       if (*werror)
-               return FALSE;
-
-       return ret;
-}
-#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 ();
-}
-
-void
-mono_network_cleanup (void)
-{
-       _wapi_cleanup_networking ();
-       mono_networking_shutdown ();
-}
-
-void
-icall_cancel_blocking_socket_operation (MonoThread *thread)
-{
-       MonoInternalThread *internal;
-
-       internal = thread->internal_thread;
-       g_assert (internal);
-
-       mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid));
-}
-
-#endif /* #ifndef DISABLE_SOCKETS */
diff --git a/mono/metadata/socket-io.h b/mono/metadata/socket-io.h
deleted file mode 100644 (file)
index 7a8c936..0000000
+++ /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 <config.h>
-#include <glib.h>
-
-#include <mono/metadata/object-internals.h>
-#include <mono/io-layer/io-layer.h>
-
-/* 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_ */
index 00b7e466933ce00e2dcf0fe0f7790d7f85e798c4..4b59150832a71ed77980c966e1a2d0c9ccb747a2 100644 (file)
@@ -29,6 +29,7 @@
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/mono-lazy-init.h>
 #include <mono/utils/mono-logger-internals.h>
+#include <mono/io-layer/io-layer.h>
 
 typedef struct {
        gboolean (*init) (gint wakeup_pipe_fd);
index 0936ee016cda8d100b6f660c7a8eace2b7f62301..c7de70f2715b9fa733dc58fc13a0ec4d61c896fc 100644 (file)
@@ -6,7 +6,6 @@
 #include <glib.h>
 
 #include <mono/metadata/object-internals.h>
-#include <mono/metadata/socket-io.h>
 
 typedef struct _MonoIOSelectorJob MonoIOSelectorJob;
 
index fa8f850ea66088dcacb4851f7c36bdaf70976584..f78ccf68b2a19822f7aa464e6d3320861fc4e59d 100644 (file)
@@ -33,6 +33,7 @@
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-rand.h>
 #include <mono/utils/refcount.h>
+#include <mono/io-layer/io-layer.h>
 
 #define CPU_USAGE_LOW 80
 #define CPU_USAGE_HIGH 95
index 84165e226b116705c394a60c72e826574bb32c2b..217384853490ca102fbde6ddfbb81730f6c5b18b 100644 (file)
@@ -45,6 +45,7 @@
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/refcount.h>
+#include <mono/io-layer/io-layer.h>
 
 typedef struct {
        MonoDomain *domain;
diff --git a/mono/metadata/w32socket-internals.h b/mono/metadata/w32socket-internals.h
new file mode 100644 (file)
index 0000000..dd4c611
--- /dev/null
@@ -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 <config.h>
+#include <glib.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#include <mono/io-layer/io-layer.h>
+
+#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 (file)
index 0000000..4b3d863
--- /dev/null
@@ -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 <config.h>
+#include <glib.h>
+
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <arpa/inet.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>    /* defines SIOCATMARK */
+#endif
+#ifndef HAVE_MSG_NOSIGNAL
+#include <signal.h>
+#endif
+#ifdef HAVE_SYS_SENDFILE_H
+#include <sys/sendfile.h>
+#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/w32socket-win32.c b/mono/metadata/w32socket-win32.c
new file mode 100644 (file)
index 0000000..9a2d452
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * 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 <config.h>
+#include <glib.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <ws2tcpip.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
+
+#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;
+       return ioctlsocket (sock, FIONBIO, &non_block) != SOCKET_ERROR;
+}
+
+static DWORD get_socket_timeout (SOCKET sock, int optname)
+{
+       DWORD timeout = 0;
+       int optlen = sizeof (DWORD);
+       if (getsockopt (sock, SOL_SOCKET, optname, (char *)&timeout, &optlen) == SOCKET_ERROR) {
+               WSASetLastError (0);
+               return WSA_INFINITE;
+       }
+       if (timeout == 0)
+               timeout = WSA_INFINITE; // 0 means infinite
+       return timeout;
+}
+
+/*
+* Performs an alertable wait for the specified event (FD_ACCEPT_BIT,
+* FD_CONNECT_BIT, FD_READ_BIT, FD_WRITE_BIT) on the specified socket.
+* Returns TRUE if the event is fired without errors. Calls WSASetLastError()
+* with WSAEINTR and returns FALSE if the thread is alerted. If the event is
+* fired but with an error WSASetLastError() is called to set the error and the
+* function returns FALSE.
+*/
+static gboolean alertable_socket_wait (SOCKET sock, int event_bit)
+{
+       static char *EVENT_NAMES[] = { "FD_READ", "FD_WRITE", NULL /*FD_OOB*/, "FD_ACCEPT", "FD_CONNECT", "FD_CLOSE" };
+       gboolean success = FALSE;
+       int error = -1;
+       DWORD timeout = WSA_INFINITE;
+       if (event_bit == FD_READ_BIT || event_bit == FD_WRITE_BIT) {
+               timeout = get_socket_timeout (sock, event_bit == FD_READ_BIT ? SO_RCVTIMEO : SO_SNDTIMEO);
+       }
+       WSASetLastError (0);
+       WSAEVENT event = WSACreateEvent ();
+       if (event != WSA_INVALID_EVENT) {
+               if (WSAEventSelect (sock, event, (1 << event_bit) | FD_CLOSE) != SOCKET_ERROR) {
+                       LOGDEBUG (g_message ("%06d - Calling WSAWaitForMultipleEvents () on socket %d", GetCurrentThreadId (), sock));
+                       DWORD ret = WSAWaitForMultipleEvents (1, &event, TRUE, timeout, TRUE);
+                       if (ret == WSA_WAIT_IO_COMPLETION) {
+                               LOGDEBUG (g_message ("%06d - WSAWaitForMultipleEvents () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), sock));
+                               error = WSAEINTR;
+                       } else if (ret == WSA_WAIT_TIMEOUT) {
+                               error = WSAETIMEDOUT;
+                       } else {
+                               g_assert (ret == WSA_WAIT_EVENT_0);
+                               WSANETWORKEVENTS ne = { 0 };
+                               if (WSAEnumNetworkEvents (sock, event, &ne) != SOCKET_ERROR) {
+                                       if (ne.lNetworkEvents & (1 << event_bit) && ne.iErrorCode[event_bit]) {
+                                               LOGDEBUG (g_message ("%06d - %s error %d on socket %d", GetCurrentThreadId (), EVENT_NAMES[event_bit], ne.iErrorCode[event_bit], sock));
+                                               error = ne.iErrorCode[event_bit];
+                                       } else if (ne.lNetworkEvents & FD_CLOSE_BIT && ne.iErrorCode[FD_CLOSE_BIT]) {
+                                               LOGDEBUG (g_message ("%06d - FD_CLOSE error %d on socket %d", GetCurrentThreadId (), ne.iErrorCode[FD_CLOSE_BIT], sock));
+                                               error = ne.iErrorCode[FD_CLOSE_BIT];
+                                       } else {
+                                               LOGDEBUG (g_message ("%06d - WSAEnumNetworkEvents () finished successfully on socket %d", GetCurrentThreadId (), sock));
+                                               success = TRUE;
+                                               error = 0;
+                                       }
+                               }
+                       }
+                       WSAEventSelect (sock, NULL, 0);
+               }
+               WSACloseEvent (event);
+       }
+       if (error != -1) {
+               WSASetLastError (error);
+       }
+       return success;
+}
+
+#define ALERTABLE_SOCKET_CALL(event_bit, blocking, repeat, ret, op, sock, ...) \
+       LOGDEBUG (g_message ("%06d - Performing %s " #op " () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", sock)); \
+       if (blocking) { \
+               if (set_blocking(sock, FALSE)) { \
+                       while (-1 == (int) (ret = op (sock, __VA_ARGS__))) { \
+                               int _error = WSAGetLastError ();\
+                               if (_error != WSAEWOULDBLOCK && _error != WSA_IO_PENDING) \
+                                       break; \
+                               if (!alertable_socket_wait (sock, event_bit) || !repeat) \
+                                       break; \
+                       } \
+                       int _saved_error = WSAGetLastError (); \
+                       set_blocking (sock, TRUE); \
+                       WSASetLastError (_saved_error); \
+               } \
+       } else { \
+               ret = op (sock, __VA_ARGS__); \
+       } \
+       int _saved_error = WSAGetLastError (); \
+       LOGDEBUG (g_message ("%06d - Finished %s " #op " () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \
+               blocking ? "blocking" : "non-blocking", sock, ret, _saved_error)); \
+       WSASetLastError (_saved_error);
+
+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 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);
+       ret = WSAGetLastError () != 0 ? SOCKET_ERROR : 0;
+       return ret;
+}
+
+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 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 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 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 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 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);
+       return ret;
+}
+
+#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)
+{
+       LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket));
+
+       int error = 0;
+       if (blocking) {
+               OVERLAPPED overlapped = { 0 };
+               overlapped.hEvent = WSACreateEvent ();
+               if (overlapped.hEvent == WSA_INVALID_EVENT)
+                       return FALSE;
+               if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) {
+                       error = WSAGetLastError ();
+                       if (error == WSA_IO_PENDING) {
+                               error = 0;
+                               // NOTE: .NET's Socket.SendFile() doesn't honor the Socket's SendTimeout so we shouldn't either
+                               DWORD ret = WaitForSingleObjectEx (overlapped.hEvent, INFINITE, TRUE);
+                               if (ret == WAIT_IO_COMPLETION) {
+                                       LOGDEBUG (g_message ("%06d - WaitForSingleObjectEx () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), hSocket));
+                                       error = WSAEINTR;
+                               } else if (ret == WAIT_TIMEOUT) {
+                                       error = WSAETIMEDOUT;
+                               } else if (ret != WAIT_OBJECT_0) {
+                                       error = GetLastError ();
+                               }
+                       }
+               }
+               WSACloseEvent (overlapped.hEvent);
+       } else {
+               if (!TransmitFile (hSocket, hFile, 0, 0, NULL, lpTransmitBuffers, dwReserved)) {
+                       error = WSAGetLastError ();
+               }
+       }
+
+       LOGDEBUG (g_message ("%06d - Finished %s TransmitFile () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \
+               blocking ? "blocking" : "non-blocking", hSocket, error == 0, error));
+       WSASetLastError (error);
+
+       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/w32socket.c b/mono/metadata/w32socket.c
new file mode 100644 (file)
index 0000000..9d45dda
--- /dev/null
@@ -0,0 +1,2716 @@
+/*
+ * socket-io.c: Socket IO internal calls
+ *
+ * Authors:
+ *     Dick Porter (dick@ximian.com)
+ *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ *
+ * This file has been re-licensed under the MIT License:
+ * http://opensource.org/licenses/MIT
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#ifndef DISABLE_SOCKETS
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#define __APPLE_USE_RFC_3542
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HOST_WIN32
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include <mono/metadata/object.h>
+#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/file-io.h>
+#include <mono/metadata/threads.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/threadpool-io.h>
+#include <mono/utils/mono-poll.h>
+/* FIXME change this code to not mess so much with the internals */
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-memory-model.h>
+#include <mono/utils/networking.h>
+#include <mono/metadata/w32handle.h>
+#include <mono/metadata/w32socket.h>
+#include <mono/metadata/w32socket-internals.h>
+
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>    /* defines SIOCATMARK */
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#ifdef HAVE_GETIFADDRS
+// <net/if.h> must be included before <ifaddrs.h>
+#include <ifaddrs.h>
+#endif
+
+#if defined(_MSC_VER) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
+#include <MSWSock.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)
+{
+       mono_thread_info_abort_socket_syscall_for_close ((MonoNativeThreadId) (gsize) data);
+}
+
+static gint32
+convert_family (MonoAddressFamily mono_family)
+{
+       switch (mono_family) {
+       case AddressFamily_Unknown:
+       case AddressFamily_ImpLink:
+       case AddressFamily_Pup:
+       case AddressFamily_Chaos:
+       case AddressFamily_Iso:
+       case AddressFamily_Ecma:
+       case AddressFamily_DataKit:
+       case AddressFamily_Ccitt:
+       case AddressFamily_DataLink:
+       case AddressFamily_Lat:
+       case AddressFamily_HyperChannel:
+       case AddressFamily_NetBios:
+       case AddressFamily_VoiceView:
+       case AddressFamily_FireFox:
+       case AddressFamily_Banyan:
+       case AddressFamily_Atm:
+       case AddressFamily_Cluster:
+       case AddressFamily_Ieee12844:
+       case AddressFamily_NetworkDesigners:
+               g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
+               return -1;
+       case AddressFamily_Unspecified:
+               return AF_UNSPEC;
+       case AddressFamily_Unix:
+               return AF_UNIX;
+       case AddressFamily_InterNetwork:
+               return AF_INET;
+       case AddressFamily_AppleTalk:
+               return AF_APPLETALK;
+       case AddressFamily_InterNetworkV6:
+               return AF_INET6;
+       case AddressFamily_DecNet:
+#ifdef AF_DECnet
+               return AF_DECnet;
+#else
+               return -1;
+#endif
+       case AddressFamily_Ipx:
+#ifdef AF_IPX
+               return AF_IPX;
+#else
+               return -1;
+#endif
+       case AddressFamily_Sna:
+#ifdef AF_SNA
+               return AF_SNA;
+#else
+               return -1;
+#endif
+       case AddressFamily_Irda:
+#ifdef AF_IRDA
+               return AF_IRDA;
+#else
+               return -1;
+#endif
+       default:
+               g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
+               return -1;
+       }
+}
+
+static MonoAddressFamily
+convert_to_mono_family (guint16 af_family)
+{
+       switch (af_family) {
+       case AF_UNSPEC:
+               return AddressFamily_Unspecified;
+       case AF_UNIX:
+               return AddressFamily_Unix;
+       case AF_INET:
+               return AddressFamily_InterNetwork;
+#ifdef AF_IPX
+       case AF_IPX:
+               return AddressFamily_Ipx;
+#endif
+#ifdef AF_SNA
+       case AF_SNA:
+               return AddressFamily_Sna;
+#endif
+#ifdef AF_DECnet
+       case AF_DECnet:
+               return AddressFamily_DecNet;
+#endif
+       case AF_APPLETALK:
+               return AddressFamily_AppleTalk;
+       case AF_INET6:
+               return AddressFamily_InterNetworkV6;
+#ifdef AF_IRDA
+       case AF_IRDA:
+               return AddressFamily_Irda;
+#endif
+       default:
+               g_warning ("unknown address family 0x%x", af_family);
+               return AddressFamily_Unknown;
+       }
+}
+
+static gint32
+convert_type (MonoSocketType mono_type)
+{
+       switch (mono_type) {
+       case SocketType_Stream:
+               return SOCK_STREAM;
+       case SocketType_Dgram:
+               return SOCK_DGRAM;
+       case SocketType_Raw:
+               return SOCK_RAW;
+       case SocketType_Rdm:
+#ifdef SOCK_RDM
+               return SOCK_RDM;
+#else
+               return -1;
+#endif
+       case SocketType_Seqpacket:
+               return SOCK_SEQPACKET;
+       case SocketType_Unknown:
+               g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
+               return -1;
+       default:
+               g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
+               return -1;
+       }
+}
+
+static gint32
+convert_proto (MonoProtocolType mono_proto)
+{
+       switch (mono_proto) {
+       case ProtocolType_IP:
+       case ProtocolType_IPv6:
+       case ProtocolType_Icmp:
+       case ProtocolType_Igmp:
+       case ProtocolType_Ggp:
+       case ProtocolType_Tcp:
+       case ProtocolType_Pup:
+       case ProtocolType_Udp:
+       case ProtocolType_Idp:
+               /* These protocols are known (on my system at least) */
+               return mono_proto;
+       case ProtocolType_ND:
+       case ProtocolType_Raw:
+       case ProtocolType_Ipx:
+       case ProtocolType_Spx:
+       case ProtocolType_SpxII:
+       case ProtocolType_Unknown:
+               /* These protocols arent */
+               g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
+               return -1;
+       default:
+               return -1;
+       }
+}
+
+/* Convert MonoSocketFlags */
+static gint32
+convert_socketflags (gint32 sflags)
+{
+       gint32 flags = 0;
+
+       if (!sflags)
+               /* SocketFlags.None */
+               return 0;
+
+       if (sflags & ~(SocketFlags_OutOfBand | SocketFlags_MaxIOVectorLength | SocketFlags_Peek | 
+                       SocketFlags_DontRoute | SocketFlags_Partial))
+               /* Contains invalid flag values */
+               return -1;
+
+       if (sflags & SocketFlags_OutOfBand)
+               flags |= MSG_OOB;
+       if (sflags & SocketFlags_Peek)
+               flags |= MSG_PEEK;
+       if (sflags & SocketFlags_DontRoute)
+               flags |= MSG_DONTROUTE;
+
+       /* Ignore Partial - see bug 349688.  Don't return -1, because
+        * according to the comment in that bug ms runtime doesn't for
+        * UDP sockets (this means we will silently ignore it for TCP
+        * too)
+        */
+#ifdef MSG_MORE
+       if (sflags & SocketFlags_Partial)
+               flags |= MSG_MORE;
+#endif
+#if 0
+       /* Don't do anything for MaxIOVectorLength */
+       if (sflags & SocketFlags_MaxIOVectorLength)
+               return -1;      
+#endif
+       return flags;
+}
+
+/*
+ * Returns:
+ *    0 on success (mapped mono_level and mono_name to system_level and system_name
+ *   -1 on error
+ *   -2 on non-fatal error (ie, must ignore)
+ */
+static gint32
+convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level, MonoSocketOptionName mono_name, int *system_level, int *system_name)
+{
+       switch (mono_level) {
+       case SocketOptionLevel_Socket:
+               *system_level = SOL_SOCKET;
+               
+               switch (mono_name) {
+               case SocketOptionName_DontLinger:
+                       /* This is SO_LINGER, because the setsockopt
+                        * internal call maps DontLinger to SO_LINGER
+                        * with l_onoff=0
+                        */
+                       *system_name = SO_LINGER;
+                       break;
+               case SocketOptionName_Debug:
+                       *system_name = SO_DEBUG;
+                       break;
+#ifdef SO_ACCEPTCONN
+               case SocketOptionName_AcceptConnection:
+                       *system_name = SO_ACCEPTCONN;
+                       break;
+#endif
+               case SocketOptionName_ReuseAddress:
+                       *system_name = SO_REUSEADDR;
+                       break;
+               case SocketOptionName_KeepAlive:
+                       *system_name = SO_KEEPALIVE;
+                       break;
+               case SocketOptionName_DontRoute:
+                       *system_name = SO_DONTROUTE;
+                       break;
+               case SocketOptionName_Broadcast:
+                       *system_name = SO_BROADCAST;
+                       break;
+               case SocketOptionName_Linger:
+                       *system_name = SO_LINGER;
+                       break;
+               case SocketOptionName_OutOfBandInline:
+                       *system_name = SO_OOBINLINE;
+                       break;
+               case SocketOptionName_SendBuffer:
+                       *system_name = SO_SNDBUF;
+                       break;
+               case SocketOptionName_ReceiveBuffer:
+                       *system_name = SO_RCVBUF;
+                       break;
+               case SocketOptionName_SendLowWater:
+                       *system_name = SO_SNDLOWAT;
+                       break;
+               case SocketOptionName_ReceiveLowWater:
+                       *system_name = SO_RCVLOWAT;
+                       break;
+               case SocketOptionName_SendTimeout:
+                       *system_name = SO_SNDTIMEO;
+                       break;
+               case SocketOptionName_ReceiveTimeout:
+                       *system_name = SO_RCVTIMEO;
+                       break;
+               case SocketOptionName_Error:
+                       *system_name = SO_ERROR;
+                       break;
+               case SocketOptionName_Type:
+                       *system_name = SO_TYPE;
+                       break;
+#ifdef SO_PEERCRED
+               case SocketOptionName_PeerCred:
+                       *system_name = SO_PEERCRED;
+                       break;
+#endif
+               case SocketOptionName_ExclusiveAddressUse:
+#ifdef SO_EXCLUSIVEADDRUSE
+                       *system_name = SO_EXCLUSIVEADDRUSE;
+                       break;
+#endif
+               case SocketOptionName_UseLoopback:
+#ifdef SO_USELOOPBACK
+                       *system_name = SO_USELOOPBACK;
+                       break;
+#endif
+               case SocketOptionName_MaxConnections:
+#ifdef SO_MAXCONN
+                       *system_name = SO_MAXCONN;
+                       break;
+#elif defined(SOMAXCONN)
+                       *system_name = SOMAXCONN;
+                       break;
+#endif
+               default:
+                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
+                       return -1;
+               }
+               break;
+               
+       case SocketOptionLevel_IP:
+               *system_level = mono_networking_get_ip_protocol ();
+               
+               switch (mono_name) {
+               case SocketOptionName_IPOptions:
+                       *system_name = IP_OPTIONS;
+                       break;
+#ifdef IP_HDRINCL
+               case SocketOptionName_HeaderIncluded:
+                       *system_name = IP_HDRINCL;
+                       break;
+#endif
+#ifdef IP_TOS
+               case SocketOptionName_TypeOfService:
+                       *system_name = IP_TOS;
+                       break;
+#endif
+#ifdef IP_TTL
+               case SocketOptionName_IpTimeToLive:
+                       *system_name = IP_TTL;
+                       break;
+#endif
+               case SocketOptionName_MulticastInterface:
+                       *system_name = IP_MULTICAST_IF;
+                       break;
+               case SocketOptionName_MulticastTimeToLive:
+                       *system_name = IP_MULTICAST_TTL;
+                       break;
+               case SocketOptionName_MulticastLoopback:
+                       *system_name = IP_MULTICAST_LOOP;
+                       break;
+               case SocketOptionName_AddMembership:
+                       *system_name = IP_ADD_MEMBERSHIP;
+                       break;
+               case SocketOptionName_DropMembership:
+                       *system_name = IP_DROP_MEMBERSHIP;
+                       break;
+#ifdef HAVE_IP_PKTINFO
+               case SocketOptionName_PacketInformation:
+                       *system_name = IP_PKTINFO;
+                       break;
+#endif /* HAVE_IP_PKTINFO */
+
+               case SocketOptionName_DontFragment:
+#ifdef HAVE_IP_DONTFRAGMENT
+                       *system_name = IP_DONTFRAGMENT;
+                       break;
+#elif defined HAVE_IP_MTU_DISCOVER
+                       /* Not quite the same */
+                       *system_name = IP_MTU_DISCOVER;
+                       break;
+#else
+                       /* If the flag is not available on this system, we can ignore this error */
+                       return -2;
+#endif /* HAVE_IP_DONTFRAGMENT */
+               case SocketOptionName_AddSourceMembership:
+               case SocketOptionName_DropSourceMembership:
+               case SocketOptionName_BlockSource:
+               case SocketOptionName_UnblockSource:
+                       /* Can't figure out how to map these, so fall
+                        * through
+                        */
+               default:
+                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
+                       return -1;
+               }
+               break;
+
+       case SocketOptionLevel_IPv6:
+               *system_level = mono_networking_get_ipv6_protocol ();
+
+               switch (mono_name) {
+               case SocketOptionName_IpTimeToLive:
+               case SocketOptionName_HopLimit:
+                       *system_name = IPV6_UNICAST_HOPS;
+                       break;
+               case SocketOptionName_MulticastInterface:
+                       *system_name = IPV6_MULTICAST_IF;
+                       break;
+               case SocketOptionName_MulticastTimeToLive:
+                       *system_name = IPV6_MULTICAST_HOPS;
+                       break;
+               case SocketOptionName_MulticastLoopback:
+                       *system_name = IPV6_MULTICAST_LOOP;
+                       break;
+               case SocketOptionName_AddMembership:
+                       *system_name = IPV6_JOIN_GROUP;
+                       break;
+               case SocketOptionName_DropMembership:
+                       *system_name = IPV6_LEAVE_GROUP;
+                       break;
+               case SocketOptionName_IPv6Only:
+#ifdef IPV6_V6ONLY
+                       *system_name = IPV6_V6ONLY;
+#else
+                       return -1;
+#endif
+                       break;
+               case SocketOptionName_PacketInformation:
+#ifdef HAVE_IPV6_PKTINFO
+                       *system_name = IPV6_PKTINFO;
+#endif
+                       break;
+               case SocketOptionName_HeaderIncluded:
+               case SocketOptionName_IPOptions:
+               case SocketOptionName_TypeOfService:
+               case SocketOptionName_DontFragment:
+               case SocketOptionName_AddSourceMembership:
+               case SocketOptionName_DropSourceMembership:
+               case SocketOptionName_BlockSource:
+               case SocketOptionName_UnblockSource:
+                       /* Can't figure out how to map these, so fall
+                        * through
+                        */
+               default:
+                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name);
+                       return -1;
+               }
+               break;  /* SocketOptionLevel_IPv6 */
+               
+       case SocketOptionLevel_Tcp:
+               *system_level = mono_networking_get_tcp_protocol ();
+               
+               switch (mono_name) {
+               case SocketOptionName_NoDelay:
+                       *system_name = TCP_NODELAY;
+                       break;
+#if 0
+                       /* The documentation is talking complete
+                        * bollocks here: rfc-1222 is titled
+                        * 'Advancing the NSFNET Routing Architecture'
+                        * and doesn't mention either of the words
+                        * "expedite" or "urgent".
+                        */
+               case SocketOptionName_BsdUrgent:
+               case SocketOptionName_Expedited:
+#endif
+               default:
+                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
+                       return -1;
+               }
+               break;
+               
+       case SocketOptionLevel_Udp:
+               g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
+
+               switch(mono_name) {
+               case SocketOptionName_NoChecksum:
+               case SocketOptionName_ChecksumCoverage:
+               default:
+                       g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
+                       return -1;
+               }
+               return -1;
+               break;
+
+       default:
+               g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
+               return -1;
+       }
+
+       return 0;
+}
+
+static MonoImage*
+get_socket_assembly (void)
+{
+       MonoDomain *domain = mono_domain_get ();
+       
+       if (domain->socket_assembly == NULL) {
+               MonoImage *socket_assembly;
+
+               socket_assembly = mono_image_loaded ("System");
+               if (!socket_assembly) {
+                       MonoAssembly *sa = mono_assembly_open ("System.dll", NULL);
+               
+                       if (!sa) {
+                               g_assert_not_reached ();
+                       } else {
+                               socket_assembly = mono_assembly_get_image (sa);
+                       }
+               }
+               mono_atomic_store_release (&domain->socket_assembly, socket_assembly);
+       }
+       
+       return domain->socket_assembly;
+}
+
+gpointer
+ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, gint32 *werror)
+{
+       SOCKET sock;
+       gint32 sock_family;
+       gint32 sock_proto;
+       gint32 sock_type;
+       
+       *werror = 0;
+       
+       sock_family = convert_family ((MonoAddressFamily)family);
+       if (sock_family == -1) {
+               *werror = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+
+       sock_proto = convert_proto ((MonoProtocolType)proto);
+       if (sock_proto == -1) {
+               *werror = WSAEPROTONOSUPPORT;
+               return NULL;
+       }
+       
+       sock_type = convert_type ((MonoSocketType)type);
+       if (sock_type == -1) {
+               *werror = WSAESOCKTNOSUPPORT;
+               return NULL;
+       }
+       
+       sock = mono_w32socket_socket (sock_family, sock_type, sock_proto);
+
+       if (sock == INVALID_SOCKET) {
+               *werror = mono_w32socket_get_last_error ();
+               return NULL;
+       }
+
+       return GUINT_TO_POINTER (sock);
+}
+
+/* FIXME: the SOCKET parameter (here and in other functions in this
+ * file) is really an IntPtr which needs to be converted to a guint32.
+ */
+void
+ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror)
+{
+       LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock));
+
+       *werror = 0;
+
+       /* Clear any pending work item from this socket if the underlying
+        * polling system does not notify when the socket is closed */
+       mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock));
+
+       MONO_ENTER_GC_SAFE;
+       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__, mono_w32socket_get_last_error ()));
+
+       return mono_w32socket_get_last_error ();
+}
+
+gint32
+ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock, gint32 *werror)
+{
+       int ret;
+       guint64 amount;
+       
+       *werror = 0;
+
+       /* FIXME: this might require amount to be unsigned long. */
+       ret = mono_w32socket_get_available (sock, &amount);
+       if (ret == SOCKET_ERROR) {
+               *werror = mono_w32socket_get_last_error ();
+               return 0;
+       }
+       
+       return amount;
+}
+
+void
+ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock, gboolean block, gint32 *werror)
+{
+       int ret;
+       
+       *werror = 0;
+
+       ret = mono_w32socket_set_blocking (sock, block);
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+}
+
+gpointer
+ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror, gboolean blocking)
+{
+       gboolean interrupted;
+       SOCKET newsock;
+
+       *werror = 0;
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return NULL;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       newsock = mono_w32socket_accept (sock, NULL, 0, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (newsock == INVALID_SOCKET)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror)
+               return NULL;
+       
+       return GUINT_TO_POINTER (newsock);
+}
+
+void
+ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog, gint32 *werror)
+{
+       int ret;
+       
+       *werror = 0;
+
+       MONO_ENTER_GC_SAFE;
+
+       ret = mono_w32socket_listen (sock, backlog);
+
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+}
+
+// Check whether it's ::ffff::0:0.
+static gboolean
+is_ipv4_mapped_any (const struct in6_addr *addr)
+{
+       int i;
+       
+       for (i = 0; i < 10; i++) {
+               if (addr->s6_addr [i])
+                       return FALSE;
+       }
+       if ((addr->s6_addr [10] != 0xff) || (addr->s6_addr [11] != 0xff))
+               return FALSE;
+       for (i = 12; i < 16; i++) {
+               if (addr->s6_addr [i])
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+static MonoObject*
+create_object_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error)
+{
+       MonoDomain *domain = mono_domain_get ();
+       MonoObject *sockaddr_obj;
+       MonoArray *data;
+       MonoAddressFamily family;
+
+       mono_error_init (error);
+
+       /* Build a System.Net.SocketAddress object instance */
+       if (!domain->sockaddr_class)
+               domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
+       sockaddr_obj = mono_object_new_checked (domain, domain->sockaddr_class, error);
+       return_val_if_nok (error, NULL);
+       
+       /* Locate the SocketAddress data buffer in the object */
+       if (!domain->sockaddr_data_field) {
+               domain->sockaddr_data_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Buffer");
+               g_assert (domain->sockaddr_data_field);
+       }
+
+       /* Locate the SocketAddress data buffer length in the object */
+       if (!domain->sockaddr_data_length_field) {
+               domain->sockaddr_data_length_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Size");
+               g_assert (domain->sockaddr_data_length_field);
+       }
+
+       /* May be the +2 here is too conservative, as sa_len returns
+        * the length of the entire sockaddr_in/in6, including
+        * sizeof (unsigned short) of the family */
+       /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
+       data = mono_array_new_cached (domain, mono_get_byte_class (), sa_size + 2, error);
+       return_val_if_nok (error, NULL);
+
+       /* The data buffer is laid out as follows:
+        * bytes 0 and 1 are the address family
+        * bytes 2 and 3 are the port info
+        * the rest is the address info
+        */
+               
+       family = convert_to_mono_family (saddr->sa_family);
+       if (family == AddressFamily_Unknown) {
+               *werror = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+
+       mono_array_set (data, guint8, 0, family & 0x0FF);
+       mono_array_set (data, guint8, 1, (family >> 8) & 0x0FF);
+       
+       if (saddr->sa_family == AF_INET) {
+               struct sockaddr_in *sa_in = (struct sockaddr_in *)saddr;
+               guint16 port = ntohs (sa_in->sin_port);
+               guint32 address = ntohl (sa_in->sin_addr.s_addr);
+               int buffer_size = 8;
+               
+               if (sa_size < buffer_size) {
+                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+                       return NULL;
+               }
+               
+               mono_array_set (data, guint8, 2, (port>>8) & 0xff);
+               mono_array_set (data, guint8, 3, (port) & 0xff);
+               mono_array_set (data, guint8, 4, (address>>24) & 0xff);
+               mono_array_set (data, guint8, 5, (address>>16) & 0xff);
+               mono_array_set (data, guint8, 6, (address>>8) & 0xff);
+               mono_array_set (data, guint8, 7, (address) & 0xff);
+       
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+
+               return sockaddr_obj;
+       } else if (saddr->sa_family == AF_INET6) {
+               struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)saddr;
+               int i;
+               int buffer_size = 28;
+
+               guint16 port = ntohs (sa_in->sin6_port);
+
+               if (sa_size < buffer_size) {
+                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+                       return NULL;
+               }
+
+               mono_array_set (data, guint8, 2, (port>>8) & 0xff);
+               mono_array_set (data, guint8, 3, (port) & 0xff);
+               
+               if (is_ipv4_mapped_any (&sa_in->sin6_addr)) {
+                       // Map ::ffff:0:0 to :: (bug #5502)
+                       for (i = 0; i < 16; i++)
+                               mono_array_set (data, guint8, 8 + i, 0);
+               } else {
+                       for (i = 0; i < 16; i++) {
+                               mono_array_set (data, guint8, 8 + i,
+                                                               sa_in->sin6_addr.s6_addr [i]);
+                       }
+               }
+
+               mono_array_set (data, guint8, 24, sa_in->sin6_scope_id & 0xff);
+               mono_array_set (data, guint8, 25,
+                                               (sa_in->sin6_scope_id >> 8) & 0xff);
+               mono_array_set (data, guint8, 26,
+                                               (sa_in->sin6_scope_id >> 16) & 0xff);
+               mono_array_set (data, guint8, 27,
+                                               (sa_in->sin6_scope_id >> 24) & 0xff);
+
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+
+               return sockaddr_obj;
+       }
+#ifdef HAVE_SYS_UN_H
+       else if (saddr->sa_family == AF_UNIX) {
+               int i;
+               int buffer_size = sa_size + 2;
+
+               for (i = 0; i < sa_size; i++)
+                       mono_array_set (data, guint8, i + 2, saddr->sa_data [i]);
+               
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
+               mono_field_set_value (sockaddr_obj, domain->sockaddr_data_length_field, &buffer_size);
+
+               return sockaddr_obj;
+       }
+#endif
+       else {
+               *werror = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+}
+
+static int
+get_sockaddr_size (int family)
+{
+       int size;
+
+       size = 0;
+       if (family == AF_INET) {
+               size = sizeof (struct sockaddr_in);
+       } else if (family == AF_INET6) {
+               size = sizeof (struct sockaddr_in6);
+       }
+#ifdef HAVE_SYS_UN_H
+       else if (family == AF_UNIX) {
+               size = sizeof (struct sockaddr_un);
+       }
+#endif
+       return size;
+}
+
+MonoObject*
+ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 af, gint32 *werror)
+{
+       gchar *sa;
+       socklen_t salen;
+       int ret;
+       MonoObject *result;
+       MonoError error;
+       
+       *werror = 0;
+       
+       salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af));
+       if (salen == 0) {
+               *werror = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+       sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
+
+       MONO_ENTER_GC_SAFE;
+
+       ret = mono_w32socket_getsockname (sock, (struct sockaddr *)sa, &salen);
+
+       MONO_EXIT_GC_SAFE;
+       
+       if (ret == SOCKET_ERROR) {
+               *werror = mono_w32socket_get_last_error ();
+               if (salen > 128)
+                       g_free (sa);
+               return NULL;
+       }
+       
+       LOGDEBUG (g_message("%s: bound to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
+
+       result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
+       if (salen > 128)
+               g_free (sa);
+       if (!mono_error_ok (&error))
+               mono_error_set_pending_exception (&error);
+       return result;
+}
+
+MonoObject*
+ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32 af, gint32 *werror)
+{
+       gchar *sa;
+       socklen_t salen;
+       int ret;
+       MonoObject *result;
+       MonoError error;
+       
+       *werror = 0;
+       
+       salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af));
+       if (salen == 0) {
+               *werror = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+       sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
+       /* Note: linux returns just 2 for AF_UNIX. Always. */
+
+       MONO_ENTER_GC_SAFE;
+
+       ret = mono_w32socket_getpeername (sock, (struct sockaddr *)sa, &salen);
+
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR) {
+               *werror = mono_w32socket_get_last_error ();
+               if (salen > 128)
+                       g_free (sa);
+               return NULL;
+       }
+       
+       LOGDEBUG (g_message("%s: connected to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port)));
+
+       result = create_object_from_sockaddr ((struct sockaddr *)sa, salen, werror, &error);
+       if (salen > 128)
+               g_free (sa);
+       if (!mono_error_ok (&error))
+               mono_error_set_pending_exception (&error);
+       return result;
+}
+
+static struct sockaddr*
+create_sockaddr_from_object (MonoObject *saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error)
+{
+       MonoDomain *domain = mono_domain_get ();
+       MonoArray *data;
+       gint32 family;
+       int len;
+
+       mono_error_init (error);
+
+       if (!domain->sockaddr_class)
+               domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
+
+       /* Locate the SocketAddress data buffer in the object */
+       if (!domain->sockaddr_data_field) {
+               domain->sockaddr_data_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Buffer");
+               g_assert (domain->sockaddr_data_field);
+       }
+
+       /* Locate the SocketAddress data buffer length in the object */
+       if (!domain->sockaddr_data_length_field) {
+               domain->sockaddr_data_length_field = mono_class_get_field_from_name (domain->sockaddr_class, "m_Size");
+               g_assert (domain->sockaddr_data_length_field);
+       }
+
+       data = *(MonoArray **)(((char *)saddr_obj) + domain->sockaddr_data_field->offset);
+
+       /* The data buffer is laid out as follows:
+        * byte 0 is the address family low byte
+        * byte 1 is the address family high byte
+        * INET:
+        *      bytes 2 and 3 are the port info
+        *      the rest is the address info
+        * UNIX:
+        *      the rest is the file name
+        */
+       len = *(int *)(((char *)saddr_obj) + domain->sockaddr_data_length_field->offset);
+       g_assert (len >= 2);
+
+       family = convert_family ((MonoAddressFamily)(mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8)));
+       if (family == AF_INET) {
+               struct sockaddr_in *sa;
+               guint16 port;
+               guint32 address;
+               
+               if (len < 8) {
+                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+                       return NULL;
+               }
+
+               sa = g_new0 (struct sockaddr_in, 1);
+               port = (mono_array_get (data, guint8, 2) << 8) +
+                       mono_array_get (data, guint8, 3);
+               address = (mono_array_get (data, guint8, 4) << 24) +
+                       (mono_array_get (data, guint8, 5) << 16 ) +
+                       (mono_array_get (data, guint8, 6) << 8) +
+                       mono_array_get (data, guint8, 7);
+
+               sa->sin_family = family;
+               sa->sin_addr.s_addr = htonl (address);
+               sa->sin_port = htons (port);
+
+               *sa_size = sizeof (struct sockaddr_in);
+               return (struct sockaddr *)sa;
+       } else if (family == AF_INET6) {
+               struct sockaddr_in6 *sa;
+               int i;
+               guint16 port;
+               guint32 scopeid;
+               
+               if (len < 28) {
+                       mono_error_set_exception_instance (error, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
+                       return NULL;
+               }
+
+               sa = g_new0 (struct sockaddr_in6, 1);
+               port = mono_array_get (data, guint8, 3) +
+                       (mono_array_get (data, guint8, 2) << 8);
+               scopeid = mono_array_get (data, guint8, 24) + 
+                       (mono_array_get (data, guint8, 25) << 8) + 
+                       (mono_array_get (data, guint8, 26) << 16) + 
+                       (mono_array_get (data, guint8, 27) << 24);
+
+               sa->sin6_family = family;
+               sa->sin6_port = htons (port);
+               sa->sin6_scope_id = scopeid;
+
+               for (i = 0; i < 16; i++)
+                       sa->sin6_addr.s6_addr [i] = mono_array_get (data, guint8, 8 + i);
+
+               *sa_size = sizeof (struct sockaddr_in6);
+               return (struct sockaddr *)sa;
+       }
+#ifdef HAVE_SYS_UN_H
+       else if (family == AF_UNIX) {
+               struct sockaddr_un *sock_un;
+               int i;
+
+               /* Need a byte for the '\0' terminator/prefix, and the first
+                * two bytes hold the SocketAddress family
+                */
+               if (len - 2 >= sizeof (sock_un->sun_path)) {
+                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
+                       return NULL;
+               }
+               
+               sock_un = g_new0 (struct sockaddr_un, 1);
+
+               sock_un->sun_family = family;
+               for (i = 0; i < len - 2; i++)
+                       sock_un->sun_path [i] = mono_array_get (data, guint8, i + 2);
+               
+               *sa_size = len;
+               return (struct sockaddr *)sock_un;
+       }
+#endif
+       else {
+               *werror = WSAEAFNOSUPPORT;
+               return 0;
+       }
+}
+
+void
+ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock, MonoObject *sockaddr, gint32 *werror)
+{
+       MonoError error;
+       struct sockaddr *sa;
+       socklen_t sa_size;
+       int ret;
+       
+       *werror = 0;
+       
+       sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
+       if (*werror != 0)
+               return;
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return;
+       }
+
+       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 = mono_w32socket_bind (sock, sa, sa_size);
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       g_free (sa);
+}
+
+enum {
+       SelectModeRead,
+       SelectModeWrite,
+       SelectModeError
+};
+
+MonoBoolean
+ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode,
+                                                                                                  gint timeout, gint32 *werror)
+{
+       MonoInternalThread *thread = mono_thread_internal_current ();
+       mono_pollfd *pfds;
+       int ret;
+       gboolean interrupted;
+       time_t start;
+
+       *werror = 0;
+
+       pfds = g_new0 (mono_pollfd, 1);
+       pfds->fd = GPOINTER_TO_INT (sock);
+
+       switch (mode) {
+       case SelectModeRead:
+               pfds->events = MONO_POLLIN;
+               break;
+       case SelectModeWrite:
+               pfds->events = MONO_POLLOUT;
+               break;
+       default:
+               pfds->events = MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL;
+               break;
+       }
+
+       timeout = (timeout >= 0) ? (timeout / 1000) : -1;
+       start = time (NULL);
+
+       do {
+               mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+               if (interrupted) {
+                       g_free (pfds);
+                       *werror = WSAEINTR;
+                       return FALSE;
+               }
+
+               MONO_ENTER_GC_SAFE;
+
+               ret = mono_poll (pfds, 1, timeout);
+
+               MONO_EXIT_GC_SAFE;
+
+               mono_thread_info_uninstall_interrupt (&interrupted);
+               if (interrupted) {
+                       g_free (pfds);
+                       *werror = WSAEINTR;
+                       return FALSE;
+               }
+
+               if (timeout > 0 && ret < 0) {
+                       int err = errno;
+                       int sec = time (NULL) - start;
+                       
+                       timeout -= sec * 1000;
+                       if (timeout < 0) {
+                               timeout = 0;
+                       }
+                       
+                       errno = err;
+               }
+
+               if (ret == -1 && errno == EINTR) {
+                       if (mono_thread_test_state (thread, (MonoThreadState)(ThreadState_AbortRequested | ThreadState_StopRequested))) {
+                               g_free (pfds);
+                               return FALSE;
+                       }
+
+                       /* Suspend requested? */
+                       mono_thread_interruption_checkpoint ();
+
+                       errno = EINTR;
+               }
+       } while (ret == -1 && errno == EINTR);
+
+       if (ret == -1) {
+               *werror = mono_w32socket_convert_error (errno);
+               g_free (pfds);
+               return FALSE;
+       }
+
+       g_free (pfds);
+       return ret != 0;
+}
+
+void
+ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObject *sockaddr, gint32 *werror, gboolean blocking)
+{
+       MonoError error;
+       struct sockaddr *sa;
+       socklen_t sa_size;
+       int ret;
+       gboolean interrupted;
+
+       *werror = 0;
+
+       sa = create_sockaddr_from_object (sockaddr, &sa_size, werror, &error);
+       if (*werror != 0)
+               return;
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return;
+       }
+
+       LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_connect (sock, sa, sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       g_free (sa);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
+
+void
+ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror)
+{
+       gboolean interrupted;
+
+       LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__, sock, reuse));
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       *werror = mono_w32socket_disconnect (sock, reuse);
+       MONO_EXIT_GC_SAFE;
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
+
+gint32
+ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking)
+{
+       int ret;
+       gchar *buf;
+       gint32 alen;
+       int recvflags = 0;
+       gboolean interrupted;
+       MonoInternalThread* curthread G_GNUC_UNUSED = mono_thread_internal_current ();
+       
+       *werror = 0;
+       
+       alen = mono_array_length (buffer);
+       if (offset > alen - count)
+               return 0;
+       
+       buf = mono_array_addr (buffer, gchar, offset);
+       
+       recvflags = convert_socketflags (flags);
+       if (recvflags == -1) {
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted)
+               return 0;
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_recv (sock, buf, count, recvflags, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror)
+               return 0;
+
+       return ret;
+}
+
+gint32
+ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
+{
+       int ret, count;
+       gboolean interrupted;
+       guint32 recv;
+       WSABUF *wsabufs;
+       guint32 recvflags = 0;
+       
+       *werror = 0;
+       
+       wsabufs = mono_array_addr (buffers, WSABUF, 0);
+       count = mono_array_length (buffers);
+       
+       recvflags = convert_socketflags (flags);
+       if (recvflags == -1) {
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return 0;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_recvbuffers (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror)
+               return 0;
+
+       return recv;
+}
+
+gint32
+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;
+       gchar *buf;
+       gint32 alen;
+       int recvflags = 0;
+       struct sockaddr *sa;
+       socklen_t sa_size;
+       gboolean interrupted;
+       
+       *werror = 0;
+       
+       alen = mono_array_length (buffer);
+       if (offset > alen - count)
+               return 0;
+
+       sa = create_sockaddr_from_object (*sockaddr, &sa_size, werror, &error);
+       if (*werror != 0)
+               return 0;
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return 0;
+       }
+       
+       buf = mono_array_addr (buffer, gchar, offset);
+       
+       recvflags = convert_socketflags (flags);
+       if (recvflags == -1) {
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               g_free (sa);
+               *werror = WSAEINTR;
+               return 0;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror) {
+               g_free(sa);
+               return 0;
+       }
+
+       /* If we didn't get a socket size, then we're probably a
+        * connected connection-oriented socket and the stack hasn't
+        * returned the remote address. All we can do is return null.
+        */
+       if (sa_size) {
+               *sockaddr = create_object_from_sockaddr (sa, sa_size, werror, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_error_set_pending_exception (&error);
+                       g_free (sa);
+                       return 0;
+               }
+       } else {
+               *sockaddr = NULL;
+       }
+
+       g_free (sa);
+       
+       return ret;
+}
+
+gint32
+ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking)
+{
+       int ret;
+       gchar *buf;
+       gint32 alen;
+       int sendflags = 0;
+       gboolean interrupted;
+       
+       *werror = 0;
+       
+       alen = mono_array_length (buffer);
+       if (offset > alen - count)
+               return 0;
+
+       LOGDEBUG (g_message("%s: alen: %d", __func__, alen));
+       
+       buf = mono_array_addr (buffer, gchar, offset);
+
+       LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
+
+       sendflags = convert_socketflags (flags);
+       if (sendflags == -1) {
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return 0;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_send (sock, buf, count, sendflags, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror)
+               return 0;
+
+       return ret;
+}
+
+gint32
+ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArray *buffers, gint32 flags, gint32 *werror, gboolean blocking)
+{
+       int ret, count;
+       guint32 sent;
+       WSABUF *wsabufs;
+       guint32 sendflags = 0;
+       gboolean interrupted;
+       
+       *werror = 0;
+       
+       wsabufs = mono_array_addr (buffers, WSABUF, 0);
+       count = mono_array_length (buffers);
+       
+       sendflags = convert_socketflags (flags);
+       if (sendflags == -1) {
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return 0;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_sendbuffers (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       if (*werror)
+               return 0;
+
+       return sent;
+}
+
+gint32
+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;
+       gchar *buf;
+       gint32 alen;
+       int sendflags = 0;
+       struct sockaddr *sa;
+       socklen_t sa_size;
+       gboolean interrupted;
+       
+       *werror = 0;
+       
+       alen = mono_array_length (buffer);
+       if (offset > alen - count) {
+               return 0;
+       }
+
+       sa = create_sockaddr_from_object(sockaddr, &sa_size, werror, &error);
+       if (*werror != 0)
+               return 0;
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return 0;
+       }
+       
+       LOGDEBUG (g_message ("%s: alen: %d", __func__, alen));
+       
+       buf = mono_array_addr (buffer, gchar, offset);
+
+       LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
+
+       sendflags = convert_socketflags (flags);
+       if (sendflags == -1) {
+               g_free (sa);
+               *werror = WSAEOPNOTSUPP;
+               return 0;
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               g_free (sa);
+               *werror = WSAEINTR;
+               return 0;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_sendto (sock, buf, count, sendflags, sa, sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
+       g_free(sa);
+
+       if (*werror)
+               return 0;
+
+       return ret;
+}
+
+static SOCKET
+Socket_to_SOCKET (MonoObject *sockobj)
+{
+       MonoSafeHandle *safe_handle;
+       MonoClassField *field;
+       
+       field = mono_class_get_field_from_name (sockobj->vtable->klass, "m_Handle");
+       safe_handle = ((MonoSafeHandle *)(*(gpointer *)(((char *)sockobj) + field->offset)));
+
+       if (safe_handle == NULL)
+               return -1;
+
+       return (SOCKET)safe_handle->handle;
+}
+
+#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
+
+void
+ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *werror)
+{
+       MonoError error;
+       MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoObject *obj;
+       mono_pollfd *pfds;
+       int nfds, idx;
+       int ret;
+       int i, count;
+       int mode;
+       MonoClass *sock_arr_class;
+       MonoArray *socks;
+       time_t start;
+       uintptr_t socks_size;
+       gboolean interrupted;
+
+       *werror = 0;
+
+       /* *sockets -> READ, null, WRITE, null, ERROR, null */
+       count = mono_array_length (*sockets);
+       nfds = count - 3; /* NULL separators */
+       pfds = g_new0 (mono_pollfd, nfds);
+       mode = idx = 0;
+       for (i = 0; i < count; i++) {
+               obj = mono_array_get (*sockets, MonoObject *, i);
+               if (obj == NULL) {
+                       mode++;
+                       continue;
+               }
+
+               if (idx >= nfds) {
+                       /* The socket array was bogus */
+                       g_free (pfds);
+                       *werror = WSAEFAULT;
+                       return;
+               }
+
+               pfds [idx].fd = Socket_to_SOCKET (obj);
+               pfds [idx].events = (mode == 0) ? MONO_POLLIN : (mode == 1) ? MONO_POLLOUT : POLL_ERRORS;
+               idx++;
+       }
+
+       timeout = (timeout >= 0) ? (timeout / 1000) : -1;
+       start = time (NULL);
+       do {
+               mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+               if (interrupted) {
+                       g_free (pfds);
+                       *werror = WSAEINTR;
+                       return;
+               }
+
+               MONO_ENTER_GC_SAFE;
+
+               ret = mono_poll (pfds, nfds, timeout);
+
+               MONO_EXIT_GC_SAFE;
+
+               mono_thread_info_uninstall_interrupt (&interrupted);
+               if (interrupted) {
+                       g_free (pfds);
+                       *werror = WSAEINTR;
+                       return;
+               }
+
+               if (timeout > 0 && ret < 0) {
+                       int err = errno;
+                       int sec = time (NULL) - start;
+
+                       timeout -= sec * 1000;
+                       if (timeout < 0)
+                               timeout = 0;
+                       errno = err;
+               }
+
+               if (ret == -1 && errno == EINTR) {
+                       if (mono_thread_test_state (thread, (MonoThreadState)(ThreadState_AbortRequested | ThreadState_StopRequested))) {
+                               g_free (pfds);
+                               *sockets = NULL;
+                               return;
+                       }
+
+                       /* Suspend requested? */
+                       mono_thread_interruption_checkpoint ();
+
+                       errno = EINTR;
+               }
+       } while (ret == -1 && errno == EINTR);
+       
+       if (ret == -1) {
+               *werror = mono_w32socket_convert_error (errno);
+               g_free (pfds);
+               return;
+       }
+
+       if (ret == 0) {
+               g_free (pfds);
+               *sockets = NULL;
+               return;
+       }
+
+       sock_arr_class = ((MonoObject *)*sockets)->vtable->klass;
+       socks_size = ((uintptr_t)ret) + 3; /* space for the NULL delimiters */
+       socks = mono_array_new_full_checked (mono_domain_get (), sock_arr_class, &socks_size, NULL, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               g_free (pfds);
+               return;
+       }
+
+       mode = idx = 0;
+       for (i = 0; i < count && ret > 0; i++) {
+               mono_pollfd *pfd;
+
+               obj = mono_array_get (*sockets, MonoObject *, i);
+               if (obj == NULL) {
+                       mode++;
+                       idx++;
+                       continue;
+               }
+
+               pfd = &pfds [i - mode];
+               if (pfd->revents == 0)
+                       continue;
+
+               ret--;
+               if (mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
+                       mono_array_setref (socks, idx++, obj);
+               } else if (mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
+                       mono_array_setref (socks, idx++, obj);
+               } else if ((pfd->revents & POLL_ERRORS) != 0) {
+                       mono_array_setref (socks, idx++, obj);
+               }
+       }
+
+       *sockets = socks;
+       g_free (pfds);
+}
+
+static MonoObject*
+int_to_object (MonoDomain *domain, int val, MonoError *error)
+{
+       return mono_value_box_checked (domain, mono_get_int32_class (), &val, error);
+}
+
+void
+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;
+       int ret;
+       int val = 0;
+       socklen_t valsize = sizeof (val);
+       struct linger linger;
+       socklen_t lingersize = sizeof (linger);
+       int time_ms = 0;
+       socklen_t time_ms_size = sizeof (time_ms);
+#ifdef SO_PEERCRED
+#  if defined(__OpenBSD__)
+       struct sockpeercred cred;
+#  else
+       struct ucred cred;
+#  endif
+       socklen_t credsize = sizeof (cred);
+#endif
+       MonoError error;
+       MonoDomain *domain = mono_domain_get ();
+       MonoObject *obj;
+       MonoClass *obj_class;
+       MonoClassField *field;
+       
+       *werror = 0;
+       
+#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
+       if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
+               system_level = SOL_SOCKET;
+               system_name = SO_REUSEADDR;
+               ret = 0;
+       } else
+#endif
+       {
+               ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level, &system_name);
+       }
+
+       if (ret == -1) {
+               *werror = WSAENOPROTOOPT;
+               return;
+       }
+       if (ret == -2) {
+               *obj_val = int_to_object (domain, 0, &error);
+               mono_error_set_pending_exception (&error);
+               return;
+       }
+
+       MONO_ENTER_GC_SAFE;
+
+       /* No need to deal with MulticastOption names here, because
+        * you cant getsockopt AddMembership or DropMembership (the
+        * int getsockopt will error, causing an exception)
+        */
+       switch (name) {
+       case SocketOptionName_Linger:
+       case SocketOptionName_DontLinger:
+               ret = mono_w32socket_getsockopt (sock, system_level, system_name, &linger, &lingersize);
+               break;
+               
+       case SocketOptionName_SendTimeout:
+       case SocketOptionName_ReceiveTimeout:
+               ret = mono_w32socket_getsockopt (sock, system_level, system_name, (char *)&time_ms, &time_ms_size);
+               break;
+
+#ifdef SO_PEERCRED
+       case SocketOptionName_PeerCred: 
+               ret = mono_w32socket_getsockopt (sock, system_level, system_name, &cred, &credsize);
+               break;
+#endif
+
+       default:
+               ret = mono_w32socket_getsockopt (sock, system_level, system_name, &val, &valsize);
+       }
+
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR) {
+               *werror = mono_w32socket_get_last_error ();
+               return;
+       }
+       
+       switch (name) {
+       case SocketOptionName_Linger:
+               /* build a System.Net.Sockets.LingerOption */
+               obj_class = mono_class_load_from_name (get_socket_assembly (),
+                                                                                          "System.Net.Sockets",
+                                                                                          "LingerOption");
+               obj = mono_object_new_checked (domain, obj_class, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_error_set_pending_exception (&error);
+                       return;
+               }
+
+               /* Locate and set the fields "bool enabled" and "int
+                * lingerTime"
+                */
+               field = mono_class_get_field_from_name(obj_class, "enabled");
+               *(guint8 *)(((char *)obj)+field->offset) = linger.l_onoff;
+
+               field = mono_class_get_field_from_name(obj_class, "lingerTime");
+               *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
+               break;
+       case SocketOptionName_DontLinger:
+               /* construct a bool int in val - true if linger is off */
+               obj = int_to_object (domain, !linger.l_onoff, &error);
+               mono_error_set_pending_exception (&error);
+               break;
+       case SocketOptionName_SendTimeout:
+       case SocketOptionName_ReceiveTimeout:
+               obj = int_to_object (domain, time_ms, &error);
+               mono_error_set_pending_exception (&error);
+               break;
+
+#ifdef SO_PEERCRED
+       case SocketOptionName_PeerCred:  {
+               /* 
+                * build a Mono.Posix.PeerCred+PeerCredData if
+                * possible
+                */
+               static MonoImage *mono_posix_image = NULL;
+               MonoPeerCredData *cred_data;
+               
+               if (mono_posix_image == NULL) {
+                       mono_posix_image = mono_image_loaded ("Mono.Posix");
+                       if (!mono_posix_image) {
+                               MonoAssembly *sa = mono_assembly_open ("Mono.Posix.dll", NULL);
+                               if (!sa) {
+                                       *werror = WSAENOPROTOOPT;
+                                       return;
+                               } else {
+                                       mono_posix_image = mono_assembly_get_image (sa);
+                               }
+                       }
+               }
+               
+               obj_class = mono_class_load_from_name (mono_posix_image,
+                                                "Mono.Posix",
+                                                "PeerCredData");
+               obj = mono_object_new_checked (domain, obj_class, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_error_set_pending_exception (&error);
+                       return;
+               }
+               cred_data = (MonoPeerCredData *)obj;
+               cred_data->pid = cred.pid;
+               cred_data->uid = cred.uid;
+               cred_data->gid = cred.gid;
+               break;
+       }
+#endif
+
+       default:
+#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
+               if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse)
+                       val = val ? 0 : 1;
+#endif
+               obj = int_to_object (domain, val, &error);
+               mono_error_set_pending_exception (&error);
+       }
+
+       *obj_val = obj;
+}
+
+void
+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;
+       int ret;
+       guchar *buf;
+       socklen_t valsize;
+       
+       *werror = 0;
+       
+       ret = convert_sockopt_level_and_name((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level,
+                                                                                &system_name);
+       if (ret == -1) {
+               *werror = WSAENOPROTOOPT;
+               return;
+       }
+       if (ret == -2)
+               return;
+
+       valsize = mono_array_length (*byte_val);
+       buf = mono_array_addr (*byte_val, guchar, 0);
+
+       MONO_ENTER_GC_SAFE;
+
+       ret = mono_w32socket_getsockopt (sock, system_level, system_name, buf, &valsize);
+
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+}
+
+#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
+static struct in_addr
+ipaddress_to_struct_in_addr (MonoObject *ipaddr)
+{
+       struct in_addr inaddr;
+       MonoClassField *field;
+       
+       field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Address");
+
+       /* No idea why .net uses a 64bit type to hold a 32bit value...
+        *
+        * Internal value of IPAddess is in little-endian order
+        */
+       inaddr.s_addr = GUINT_FROM_LE ((guint32)*(guint64 *)(((char *)ipaddr) + field->offset));
+       
+       return inaddr;
+}
+
+static struct in6_addr
+ipaddress_to_struct_in6_addr (MonoObject *ipaddr)
+{
+       struct in6_addr in6addr;
+       MonoClassField *field;
+       MonoArray *data;
+       int i;
+
+       field = mono_class_get_field_from_name (ipaddr->vtable->klass, "m_Numbers");
+       g_assert (field);
+       data = *(MonoArray **)(((char *)ipaddr) + field->offset);
+
+       for (i = 0; i < 8; i++) {
+               const guint16 s = GUINT16_TO_BE (mono_array_get (data, guint16, i));
+
+/* Solaris/MacOS have only the 8 bit version. */
+#ifndef s6_addr16
+               in6addr.s6_addr[2 * i + 1] = (s >> 8) & 0xff;
+               in6addr.s6_addr[2 * i] = s & 0xff;
+#else
+               in6addr.s6_addr16[i] = s;
+#endif
+       }
+       return in6addr;
+}
+#endif
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+
+static int
+get_local_interface_id (int family)
+{
+#if !defined(HAVE_GETIFADDRS) || !defined(HAVE_IF_NAMETOINDEX)
+       return 0;
+#else
+       struct ifaddrs *ifap = NULL, *ptr;
+       int idx = 0;
+       
+       if (getifaddrs (&ifap))
+               return 0;
+       
+       for (ptr = ifap; ptr; ptr = ptr->ifa_next) {
+               if (!ptr->ifa_addr || !ptr->ifa_name)
+                       continue;
+               if (ptr->ifa_addr->sa_family != family)
+                       continue;
+               if ((ptr->ifa_flags & IFF_LOOPBACK) != 0)
+                       continue;
+               if ((ptr->ifa_flags & IFF_MULTICAST) == 0)
+                       continue;
+                       
+               idx = if_nametoindex (ptr->ifa_name);
+               break;
+       }
+       
+       freeifaddrs (ifap);
+       return idx;
+#endif
+}
+
+#endif /* defined(__APPLE__) || defined(__FreeBSD__) */
+
+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 *werror)
+{
+       struct linger linger;
+       int system_level = 0;
+       int system_name = 0;
+       int ret;
+       int sol_ip;
+       int sol_ipv6;
+
+       *werror = 0;
+
+       sol_ipv6 = mono_networking_get_ipv6_protocol ();
+       sol_ip = mono_networking_get_ip_protocol ();
+
+       ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level,
+                                                                                 &system_name);
+
+#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
+       if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
+               system_name = SO_REUSEADDR;
+               int_val = int_val ? 0 : 1;
+               ret = 0;
+       }
+#endif
+
+       if (ret == -1) {
+               *werror = WSAENOPROTOOPT;
+               return;
+       }
+       if (ret == -2)
+               return;
+
+       /* Only one of obj_val, byte_val or int_val has data */
+       if (obj_val) {
+               MonoClassField *field;
+               int valsize;
+               
+               switch (name) {
+               case SocketOptionName_Linger:
+                       /* Dig out "bool enabled" and "int lingerTime"
+                        * fields
+                        */
+                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "enabled");
+                       linger.l_onoff = *(guint8 *)(((char *)obj_val) + field->offset);
+                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "lingerTime");
+                       linger.l_linger = *(guint32 *)(((char *)obj_val) + field->offset);
+                       
+                       valsize = sizeof (linger);
+                       ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, valsize);
+                       break;
+               case SocketOptionName_AddMembership:
+               case SocketOptionName_DropMembership:
+#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
+               {
+                       MonoObject *address = NULL;
+
+                       if (system_level == sol_ipv6) {
+                               struct ipv6_mreq mreq6;
+
+                               /*
+                                *      Get group address
+                                */
+                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Group");
+                               g_assert (field);
+                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
+                               
+                               if (address)
+                                       mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
+
+                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "m_Interface");
+                               mreq6.ipv6mr_interface = *(guint64 *)(((char *)obj_val) + field->offset);
+                               
+#if defined(__APPLE__) || defined(__FreeBSD__)
+                               /*
+                               * Bug #5504:
+                               *
+                               * Mac OS Lion doesn't allow ipv6mr_interface = 0.
+                               *
+                               * Tests on Windows and Linux show that the multicast group is only
+                               * joined on one NIC when interface = 0, so we simply use the interface
+                               * id from the first non-loopback interface (this is also what
+                               * Dns.GetHostName (string.Empty) would return).
+                               */
+                               if (!mreq6.ipv6mr_interface)
+                                       mreq6.ipv6mr_interface = get_local_interface_id (AF_INET6);
+#endif
+                                       
+                               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}};
+#else
+                               struct ip_mreq mreq = {{0}};
+#endif /* HAVE_STRUCT_IP_MREQN */
+                       
+                               /*
+                                * pain! MulticastOption holds two IPAddress
+                                * members, so I have to dig the value out of
+                                * those :-(
+                                */
+                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
+                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
+
+                               /* address might not be defined and if so, set the address to ADDR_ANY.
+                                */
+                               if (address)
+                                       mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
+
+                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "localAddress");
+                               address = *(MonoObject **)(((char *)obj_val) + field->offset);
+
+#ifdef HAVE_STRUCT_IP_MREQN
+                               if (address)
+                                       mreq.imr_address = ipaddress_to_struct_in_addr (address);
+
+                               field = mono_class_get_field_from_name (obj_val->vtable->klass, "ifIndex");
+                               mreq.imr_ifindex = *(gint32 *)(((char *)obj_val) + field->offset);
+#else
+                               if (address)
+                                       mreq.imr_interface = ipaddress_to_struct_in_addr (address);
+#endif /* HAVE_STRUCT_IP_MREQN */
+
+                               ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq, sizeof (mreq));
+                       }
+                       break;
+               }
+#endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
+               default:
+                       /* Cause an exception to be thrown */
+                       *werror = WSAEINVAL;
+                       return;
+               }
+       } else if (byte_val!=NULL) {
+               int valsize = mono_array_length (byte_val);
+               guchar *buf = mono_array_addr (byte_val, guchar, 0);
+               
+               switch(name) {
+               case SocketOptionName_DontLinger:
+                       if (valsize == 1) {
+                               linger.l_onoff = (*buf) ? 0 : 1;
+                               linger.l_linger = 0;
+                               ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
+                       } else {
+                               *werror = WSAEINVAL;
+                       }
+                       break;
+               default:
+                       ret = mono_w32socket_setsockopt (sock, system_level, system_name, buf, valsize);
+                       break;
+               }
+       } else {
+               /* ReceiveTimeout/SendTimeout get here */
+               switch (name) {
+               case SocketOptionName_DontLinger:
+                       linger.l_onoff = !int_val;
+                       linger.l_linger = 0;
+                       ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
+                       break;
+               case SocketOptionName_MulticastInterface:
+#ifndef HOST_WIN32
+#ifdef HAVE_STRUCT_IP_MREQN
+                       int_val = GUINT32_FROM_BE (int_val);
+                       if ((int_val & 0xff000000) == 0) {
+                               /* int_val is interface index */
+                               struct ip_mreqn mreq = {{0}};
+                               mreq.imr_ifindex = int_val;
+                               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 = mono_w32socket_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
+                       break;
+               case SocketOptionName_DontFragment:
+#ifdef HAVE_IP_MTU_DISCOVER
+                       /* Fiddle with the value slightly if we're
+                        * turning DF on
+                        */
+                       if (int_val == 1)
+                               int_val = IP_PMTUDISC_DO;
+                       /* Fall through */
+#endif
+                       
+               default:
+                       ret = mono_w32socket_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
+               }
+       }
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+}
+
+void
+ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, gint32 *werror)
+{
+       int ret;
+       gboolean interrupted;
+
+       *werror = 0;
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+               return;
+       }
+
+       MONO_ENTER_GC_SAFE;
+
+       /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
+       ret = mono_w32socket_shutdown (sock, how);
+
+       MONO_EXIT_GC_SAFE;
+
+       if (ret == SOCKET_ERROR)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted) {
+               *werror = WSAEINTR;
+       }
+
+}
+
+gint
+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;
+       gint i_len, o_len;
+       gint ret;
+
+       *werror = 0;
+       
+       if ((guint32)code == FIONBIO)
+               /* Invalid command. Must use Socket.Blocking */
+               return -1;
+
+       if (input == NULL) {
+               i_buffer = NULL;
+               i_len = 0;
+       } else {
+               i_buffer = mono_array_addr (input, gchar, 0);
+               i_len = mono_array_length (input);
+       }
+
+       if (output == NULL) {
+               o_buffer = NULL;
+               o_len = 0;
+       } else {
+               o_buffer = mono_array_addr (output, gchar, 0);
+               o_len = mono_array_length (output);
+       }
+
+       MONO_ENTER_GC_SAFE;
+
+       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 = mono_w32socket_get_last_error ();
+               return -1;
+       }
+
+       return (gint)output_bytes;
+}
+
+static gboolean 
+addrinfo_to_IPHostEntry (MonoAddressInfo *info, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gboolean add_local_ips, MonoError *error)
+{
+       gint32 count, i;
+       MonoAddressEntry *ai = NULL;
+       struct in_addr *local_in = NULL;
+       int nlocal_in = 0;
+       struct in6_addr *local_in6 = NULL;
+       int nlocal_in6 = 0;
+       int addr_index;
+       MonoDomain *domain = mono_domain_get ();
+
+       mono_error_init (error);
+       addr_index = 0;
+       *h_aliases = mono_array_new_checked (domain, mono_get_string_class (), 0, error);
+       return_val_if_nok (error, FALSE);
+       if (add_local_ips) {
+               local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in);
+               local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6);
+               if (nlocal_in || nlocal_in6) {
+                       char addr [INET6_ADDRSTRLEN];
+                       *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), nlocal_in + nlocal_in6, error);
+                       if (!is_ok (error))
+                               goto leave;
+                       
+                       if (nlocal_in) {
+                               MonoString *addr_string;
+                               int i;
+
+                               for (i = 0; i < nlocal_in; i++) {
+                                       MonoAddress maddr;
+                                       mono_address_init (&maddr, AF_INET, &local_in [i]);
+                                       if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
+                                               addr_string = mono_string_new (domain, addr);
+                                               mono_array_setref (*h_addr_list, addr_index, addr_string);
+                                               addr_index++;
+                                       }
+                               }
+                       }
+
+                       if (nlocal_in6) {
+                               MonoString *addr_string;
+                               int i;
+
+                               for (i = 0; i < nlocal_in6; i++) {
+                                       MonoAddress maddr;
+                                       mono_address_init (&maddr, AF_INET6, &local_in6 [i]);
+                                       if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
+                                               addr_string = mono_string_new (domain, addr);
+                                               mono_array_setref (*h_addr_list, addr_index, addr_string);
+                                               addr_index++;
+                                       }
+                               }
+                       }
+
+               leave:
+                       g_free (local_in);
+                       g_free (local_in6);
+                       if (info)
+                               mono_free_address_info (info);
+                       return is_ok (error);;
+               }
+
+               g_free (local_in);
+               g_free (local_in6);
+       }
+
+       for (count = 0, ai = info->entries; ai != NULL; ai = ai->next) {
+               if (ai->family != AF_INET && ai->family != AF_INET6)
+                       continue;
+               count++;
+       }
+
+       *h_addr_list = mono_array_new_checked (domain, mono_get_string_class (), count, error);
+       if (!is_ok (error))
+               goto leave2;
+
+       for (ai = info->entries, i = 0; ai != NULL; ai = ai->next) {
+               MonoAddress maddr;
+               MonoString *addr_string;
+               char buffer [INET6_ADDRSTRLEN]; /* Max. size for IPv6 */
+
+               if ((ai->family != PF_INET) && (ai->family != PF_INET6))
+                       continue;
+
+               mono_address_init (&maddr, ai->family, &ai->address);
+               if (mono_networking_addr_to_str (&maddr, buffer, sizeof (buffer)))
+                       addr_string = mono_string_new (domain, buffer);
+               else
+                       addr_string = mono_string_new (domain, "");
+
+               mono_array_setref (*h_addr_list, addr_index, addr_string);
+
+               if (!i) {
+                       i++;
+                       if (ai->canonical_name != NULL) {
+                               *h_name = mono_string_new (domain, ai->canonical_name);
+                       } else {
+                               *h_name = mono_string_new (domain, buffer);
+                       }
+               }
+
+               addr_index++;
+       }
+
+leave2:
+       if (info)
+               mono_free_address_info (info);
+
+       return is_ok (error);
+}
+
+MonoBoolean
+ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
+{
+       MonoError error;
+       gboolean add_local_ips = FALSE, add_info_ok = TRUE;
+       gchar this_hostname [256];
+       MonoAddressInfo *info = NULL;
+
+       char *hostname = mono_string_to_utf8_checked (host, &error);
+       if (mono_error_set_pending_exception (&error))
+               return FALSE;
+
+       if (*hostname == '\0') {
+               add_local_ips = TRUE;
+               *h_name = host;
+       }
+
+       if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) {
+               if (!strcmp (hostname, this_hostname)) {
+                       add_local_ips = TRUE;
+                       *h_name = host;
+               }
+       }
+
+#ifdef HOST_WIN32
+       // Win32 APIs already returns local interface addresses for empty hostname ("")
+       // so we never want to add them manually.
+       add_local_ips = FALSE;
+       if (mono_get_address_info(hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info))
+               add_info_ok = FALSE;
+#else
+       if (*hostname && mono_get_address_info (hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info))
+               add_info_ok = FALSE;
+#endif
+
+       g_free(hostname);
+
+       if (add_info_ok) {
+               MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, add_local_ips, &error);
+               mono_error_set_pending_exception (&error);
+               return result;
+       }
+       return FALSE;
+}
+
+MonoBoolean
+ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gint32 hint)
+{
+       char *address;
+       struct sockaddr_in saddr;
+       struct sockaddr_in6 saddr6;
+       MonoAddressInfo *info = NULL;
+       MonoError error;
+       gint32 family;
+       gchar hostname [NI_MAXHOST] = { 0 };
+       gboolean ret;
+
+       address = mono_string_to_utf8_checked (addr, &error);
+       if (mono_error_set_pending_exception (&error))
+               return FALSE;
+
+       if (inet_pton (AF_INET, address, &saddr.sin_addr ) == 1) {
+               family = AF_INET;
+               saddr.sin_family = AF_INET;
+       } else if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) == 1) {
+               family = AF_INET6;
+               saddr6.sin6_family = AF_INET6;
+       } else {
+               g_free (address);
+               return FALSE;
+       }
+
+       g_free (address);
+
+       MONO_ENTER_GC_SAFE;
+
+       switch (family) {
+       case AF_INET: {
+#if HAVE_SOCKADDR_IN_SIN_LEN
+               saddr.sin_len = sizeof (saddr);
+#endif
+               ret = getnameinfo ((struct sockaddr*)&saddr, sizeof (saddr), hostname, sizeof (hostname), NULL, 0, 0) == 0;
+               break;
+       }
+       case AF_INET6: {
+#if HAVE_SOCKADDR_IN6_SIN_LEN
+               saddr6.sin6_len = sizeof (saddr6);
+#endif
+               ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof (saddr6), hostname, sizeof (hostname), NULL, 0, 0) == 0;
+               break;
+       }
+       default:
+               g_assert_not_reached ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+
+       if (!ret)
+               return FALSE;
+
+       if (mono_get_address_info (hostname, 0, hint | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info) != 0)
+               return FALSE;
+
+       MonoBoolean result = addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, FALSE, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
+MonoBoolean
+ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name)
+{
+       gchar hostname [NI_MAXHOST] = { 0 };
+       int ret;
+
+       ret = gethostname (hostname, sizeof (hostname));
+       if (ret == -1)
+               return FALSE;
+
+       *h_name = mono_string_new (mono_domain_get (), hostname);
+
+       return TRUE;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
+gboolean
+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;
+       gboolean interrupted;
+       TRANSMIT_FILE_BUFFERS buffers;
+
+       if (filename == NULL)
+               return FALSE;
+
+       /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
+
+       file = ves_icall_System_IO_MonoIO_Open (filename, FileMode_Open, FileAccess_Read, FileShare_Read, 0, werror);
+
+       if (file == INVALID_HANDLE_VALUE) {
+               SetLastError (*werror);
+               return FALSE;
+       }
+
+       memset (&buffers, 0, sizeof (buffers));
+       if (pre_buffer != NULL) {
+               buffers.Head = mono_array_addr (pre_buffer, guchar, 0);
+               buffers.HeadLength = mono_array_length (pre_buffer);
+       }
+       if (post_buffer != NULL) {
+               buffers.Tail = mono_array_addr (post_buffer, guchar, 0);
+               buffers.TailLength = mono_array_length (post_buffer);
+       }
+
+       mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
+       if (interrupted) {
+               CloseHandle (file);
+               SetLastError (WSAEINTR);
+               return FALSE;
+       }
+
+       MONO_ENTER_GC_SAFE;
+       ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking);
+       MONO_EXIT_GC_SAFE;
+
+       if (!ret)
+               *werror = mono_w32socket_get_last_error ();
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted) {
+               CloseHandle (file);
+               *werror = WSAEINTR;
+               return FALSE;
+       }
+
+       MONO_ENTER_GC_SAFE;
+
+       CloseHandle (file);
+
+       MONO_EXIT_GC_SAFE;
+
+       if (*werror)
+               return FALSE;
+
+       return ret;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
+
+void
+mono_network_init (void)
+{
+       mono_networking_init ();
+       mono_w32socket_initialize ();
+}
+
+void
+mono_network_cleanup (void)
+{
+       mono_w32socket_cleanup ();
+       mono_networking_shutdown ();
+}
+
+void
+icall_cancel_blocking_socket_operation (MonoThread *thread)
+{
+       MonoInternalThread *internal;
+
+       internal = thread->internal_thread;
+       g_assert (internal);
+
+       mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid));
+}
+
+#endif /* #ifndef DISABLE_SOCKETS */
diff --git a/mono/metadata/w32socket.h b/mono/metadata/w32socket.h
new file mode 100644 (file)
index 0000000..dade775
--- /dev/null
@@ -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 <config.h>
+#include <glib.h>
+
+#include <mono/metadata/object-internals.h>
+
+#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_ */
index 0e95ae85f204cbb403abaf29880c74fde4690c6c..ce2656126b6d1750e130ee034779a0be7664e87b 100644 (file)
 #include <mono/metadata/environment.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/threadpool.h>
-#include <mono/metadata/socket-io.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/runtime.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/w32socket.h>
 #include <mono/utils/mono-coop-mutex.h>
 #include <mono/utils/mono-coop-semaphore.h>
 #include <mono/utils/mono-error-internals.h>
index da2033e5e8c97e613bda1fddc8b6fea7d4c2af10..40de446bc05907dfe1468965c7c7e47e9e3d8745 100644 (file)
@@ -33,7 +33,6 @@
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/marshal.h>
-#include <mono/metadata/socket-io.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/io-layer/io-layer.h>
index f0e8db4e9a8ae60b17f5af430bd913b3e1cb8329..6c94d1ff21e1fdfebad47c3634bf9bd1819de0bb 100644 (file)
@@ -28,7 +28,7 @@
     <ClCompile Include="..\mono\metadata\cominterop.c" />\r
     <ClCompile Include="..\mono\metadata\console-win32.c" />\r
     <ClCompile Include="..\mono\metadata\property-bag.c" />\r
-    <ClCompile Include="..\mono\metadata\socket-io-windows.c" />\r
+    <ClCompile Include="..\mono\metadata\w32socket-win32.c" />\r
     <ClCompile Include="..\mono\metadata\file-io-windows.c" />\r
     <ClCompile Include="..\mono\metadata\icall-windows.c" />\r
     <ClCompile Include="..\mono\metadata\marshal-windows.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-tarjan-bridge.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-toggleref.c" />\r
     <ClCompile Include="..\mono\metadata\sgen-stw.c" />\r
-    <ClCompile Include="..\mono\metadata\socket-io.c" />\r
+    <ClCompile Include="..\mono\metadata\w32socket.c" />\r
     <ClCompile Include="..\mono\metadata\sre.c" />\r
     <ClCompile Include="..\mono\metadata\sre-encode.c" />\r
     <ClCompile Include="..\mono\metadata\sre-save.c" />\r
     <ClInclude Include="..\mono\metadata\seq-points-data.h" />\r
     <ClInclude Include="..\mono\metadata\sgen-bridge-internals.h" />\r
     <ClInclude Include="..\mono\metadata\sgen-client-mono.h" />\r
-    <ClInclude Include="..\mono\metadata\socket-io-windows-internals.h" />\r
+    <ClInclude Include="..\mono\metadata\w32socket-internals.h" />\r
     <ClInclude Include="..\mono\metadata\threadpool-io.h" />\r
     <ClInclude Include="..\mono\metadata\threadpool.h" />\r
     <ClInclude Include="..\mono\metadata\threadpool-worker.h" />\r
     <ClInclude Include="..\mono\metadata\security.h" />\r
     <ClInclude Include="..\mono\metadata\sgen-bridge.h" />\r
     <ClInclude Include="..\mono\metadata\sgen-toggleref.h" />\r
-    <ClInclude Include="..\mono\metadata\socket-io.h" />\r
+    <ClInclude Include="..\mono\metadata\w32socket.h" />\r
     <ClInclude Include="..\mono\metadata\sre-internals.h" />\r
     <ClInclude Include="..\mono\metadata\string-icalls.h" />\r
     <ClInclude Include="..\mono\metadata\sysmath.h" />\r
index 1154e5e8fc734e1417de4409a23b708909f90bc7..8de9920a9ea5b71ce137255db089e3949d93924a 100644 (file)
     <ClCompile Include="..\mono\metadata\seq-points-data.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\socket-io.c">\r
+    <ClCompile Include="..\mono\metadata\w32socket.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\string-icalls.c">\r
     <ClCompile Include="..\mono\metadata\sre-save.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\socket-io-windows.c">\r
+    <ClCompile Include="..\mono\metadata\w32socket-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\file-io-windows.c">\r
     <ClInclude Include="..\mono\metadata\seq-points-data.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\mono\metadata\socket-io.h">\r
+    <ClInclude Include="..\mono\metadata\w32socket.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\mono\metadata\string-icalls.h">\r
     <ClInclude Include="..\mono\metadata\sre-internals.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\mono\metadata\socket-io-windows-internals.h">\r
+    <ClInclude Include="..\mono\metadata\w32socket-internals.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\mono\metadata\coree-internals.h">\r
index ad0d476fd93bb58a0f64d00d9978c38a414291e0..e997a22ae4b7fcee570b6990bbe19e477a24c8d5 100644 (file)
     <ClCompile Include="..\mono\metadata\rand.c" />\r
     <ClCompile Include="..\mono\metadata\reflection.c" />\r
     <ClCompile Include="..\mono\metadata\security-manager.c" />\r
-    <ClCompile Include="..\mono\metadata\socket-io.c" />\r
+    <ClCompile Include="..\mono\metadata\w32socket.c" />\r
     <ClCompile Include="..\mono\metadata\string-icalls.c" />\r
     <ClCompile Include="..\mono\metadata\sysmath.c" />\r
     <ClCompile Include="..\mono\metadata\threads.c" />\r
index 72a54e162553c060c3b513b3724e503de4a7dff7..c7f55c9b0d13f29c955a1a0f1f879f8f99ee8e35 100644 (file)
@@ -79,7 +79,7 @@
     <ClCompile Include="..\mono\metadata\security-manager.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\socket-io.c">\r
+    <ClCompile Include="..\mono\metadata\w32socket.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\string-icalls.c">\r