[gnio] Convert GSocket to GInitable and update users



commit 12f26bcb477a20804d28a52f1461699325f7d5cf
Author: Alexander Larsson <alexl redhat com>
Date:   Wed May 6 23:14:47 2009 +0200

    Convert GSocket to GInitable and update users
    
    This removes g_socket_has_error and instead introduces a GError in
    the GSocket C constuctor helpers that are now switched to use
    g_initable_new.
    
    Also, all users are changed to comply with the API changes.
---
 gio/gsocket.c       |  115 ++++++++++++++++++++++++++++++++++++++------------
 gio/gsocket.h       |    8 ++--
 gio/gsocketclient.c |   74 +++++++++++++++++---------------
 gio/gsocketclient.h |    3 +-
 gio/gtcpclient.c    |    5 +-
 gio/gtcplistener.c  |   10 ++--
 gio/gunixclient.c   |    5 +-
 gio/gunixlistener.c |    5 ++-
 test/server.c       |    4 +-
 9 files changed, 149 insertions(+), 80 deletions(-)

diff --git a/gio/gsocket.c b/gio/gsocket.c
index d570210..3be1072 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -42,15 +42,21 @@
 
 #include <gio/gcancellable.h>
 #include <gio/gioenumtypes.h>
+#include <gio/ginitable.h>
 #include "gsocketcontrol-private.h"
 #include "gasynchelper.h"
 #include "gnioerror.h"
 #include "gnioenums.h"
 #include <gio/gioerror.h>
 
+static void     g_socket_initable_iface_init (GInitableIface  *iface);
+static gboolean g_socket_initable_init       (GInitable       *initable,
+					      GCancellable    *cancellable,
+					      GError         **error);
 
-
-G_DEFINE_TYPE (GSocket, g_socket, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE (GSocket, g_socket, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+						g_socket_initable_iface_init));
 
 enum
 {
@@ -77,6 +83,7 @@ struct _GSocketPrivate
   GError         *construct_error;
   GSocketAddress *local_address;
   GSocketAddress *remote_address;
+  guint           inited : 1;
   guint           blocking : 1;
   guint           reuse_address : 1;
   guint           keepalive : 1;
@@ -172,17 +179,25 @@ static gboolean
 check_socket (GSocket *socket,
 	      GError **error)
 {
+  if (!socket->priv->inited)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+		   _("Invalid socket, not initialized"));
+      return FALSE;
+    }
+
   if (socket->priv->construct_error)
     {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
-		   _("Invalid socket, creation failed due to: %s"),
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+		   _("Invalid socket, initialization failed due to: %s"),
 		   socket->priv->construct_error->message);
       return FALSE;
     }
+
   if (socket->priv->closed)
     {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
-                           _("Socket is already closed"));
+			   _("Socket is already closed"));
       return FALSE;
     }
   return TRUE;
@@ -673,6 +688,12 @@ g_socket_class_init (GSocketClass *klass)
 }
 
 static void
+g_socket_initable_iface_init (GInitableIface *iface)
+{
+  iface->init = g_socket_initable_init;
+}
+
+static void
 g_socket_init (GSocket *socket)
 {
   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket, G_TYPE_SOCKET, GSocketPrivate);
@@ -689,18 +710,60 @@ g_socket_init (GSocket *socket)
 #endif
 }
 
+static gboolean
+g_socket_initable_init (GInitable *initable,
+			GCancellable *cancellable,
+			GError  **error)
+{
+  GSocket  *socket;
+
+  g_return_val_if_fail (G_IS_SOCKET (initable), FALSE);
+
+  socket = G_SOCKET (initable);
+
+  if (cancellable != NULL)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+		   _("Cancellable initialization not supported"));
+      return FALSE;
+    }
+
+  socket->priv->inited = TRUE;
+
+  if (socket->priv->construct_error)
+    {
+      if (error)
+	*error = g_error_copy (socket->priv->construct_error);
+      return FALSE;
+    }
+
+
+  return TRUE;
+}
+
+
 GSocket *
 g_socket_new (GSocketFamily family,
 	      GSocketType type,
-	      const char *protocol)
+	      const char *protocol,
+	      GError **error)
 {
-  return G_SOCKET (g_object_new (G_TYPE_SOCKET, "family", family, "type", type, "protocol", protocol, NULL));
+  return G_SOCKET (g_initable_new (G_TYPE_SOCKET,
+				   NULL, error,
+				   "family", family,
+				   "type", type,
+				   "protocol", protocol,
+				   NULL));
 }
 
 GSocket *
