[glib] Add g_socket_connection_connect(), etc



commit 57f279988cc2219a974042a29cbb12efd2422540
Author: Dan Winship <danw gnome org>
Date:   Sun Jun 12 16:29:04 2011 -0400

    Add g_socket_connection_connect(), etc
    
    Previously it was more or less assumed that GSocketConnections were
    always connected, although this was not enforced. Make it explicit
    that they don't need to be, and add methods to connect them, and
    simplify GSocketClient by using those methods.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=665805

 docs/reference/gio/gio-sections.txt |    5 +
 gio/gio.symbols                     |    4 +
 gio/gsocketclient.c                 |  129 +++++++++-------------------
 gio/gsocketconnection.c             |  159 +++++++++++++++++++++++++++++++++++
 gio/gsocketconnection.h             |   15 ++++
 5 files changed, 223 insertions(+), 89 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 1cea4f3..31d3bb2 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1885,6 +1885,11 @@ g_socket_client_get_type
 <FILE>gsocketconnection</FILE>
 <TITLE>GSocketConnection</TITLE>
 GSocketConnection
+g_socket_connection_connect
+g_socket_connection_connect_async
+g_socket_connection_connect_finish
+<SUBSECTION>
+g_socket_connection_is_connected
 g_socket_connection_get_local_address
 g_socket_connection_get_remote_address
 g_socket_connection_get_socket
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 3ea45b7..a23f8ad 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1022,6 +1022,10 @@ g_socket_connection_factory_register_type
 g_socket_connection_get_local_address
 g_socket_connection_get_remote_address
 g_socket_connection_get_socket
+g_socket_connection_is_connected
+g_socket_connection_connect
+g_socket_connection_connect_async
+g_socket_connection_connect_finish
 g_socket_listener_get_type
 g_socket_listener_accept
 g_socket_listener_accept_async
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index da534e7..88f2b36 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -845,10 +845,14 @@ g_socket_client_connect (GSocketClient       *client,
 	  continue;
 	}
 
-      if (g_socket_connect (socket, address, cancellable, &last_error))
-	connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
-      else
-	clarify_connect_error (last_error, connectable, address);
+      connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
+      if (!g_socket_connection_connect (G_SOCKET_CONNECTION (connection),
+					address, cancellable, &last_error))
+	{
+	  clarify_connect_error (last_error, connectable, address);
+	  g_object_unref (connection);
+	  connection = NULL;
+	}
 
       if (connection &&
 	  G_IS_PROXY_ADDRESS (address) &&
@@ -1264,11 +1268,30 @@ g_socket_client_proxy_connect_callback (GObject      *object,
 }
 
 static void
-g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
+g_socket_client_connected_callback (GObject      *source,
+				    GAsyncResult *result,
+				    gpointer      user_data)
 {
+  GSocketClientAsyncConnectData *data = user_data;
+  GError *error = NULL;
   GProxy *proxy;
   const gchar *protocol;
 
+  if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source),
+					   result, &error))
+    {
+      clarify_connect_error (error, data->connectable,
+			     data->current_addr);
+      set_last_error (data, error);
+
+      /* try next one */
+      enumerator_next_async (data);
+      return;
+    }
+
+  /* wrong, but backward compatible */
+  g_socket_set_blocking (data->current_socket, TRUE);
+
   if (!data->proxy_addr)
     {
       g_socket_client_tls_handshake (data);
@@ -1278,7 +1301,7 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
   protocol  = g_proxy_address_get_protocol (data->proxy_addr);
   proxy = g_proxy_get_default_for_protocol (protocol);
 
-  /* The connection should not be anything else then TCP Connection,
+  /* The connection should not be anything other than TCP,
    * but let's put a safety guard in case
    */
   if (!G_IS_TCP_CONNECTION (data->connection))
@@ -1322,54 +1345,6 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
 }
 
 static void
