summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2011-08-19 10:23:12 -0400
committerDan Winship <danw@gnome.org>2014-10-01 10:03:50 -0400
commitc7867d4ae548d221294898e5cf2ce9bba64948f1 (patch)
treeb4d044b21130ce97519ae69e270900b9685b0543
parentdd7135b2dce38c97eafbedf35c6656ee9aeadadf (diff)
downloadglib-wip/danw/socket-connected.tar.gz
-rw-r--r--gio/gioenums.h1
-rw-r--r--gio/gioerror.c11
-rw-r--r--gio/gsocket.c31
-rw-r--r--gio/tests/socket.c38
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));