-g_socket_new_from_fd (gint fd)
+g_socket_new_from_fd (gint fd,
+		      GError **error)
 {
-  return G_SOCKET (g_object_new (G_TYPE_SOCKET, "fd", fd, NULL));
+  return G_SOCKET (g_initable_new (G_TYPE_SOCKET,
+				   NULL, error,
+				   "fd", fd,
+				   NULL));
 }
 
 void
@@ -899,21 +962,6 @@ g_socket_get_remote_address (GSocket  *socket,
 }
 
 gboolean
-g_socket_has_error (GSocket  *socket,
-                    GError  **error)
-{
-  g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
-
-  if (!socket->priv->construct_error)
-    return FALSE;
-
-  if (error)
-    *error = g_error_copy (socket->priv->construct_error);
-
-  return TRUE;
-}
-
-gboolean
 g_socket_is_connected (GSocket *socket)
 {
   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
@@ -1039,13 +1087,24 @@ g_socket_accept (GSocket       *socket,
   }
 #endif
 
-  new_socket = g_socket_new_from_fd (ret);
+  new_socket = g_socket_new_from_fd (ret, error);
 
+  if (new_socket)
+    {
+#ifdef G_OS_WIN32
+      /* We set blocking above, and new_from_fd can't read this on win32 */
+      new_socket->priv->blocking = TRUE;
+      new_socket->priv->blocking_mode_unknown = FALSE;
+#endif
+    }
+  else
+    {
 #ifdef G_OS_WIN32
-  /* We set blocking above, and new_from_fd can't read this on win32 */
-  new_socket->priv->blocking = TRUE;
-  new_socket->priv->blocking_mode_unknown = FALSE;
+      closesocket (ret);
+#else
+      close (ret);
 #endif
+    }
 
   return new_socket;
 }
diff --git a/gio/gsocket.h b/gio/gsocket.h
index dd65b29..c604b37 100644
--- a/gio/gsocket.h
+++ b/gio/gsocket.h
@@ -91,8 +91,10 @@ typedef gboolean (*GSocketSourceFunc) (gpointer     user_data,
 GType                  g_socket_get_type                (void);
 GSocket *              g_socket_new                     (GSocketFamily            family,
 							 GSocketType              type,
-							 const char              *protocol);
-GSocket *              g_socket_new_from_fd             (gint                     fd);
+							 const char              *protocol,
+							 GError                 **error);
+GSocket *              g_socket_new_from_fd             (gint                     fd,
+							 GError                 **error);
 int                    g_socket_get_fd                  (GSocket                 *socket);
 GSocketAddress *       g_socket_get_local_address       (GSocket                 *socket,
 							 GError                 **error);
@@ -110,8 +112,6 @@ gboolean               g_socket_get_keepalive           (GSocket
 gint                   g_socket_get_listen_backlog      (GSocket                 *socket);
 void                   g_socket_set_listen_backlog      (GSocket                 *socket,
 							 gint                     backlog);
-gboolean               g_socket_has_error               (GSocket                 *socket,
-							 GError                 **error);
 gboolean               g_socket_is_connected            (GSocket                 *socket);
 gboolean               g_socket_bind                    (GSocket                 *socket,
 							 GSocketAddress          *address,
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index 559c8b3..2e9245c 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -33,10 +33,11 @@ G_DEFINE_TYPE (GSocketClient, g_socket_client, G_TYPE_OBJECT);
 
 static GSocket *
 g_socket_client_real_socket_factory (GSocketClient  *client,
-                                     GSocketAddress *address)
+                                     GSocketAddress *address,
+				     GError        **error)
 {
   return g_socket_new (g_socket_address_get_family (address),
-                       G_SOCKET_TYPE_STREAM, NULL);
+                       G_SOCKET_TYPE_STREAM, NULL, error);
 }
 
 static void