-g_socket_client_socket_connected (GSocketClientAsyncConnectData *data)
-{
-  g_socket_set_blocking (data->current_socket, TRUE);
-
-  data->connection = (GIOStream *)
-    g_socket_connection_factory_create_connection (data->current_socket);
-
-  g_socket_client_proxy_connect (data);
-}
-
-static gboolean
-g_socket_client_socket_callback (GSocket *socket,
-				 GIOCondition condition,
-				 GSocketClientAsyncConnectData *data)
-{
-  GError *error = NULL;
-
-  if (g_cancellable_is_cancelled (data->cancellable))
-    {
-      /* Cancelled, return done with last error being cancelled */
-      g_clear_error (&data->last_error);
-      g_cancellable_set_error_if_cancelled (data->cancellable,
-					    &data->last_error);
-
-      g_socket_client_async_connect_complete (data);
-      return FALSE;
-    }
-  else
-    {
-      /* socket is ready for writing means connect done, did it succeed? */
-      if (!g_socket_check_connect_result (data->current_socket, &error))
-	{
-	  clarify_connect_error (error, data->connectable,
-				 data->current_addr);
-	  set_last_error (data, error);
-
-	  /* try next one */
-	  enumerator_next_async (data);
-
-	  return FALSE;
-	}
-    }
-
-  g_socket_client_socket_connected (data);
-  return FALSE;
-}
-
-static void
 g_socket_client_enumerator_callback (GObject      *object,
 				     GAsyncResult *result,
 				     gpointer      user_data)
