From fc03ecce831cd94639df1a355f5dd8c9b8eebfae Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 10 Aug 2010 15:45:32 -0400 Subject: [PATCH] Implemented proxy_enumerate() for all Connectables This patch implements method proxy_enumerate from GSocketConnectable for all connectables (GNetworkAddress, GNetworkService, GInetSocketAddress and GUnixSocketAddress). Reviewed-by: Dan Winship --- docs/reference/gio/gio-sections.txt | 2 + gio/gio.symbols | 2 + gio/gnetworkaddress.c | 28 +- gio/gnetworkservice.c | 449 ++++++++++++++++------------ gio/gnetworkservice.h | 2 + gio/gsocketaddress.c | 42 ++- 6 files changed, 333 insertions(+), 192 deletions(-) diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index ce903a50e..d0b1982eb 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -1698,6 +1698,8 @@ g_network_service_new g_network_service_get_service g_network_service_get_protocol g_network_service_get_domain +g_network_service_get_scheme +g_network_service_set_scheme GNetworkServiceClass GNetworkServicePrivate diff --git a/gio/gio.symbols b/gio/gio.symbols index ede00ac77..835debd7c 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -1242,6 +1242,8 @@ g_network_service_get_type G_GNUC_CONST g_network_service_get_service g_network_service_get_protocol g_network_service_get_domain +g_network_service_get_scheme +g_network_service_set_scheme g_network_service_new #endif #endif diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index e2ed039bd..80a3e31a6 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -30,6 +30,7 @@ #include "ginetaddress.h" #include "ginetsocketaddress.h" #include "gnetworkingprivate.h" +#include "gproxyaddressenumerator.h" #include "gresolver.h" #include "gsimpleasyncresult.h" #include "gsocketaddressenumerator.h" @@ -82,8 +83,9 @@ static void g_network_address_get_property (GObject *object, GValue *value, GParamSpec *pspec); -static void g_network_address_connectable_iface_init (GSocketConnectableIface *iface); -static GSocketAddressEnumerator *g_network_address_connectable_enumerate (GSocketConnectable *connectable); +static void g_network_address_connectable_iface_init (GSocketConnectableIface *iface); +static GSocketAddressEnumerator *g_network_address_connectable_enumerate (GSocketConnectable *connectable); +static GSocketAddressEnumerator *g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable); G_DEFINE_TYPE_WITH_CODE (GNetworkAddress, g_network_address, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, @@ -151,6 +153,7 @@ static void g_network_address_connectable_iface_init (GSocketConnectableIface *connectable_iface) { connectable_iface->enumerate = g_network_address_connectable_enumerate; + connectable_iface->proxy_enumerate = g_network_address_connectable_proxy_enumerate; } static void @@ -909,3 +912,24 @@ g_network_address_connectable_enumerate (GSocketConnectable *connectable) return (GSocketAddressEnumerator *)addr_enum; } + +static GSocketAddressEnumerator * +g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable) +{ + GNetworkAddress *self = G_NETWORK_ADDRESS (connectable); + GSocketAddressEnumerator *proxy_enum; + gchar *uri; + + uri = g_strdup_printf ("%s://%s:%u", + self->priv->scheme ? self->priv->scheme : "none", + self->priv->hostname, self->priv->port); + + proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, + "connectable", connectable, + "uri", uri, + NULL); + + g_free (uri); + + return proxy_enum; +} diff --git a/gio/gnetworkservice.c b/gio/gnetworkservice.c index 607e45eca..dc48772d1 100644 --- a/gio/gnetworkservice.c +++ b/gio/gnetworkservice.c @@ -25,9 +25,12 @@ #include "glibintl.h" #include "gnetworkservice.h" + #include "gcancellable.h" #include "ginetaddress.h" #include "ginetsocketaddress.h" +#include "gioerror.h" +#include "gnetworkaddress.h" #include "gresolver.h" #include "gsimpleasyncresult.h" #include "gsocketaddressenumerator.h" @@ -63,7 +66,7 @@ struct _GNetworkServicePrivate { - gchar *service, *protocol, *domain; + gchar *service, *protocol, *domain, *scheme; GList *targets; }; @@ -72,6 +75,7 @@ enum { PROP_SERVICE, PROP_PROTOCOL, PROP_DOMAIN, + PROP_SCHEME }; static void g_network_service_set_property (GObject *object, @@ -83,8 +87,9 @@ static void g_network_service_get_property (GObject *object, GValue *value, GParamSpec *pspec); -static void g_network_service_connectable_iface_init (GSocketConnectableIface *iface); -static GSocketAddressEnumerator *g_network_service_connectable_enumerate (GSocketConnectable *connectable); +static void g_network_service_connectable_iface_init (GSocketConnectableIface *iface); +static GSocketAddressEnumerator *g_network_service_connectable_enumerate (GSocketConnectable *connectable); +static GSocketAddressEnumerator *g_network_service_connectable_proxy_enumerate (GSocketConnectable *connectable); G_DEFINE_TYPE_WITH_CODE (GNetworkService, g_network_service, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, @@ -98,6 +103,7 @@ g_network_service_finalize (GObject *object) g_free (srv->priv->service); g_free (srv->priv->protocol); g_free (srv->priv->domain); + g_free (srv->priv->scheme); if (srv->priv->targets) g_resolver_free_targets (srv->priv->targets); @@ -140,12 +146,21 @@ g_network_service_class_init (GNetworkServiceClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DOMAIN, + g_param_spec_string ("scheme", + P_("Scheme"), + P_("Network scheme (default is to use service)"), + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + } static void g_network_service_connectable_iface_init (GSocketConnectableIface *connectable_iface) { connectable_iface->enumerate = g_network_service_connectable_enumerate; + connectable_iface->proxy_enumerate = g_network_service_connectable_proxy_enumerate; } static void @@ -177,6 +192,10 @@ g_network_service_set_property (GObject *object, srv->priv->domain = g_value_dup_string (value); break; + case PROP_SCHEME: + g_network_service_set_scheme (srv, g_value_get_string (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -205,6 +224,10 @@ g_network_service_get_property (GObject *object, g_value_set_string (value, g_network_service_get_domain (srv)); break; + case PROP_SCHEME: + g_value_set_string (value, g_network_service_get_scheme (srv)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -292,6 +315,50 @@ g_network_service_get_domain (GNetworkService *srv) return srv->priv->domain; } +/** + * g_network_service_get_scheme: + * @srv: a #GNetworkService + * + * Get's the URI scheme used to resolve proxies. By default, the service name + * is used as scheme. + * + * Return value: @srv's scheme name + * + * Since: 2.26 + */ +const gchar * +g_network_service_get_scheme (GNetworkService *srv) +{ + g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL); + + if (srv->priv->scheme) + return srv->priv->scheme; + else + return srv->priv->service; +} + +/** + * g_network_service_set_scheme: + * @srv: a #GNetworkService + * + * Set's the URI scheme used to resolve proxies. By default, the service name + * is used as scheme. + * + * Since: 2.26 + */ +void +g_network_service_set_scheme (GNetworkService *srv, const gchar *scheme) +{ + g_return_if_fail (G_IS_NETWORK_SERVICE (srv)); + + if (srv->priv->scheme) + g_free (srv->priv->scheme); + srv->priv->scheme = g_strdup (scheme); + + g_object_notify (G_OBJECT (srv), "scheme"); +} + + #define G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR (_g_network_service_address_enumerator_get_type ()) #define G_NETWORK_SERVICE_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, GNetworkServiceAddressEnumerator)) @@ -300,7 +367,9 @@ typedef struct { GResolver *resolver; GNetworkService *srv; - GList *addrs, *a, *t; + GSocketAddressEnumerator *addr_enum; + GList *t; + gboolean use_proxy; GError *error; @@ -316,29 +385,6 @@ typedef struct { G_DEFINE_TYPE (GNetworkServiceAddressEnumerator, _g_network_service_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR) -static void -g_network_service_address_enumerator_finalize (GObject *object) -{ - GNetworkServiceAddressEnumerator *srv_enum = - G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (object); - - g_object_unref (srv_enum->srv); - if (srv_enum->addrs) - { - while (srv_enum->a) - { - g_object_unref (srv_enum->a->data); - srv_enum->a = srv_enum->a->next; - } - g_list_free (srv_enum->addrs); - } - g_object_unref (srv_enum->resolver); - if (srv_enum->error) - g_error_free (srv_enum->error); - - G_OBJECT_CLASS (_g_network_service_address_enumerator_parent_class)->finalize (object); -} - static GSocketAddress * g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator, GCancellable *cancellable, @@ -346,8 +392,7 @@ g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator { GNetworkServiceAddressEnumerator *srv_enum = G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator); - GSrvTarget *target; - GSocketAddress *sockaddr; + GSocketAddress *ret = NULL; /* If we haven't yet resolved srv, do that */ if (!srv_enum->srv->priv->targets) @@ -362,91 +407,99 @@ g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator if (!targets) return NULL; - if (!srv_enum->srv->priv->targets) - srv_enum->srv->priv->targets = targets; + srv_enum->srv->priv->targets = targets; srv_enum->t = srv_enum->srv->priv->targets; } - /* Make sure we have a set of resolved addresses for the current - * target. When resolving the first target, we save the GError, if - * any. If any later target succeeds, we'll free the earlier error, - * but if we get to the last target without any of them resolving, - * we return that initial error. - */ + /* Delegate to GNetworkAddress */ do { - /* Return if we're out of targets. */ - if (!srv_enum->t) + if (srv_enum->addr_enum == NULL && srv_enum->t) { - if (srv_enum->error) + GError *error = NULL; + gchar *uri; + gchar *hostname; + GSocketConnectable *addr; + GSrvTarget *target = srv_enum->t->data; + + srv_enum->t = g_list_next (srv_enum->t); + + hostname = g_hostname_to_ascii (g_srv_target_get_hostname (target)); + + if (hostname == NULL) { - g_propagate_error (error, srv_enum->error); - srv_enum->error = NULL; + if (srv_enum->error == NULL) + srv_enum->error = + g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Received invalid hostname '%s' from GSrvTarget", + g_srv_target_get_hostname (target)); + continue; } - return NULL; - } - target = srv_enum->t->data; - /* If we haven't resolved the addrs for the current target, do that */ - if (!srv_enum->addrs) - { - GError **error_p; + uri = g_strdup_printf ("%s://%s:%u", + g_network_service_get_scheme (srv_enum->srv), + hostname, + g_srv_target_get_port (target)); + g_free (hostname); - error_p = (srv_enum->t == srv_enum->srv->priv->targets) ? &srv_enum->error : NULL; - srv_enum->addrs = g_resolver_lookup_by_name (srv_enum->resolver, - g_srv_target_get_hostname (target), - cancellable, error_p); - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return NULL; + addr = g_network_address_parse_uri (uri, + g_srv_target_get_port (target), + &error); + g_free (uri); - if (srv_enum->addrs) + if (addr == NULL) { - srv_enum->a = srv_enum->addrs; - if (srv_enum->error) - { - g_error_free (srv_enum->error); - srv_enum->error = NULL; - } + if (srv_enum->error == NULL) + srv_enum->error = error; + continue; } + + if (srv_enum->use_proxy) + srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr); else + srv_enum->addr_enum = g_socket_connectable_enumerate (addr); + g_object_unref (addr); + } + + if (srv_enum->addr_enum) + { + GError *error = NULL; + + ret = g_socket_address_enumerator_next (srv_enum->addr_enum, + cancellable, + &error); + + if (error) { - /* Try the next target */ - srv_enum->t = srv_enum->t->next; + if (srv_enum->error == NULL) + srv_enum->error = error; + else + g_error_free (error); + + g_object_unref (srv_enum->addr_enum); + srv_enum->addr_enum = NULL; } } } - while (!srv_enum->addrs); + while (srv_enum->addr_enum == NULL && srv_enum->t); - /* Return the next address for this target. If it's the last one, - * advance the target counter. - */ - sockaddr = g_inet_socket_address_new (srv_enum->a->data, - g_srv_target_get_port (target)); - g_object_unref (srv_enum->a->data); - srv_enum->a = srv_enum->a->next; - - if (!srv_enum->a) + if (ret == NULL && srv_enum->error) { - g_list_free (srv_enum->addrs); - srv_enum->addrs = NULL; - srv_enum->t = srv_enum->t->next; + g_propagate_error (error, srv_enum->error); + srv_enum->error = NULL; } - return sockaddr; + return ret; } static void next_async_resolved_targets (GObject *source_object, GAsyncResult *result, gpointer user_data); static void next_async_have_targets (GNetworkServiceAddressEnumerator *srv_enum); -static void next_async_resolved_addresses (GObject *source_object, +static void next_async_have_address (GObject *source_object, GAsyncResult *result, gpointer user_data); -static void next_async_have_addresses (GNetworkServiceAddressEnumerator *srv_enum); -/* The async version is basically the same as the sync, except we have - * to split it into multiple functions. - */ static void g_network_service_address_enumerator_next_async (GSocketAddressEnumerator *enumerator, GCancellable *cancellable, @@ -461,7 +514,9 @@ g_network_service_address_enumerator_next_async (GSocketAddressEnumerator *enum srv_enum->result = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_network_service_address_enumerator_next_async); - srv_enum->cancellable = cancellable; + + if (cancellable) + srv_enum->cancellable = g_object_ref (cancellable); /* If we haven't yet resolved srv, do that */ if (!srv_enum->srv->priv->targets) @@ -484,137 +539,113 @@ next_async_resolved_targets (GObject *source_object, gpointer user_data) { GNetworkServiceAddressEnumerator *srv_enum = user_data; - GList *targets; GError *error = NULL; - targets = g_resolver_lookup_service_finish (srv_enum->resolver, result, &error); - if (!srv_enum->srv->priv->targets) + srv_enum->srv->priv->targets = + g_resolver_lookup_service_finish (srv_enum->resolver, result, &error); + + if (error) { - if (error) - { - GSimpleAsyncResult *simple = srv_enum->result; + GSimpleAsyncResult *simple = srv_enum->result; - srv_enum->result = NULL; - g_simple_async_result_set_from_error (simple, error); - g_error_free (error); - g_simple_async_result_complete (simple); - g_object_unref (simple); - return; - } - - srv_enum->srv->priv->targets = targets; - srv_enum->t = srv_enum->srv->priv->targets; + srv_enum->result = NULL; + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + } + else + { + srv_enum->t = srv_enum->srv->priv->targets; + next_async_have_targets (srv_enum); } - - next_async_have_targets (srv_enum); } static void next_async_have_targets (GNetworkServiceAddressEnumerator *srv_enum) { - GSrvTarget *target; - - /* Get the current target, check if we're already done. */ - if (!srv_enum->t) + /* Delegate to GNetworkAddress */ + if (srv_enum->addr_enum == NULL && srv_enum->t) { + GSocketConnectable *addr; + GSrvTarget *target = srv_enum->t->data; + + srv_enum->t = g_list_next (srv_enum->t); + addr = g_network_address_new (g_srv_target_get_hostname (target), + (guint16) g_srv_target_get_port (target)); + + if (srv_enum->use_proxy) + srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr); + else + srv_enum->addr_enum = g_socket_connectable_enumerate (addr); + + g_object_unref (addr); + } + + if (srv_enum->addr_enum) + { + g_socket_address_enumerator_next_async (srv_enum->addr_enum, + srv_enum->cancellable, + next_async_have_address, + srv_enum); + } + else + { + GSimpleAsyncResult *simple = srv_enum->result; + srv_enum->result = NULL; + if (srv_enum->error) { - g_simple_async_result_set_from_error (srv_enum->result, srv_enum->error); + g_simple_async_result_set_from_error (simple, srv_enum->error); g_error_free (srv_enum->error); srv_enum->error = NULL; } - g_simple_async_result_complete_in_idle (srv_enum->result); - g_object_unref (srv_enum->result); - srv_enum->result = NULL; - return; - } - target = srv_enum->t->data; - /* If we haven't resolved the addrs for the current target, do that */ - if (!srv_enum->addrs) - { - g_resolver_lookup_by_name_async (srv_enum->resolver, - g_srv_target_get_hostname (target), - srv_enum->cancellable, - next_async_resolved_addresses, - srv_enum); + g_simple_async_result_complete (simple); + g_object_unref (simple); } - else - next_async_have_addresses (srv_enum); } static void -next_async_resolved_addresses (GObject *source_object, - GAsyncResult *result, - gpointer user_data) +next_async_have_address (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { GNetworkServiceAddressEnumerator *srv_enum = user_data; + GSocketAddress *address; GError *error = NULL; + + address = g_socket_address_enumerator_next_finish (srv_enum->addr_enum, + result, + &error); - srv_enum->addrs = g_resolver_lookup_by_name_finish (srv_enum->resolver, result, &error); - if (srv_enum->addrs) + if (error) { - srv_enum->a = srv_enum->addrs; - if (srv_enum->error) - { - g_error_free (srv_enum->error); - srv_enum->error = NULL; - } - next_async_have_addresses (srv_enum); + if (srv_enum->error == NULL) + srv_enum->error = error; + else + g_error_free (error); + + g_object_unref (srv_enum->addr_enum); + srv_enum->addr_enum = NULL; + + next_async_have_targets (srv_enum); } else { - if (g_cancellable_is_cancelled (srv_enum->cancellable)) - { - GSimpleAsyncResult *simple = srv_enum->result; + GSimpleAsyncResult *simple = srv_enum->result; - srv_enum->result = NULL; - g_simple_async_result_set_from_error (srv_enum->result, error); - g_error_free (error); - g_simple_async_result_complete (simple); - g_object_unref (simple); - } - else - { - if (srv_enum->t == srv_enum->srv->priv->targets) - srv_enum->error = error; - else - g_error_free (error); + srv_enum->result = NULL; - /* Try the next target */ - srv_enum->t = srv_enum->t->next; - next_async_have_targets (srv_enum); - } + if (address) + g_simple_async_result_set_op_res_gpointer (simple, + address, g_object_unref); + + g_simple_async_result_complete (simple); + g_object_unref (simple); } } -static void -next_async_have_addresses (GNetworkServiceAddressEnumerator *srv_enum) -{ - GSocketAddress *sockaddr; - GSimpleAsyncResult *simple = srv_enum->result; - - /* Return the next address for this target. If it's the last one, - * advance the target counter. - */ - sockaddr = g_inet_socket_address_new (srv_enum->a->data, - g_srv_target_get_port (srv_enum->t->data)); - g_object_unref (srv_enum->a->data); - - srv_enum->a = srv_enum->a->next; - if (!srv_enum->a) - { - g_list_free (srv_enum->addrs); - srv_enum->addrs = NULL; - srv_enum->t = srv_enum->t->next; - } - - srv_enum->result = NULL; - g_simple_async_result_set_op_res_gpointer (simple, sockaddr, NULL); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); -} - static GSocketAddress * g_network_service_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator, GAsyncResult *result, @@ -636,15 +667,43 @@ _g_network_service_address_enumerator_init (GNetworkServiceAddressEnumerator *en } static void -_g_network_service_address_enumerator_class_init (GNetworkServiceAddressEnumeratorClass *addrenum_class) +g_network_service_address_enumerator_finalize (GObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (addrenum_class); - GSocketAddressEnumeratorClass *enumerator_class = - G_SOCKET_ADDRESS_ENUMERATOR_CLASS (addrenum_class); + GNetworkServiceAddressEnumerator *srv_enum = + G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (object); - enumerator_class->next = g_network_service_address_enumerator_next; - enumerator_class->next_async = g_network_service_address_enumerator_next_async; + if (srv_enum->srv) + g_object_unref (srv_enum->srv); + + if (srv_enum->addr_enum) + g_object_unref (srv_enum->addr_enum); + + if (srv_enum->resolver) + g_object_unref (srv_enum->resolver); + + if (srv_enum->result) + g_object_unref (srv_enum->result); + + if (srv_enum->cancellable) + g_object_unref (srv_enum->cancellable); + + if (srv_enum->error) + g_error_free (srv_enum->error); + + G_OBJECT_CLASS (_g_network_service_address_enumerator_parent_class)->finalize (object); +} + +static void +_g_network_service_address_enumerator_class_init (GNetworkServiceAddressEnumeratorClass *srvenum_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (srvenum_class); + GSocketAddressEnumeratorClass *enumerator_class = + G_SOCKET_ADDRESS_ENUMERATOR_CLASS (srvenum_class); + + enumerator_class->next = g_network_service_address_enumerator_next; + enumerator_class->next_async = g_network_service_address_enumerator_next_async; enumerator_class->next_finish = g_network_service_address_enumerator_next_finish; + object_class->finalize = g_network_service_address_enumerator_finalize; } @@ -656,6 +715,20 @@ g_network_service_connectable_enumerate (GSocketConnectable *connectable) srv_enum = g_object_new (G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, NULL); srv_enum->srv = g_object_ref (connectable); srv_enum->resolver = g_resolver_get_default (); + srv_enum->use_proxy = FALSE; - return (GSocketAddressEnumerator *)srv_enum; + return G_SOCKET_ADDRESS_ENUMERATOR (srv_enum); +} + +static GSocketAddressEnumerator * +g_network_service_connectable_proxy_enumerate (GSocketConnectable *connectable) +{ + GSocketAddressEnumerator *addr_enum; + GNetworkServiceAddressEnumerator *srv_enum; + + addr_enum = g_network_service_connectable_enumerate (connectable); + srv_enum = G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (addr_enum); + srv_enum->use_proxy = TRUE; + + return addr_enum; } diff --git a/gio/gnetworkservice.h b/gio/gnetworkservice.h index b1a754ba7..1f6dbea86 100644 --- a/gio/gnetworkservice.h +++ b/gio/gnetworkservice.h @@ -62,6 +62,8 @@ GSocketConnectable *g_network_service_new (const gchar *service, const gchar *g_network_service_get_service (GNetworkService *srv); const gchar *g_network_service_get_protocol (GNetworkService *srv); const gchar *g_network_service_get_domain (GNetworkService *srv); +const gchar *g_network_service_get_scheme (GNetworkService *srv); +void g_network_service_set_scheme (GNetworkService *srv, const gchar *scheme); G_END_DECLS diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c index 6511e57c3..95fbea944 100644 --- a/gio/gsocketaddress.c +++ b/gio/gsocketaddress.c @@ -28,6 +28,7 @@ #include "ginetaddress.h" #include "ginetsocketaddress.h" #include "gnetworkingprivate.h" +#include "gproxyaddressenumerator.h" #include "gsocketaddressenumerator.h" #include "gsocketconnectable.h" #include "glibintl.h" @@ -62,8 +63,9 @@ enum PROP_FAMILY }; -static void g_socket_address_connectable_iface_init (GSocketConnectableIface *iface); -static GSocketAddressEnumerator *g_socket_address_connectable_enumerate (GSocketConnectable *connectable); +static void g_socket_address_connectable_iface_init (GSocketConnectableIface *iface); +static GSocketAddressEnumerator *g_socket_address_connectable_enumerate (GSocketConnectable *connectable); +static GSocketAddressEnumerator *g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable); G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GSocketAddress, g_socket_address, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, @@ -125,6 +127,7 @@ static void g_socket_address_connectable_iface_init (GSocketConnectableIface *connectable_iface) { connectable_iface->enumerate = g_socket_address_connectable_enumerate; + connectable_iface->proxy_enumerate = g_socket_address_connectable_proxy_enumerate; } static void @@ -351,3 +354,38 @@ g_socket_address_connectable_enumerate (GSocketConnectable *connectable) return (GSocketAddressEnumerator *)sockaddr_enum; } + +static GSocketAddressEnumerator * +g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable) +{ + GSocketAddressEnumerator *addr_enum = NULL; + + if (G_IS_INET_SOCKET_ADDRESS (connectable) && + !G_IS_PROXY_ADDRESS (connectable)) + { + GInetAddress *addr; + guint port; + gchar *uri; + gchar *ip; + + g_object_get (connectable, "address", &addr, "port", &port, NULL); + + ip = g_inet_address_to_string (addr); + uri = g_strdup_printf ("none://%s:%u", ip, port); + + addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, + "connectable", connectable, + "uri", uri, + NULL); + + g_object_unref (addr); + g_free (ip); + g_free (uri); + } + else + { + addr_enum = g_socket_address_connectable_enumerate (connectable); + } + + return addr_enum; +}