[glib] GSocketClient: For _CONNECTING event, make remote address accessible



commit a46459b0002af97c035133907706caeba76f7863
Author: Colin Walters <walters verbum org>
Date:   Mon Nov 18 16:15:34 2013 -0500

    GSocketClient: For _CONNECTING event, make remote address accessible
    
    My application (hotssh) would like to get the resolved address from DNS,
    before we start the connect().
    
    We could add a new event, but it's easy enough to just cache it on the
    GSocketConnection; this avoids any new API.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=712547

 gio/gioprivate.h        |    6 ++++++
 gio/gsocketclient.c     |    8 +++++++-
 gio/gsocketconnection.c |   30 ++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletions(-)
---
diff --git a/gio/gioprivate.h b/gio/gioprivate.h
index d190f19..ab07c6c 100644
--- a/gio/gioprivate.h
+++ b/gio/gioprivate.h
@@ -23,12 +23,18 @@
 
 #include "ginputstream.h"
 #include "goutputstream.h"
+#include "gsocketconnection.h"
+#include "gsocketaddress.h"
 
 G_BEGIN_DECLS
 
 gboolean g_input_stream_async_read_is_via_threads (GInputStream *stream);
 gboolean g_output_stream_async_write_is_via_threads (GOutputStream *stream);
 
+void g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
+                                                    GSocketAddress    *address);
+
+
 G_END_DECLS
 
 #endif /* __G_IO_PRIVATE__ */
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index cf71364..9e32248 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -32,6 +32,7 @@
 #include <gio/gsocketaddressenumerator.h>
 #include <gio/gsocketconnectable.h>
 #include <gio/gsocketconnection.h>
+#include <gio/gioprivate.h>
 #include <gio/gproxyaddressenumerator.h>
 #include <gio/gproxyaddress.h>
 #include <gio/gtask.h>
@@ -796,7 +797,8 @@ g_socket_client_class_init (GSocketClientClass *class)
    *       @client is about to make a connection to a remote host;
    *       either a proxy server or the destination server itself.
    *       @connection is the #GSocketConnection, which is not yet
-   *       connected.
+   *       connected.  Since GLib 2.40, you can access the remote
+   *       address via g_socket_connection_get_remote_address().
    *     </para></listitem>
    *   </varlistentry>
    *   <varlistentry>
@@ -1084,11 +1086,13 @@ g_socket_client_connect (GSocketClient       *client,
        }
 
       connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
+      g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, address);
       g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTING, connectable, connection);
 
       if (g_socket_connection_connect (G_SOCKET_CONNECTION (connection),
                                       address, cancellable, &last_error))
        {
+          g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, NULL);
          g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTED, connectable, connection);
        }
       else
@@ -1542,6 +1546,7 @@ g_socket_client_connected_callback (GObject      *source,
       return;
     }
 
+  g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, NULL);
   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, data->connection);
 
   /* wrong, but backward compatible */
@@ -1657,6 +1662,7 @@ g_socket_client_enumerator_callback (GObject      *object,
   data->current_addr = address;
   data->connection = (GIOStream *) g_socket_connection_factory_create_connection (socket);
 
+  g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, address);
   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, data->connection);
   g_socket_connection_connect_async (G_SOCKET_CONNECTION (data->connection),
                                     address,
diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c
index ac1db4a..6127a84 100644
--- a/gio/gsocketconnection.c
+++ b/gio/gsocketconnection.c
@@ -31,6 +31,7 @@
 
 #include "gsocketoutputstream.h"
 #include "gsocketinputstream.h"
+#include "gioprivate.h"
 #include <gio/giostream.h>
 #include <gio/gtask.h>
 #include "gunixconnection.h"
@@ -72,6 +73,8 @@ struct _GSocketConnectionPrivate
   GInputStream  *input_stream;
   GOutputStream *output_stream;
 
+  GSocketAddress *cached_remote_address;
+
   gboolean       in_dispose;
 };
 
@@ -305,6 +308,13 @@ g_socket_connection_get_local_address (GSocketConnection  *connection,
  *
  * Try to get the remote address of a socket connection.
  *
+ * Since GLib 2.40, when used with g_socket_client_connect() or
+ * g_socket_client_connect_async(), during emission of
+ * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
+ * address that will be used for the connection.  This allows
+ * applications to print e.g. "Connecting to example.com
+ * (10.42.77.3)...".
+ *
  * Returns: (transfer full): a #GSocketAddress or %NULL on error.
  *     Free the returned object with g_object_unref().
  *
@@ -314,9 +324,27 @@ GSocketAddress *
 g_socket_connection_get_remote_address (GSocketConnection  *connection,
                                        GError            **error)
 {
+  if (!g_socket_is_connected (connection->priv->socket))
+    {
+      return connection->priv->cached_remote_address ?
+        g_object_ref (connection->priv->cached_remote_address) : NULL;
+    }
   return g_socket_get_remote_address (connection->priv->socket, error);
 }
 
+/* Private API allowing applications to retrieve the resolved address
+ * now, before we start connecting.
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=712547
+ */
+void
+g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
+                                               GSocketAddress    *address)
+{
+  g_clear_object (&connection->priv->cached_remote_address);
+  connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
+}
+
 static void
 g_socket_connection_get_property (GObject    *object,
                                   guint       prop_id,
@@ -370,6 +398,8 @@ g_socket_connection_dispose (GObject *object)
 
   connection->priv->in_dispose = TRUE;
 
+  g_clear_object (&connection->priv->cached_remote_address);
+
   G_OBJECT_CLASS (g_socket_connection_parent_class)
     ->dispose (object);
 


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