[glib/tls: 8/9] make GProxyConnection public, as GTcpWrapperConnection



commit 05b3108313f785dba87de9528560636e9cf2fe4f
Author: Dan Winship <danw gnome org>
Date:   Mon Nov 1 20:22:24 2010 -0400

    make GProxyConnection public, as GTcpWrapperConnection
    
    GProxyConnection is a class that was added for proxy support;
    g_socket_client_connect() returns a GSocketConnection, but in some
    cases (eg, encrypted SOCKS), GProxy might return a GIOStream that is
    not a GSocketConnection. In that case, GSocketClient would wrap the
    stream up in a GProxyConnection, which is a subclass of
    GSocketConnection but uses the input/output streams of the wrapped
    connection.
    
    GTlsConnection is not a GSocketConnection, so it has the same problem,
    so it will need the same treatment. Rename the class to
    GTcpWrapperStream, and make it public, so people can extract the base
    stream from it when necessary.
    
    (This is not ideal and GSocketClient will need to be revisited as an
    API at some point...)

 docs/reference/gio/gio-docs.xml     |    1 +
 docs/reference/gio/gio-sections.txt |   19 ++++
 gio/Makefile.am                     |    4 +-
 gio/gio.h                           |    1 +
 gio/gio.symbols                     |    8 ++
 gio/giotypes.h                      |    1 +
 gio/gproxyconnection.c              |  155 ---------------------------
 gio/gproxyconnection.h              |   69 ------------
 gio/gsocketclient.c                 |   55 +++++-----
 gio/gtcpwrapperconnection.c         |  200 +++++++++++++++++++++++++++++++++++
 gio/gtcpwrapperconnection.h         |   68 ++++++++++++
 11 files changed, 330 insertions(+), 251 deletions(-)
---
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index a04cf8f..4285a65 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -121,6 +121,7 @@
       <xi:include href="xml/gsocketconnection.xml"/>
       <xi:include href="xml/gunixconnection.xml"/>
       <xi:include href="xml/gtcpconnection.xml"/>
+      <xi:include href="xml/gtcpwrapperconnection.xml"/>
       <xi:include href="xml/gsocketlistener.xml"/>
       <xi:include href="xml/gsocketservice.xml"/>
       <xi:include href="xml/gthreadedsocketservice.xml"/>
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 18d31c9..1c76c5b 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1880,6 +1880,25 @@ g_tcp_connection_get_type
 </SECTION>
 
 <SECTION>
+<FILE>gtcpwrapperconnection</FILE>
+<TITLE>GTcpWrapperConnection</TITLE>
+GTcpWrapperConnection
+g_tcp_wrapper_connection_new
+g_tcp_wrapper_connection_get_base_io_stream
+<SUBSECTION Standard>
+GTcpWrapperConnectionClass
+G_IS_TCP_WRAPPER_CONNECTION
+G_IS_TCP_WRAPPER_CONNECTION_CLASS
+G_TYPE_TCP_WRAPPER_CONNECTION
+G_TCP_WRAPPER_CONNECTION
+G_TCP_WRAPPER_CONNECTION_CLASS
+G_TCP_WRAPPER_CONNECTION_GET_CLASS
+<SUBSECTION Private>
+GTcpWrapperConnectionPrivate
+g_tcp_wrapper_connection_get_type
+</SECTION>
+
+<SECTION>
 <FILE>gsocketcontrolmessage</FILE>
 <TITLE>GSocketControlMessage</TITLE>
 GSocketControlMessage
diff --git a/gio/Makefile.am b/gio/Makefile.am
index fc2dad6..06c444f 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -374,11 +374,10 @@ libgio_2_0_la_SOURCES =		\
 	gproxy.c		\
 	gproxyaddress.c         \
 	gproxyaddressenumerator.c \
-	gproxyconnection.c      \
-	gproxyconnection.h      \
 	gsocketservice.c	\
 	gsrvtarget.c		\
 	gtcpconnection.c	\
+	gtcpwrapperconnection.c \
 	gthreadedsocketservice.c\
 	gthemedicon.c 		\
 	gthreadedresolver.c	\
@@ -530,6 +529,7 @@ gio_headers =			\
 	gsocketservice.h	\
 	gsrvtarget.h		\
 	gtcpconnection.h	\
+	gtcpwrapperconnection.h \
 	gthreadedsocketservice.h\
 	gthemedicon.h 		\
 	gvfs.h 			\
diff --git a/gio/gio.h b/gio/gio.h
index e013942..6f650df 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -118,6 +118,7 @@
 #include <gio/gsocketservice.h>
 #include <gio/gsrvtarget.h>
 #include <gio/gtcpconnection.h>