@@ -62,6 +63,9 @@ g_socket_client_connect (GSocketClient       *client,
 
   class = G_SOCKET_CLIENT_GET_CLASS (client);
 
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
+
   enumerator = g_socket_connectable_enumerate (connectable);
   while (!connection && !g_cancellable_is_cancelled (cancellable))
     {
@@ -74,7 +78,6 @@ g_socket_client_connect (GSocketClient       *client,
       if (address == NULL)
         {
           g_assert (error == NULL || *error != NULL);
-
 	  break;
         }
 
@@ -82,14 +85,14 @@ g_socket_client_connect (GSocketClient       *client,
       if (error && *error)
         g_clear_error (error);
 
-      socket = class->socket_factory (client, address);
-
-      if (g_cancellable_is_cancelled (cancellable))
-        break;
-
-      if (g_socket_connect (socket, address, error))
-        connection = class->connection_factory (client, socket);
+      socket = class->socket_factory (client, address, error);
+      if (socket != NULL)
+	{
+	  if (g_socket_connect (socket, address, error))
+	    connection = class->connection_factory (client, socket);
+	}
 
+      g_object_unref (address);
       g_object_unref (socket);
     }
   g_object_unref (enumerator);
@@ -146,19 +149,17 @@ static gboolean
 g_socket_client_socket_callback (GSocketClientAsyncConnectData *data,
                                  GIOCondition                   condition)
 {
-  if (condition & G_IO_OUT)
-    /* socket is ready for writing = success. */
-    ;
-
-  else if (condition)
+  if (g_cancellable_set_error_if_cancelled (data->cancellable,
+					    &data->last_error))
     {
-      if (!g_socket_has_error (data->current_socket, &data->last_error))
-        {
-          g_warning ("Failed to connect async, but socket didn't set error");
-          g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Async connection failed and socket didn't set error");
-        }
-
+    }
+  else if (condition & G_IO_OUT)
+    {
+      /* socket is ready for writing = success. */
+    }
+  else
+    {
+      /* socket error */
       g_object_unref (data->current_socket);
       data->current_socket = NULL;
 
@@ -169,20 +170,12 @@ g_socket_client_socket_callback (GSocketClientAsyncConnectData *data,
       return FALSE;
     }
 
-  else /* cancelled */
-    {
-      gboolean cancelled;
-
-      cancelled = g_cancellable_set_error_if_cancelled (data->cancellable,
-                                                        &data->last_error);
-      g_assert (cancelled);
-    }
-
   g_socket_client_async_connect_complete (data);
 
   return FALSE;
 }
 
+
 static void
 g_socket_client_enumerator_callback (GObject      *object,
 				     GAsyncResult *result,
@@ -196,10 +189,9 @@ g_socket_client_enumerator_callback (GObject      *object,
 
     address = g_socket_address_enumerator_next_finish (data->enumerator,
 						       result, &tmp_error);
-
-    if ((address || tmp_error) && data->last_error)
+    if (address || tmp_error)
       g_clear_error (&data->last_error);
-    
+
     if (tmp_error)
       data->last_error = tmp_error;
   }
@@ -212,7 +204,19 @@ g_socket_client_enumerator_callback (GObject      *object,
       GSocket *socket;
 
       class = G_SOCKET_CLIENT_GET_CLASS (data->client);
-      socket = class->socket_factory (data->client, address);
+      socket = class->socket_factory (data->client, address, &tmp_error);
+
+      if (socket == NULL)
+	{
+	  g_clear_error (&data->last_error);
+	  data->last_error = tmp_error;
+	  g_socket_address_enumerator_next_async (data->enumerator,
+						  data->cancellable,
+						  g_socket_client_enumerator_callback,
+						  data);
+	  g_object_unref (address);
+	  return;
+	}
 
       g_socket_set_blocking (socket, FALSE);
       pending = (g_socket_connect (socket, address, &tmp_error) == FALSE) &&
diff --git a/gio/gsocketclient.h b/gio/gsocketclient.h
index af39bd5..014633a 100644
--- a/gio/gsocketclient.h
+++ b/gio/gsocketclient.h
@@ -46,7 +46,8 @@ struct _GSocketClientClass
   GSocketConnection * (* connection_factory)  (GSocketClient  *client,
                                                GSocket        *socket);
   GSocket           * (* socket_factory)      (GSocketClient  *client,
-                                               GSocketAddress *address);
+                                               GSocketAddress *address,
+					       GError        **error);
   gpointer padding[5];
 };
 
diff --git a/gio/gtcpclient.c b/gio/gtcpclient.c
index 5edd09d..19df7ab 100644
--- a/gio/gtcpclient.c
+++ b/gio/gtcpclient.c
@@ -630,10 +630,11 @@ g_tcp_client_connection_factory (GSocketClient *client,
 
 static GSocket *
 g_tcp_client_socket_factory (GSocketClient  *client,
-                             GSocketAddress *address)
+                             GSocketAddress *address,
+			     GError **error)
 {
   return G_SOCKET_CLIENT_CLASS (g_tcp_client_parent_class)
-    ->socket_factory (client, address);
+    ->socket_factory (client, address, error);
 }
 
 static void
diff --git a/gio/gtcplistener.c b/gio/gtcplistener.c
index b53c596..02a2c1a 100644
--- a/gio/gtcplistener.c
+++ b/gio/gtcplistener.c
@@ -55,7 +55,7 @@ g_tcp_listener_socket_factory (GSocketListener  *listener,
       GSocketFamily family;
 
       family = g_inet_address_get_family (tcp_listener->priv->address);
-      socket = g_socket_new (family, G_SOCKET_TYPE_STREAM, NULL);
+      socket = g_socket_new (family, G_SOCKET_TYPE_STREAM, NULL, error);
       address = g_object_ref (tcp_listener->priv->address);
 
       if (family == G_SOCKET_FAMILY_IPV6)
@@ -67,9 +67,9 @@ g_tcp_listener_socket_factory (GSocketListener  *listener,
       /* try to get a hybrid ipv6/ipv4 socket first */
       socket = g_socket_new (G_SOCKET_FAMILY_IPV6,
                              G_SOCKET_TYPE_STREAM,
-			     NULL);
+			     NULL, NULL);
 
-      if (!g_socket_has_error (socket, NULL))
+      if (socket != NULL)
         /* we can do ipv6, so bind to :: */
         address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
 
@@ -78,12 +78,12 @@ g_tcp_listener_socket_factory (GSocketListener  *listener,
         {
           socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
                                  G_SOCKET_TYPE_STREAM,
-				 NULL);
+				 NULL, error);
           address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
         }
     }
 
-  if (g_socket_has_error (socket, error))
+  if (socket == NULL)
     return NULL;
 
   g_socket_set_reuse_address (socket, TRUE);
diff --git a/gio/gunixclient.c b/gio/gunixclient.c
index d1d3a39..f2229b9 100644
--- a/gio/gunixclient.c
+++ b/gio/gunixclient.c
@@ -159,10 +159,11 @@ g_unix_client_connection_factory (GSocketClient *client,
 
 static GSocket *
 g_unix_client_socket_factory (GSocketClient  *client,
-                             GSocketAddress *address)
+			      GSocketAddress *address,
+			      GError **error)
 {
   return G_SOCKET_CLIENT_CLASS (g_unix_client_parent_class)
-    ->socket_factory (client, address);
+    ->socket_factory (client, address, error);
 }
 
 static void
diff --git a/gio/gunixlistener.c b/gio/gunixlistener.c
index 0fc89e5..4cba4ca 100644
--- a/gio/gunixlistener.c
+++ b/gio/gunixlistener.c
@@ -47,7 +47,10 @@ g_unix_listener_socket_factory (GSocketListener  *listener,
 
   socket = g_socket_new (G_SOCKET_FAMILY_UNIX,
                          G_SOCKET_TYPE_STREAM,
-			 NULL);
+			 NULL, error);
+  if (socket == NULL)
+    return NULL;
+
   sockaddr = g_unix_socket_address_new (unix_listener->priv->path);
 
   /* XXX fix */
diff --git a/test/server.c b/test/server.c
index 904bb30..11a93ed 100644
--- a/test/server.c
+++ b/test/server.c
@@ -143,9 +143,9 @@ main (int argc,
   else
     socket_type = G_SOCKET_TYPE_STREAM;
 
-  socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, NULL);
+  socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, NULL, &error);
 
-  if (g_socket_has_error (socket, &error))
+  if (socket == NULL)
     {
       g_printerr ("%s: %s\n", argv[0], error->message);
       return 1;



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