@@ -1409,44 +1384,20 @@ g_socket_client_enumerator_callback (GObject      *object,
   g_clear_error (&data->last_error);
 
   socket = create_socket (data->client, address, &data->last_error);
-  if (socket != NULL)
+  if (socket == NULL)
     {
-      g_socket_set_blocking (socket, FALSE);
-      if (g_socket_connect (socket, address, data->cancellable, &tmp_error))
-	{
-	  data->current_socket = socket;
-	  g_socket_client_socket_connected (data);
-
-	  g_object_unref (address);
-	  return;
-	}
-      else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
-	{
-	  GSource *source;
-
-	  data->current_socket = socket;
-	  data->current_addr = address;
-	  g_error_free (tmp_error);
-
-	  source = g_socket_create_source (socket, G_IO_OUT,
-					   data->cancellable);
-	  g_source_set_callback (source,
-				 (GSourceFunc) g_socket_client_socket_callback,
-				 data, NULL);
-	  g_source_attach (source, g_main_context_get_thread_default ());
-	  g_source_unref (source);
-	  return;
-	}
-      else
-	{
-	  clarify_connect_error (tmp_error, data->connectable, address);
-	  data->last_error = tmp_error;
-	  g_object_unref (socket);
-	}
+      g_object_unref (address);
+      enumerator_next_async (data);
+      return;
     }
 
-  g_object_unref (address);
-  enumerator_next_async (data);
+  data->current_socket = socket;
+  data->current_addr = address;
+  data->connection = (GIOStream *) g_socket_connection_factory_create_connection (socket);
+
+  g_socket_connection_connect_async (G_SOCKET_CONNECTION (data->connection),
+				     address, data->cancellable,
+				     g_socket_client_connected_callback, data);
 }
 
 /**
diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c
index 6f2f102..ee391ab 100644
--- a/gio/gsocketconnection.c
+++ b/gio/gsocketconnection.c
@@ -114,6 +114,165 @@ g_socket_connection_get_output_stream (GIOStream *io_stream)
 }
 
 /**
+ * g_socket_connection_is_connected:
+ * @connection: a #GSocketConnection
+ *
+ * Checks if @connection is connected. This is equivalent to calling
+ * g_socket_is_connected() on @connection's underlying #GSocket.
+ *
+ * Returns: whether @connection is connected
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_is_connected (GSocketConnection  *connection)
+{
+  return g_socket_is_connected (connection->priv->socket);
+}
+
+/**
+ * g_socket_connection_connect:
+ * @connection: a #GSocketConnection
+ * @address: a #GSocketAddress specifying the remote address.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Connect @connection to the specified remote address.
+ *
+ * Returns: %TRUE if the connection succeeded, %FALSE on error
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_connect (GSocketConnection  *connection,
+			     GSocketAddress     *address,
+			     GCancellable       *cancellable,
+			     GError            **error)
+{
+  g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
+
+  return g_socket_connect (connection->priv->socket, address,
+			   cancellable, error);
+}
+
+static gboolean g_socket_connection_connect_callback (GSocket      *socket,
+						      GIOCondition  condition,
+						      gpointer      user_data);
+
+/**
+ * g_socket_connection_connect_async:
+ * @connection: a #GSocketConnection
+ * @address: a #GSocketAddress specifying the remote address.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback
+ * @user_data: (closure): user data for the callback
+ *
+ * Asynchronously connect @connection to the specified remote address.
+ *
+ * This clears the #GSocket:blocking flag on @connection's underlying
+ * socket if it is currently set.
+ *
+ * Use g_socket_connection_connect_finish() to retrieve the result.
+ *
+ * Since: 2.32
+ */
+void
+g_socket_connection_connect_async (GSocketConnection   *connection,
+				   GSocketAddress      *address,
+				   GCancellable        *cancellable,
+				   GAsyncReadyCallback  callback,
+				   gpointer             user_data)
+{
+  GSimpleAsyncResult *simple;
+  GError *tmp_error = NULL;
+
+  g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
+  g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
+
+  simple = g_simple_async_result_new (G_OBJECT (connection),
+				      callback, user_data,
+				      g_socket_connection_connect_async);
+
+  g_socket_set_blocking (connection->priv->socket, FALSE);
+
+  if (g_socket_connect (connection->priv->socket, address,
+			cancellable, &tmp_error))
+    {
+      g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+      g_simple_async_result_complete_in_idle (simple);
+    }
+  else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
+    {
+      GSource *source;
+
+      g_error_free (tmp_error);
+      source = g_socket_create_source (connection->priv->socket,
+				       G_IO_OUT, cancellable);
+      g_source_set_callback (source,
+			     (GSourceFunc) g_socket_connection_connect_callback,
+			     simple, NULL);
+      g_source_attach (source, g_main_context_get_thread_default ());
+      g_source_unref (source);
+    }
+  else
+    {
+      g_simple_async_result_take_error (simple, tmp_error);
+      g_simple_async_result_complete_in_idle (simple);
+    }
+}
+
+static gboolean
+g_socket_connection_connect_callback (GSocket      *socket,
+				      GIOCondition  condition,
+				      gpointer      user_data)
+{
+  GSimpleAsyncResult *simple = user_data;
+  GSocketConnection *connection;
+  GError *error = NULL;
+
+  connection = G_SOCKET_CONNECTION (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+  g_object_unref (connection);
+
+  if (g_socket_check_connect_result (connection->priv->socket, &error))
+    g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+  else
+    g_simple_async_result_take_error (simple, error);
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+  return FALSE;
+}
+
+/**
+ * g_socket_connection_connect_finish:
+ * @connection: a #GSocketConnection
+ * @result: the #GAsyncResult
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Gets the result of a g_socket_connection_connect_async() call.
+ *
+ * Returns: %TRUE if the connection succeeded, %FALSE on error
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_connect_finish (GSocketConnection  *connection,
+				    GAsyncResult       *result,
+				    GError            **error)
+{
+  GSimpleAsyncResult *simple;
+
+  g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), g_socket_connection_connect_async), FALSE);
+
+  simple = G_SIMPLE_ASYNC_RESULT (result);
+  if (g_simple_async_result_propagate_error (simple, error))
+    return FALSE;
+  return TRUE;
+}
+
+/**
  * g_socket_connection_get_socket:
  * @connection: a #GSocketConnection
  *
diff --git a/gio/gsocketconnection.h b/gio/gsocketconnection.h
index 1edc2f4..34a0cb1 100644
--- a/gio/gsocketconnection.h
+++ b/gio/gsocketconnection.h
@@ -72,11 +72,26 @@ struct _GSocketConnection
 
 GType              g_socket_connection_get_type                  (void) G_GNUC_CONST;
 
+gboolean           g_socket_connection_is_connected              (GSocketConnection  *connection);
+gboolean           g_socket_connection_connect                   (GSocketConnection  *connection,
+								  GSocketAddress     *address,
+								  GCancellable       *cancellable,
+								  GError            **error);
+void               g_socket_connection_connect_async             (GSocketConnection  *connection,
+								  GSocketAddress     *address,
+								  GCancellable       *cancellable,
+								  GAsyncReadyCallback callback,
+								  gpointer            user_data);
+gboolean           g_socket_connection_connect_finish            (GSocketConnection  *connection,
+								  GAsyncResult       *result,
+								  GError            **error);
+
 GSocket           *g_socket_connection_get_socket                (GSocketConnection  *connection);
 GSocketAddress    *g_socket_connection_get_local_address         (GSocketConnection  *connection,
 								  GError            **error);
 GSocketAddress    *g_socket_connection_get_remote_address        (GSocketConnection  *connection,
 								  GError            **error);
+
 void               g_socket_connection_factory_register_type     (GType               g_type,
 								  GSocketFamily       family,
 								  GSocketType         type,



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