Standardized Mainsoft ConstraintCollection tests.
[mono.git] / mono / io-layer / sockets.c
index 9afc50b529041c92b16acdea72024b23e884f605..b2cf55faf211c4398f153bba7e86636c7d907b4a 100644 (file)
 #include <signal.h>
 #endif
 
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO        1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
 #include <mono/io-layer/socket-private.h>
 #undef DEBUG
 
 static guint32 startup_count=0;
-static GPtrArray *sockets=NULL;
 static pthread_key_t error_key;
 static mono_once_t error_key_once=MONO_ONCE_INIT;
 
-static void socket_close (gpointer handle);
+static void socket_close (gpointer handle, gpointer data);
 
 struct _WapiHandleOps _wapi_socket_ops = {
        socket_close,           /* close */
@@ -69,7 +56,7 @@ static void socket_ops_init (void)
        /* No capabilities to register */
 }
 
-static void socket_close (gpointer handle)
+static void socket_close (gpointer handle, gpointer data G_GNUC_UNUSED)
 {
        int ret;
 
@@ -82,8 +69,6 @@ static void socket_close (gpointer handle)
                return;
        }
 
-       g_ptr_array_remove_fast (sockets, handle);
-
        do {
                ret = close (GPOINTER_TO_UINT(handle));
        } while (ret == -1 && errno == EINTR &&
@@ -110,10 +95,6 @@ int WSAStartup(guint32 requested, WapiWSAData *data)
                return(WSAVERNOTSUPPORTED);
        }
 
-       if (startup_count == 0) {
-               sockets = g_ptr_array_new();
-       }
-       
        startup_count++;
 
        /* I've no idea what is the minor version of the spec I read */
@@ -132,10 +113,15 @@ int WSAStartup(guint32 requested, WapiWSAData *data)
        return(0);
 }
 
+static gboolean
+cleanup_close (gpointer handle, gpointer data)
+{
+       _wapi_handle_ops_close (handle, NULL);
+       return TRUE;
+}
+
 int WSACleanup(void)
 {
-       guint32 i;
-       
 #ifdef DEBUG
        g_message ("%s: cleaning up", __func__);
 #endif
@@ -144,18 +130,8 @@ int WSACleanup(void)
                /* Do nothing */
                return(0);
        }
-       
-       /* Close down all sockets */
-       for (i = 0; i < sockets->len; i++) {
-               gpointer handle;
-
-               handle = g_ptr_array_index (sockets, i);
-               _wapi_handle_ops_close (handle);
-       }
 
-       g_ptr_array_free (sockets, FALSE);
-       sockets = NULL;
-       
+       _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
        return(0);
 }
 
@@ -253,8 +229,6 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
                return(INVALID_SOCKET);
        }
 
-       g_ptr_array_add (sockets, new_handle);
-       
 #ifdef DEBUG
        g_message ("%s: returning newly accepted socket handle %p with",
                   __func__, new_handle);
@@ -339,6 +313,9 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
                           strerror (errnum));
 #endif
                errnum = errno_to_WSA (errnum, __func__);
+               if (errnum == WSAEINPROGRESS)
+                       errnum = WSAEWOULDBLOCK; /* see bug #73053 */
+
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -415,7 +392,9 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
 {
        gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
-       
+       struct timeval tv;
+       void *tmp_val;
+
        if (startup_count == 0) {
                WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
@@ -425,8 +404,14 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
                WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
-       
-       ret = getsockopt (fd, level, optname, optval, optlen);
+
+       tmp_val = optval;
+       if (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;
 #ifdef DEBUG
@@ -439,6 +424,11 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
                
                return(SOCKET_ERROR);
        }
+
+       if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+               *((int *) optval)  = tv.tv_sec * 1000 + tv.tv_usec;
+               *optlen = sizeof (int);
+       }
        
        return(ret);
 }
@@ -624,6 +614,8 @@ int _wapi_setsockopt(guint32 fd, int level, int optname,
 {
        gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
+       const void *tmp_val;
+       struct timeval tv;
        
        if (startup_count == 0) {
                WSASetLastError (WSANOTINITIALISED);
@@ -634,8 +626,17 @@ int _wapi_setsockopt(guint32 fd, int level, int optname,
                WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
-       
-       ret = setsockopt (fd, level, optname, optval, optlen);
+
+       tmp_val = optval;
+       if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+               int ms = *((int *) optval);
+               tv.tv_sec = ms / 1000;
+               tv.tv_usec = ms % 1000;
+               tmp_val = &tv;
+               optlen = sizeof (tv);
+       }
+               
+       ret = setsockopt (fd, level, optname, tmp_val, optlen);
        if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
@@ -728,8 +729,6 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
                return(INVALID_SOCKET);
        }
 
-       g_ptr_array_add (sockets, handle);
-
 #ifdef DEBUG
        g_message ("%s: returning socket handle %p", __func__, handle);
 #endif
@@ -865,9 +864,9 @@ int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
                ret = fcntl (fd, F_GETFL, 0);
                if (ret != -1) {
                        if (*(gboolean *)arg) {
-                               ret &= ~O_NONBLOCK;
-                       } else {
                                ret |= O_NONBLOCK;
+                       } else {
+                               ret &= ~O_NONBLOCK;
                        }
                        ret = fcntl (fd, F_SETFL, ret);
                }
@@ -957,109 +956,3 @@ void _wapi_FD_SET(guint32 fd, fd_set *set)
        FD_SET (fd, set);
 }
 
-#ifdef USE_AIO
-
-typedef struct {
-       struct aiocb *aio;
-       gpointer ares;
-       SocketAsyncCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
-       notifier_data_t *ndata = SIGPTR (sig);
-       guint32 error;
-       guint32 numbytes;
-
-       error = aio_return (ndata->aio);
-       if (error < 0) {
-               error = _wapi_get_win32_file_error (error);
-               numbytes = 0;
-       } else {
-               numbytes = error;
-               error = 0;
-       }
-
-       ndata->callback (error, numbytes, ndata->ares);
-       g_free (ndata->aio);
-       g_free (ndata);
-}
-
-static gboolean
-do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
-               guint32 numbytes, guint32 *out_bytes,
-               gpointer ares,
-               SocketAsyncCB callback)
-{
-       int fd = GPOINTER_TO_UINT (handle);
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-       
-       if (handle == NULL ||
-           _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
-               WSASetLastError (WSAENOTSOCK);
-               return FALSE;
-       }
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->ares = ares;
-       ndata->aio = aio;
-       ndata->callback = callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = 0;
-       aio->aio_buf = buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       if (is_read) {
-               result = aio_read (aio);
-       } else {
-               result = aio_write (aio);
-       }
-
-       if (result == -1) {
-               WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
-               return FALSE;
-       }
-
-       result = aio_error (aio);
-       if (result == 0) {
-               numbytes = aio_return (aio);
-       } else {
-               WSASetLastError (errno_to_WSA (result, "do_aio_call"));
-               return FALSE;
-       }
-
-       if (out_bytes)
-               *out_bytes = numbytes;
-
-       return TRUE;
-}
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *bytesread, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
-}
-
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *byteswritten, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
-}
-
-#endif /* USE_AIO */
-