[glib/wip/danw/socket2: 3/3] wip



commit c7867d4ae548d221294898e5cf2ce9bba64948f1
Author: Dan Winship <danw gnome org>
Date:   Fri Aug 19 10:23:12 2011 -0400

    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 1ca5be5..2d4ce2e 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 fbae67d..dbf42d6 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 16566aa..e4720d7 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 cb8b8c8..c4bd1e4 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));
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]