+#include <gio/gtcpwrapperconnection.h>
 #include <gio/gthemedicon.h>
 #include <gio/gthreadedsocketservice.h>
 #include <gio/gvfs.h>
diff --git a/gio/gio.symbols b/gio/gio.symbols
index eea5deb..f35b3e0 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1994,3 +1994,11 @@ g_pollable_output_stream_is_writable
 g_pollable_output_stream_write_nonblocking
 #endif
 #endif
+
+#if IN_HEADER(__G_TCP_WRAPPER_CONNECTION_H__)
+#if IN_FILE(__G_TCP_WRAPPER_CONNECTION_C__)
+g_tcp_wrapper_connection_get_type G_GNUC_CONST
+g_tcp_wrapper_connection_get_base_io_stream
+g_tcp_wrapper_connection_new
+#endif
+#endif
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 3c47a7c..cb48a12 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -192,6 +192,7 @@ typedef struct _GSrvTarget                    GSrvTarget;
  * Since: 2.22
  **/
 typedef struct _GTcpConnection                              GTcpConnection;
+typedef struct _GTcpWrapperConnection                       GTcpWrapperConnection;
 /**
  * GThreadedSocketService:
  *
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index 982dedc..4a1c832 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -34,7 +34,6 @@
 #include <gio/gsocketconnection.h>
 #include <gio/gproxyaddressenumerator.h>
 #include <gio/gproxyaddress.h>
-#include <gio/gproxyconnection.h>
 #include <gio/gsimpleasyncresult.h>
 #include <gio/gcancellable.h>
 #include <gio/gioerror.h>
@@ -44,6 +43,7 @@
 #include <gio/gproxy.h>
 #include <gio/gsocketaddress.h>
 #include <gio/gtcpconnection.h>
+#include <gio/gtcpwrapperconnection.h>
 #include "glibintl.h"
 
 
@@ -679,14 +679,15 @@ g_socket_client_connect (GSocketClient       *client,
       g_clear_error (&last_error);
 
       socket = create_socket (client, address, &last_error);
-      if (socket != NULL)
+      if (socket == NULL)
 	{
-	  if (g_socket_connect (socket, address, cancellable, &last_error))
-	    connection = g_socket_connection_factory_create_connection (socket);
-
-	  g_object_unref (socket);
+	  g_object_unref (address);
+	  continue;
 	}
 
+      if (g_socket_connect (socket, address, cancellable, &last_error))
+	connection = g_socket_connection_factory_create_connection (socket);
+
       if (connection &&
 	  G_IS_PROXY_ADDRESS (address) &&
 	  client->priv->enable_proxy)
@@ -716,31 +717,30 @@ g_socket_client_connect (GSocketClient       *client,
           else if (proxy)
 	    {
               GIOStream *io_stream;
-              GTcpConnection *old_connection = G_TCP_CONNECTION (connection);
 
 	      io_stream = g_proxy_connect (proxy,
-					   G_IO_STREAM (old_connection),
+					   G_IO_STREAM (connection),
 					   proxy_addr,
 					   cancellable,
 					   &last_error);
+	      g_object_unref (connection);
+	      g_object_unref (proxy);
 
               if (io_stream)
                 {
                   if (G_IS_SOCKET_CONNECTION (io_stream))
-                    connection = G_SOCKET_CONNECTION (g_object_ref (io_stream));
+                    connection = G_SOCKET_CONNECTION (io_stream);
                   else
-                    connection = _g_proxy_connection_new (old_connection,
-                                                          io_stream);
-
-                  g_object_unref (io_stream);
+		    {
+		      connection = g_tcp_wrapper_connection_new (io_stream,
+								 socket);
+		      g_object_unref (io_stream);
+		    }
                 }
               else
                 {
                   connection = NULL;
                 }
-
-              g_object_unref (old_connection);
-	      g_object_unref (proxy);
 	    }
 	  else if (!g_hash_table_lookup_extended (client->priv->app_proxies,
 						  protocol, NULL, NULL))
@@ -753,6 +753,7 @@ g_socket_client_connect (GSocketClient       *client,
 	    }
 	}
 
+      g_object_unref (socket);
       g_object_unref (address);
     }
   g_object_unref (enumerator);
@@ -991,28 +992,30 @@ g_socket_client_proxy_connect_callback (GObject      *object,
 {
   GSocketClientAsyncConnectData *data = user_data;
   GIOStream *io_stream;
-  GTcpConnection *old_connection = G_TCP_CONNECTION (data->connection);
 
   io_stream = g_proxy_connect_finish (G_PROXY (object),
 				      result,
 				      &data->last_error);
+  g_object_unref (data->connection);
 
   if (io_stream)
     {
       if (G_IS_SOCKET_CONNECTION (io_stream))
-        data->connection = G_SOCKET_CONNECTION (g_object_ref (io_stream));
+        data->connection = G_SOCKET_CONNECTION (io_stream);
       else
-        data->connection = _g_proxy_connection_new (old_connection,
-                                                    io_stream);
-      g_object_unref (io_stream);
+	{
+	  data->connection = g_tcp_wrapper_connection_new (io_stream,
+							   data->current_socket);
+	  g_object_unref (io_stream);
+	}
     }
   else
     {
       data->connection = NULL;
+      g_object_unref (data->current_socket);
+      data->current_socket = NULL;
     }
 
-  g_object_unref (old_connection);
-
   g_socket_client_async_connect_complete (data);
 }
 
@@ -1038,6 +1041,8 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
 
       g_object_unref (data->connection);
       data->connection = NULL;
+      g_object_unref (data->current_socket);
+      data->current_socket = NULL;
 
       enumerator_next_async (data);
     }
@@ -1062,6 +1067,8 @@ g_socket_client_proxy_connect (GSocketClientAsyncConnectData *data)
 
       g_object_unref (data->connection);
       data->connection = NULL;
+      g_object_unref (data->current_socket);
+      data->current_socket = NULL;
 
       enumerator_next_async (data);
     }
@@ -1074,8 +1081,6 @@ g_socket_client_socket_connected (GSocketClientAsyncConnectData *data)
 
   data->connection =
     g_socket_connection_factory_create_connection (data->current_socket);
-  g_object_unref (data->current_socket);
-  data->current_socket = NULL;
 
   if (data->proxy_addr)
     g_socket_client_proxy_connect (data);
diff --git a/gio/gtcpwrapperconnection.c b/gio/gtcpwrapperconnection.c
new file mode 100644
index 0000000..47970ad
--- /dev/null
+++ b/gio/gtcpwrapperconnection.c
@@ -0,0 +1,200 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Nicolas Dufresne <nicolas dufresne colllabora co uk>
+ */
+
+/**
+ * SECTION: gtcpwrapperconnection
+ * @title: GTcpWrapperConnection
+ * @short_description: a wrapper for non-#GSocketConnection-based
+ *   #GIOStream<!-- -->s that are nonetheless based on a #GSocket
+ * @see_also: #GSocketConnection.
+ *
+ * A #GTcpWrapperConnection can be used to wrap a #GIOStream that is
+ * based on a #GSocket, but which is not actually a
+ * #GSocketConnection. This is used by #GSocketClient so that it can
+ * always return a #GSocketConnection, even when the connection it has
+ * actually created is not directly a #GSocketConnection.
+ *
+ * Since: 2.28
+ */
+
+#include "config.h"
+
+#include "gtcpwrapperconnection.h"
+
+#include "gtcpconnection.h"
+#include "glibintl.h"
+
+G_DEFINE_TYPE (GTcpWrapperConnection,
+	       g_tcp_wrapper_connection, G_TYPE_TCP_CONNECTION);
+
+enum
+{
+  PROP_NONE,
+  PROP_BASE_IO_STREAM
+};
+
+struct _GTcpWrapperConnectionPrivate
+{
+  GIOStream *base_io_stream;
+};
+
+static GInputStream *
+g_tcp_wrapper_connection_get_input_stream (GIOStream *io_stream)
+{
+  GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (io_stream);
+
+  return g_io_stream_get_input_stream (connection->priv->base_io_stream);
+}
+
+static GOutputStream *
+g_tcp_wrapper_connection_get_output_stream (GIOStream *io_stream)
+{
+  GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (io_stream);
+
+  return g_io_stream_get_output_stream (connection->priv->base_io_stream);
+}
+
+static void
+g_tcp_wrapper_connection_get_property (GObject    *object,
+				       guint       prop_id,
+				       GValue     *value,
+				       GParamSpec *pspec)
+{
+  GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
+
+  switch (prop_id)
+    {
+     case PROP_BASE_IO_STREAM:
+      g_value_set_object (value, connection->priv->base_io_stream);
+      break;
+
+     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_tcp_wrapper_connection_set_property (GObject      *object,
+                                        guint         prop_id,
+                                        const GValue *value,
+                                        GParamSpec   *pspec)
+{
+  GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
+
+  switch (prop_id)
+    {
+     case PROP_BASE_IO_STREAM:
+      connection->priv->base_io_stream = g_value_dup_object (value);
+      break;
+
+     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_tcp_wrapper_connection_finalize (GObject *object)
+{
+  GTcpWrapperConnection *connection = G_TCP_WRAPPER_CONNECTION (object);
+
+  if (connection->priv->base_io_stream)
+    g_object_unref (connection->priv->base_io_stream);
+
+  G_OBJECT_CLASS (g_tcp_wrapper_connection_parent_class)->finalize (object);
+}
+
+static void
+g_tcp_wrapper_connection_class_init (GTcpWrapperConnectionClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GTcpWrapperConnectionPrivate));
+
+  gobject_class->set_property = g_tcp_wrapper_connection_set_property;
+  gobject_class->get_property = g_tcp_wrapper_connection_get_property;
+  gobject_class->finalize = g_tcp_wrapper_connection_finalize;
+
+  stream_class->get_input_stream = g_tcp_wrapper_connection_get_input_stream;
+  stream_class->get_output_stream = g_tcp_wrapper_connection_get_output_stream;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_BASE_IO_STREAM,
+                                   g_param_spec_object ("base-io-stream",
+			                                P_("Base IO Stream"),
+			                                P_("The wrapped GIOStream"),
+                                                        G_TYPE_IO_STREAM,
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_STATIC_STRINGS));
+}
+
+static void
+g_tcp_wrapper_connection_init (GTcpWrapperConnection *connection)
+{
+  connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION,
+                                                  GTcpWrapperConnectionPrivate);
+}
+
+/**
+ * g_tcp_wrapper_connection_new:
+ * @base_io_stream: the #GIOStream to wrap
+ * @socket: the #GSocket associated with @base_io_stream
+ *
+ * Wraps @base_io_stream and @socket together as a #GSocketConnection.
+ *
+ * Return value: the new #GSocketConnection.
+ *
+ * Since: 2.28
+ */
+GSocketConnection *
+g_tcp_wrapper_connection_new (GIOStream *base_io_stream,
+			      GSocket   *socket)
+{
+  g_return_val_if_fail (G_IS_IO_STREAM (base_io_stream), NULL);
+  g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
+  g_return_val_if_fail (g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV4 ||
+			g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6, NULL);
+  g_return_val_if_fail (g_socket_get_socket_type (socket) == G_SOCKET_TYPE_STREAM, NULL);
+
+  return g_object_new (G_TYPE_TCP_WRAPPER_CONNECTION,
+		       "base-io-stream", base_io_stream,
+		       "socket", socket,
+		       NULL);
+}
+
+/**
+ * g_tcp_wrapper_connection_get_base_io_stream:
+ * @conn: a #GTcpWrapperConnection
+ *
+ * Get's @conn's base #GIOStream
+ *
+ * Return value: (transfer none): @conn's base #GIOStream
+ */
+GIOStream *
+g_tcp_wrapper_connection_get_base_io_stream (GTcpWrapperConnection *conn)
+{
+  g_return_val_if_fail (G_IS_TCP_WRAPPER_CONNECTION (conn), NULL);
+
+  return conn->priv->base_io_stream;
+}
diff --git a/gio/gtcpwrapperconnection.h b/gio/gtcpwrapperconnection.h
new file mode 100644
index 0000000..01d3a03
--- /dev/null
+++ b/gio/gtcpwrapperconnection.h
@@ -0,0 +1,68 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * Copyright © 2010 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Nicolas Dufresne <nicolas dufresne collabora co uk>
+ *
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_TCP_WRAPPER_CONNECTION_H__
+#define __G_TCP_WRAPPER_CONNECTION_H__
+
+#include <gio/gtcpconnection.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TCP_WRAPPER_CONNECTION            (g_tcp_wrapper_connection_get_type ())
+#define G_TCP_WRAPPER_CONNECTION(inst)           (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnection))
+#define G_TCP_WRAPPER_CONNECTION_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnectionClass))
+#define G_IS_TCP_WRAPPER_CONNECTION(inst)        (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION))
+#define G_IS_TCP_WRAPPER_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION))
+#define G_TCP_WRAPPER_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                  G_TYPE_TCP_WRAPPER_CONNECTION, GTcpWrapperConnectionClass))
+
+typedef struct _GTcpWrapperConnectionPrivate GTcpWrapperConnectionPrivate;
+typedef struct _GTcpWrapperConnectionClass   GTcpWrapperConnectionClass;
+
+struct _GTcpWrapperConnectionClass
+{
+  GTcpConnectionClass parent_class;
+};
+
+struct _GTcpWrapperConnection
+{
+  GTcpConnection parent_instance;
+  GTcpWrapperConnectionPrivate *priv;
+};
+
+GType              g_tcp_wrapper_connection_get_type (void) G_GNUC_CONST;
+
+GSocketConnection *g_tcp_wrapper_connection_new                (GIOStream             *base_io_stream,
+								GSocket               *socket);
+GIOStream         *g_tcp_wrapper_connection_get_base_io_stream (GTcpWrapperConnection *conn);
+
+G_END_DECLS
+
+#endif /* __G_TCP_WRAPPER_CONNECTION_H__ */



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