From c7867d4ae548d221294898e5cf2ce9bba64948f1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 19 Aug 2011 10:23:12 -0400 Subject: wip --- gio/gioenums.h | 1 + gio/gioerror.c | 11 +++++++++++ gio/gsocket.c | 31 ++++++++++++++----------------- gio/tests/socket.c | 38 ++++++++++++++++++++++++++++++++------ 4 files changed, 58 insertions(+), 23 deletions(-) diff --git a/gio/gioenums.h b/gio/gioenums.h index 1ca5be558..2d4ce2e3e 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -470,6 +470,7 @@ typedef enum { * @G_IO_ERROR_PROXY_NOT_ALLOWED: Proxy connection is not allowed by ruleset. * Since 2.26 * @G_IO_ERROR_BROKEN_PIPE: Broken pipe. Since 2.36 + * @G_IO_ERROR_CONNECTION_CLOSED: Connection closed by peer. Since 2.36 * * Error codes returned by GIO functions. * diff --git a/gio/gioerror.c b/gio/gioerror.c index fbae67d45..dbf42d6a9 100644 --- a/gio/gioerror.c +++ b/gio/gioerror.c @@ -242,6 +242,12 @@ g_io_error_from_errno (gint err_no) break; #endif +#ifdef ECONNRESET + case ECONNRESET: + return G_IO_ERROR_CONNECTION_CLOSED; + break; +#endif + default: return G_IO_ERROR_FAILED; break; @@ -305,6 +311,11 @@ g_io_error_from_win32_error (gint error_code) case WSAEAFNOSUPPORT: return G_IO_ERROR_NOT_SUPPORTED; + case WSAECONNRESET: + case WSAECONNABORTED: + case WSAECONNSHUTDOWN: + return G_IO_ERROR_CONNECTION_CLOSED; + default: return G_IO_ERROR_FAILED; } diff --git a/gio/gsocket.c b/gio/gsocket.c index 16566aa17..e4720d754 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -209,7 +209,10 @@ socket_io_error_from_errno (int err) #ifdef G_OS_WIN32 return g_io_error_from_win32_error (err); #else - return g_io_error_from_errno (err); + if (err == EPIPE) + return G_IO_ERROR_CONNECTION_CLOSED; + else + return g_io_error_from_errno (err); #endif } @@ -2645,24 +2648,20 @@ g_socket_receive_with_blocking (GSocket *socket, if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0) { int errsv = get_socket_errno (); + GIOErrorEnum gioerr; if (errsv == EINTR) continue; - if (blocking) - { -#ifdef WSAEWOULDBLOCK - if (errsv == WSAEWOULDBLOCK) - continue; -#else - if (errsv == EWOULDBLOCK || - errsv == EAGAIN) - continue; -#endif - } + gioerr = socket_io_error_from_errno (errsv); + if (blocking && gioerr == G_IO_ERROR_WOULD_BLOCK) + continue; win32_unset_event_mask (socket, FD_READ); + if (gioerr == G_IO_ERROR_CONNECTION_CLOSED) + g_socket_set_connected (socket, FALSE); + g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv), _("Error receiving data: %s"), socket_strerror (errsv)); @@ -2674,11 +2673,9 @@ g_socket_receive_with_blocking (GSocket *socket, break; } - if (ret == 0 && size != 0 && socket->priv->connected) - { - socket->priv->connected = FALSE; - g_object_notify (G_OBJECT (socket), "connected"); - } + if (ret == 0 && size != 0) + g_socket_set_connected (socket, FALSE); + return ret; } diff --git a/gio/tests/socket.c b/gio/tests/socket.c index cb8b8c846..c4bd1e440 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -355,9 +355,20 @@ test_ip_async (GSocketFamily family) g_thread_join (data->thread); g_assert_cmpint (data->client_connected_changed, ==, 1); - len = g_socket_receive (client, buf, sizeof (buf), NULL, &error); - g_assert_no_error (error); - g_assert_cmpint (len, ==, 0); + if (family == G_SOCKET_FAMILY_IPV4) + { + len = g_socket_receive_with_blocking (client, buf, sizeof (buf), + TRUE, NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (len, ==, 0); + } + else + { + len = g_socket_send_with_blocking (client, testbuf, strlen (testbuf) + 1, + TRUE, NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_assert_cmpint (len, ==, -1); + } g_assert_cmpint (data->client_connected_changed, ==, 2); g_assert (!g_socket_is_connected (client)); @@ -462,9 +473,24 @@ test_ip_sync (GSocketFamily family) g_thread_join (data->thread); g_assert_cmpint (data->client_connected_changed, ==, 1); - len = g_socket_receive (client, buf, sizeof (buf), NULL, &error); - g_assert_no_error (error); - g_assert_cmpint (len, ==, 0); + if (family == G_SOCKET_FAMILY_IPV4) + { + /* Test that reading on a remote-closed socket gets back + * 0 bytes and emits notify::connected. + */ + len = g_socket_receive (client, buf, sizeof (buf), NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (len, ==, 0); + } + else + { + /* Test that writing to a remote-closed socket gets back + * EPIPE and emits notify::connected. + */ + len = g_socket_send (client, testbuf, strlen (testbuf) + 1, NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_assert_cmpint (len, ==, -1); + } g_assert_cmpint (data->client_connected_changed, ==, 2); g_assert (!g_socket_is_connected (client)); -- cgit v1.2.1