#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 */
/* No capabilities to register */
}
-static void socket_close (gpointer handle)
+static void socket_close (gpointer handle, gpointer data G_GNUC_UNUSED)
{
int ret;
return;
}
- g_ptr_array_remove_fast (sockets, handle);
-
do {
ret = close (GPOINTER_TO_UINT(handle));
} while (ret == -1 && errno == EINTR &&
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 */
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
/* 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);
}
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);
strerror (errnum));
#endif
errnum = errno_to_WSA (errnum, __func__);
+ if (errnum == WSAEINPROGRESS)
+ errnum = WSAEWOULDBLOCK; /* see bug #73053 */
+
WSASetLastError (errnum);
return(SOCKET_ERROR);
{
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
-
+ struct timeval tv;
+ void *tmp_val;
+
if (startup_count == 0) {
WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
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
return(SOCKET_ERROR);
}
+
+ if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+ *((int *) optval) = tv.tv_sec * 1000 + tv.tv_usec;
+ *optlen = sizeof (int);
+ }
return(ret);
}
{
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
+ const void *tmp_val;
+ struct timeval tv;
if (startup_count == 0) {
WSASetLastError (WSANOTINITIALISED);
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
return(INVALID_SOCKET);
}
- g_ptr_array_add (sockets, handle);
-
#ifdef DEBUG
g_message ("%s: returning socket handle %p", __func__, handle);
#endif
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);
}
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 */
-