[glib] GSocketClient: add proxy-resolver property
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] GSocketClient: add proxy-resolver property
- Date: Thu, 14 Feb 2013 22:23:21 +0000 (UTC)
commit 7c49869eaef4d49c57bbdf4e95989e4d8f864623
Author: Dan Winship <danw gnome org>
Date: Sun Jan 27 13:53:36 2013 -0500
GSocketClient: add proxy-resolver property
Add a proxy-resolver property to GSocketClient, to allow overriding
proxy resolution in situations where you need to force a particular
proxy rather than using the system defaults.
https://bugzilla.gnome.org/show_bug.cgi?id=691105
docs/reference/gio/gio-sections.txt | 2 +
gio/gproxyaddressenumerator.c | 43 +++++++++-
gio/gsocketclient.c | 113 ++++++++++++++++++++++++-
gio/gsocketclient.h | 5 +
gio/tests/proxy-test.c | 154 +++++++++++++++++++++++++++++++++-
5 files changed, 302 insertions(+), 15 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index dc2b27d..04e9310 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1958,6 +1958,7 @@ g_socket_client_set_protocol
g_socket_client_set_socket_type
g_socket_client_set_timeout
g_socket_client_set_enable_proxy
+g_socket_client_set_proxy_resolver
g_socket_client_set_tls
g_socket_client_set_tls_validation_flags
g_socket_client_get_family
@@ -1966,6 +1967,7 @@ g_socket_client_get_protocol
g_socket_client_get_socket_type
g_socket_client_get_timeout
g_socket_client_get_enable_proxy
+g_socket_client_get_proxy_resolver
g_socket_client_get_tls
g_socket_client_get_tls_validation_flags
g_socket_client_add_application_proxy
diff --git a/gio/gproxyaddressenumerator.c b/gio/gproxyaddressenumerator.c
index fecb4c8..32a684f 100644
--- a/gio/gproxyaddressenumerator.c
+++ b/gio/gproxyaddressenumerator.c
@@ -47,7 +47,8 @@ enum
{
PROP_0,
PROP_URI,
- PROP_CONNECTABLE
+ PROP_CONNECTABLE,
+ PROP_PROXY_RESOLVER
};
struct _GProxyAddressEnumeratorPrivate
@@ -60,6 +61,7 @@ struct _GProxyAddressEnumeratorPrivate
GList *dest_ips;
/* Proxy enumeration */
+ GProxyResolver *proxy_resolver;
gchar **proxies;
gchar **next_proxy;
GSocketAddressEnumerator *addr_enum;
@@ -180,8 +182,7 @@ g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator,
if (priv->proxies == NULL)
{
- GProxyResolver *resolver = g_proxy_resolver_get_default ();
- priv->proxies = g_proxy_resolver_lookup (resolver,
+ priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
priv->dest_uri,
cancellable,
error);
@@ -530,8 +531,7 @@ g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
if (priv->proxies == NULL)
{
- GProxyResolver *resolver = g_proxy_resolver_get_default ();
- g_proxy_resolver_lookup_async (resolver,
+ g_proxy_resolver_lookup_async (priv->proxy_resolver,
priv->dest_uri,
cancellable,
proxy_lookup_cb,
@@ -586,6 +586,10 @@ g_proxy_address_enumerator_get_property (GObject *object,
g_value_set_object (value, priv->connectable);
break;
+ case PROP_PROXY_RESOLVER:
+ g_value_set_object (value, priv->proxy_resolver);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -643,6 +647,15 @@ g_proxy_address_enumerator_set_property (GObject *object,
priv->connectable = g_value_dup_object (value);
break;
+ case PROP_PROXY_RESOLVER:
+ if (priv->proxy_resolver)
+ g_object_unref (priv->proxy_resolver);
+ priv->proxy_resolver = g_value_get_object (value);
+ if (!priv->proxy_resolver)
+ priv->proxy_resolver = g_proxy_resolver_get_default ();
+ g_object_ref (priv->proxy_resolver);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -656,6 +669,9 @@ g_proxy_address_enumerator_finalize (GObject *object)
if (priv->connectable)
g_object_unref (priv->connectable);
+ if (priv->proxy_resolver)
+ g_object_unref (priv->proxy_resolver);
+
g_free (priv->dest_uri);
g_free (priv->dest_hostname);
@@ -720,4 +736,21 @@ g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enume
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GProxyAddressEnumerator:proxy-resolver:
+ *
+ * The proxy resolver to use.
+ *
+ * Since: 2.36
+ */
+ g_object_class_install_property (object_class,
+ PROP_PROXY_RESOLVER,
+ g_param_spec_object ("proxy-resolver",
+ P_("Proxy resolver"),
+ P_("The proxy resolver to use."),
+ G_TYPE_PROXY_RESOLVER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
}
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index ddbe697..00e3481 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -41,6 +41,7 @@
#include <gio/gnetworkaddress.h>
#include <gio/gnetworkservice.h>
#include <gio/gproxy.h>
+#include <gio/gproxyresolver.h>
#include <gio/gsocketaddress.h>
#include <gio/gtcpconnection.h>
#include <gio/gtcpwrapperconnection.h>
@@ -94,7 +95,8 @@ enum
PROP_TIMEOUT,
PROP_ENABLE_PROXY,
PROP_TLS,
- PROP_TLS_VALIDATION_FLAGS
+ PROP_TLS_VALIDATION_FLAGS,
+ PROP_PROXY_RESOLVER
};
struct _GSocketClientPrivate
@@ -108,6 +110,7 @@ struct _GSocketClientPrivate
GHashTable *app_proxies;
gboolean tls;
GTlsCertificateFlags tls_validation_flags;
+ GProxyResolver *proxy_resolver;
};
static GSocket *
@@ -227,8 +230,8 @@ g_socket_client_finalize (GObject *object)
{
GSocketClient *client = G_SOCKET_CLIENT (object);
- if (client->priv->local_address)
- g_object_unref (client->priv->local_address);
+ g_clear_object (&client->priv->local_address);
+ g_clear_object (&client->priv->proxy_resolver);
if (G_OBJECT_CLASS (g_socket_client_parent_class)->finalize)
(*G_OBJECT_CLASS (g_socket_client_parent_class)->finalize) (object);
@@ -278,6 +281,10 @@ g_socket_client_get_property (GObject *object,
g_value_set_flags (value, g_socket_client_get_tls_validation_flags (client));
break;
+ case PROP_PROXY_RESOLVER:
+ g_value_set_object (value, g_socket_client_get_proxy_resolver (client));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -325,6 +332,10 @@ g_socket_client_set_property (GObject *object,
g_socket_client_set_tls_validation_flags (client, g_value_get_flags (value));
break;
+ case PROP_PROXY_RESOLVER:
+ g_socket_client_set_proxy_resolver (client, g_value_get_object (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -579,6 +590,8 @@ g_socket_client_get_enable_proxy (GSocketClient *client)
* #GProxyResolver to determine if a proxy protocol such as SOCKS is
* needed, and automatically do the necessary proxy negotiation.
*
+ * See also g_socket_client_set_proxy_resolver().
+ *
* Since: 2.26
*/
void
@@ -686,6 +699,64 @@ g_socket_client_set_tls_validation_flags (GSocketClient *client,
}
}
+/**
+ * g_socket_client_get_proxy_resolver:
+ * @client: a #GSocketClient.
+ *
+ * Gets the #GProxyResolver being used by @client. Normally, this will
+ * be the resolver returned by g_proxy_resolver_get_default(), but you
+ * can override it with g_socket_client_set_proxy_resolver().
+ *
+ * Returns: (transfer none): The #GProxyResolver being used by
+ * @client.
+ *
+ * Since: 2.36
+ */
+GProxyResolver *
+g_socket_client_get_proxy_resolver (GSocketClient *client)
+{
+ if (client->priv->proxy_resolver)
+ return client->priv->proxy_resolver;
+ else
+ return g_proxy_resolver_get_default ();
+}
+
+/**
+ * g_socket_client_set_proxy_resolver:
+ * @client: a #GSocketClient.
+ * @proxy_resolver: (allow-none): a #GProxyResolver, or %NULL for the
+ * default.
+ *
+ * Overrides the #GProxyResolver used by @client. You can call this if
+ * you want to use specific proxies, rather than using the system
+ * default proxy settings.
+ *
+ * Note that whether or not the proxy resolver is actually used
+ * depends on the setting of #GSocketClient:enable-proxy, which is not
+ * changed by this function (but which is %TRUE by default)
+ *
+ * Since: 2.36
+ */
+void
+g_socket_client_set_proxy_resolver (GSocketClient *client,
+ GProxyResolver *proxy_resolver)
+{
+ /* We have to be careful to avoid calling
+ * g_proxy_resolver_get_default() until we're sure we need it,
+ * because trying to load the default proxy resolver module will
+ * break some test programs that aren't expecting it (eg,
+ * tests/gsettings).
+ */
+
+ if (client->priv->proxy_resolver)
+ g_object_unref (client->priv->proxy_resolver);
+
+ client->priv->proxy_resolver = proxy_resolver;
+
+ if (client->priv->proxy_resolver)
+ g_object_ref (client->priv->proxy_resolver);
+}
+
static void
g_socket_client_class_init (GSocketClientClass *class)
{
@@ -881,6 +952,22 @@ g_socket_client_class_init (GSocketClientClass *class)
G_PARAM_CONSTRUCT |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GSocketClient:proxy-resolver:
+ *
+ * The proxy resolver to use
+ *
+ * Since: 2.36
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_RESOLVER,
+ g_param_spec_object ("proxy-resolver",
+ P_("Proxy resolver"),
+ P_("The proxy resolver to use"),
+ G_TYPE_PROXY_RESOLVER,
+ G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
}
static void
@@ -936,7 +1023,15 @@ g_socket_client_connect (GSocketClient *client,
last_error = NULL;
if (can_use_proxy (client))
- enumerator = g_socket_connectable_proxy_enumerate (connectable);
+ {
+ enumerator = g_socket_connectable_proxy_enumerate (connectable);
+ if (client->priv->proxy_resolver &&
+ G_IS_PROXY_ADDRESS_ENUMERATOR (enumerator))
+ {
+ g_object_set (G_OBJECT (enumerator), "proxy-resolver",
+ client->priv->proxy_resolver);
+ }
+ }
else
enumerator = g_socket_connectable_enumerate (connectable);
@@ -1605,9 +1700,17 @@ g_socket_client_connect_async (GSocketClient *client,
data->connectable = g_object_ref (connectable);
if (can_use_proxy (client))
+ {
data->enumerator = g_socket_connectable_proxy_enumerate (connectable);
+ if (client->priv->proxy_resolver &&
+ G_IS_PROXY_ADDRESS_ENUMERATOR (data->enumerator))
+ {
+ g_object_set (G_OBJECT (data->enumerator), "proxy-resolver",
+ client->priv->proxy_resolver);
+ }
+ }
else
- data->enumerator = g_socket_connectable_enumerate (connectable);
+ data->enumerator = g_socket_connectable_enumerate (connectable);
data->task = g_task_new (client, cancellable, callback, user_data);
g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
diff --git a/gio/gsocketclient.h b/gio/gsocketclient.h
index 11748ba..0cf6bf5 100644
--- a/gio/gsocketclient.h
+++ b/gio/gsocketclient.h
@@ -117,6 +117,11 @@ GTlsCertificateFlags g_socket_client_get_tls_validation_flags (GSocket
GLIB_AVAILABLE_IN_ALL
void g_socket_client_set_tls_validation_flags (GSocketClient *client,
GTlsCertificateFlags flags);
+GLIB_AVAILABLE_IN_2_36
+GProxyResolver *g_socket_client_get_proxy_resolver (GSocketClient *client);
+GLIB_AVAILABLE_IN_2_36
+void g_socket_client_set_proxy_resolver (GSocketClient *client,
+ GProxyResolver
*proxy_resolver);
GLIB_AVAILABLE_IN_ALL
GSocketConnection * g_socket_client_connect (GSocketClient *client,
diff --git a/gio/tests/proxy-test.c b/gio/tests/proxy-test.c
index da0e837..2ab27aa 100644
--- a/gio/tests/proxy-test.c
+++ b/gio/tests/proxy-test.c
@@ -26,7 +26,7 @@
/* Overview:
*
* We have an echo server, two proxy servers, two GProxy
- * implementations, and a GProxyResolver implementation.
+ * implementations, and two GProxyResolver implementations.
*
* The echo server runs at @server.server_addr (on
* @server.server_port).
@@ -42,9 +42,10 @@
* hostname resolution (but it just ignores the hostname and always
* connects to @server_addr anyway).
*
- * The GProxyResolver (GTestProxyResolver) looks at its URI and
- * returns [ "direct://" ] for "simple://" URIs, and [ proxy_a.uri,
- * proxy_b.uri ] for other URIs.
+ * The default GProxyResolver (GTestProxyResolver) looks at its URI
+ * and returns [ "direct://" ] for "simple://" URIs, and [
+ * proxy_a.uri, proxy_b.uri ] for other URIs. The other GProxyResolver
+ * (GTestAltProxyResolver) always returns [ proxy_a.uri ].
*/
typedef struct {
@@ -163,7 +164,7 @@ g_test_proxy_resolver_lookup_async (GProxyResolver *resolver,
GTask *task;
gchar **proxies;
- proxies = g_test_proxy_resolver_lookup (resolver, uri, cancellable, &error);
+ proxies = g_proxy_resolver_lookup (resolver, uri, cancellable, &error);
task = g_task_new (resolver, NULL, callback, user_data);
if (proxies == NULL)
@@ -196,6 +197,56 @@ g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface)
iface->lookup_finish = g_test_proxy_resolver_lookup_finish;
}
+/****************************/
+/* Alternate GProxyResolver */
+/****************************/
+
+typedef GTestProxyResolver GTestAltProxyResolver;
+typedef GTestProxyResolverClass GTestAltProxyResolverClass;
+
+static void g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface);
+
+static GType _g_test_alt_proxy_resolver_get_type (void);
+#define g_test_alt_proxy_resolver_get_type _g_test_alt_proxy_resolver_get_type
+G_DEFINE_TYPE_WITH_CODE (GTestAltProxyResolver, g_test_alt_proxy_resolver, g_test_proxy_resolver_get_type (),
+ G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
+ g_test_alt_proxy_resolver_iface_init);
+ )
+
+static void
+g_test_alt_proxy_resolver_init (GTestProxyResolver *resolver)
+{
+}
+
+static gchar **
+g_test_alt_proxy_resolver_lookup (GProxyResolver *resolver,
+ const gchar *uri,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gchar **proxies;
+
+ proxies = g_new (gchar *, 2);
+
+ proxies[0] = g_strdup (proxy_a.uri);
+ proxies[1] = NULL;
+
+ last_proxies = g_strdupv (proxies);
+
+ return proxies;
+}
+
+static void
+g_test_alt_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
+{
+}
+
+static void
+g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface)
+{
+ iface->lookup = g_test_alt_proxy_resolver_lookup;
+}
+
/****************************************/
/* Test proxy implementation base class */
@@ -1093,6 +1144,98 @@ test_dns (gpointer fixture,
teardown_test (NULL, NULL);
}
+static void
+assert_override (GSocketConnection *conn)
+{
+ g_assert_cmpint (g_strv_length (last_proxies), ==, 1);
+ g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
+
+ if (conn)
+ g_assert_no_error (proxy_a.last_error);
+ else
+ g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+}
+
+static void
+test_override (gpointer fixture,
+ gconstpointer user_data)
+{
+ GProxyResolver *alt_resolver;
+ GSocketConnection *conn;
+ GError *error = NULL;
+ gchar *uri;
+
+ g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ());
+ alt_resolver = g_object_new (g_test_alt_proxy_resolver_get_type (), NULL);
+ g_socket_client_set_proxy_resolver (client, alt_resolver);
+ g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver);
+
+ /* Alt proxy resolver always returns Proxy A, so alpha:// should
+ * succeed, and simple:// and beta:// should fail.
+ */
+
+ /* simple */
+ uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
+ conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+ g_clear_error (&error);
+ assert_override (conn);
+ teardown_test (NULL, NULL);
+
+ g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
+ async_got_error, &error);
+ while (error == NULL)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+ g_clear_error (&error);
+ assert_override (conn);
+ g_free (uri);
+ teardown_test (NULL, NULL);
+
+ /* alpha */
+ uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
+ conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
+ g_assert_no_error (error);
+ assert_override (conn);
+ do_echo_test (conn);
+ g_clear_object (&conn);
+ teardown_test (NULL, NULL);
+
+ conn = NULL;
+ g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
+ async_got_conn, &conn);
+ while (conn == NULL)
+ g_main_context_iteration (NULL, TRUE);
+ assert_override (conn);
+ do_echo_test (conn);
+ g_clear_object (&conn);
+ g_free (uri);
+ teardown_test (NULL, NULL);
+
+ /* beta */
+ uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
+ conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+ g_clear_error (&error);
+ assert_override (conn);
+ teardown_test (NULL, NULL);
+
+ g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
+ async_got_error, &error);
+ while (error == NULL)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+ g_clear_error (&error);
+ assert_override (conn);
+ g_free (uri);
+ teardown_test (NULL, NULL);
+
+ g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver);
+ g_socket_client_set_proxy_resolver (client, NULL);
+ g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ());
+ g_object_unref (alt_resolver);
+}
+
int
main (int argc,
char *argv[])
@@ -1132,6 +1275,7 @@ main (int argc,
g_test_add_vtable ("/proxy/multiple_sync", 0, NULL, setup_test, test_multiple_sync, teardown_test);
g_test_add_vtable ("/proxy/multiple_async", 0, NULL, setup_test, test_multiple_async, teardown_test);
g_test_add_vtable ("/proxy/dns", 0, NULL, setup_test, test_dns, teardown_test);
+ g_test_add_vtable ("/proxy/override", 0, NULL, setup_test, test_override, teardown_test);
result = g_test_run();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]