From a7e0e8fc0852255d430daa90e7345db67a2a9594 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 10 Aug 2010 15:25:11 -0400 Subject: [PATCH] Adding GProxyAddressEnumerator class An implementation of GSocketAddressEnumerator that handles proxy enumeration. This class is mainly usefull for Connectables implementation such as NetworkService, NetworkAddress and SocketAddress to handle proxies. Reviewed-by: Dan Winship --- docs/reference/gio/gio-sections.txt | 13 +- docs/reference/gio/gio.types | 1 + gio/Makefile.am | 2 + gio/gio.h | 1 + gio/gio.symbols | 6 + gio/giotypes.h | 1 + gio/gproxyaddressenumerator.c | 728 ++++++++++++++++++++++++++++++++++++ gio/gproxyaddressenumerator.h | 73 ++++ 8 files changed, 824 insertions(+), 1 deletion(-) create mode 100644 gio/gproxyaddressenumerator.c create mode 100644 gio/gproxyaddressenumerator.h diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 9bcb5bd..e3740c5 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -1638,6 +1638,8 @@ GSocketAddressEnumerator g_socket_address_enumerator_next g_socket_address_enumerator_next_async g_socket_address_enumerator_next_finish + +GProxyAddressEnumerator G_IS_SOCKET_CONNECTABLE G_SOCKET_CONNECTABLE @@ -1650,7 +1652,16 @@ G_SOCKET_ADDRESS_ENUMERATOR G_SOCKET_ADDRESS_ENUMERATOR_CLASS G_SOCKET_ADDRESS_ENUMERATOR_GET_CLASS G_TYPE_SOCKET_ADDRESS_ENUMERATOR - +GProxyAddressEnumeratorClass +G_IS_PROXY_ADDRESS_ENUMERATOR +G_IS_PROXY_ADDRESS_ENUMERATOR_CLASS +G_PROXY_ADDRESS_ENUMERATOR +G_PROXY_ADDRESS_ENUMERATOR_CLASS +G_PROXY_ADDRESS_ENUMERATOR_GET_CLASS +G_TYPE_PROXY_ADDRESS_ENUMERATOR + +GProxyAddressEnumeratorPrivate +g_proxy_address_enumerator_get_type g_socket_address_enumerator_get_type g_socket_connectable_get_type diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types index 3ca12f2..1b0a4da 100644 --- a/docs/reference/gio/gio.types +++ b/docs/reference/gio/gio.types @@ -75,6 +75,7 @@ g_output_stream_get_type g_output_stream_splice_flags_get_type g_password_save_get_type g_permission_get_type +g_proxy_address_enumerator_get_type g_proxy_address_get_type g_proxy_get_type g_proxy_resolver_get_type diff --git a/gio/Makefile.am b/gio/Makefile.am index 9774a12..30cce03 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -352,6 +352,7 @@ libgio_2_0_la_SOURCES = \ gsocketoutputstream.h \ gproxy.c \ gproxyaddress.c \ + gproxyaddressenumerator.c \ gsocketservice.c \ gsrvtarget.c \ gtcpconnection.c \ @@ -485,6 +486,7 @@ gio_headers = \ gpermission.h \ gproxyaddress.h \ gproxy.h \ + gproxyaddressenumerator.h \ gproxyresolver.h \ gresolver.h \ gseekable.h \ diff --git a/gio/gio.h b/gio/gio.h index 1e265a2..ad16d90 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -94,6 +94,7 @@ #include #include #include +#include #include #include #include diff --git a/gio/gio.symbols b/gio/gio.symbols index 30a5a61..6b4e57a 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -1162,6 +1162,12 @@ g_proxy_address_get_password #endif #endif +#if IN_HEADER(__G_PROXY_ADDRESS_ENUMERATOR_H__) +#if IN_FILE(__G_PROXY_ADDRESS_ENUMERATOR_C__) +g_proxy_address_enumerator_get_type +#endif +#endif + #if IN_HEADER(__G_RESOLVER_H__) #if IN_FILE(__G_RESOLVER_C__) g_resolver_error_quark diff --git a/gio/giotypes.h b/gio/giotypes.h index 2240b8f..65788e3 100644 --- a/gio/giotypes.h +++ b/gio/giotypes.h @@ -208,6 +208,7 @@ typedef struct _GVfs GVfs; /* Dummy typedef */ typedef struct _GProxyResolver GProxyResolver; typedef struct _GProxy GProxy; typedef struct _GProxyAddress GProxyAddress; +typedef struct _GProxyAddressEnumerator GProxyAddressEnumerator; /** * GVolume: diff --git a/gio/gproxyaddressenumerator.c b/gio/gproxyaddressenumerator.c new file mode 100644 index 0000000..7630897 --- /dev/null +++ b/gio/gproxyaddressenumerator.c @@ -0,0 +1,728 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 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. + * + * Author: Nicolas Dufresne + */ + +#include "config.h" +#include "gproxyaddressenumerator.h" + +#include + +#include "gasyncresult.h" +#include "ginetaddress.h" +#include "glibintl.h" +#include "gnetworkaddress.h" +#include "gnetworkingprivate.h" +#include "gproxy.h" +#include "gproxyaddress.h" +#include "gproxyresolver.h" +#include "gsimpleasyncresult.h" +#include "gresolver.h" +#include "gsocketaddress.h" +#include "gsocketaddressenumerator.h" +#include "gsocketconnectable.h" + +G_DEFINE_TYPE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR); + +#define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv) + +enum +{ + PROP_0, + PROP_URI, + PROP_CONNECTABLE +}; + +struct _GProxyAddressEnumeratorPrivate +{ + /* Destination address */ + GSocketConnectable *connectable; + gchar *dest_uri; + gchar *dest_hostname; + guint16 dest_port; + GList *dest_ips; + + /* Proxy enumeration */ + gchar **proxies; + gchar **next_proxy; + GSocketAddressEnumerator *addr_enum; + GSocketAddress *proxy_address; + gchar *proxy_type; + gchar *proxy_username; + gchar *proxy_password; + gboolean supports_hostname; + GList *next_dest_ip; + + /* Async attributes */ + GSimpleAsyncResult *simple; + GCancellable *cancellable; +}; + +static void +save_userinfo (GProxyAddressEnumeratorPrivate *priv, + const gchar *proxy) +{ + gchar *userinfo; + + if (priv->proxy_username) + { + g_free (priv->proxy_username); + priv->proxy_username = NULL; + } + + if (priv->proxy_password) + { + g_free (priv->proxy_password); + priv->proxy_password = NULL; + } + + if (_g_uri_parse_authority (proxy, NULL, NULL, &userinfo)) + { + if (userinfo) + { + gchar **split = g_strsplit (userinfo, ":", 2); + + if (split[0] != NULL) + { + priv->proxy_username = g_uri_unescape_string (split[0], NULL); + if (split[1] != NULL) + priv->proxy_password = g_uri_unescape_string (split[1], NULL); + } + + g_strfreev (split); + g_free (userinfo); + } + } +} + +static void +next_enumerator (GProxyAddressEnumeratorPrivate *priv) +{ + if (priv->proxy_address) + return; + + while (priv->addr_enum == NULL && *priv->next_proxy) + { + GSocketConnectable *connectable = NULL; + const gchar *proxy_uri; + GProxy *proxy; + + proxy_uri = *priv->next_proxy++; + g_free (priv->proxy_type); + priv->proxy_type = g_uri_parse_scheme (proxy_uri); + + if (priv->proxy_type == NULL) + continue; + + /* Assumes hostnames are supported for unkown protocols */ + priv->supports_hostname = TRUE; + proxy = g_proxy_get_default_for_protocol (priv->proxy_type); + if (proxy) + { + priv->supports_hostname = g_proxy_supports_hostname (proxy); + g_object_unref (proxy); + } + + if (strcmp ("direct", priv->proxy_type) == 0) + { + if (priv->connectable) + connectable = g_object_ref (priv->connectable); + else + connectable = g_network_address_new (priv->dest_hostname, + priv->dest_port); + } + else + { + GError *error = NULL; + + connectable = g_network_address_parse_uri (proxy_uri, 0, &error); + + if (error) + { + g_warning ("Invalid proxy URI '%s': %s", + proxy_uri, error->message); + g_error_free (error); + } + + save_userinfo (priv, proxy_uri); + } + + if (connectable) + { + priv->addr_enum = g_socket_connectable_enumerate (connectable); + g_object_unref (connectable); + } + } +} + +static GSocketAddress * +g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator, + GCancellable *cancellable, + GError **error) +{ + GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator); + GSocketAddress *result = NULL; + GError *first_error = NULL; + + if (priv->proxies == NULL) + { + GProxyResolver *resolver = g_proxy_resolver_get_default (); + priv->proxies = g_proxy_resolver_lookup (resolver, + priv->dest_uri, + cancellable, + error); + priv->next_proxy = priv->proxies; + + if (priv->proxies == NULL) + return NULL; + } + + while (result == NULL && (*priv->next_proxy || priv->addr_enum)) + { + gchar *dest_hostname; + GInetSocketAddress *inetsaddr; + GInetAddress *inetaddr; + guint16 port; + + next_enumerator (priv); + + if (!priv->addr_enum) + continue; + + if (priv->proxy_address == NULL) + { + priv->proxy_address = g_socket_address_enumerator_next ( + priv->addr_enum, + cancellable, + first_error ? NULL : &first_error); + } + + if (priv->proxy_address == NULL) + { + g_object_unref (priv->addr_enum); + priv->addr_enum = NULL; + + if (priv->dest_ips) + { + g_resolver_free_addresses (priv->dest_ips); + priv->dest_ips = NULL; + } + + continue; + } + + if (strcmp ("direct", priv->proxy_type) == 0) + { + result = priv->proxy_address; + priv->proxy_address = NULL; + continue; + } + + if (!priv->supports_hostname) + { + GInetAddress *dest_ip; + + if (!priv->dest_ips) + { + GResolver *resolver; + + resolver = g_resolver_get_default(); + priv->dest_ips = g_resolver_lookup_by_name (resolver, + priv->dest_hostname, + cancellable, + first_error ? NULL : &first_error); + g_object_unref (resolver); + + if (!priv->dest_ips) + { + g_object_unref (priv->proxy_address); + priv->proxy_address = NULL; + continue; + } + } + + if (!priv->next_dest_ip) + priv->next_dest_ip = priv->dest_ips; + + dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data); + dest_hostname = g_inet_address_to_string (dest_ip); + + priv->next_dest_ip = g_list_next (priv->next_dest_ip); + } + else + { + dest_hostname = g_strdup (priv->dest_hostname); + } + + + g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address), + NULL); + + inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); + inetaddr = g_inet_socket_address_get_address (inetsaddr); + port = g_inet_socket_address_get_port (inetsaddr); + + result = g_proxy_address_new (inetaddr, port, + priv->proxy_type, + dest_hostname, priv->dest_port, + priv->proxy_username, + priv->proxy_password); + + g_free (dest_hostname); + + if (priv->supports_hostname || priv->next_dest_ip == NULL) + { + g_object_unref (priv->proxy_address); + priv->proxy_address = NULL; + } + } + + if (result == NULL && first_error) + g_propagate_error (error, first_error); + else if (first_error) + g_error_free (first_error); + + return result; +} + + + +static void +complete_async (GProxyAddressEnumeratorPrivate *priv) +{ + GSimpleAsyncResult *simple = priv->simple; + + if (priv->cancellable) + { + g_object_unref (priv->cancellable); + priv->cancellable = NULL; + } + + priv->simple = NULL; + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +save_result (GProxyAddressEnumeratorPrivate *priv) +{ + GSocketAddress *result; + + if (strcmp ("direct", priv->proxy_type) == 0) + { + result = priv->proxy_address; + priv->proxy_address = NULL; + } + else + { + gchar *dest_hostname; + GInetSocketAddress *inetsaddr; + GInetAddress *inetaddr; + guint16 port; + + if (!priv->supports_hostname) + { + GInetAddress *dest_ip; + + if (!priv->next_dest_ip) + priv->next_dest_ip = priv->dest_ips; + + dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data); + dest_hostname = g_inet_address_to_string (dest_ip); + + priv->next_dest_ip = g_list_next (priv->next_dest_ip); + } + else + { + dest_hostname = g_strdup (priv->dest_hostname); + } + + g_return_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address)); + + inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); + inetaddr = g_inet_socket_address_get_address (inetsaddr); + port = g_inet_socket_address_get_port (inetsaddr); + + result = g_proxy_address_new (inetaddr, port, + priv->proxy_type, + dest_hostname, priv->dest_port, + priv->proxy_username, + priv->proxy_password); + + g_free (dest_hostname); + + if (priv->supports_hostname || priv->next_dest_ip == NULL) + { + g_object_unref (priv->proxy_address); + priv->proxy_address = NULL; + } + } + + g_simple_async_result_set_op_res_gpointer (priv->simple, + result, + g_object_unref); +} + +static void +dest_hostname_lookup_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GProxyAddressEnumeratorPrivate *priv = user_data; + GSimpleAsyncResult *simple = priv->simple; + + priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object), + result, + &error); + if (priv->dest_ips) + { + save_result (priv); + } + else + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + + complete_async (priv); +} + +static void +address_enumerate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GProxyAddressEnumeratorPrivate *priv = user_data; + GSimpleAsyncResult *simple = priv->simple; + + priv->proxy_address = + g_socket_address_enumerator_next_finish (priv->addr_enum, + result, + &error); + if (priv->proxy_address) + { + if (!priv->supports_hostname && !priv->dest_ips) + { + GResolver *resolver; + resolver = g_resolver_get_default(); + g_resolver_lookup_by_name_async (resolver, + priv->dest_hostname, + priv->cancellable, + dest_hostname_lookup_cb, + priv); + g_object_unref (resolver); + return; + } + + save_result (priv); + } + else if (*priv->next_proxy) + { + g_object_unref (priv->addr_enum); + priv->addr_enum = NULL; + + if (priv->dest_ips) + { + g_resolver_free_addresses (priv->dest_ips); + priv->dest_ips = NULL; + } + + next_enumerator (priv); + + if (priv->addr_enum) + { + g_socket_address_enumerator_next_async (priv->addr_enum, + priv->cancellable, + address_enumerate_cb, + priv); + return; + } + } + + if (error) + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + + complete_async (priv); +} + +static void +proxy_lookup_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GProxyAddressEnumeratorPrivate *priv = user_data; + GSimpleAsyncResult *simple = priv->simple; + + priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object), + result, + &error); + priv->next_proxy = priv->proxies; + + if (error) + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + else + { + next_enumerator (priv); + if (priv->addr_enum) + { + g_socket_address_enumerator_next_async (priv->addr_enum, + priv->cancellable, + address_enumerate_cb, + priv); + return; + } + } + + complete_async (priv); +} + +static void +g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator); + + g_return_if_fail (priv->simple == NULL); + g_return_if_fail (priv->cancellable == NULL); + + priv->simple = g_simple_async_result_new (G_OBJECT (enumerator), + callback, user_data, + g_proxy_address_enumerator_next_async); + + priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + if (priv->proxies == NULL) + { + GProxyResolver *resolver = g_proxy_resolver_get_default (); + g_proxy_resolver_lookup_async (resolver, + priv->dest_uri, + cancellable, + proxy_lookup_cb, + priv); + return; + } + + if (priv->addr_enum) + { + if (priv->proxy_address) + { + save_result (priv); + } + else + { + g_socket_address_enumerator_next_async (priv->addr_enum, + cancellable, + address_enumerate_cb, + priv); + return; + } + } + + g_simple_async_result_complete_in_idle (priv->simple); + + g_object_unref (priv->simple); + priv->simple = NULL; + + if (priv->cancellable) + { + g_object_unref (priv->cancellable); + priv->cancellable = NULL; + } +} + +static GSocketAddress * +g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + GSocketAddress *address; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + address = g_simple_async_result_get_op_res_gpointer (simple); + if (address) + g_object_ref (address); + + return address; +} + +static void +g_proxy_address_enumerator_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object); + switch (property_id) + { + case PROP_URI: + g_value_set_string (value, priv->dest_uri); + break; + + case PROP_CONNECTABLE: + g_value_set_object (value, priv->connectable); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +g_proxy_address_enumerator_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object); + switch (property_id) + { + case PROP_URI: + { + const gchar *uri; + + g_free (priv->dest_hostname); + priv->dest_hostname = NULL; + priv->dest_port = 0; + + g_free (priv->dest_uri); + priv->dest_uri = NULL; + + uri = g_value_get_string (value); + + if (uri) + { + GSocketConnectable *conn; + + conn = g_network_address_parse_uri (uri, 0, NULL); + if (conn) + { + priv->dest_uri = g_strdup (uri); + + g_object_get (conn, + "hostname", &priv->dest_hostname, + "port", &priv->dest_port, + NULL); + + g_object_unref (conn); + } + else + g_warning ("Invalid URI '%s'", uri); + } + + break; + } + + case PROP_CONNECTABLE: + priv->connectable = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +g_proxy_address_enumerator_finalize (GObject *object) +{ + GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object); + + if (priv->connectable) + g_object_unref (priv->connectable); + + g_free (priv->dest_uri); + g_free (priv->dest_hostname); + + if (priv->dest_ips) + g_resolver_free_addresses (priv->dest_ips); + + g_strfreev (priv->proxies); + + if (priv->addr_enum) + g_object_unref (priv->addr_enum); + + g_free (priv->proxy_type); + g_free (priv->proxy_username); + g_free (priv->proxy_password); + + if (priv->cancellable) + g_object_unref (priv->cancellable); + + G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object); +} + +static void +g_proxy_address_enumerator_init (GProxyAddressEnumerator *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + G_TYPE_PROXY_ADDRESS_ENUMERATOR, + GProxyAddressEnumeratorPrivate); +} + +static void +g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class); + GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class); + + g_type_class_add_private (enumerator_class, + sizeof (GProxyAddressEnumeratorPrivate)); + + object_class->set_property = g_proxy_address_enumerator_set_property; + object_class->get_property = g_proxy_address_enumerator_get_property; + object_class->finalize = g_proxy_address_enumerator_finalize; + + enumerator_class->next = g_proxy_address_enumerator_next; + enumerator_class->next_async = g_proxy_address_enumerator_next_async; + enumerator_class->next_finish = g_proxy_address_enumerator_next_finish; + + g_object_class_install_property (object_class, + PROP_URI, + g_param_spec_string ("uri", + P_("URI"), + P_("The destination URI, use none:// for generic socket"), + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_CONNECTABLE, + g_param_spec_object ("connectable", + P_("Connectable"), + P_("The connectable being enumerated."), + G_TYPE_SOCKET_CONNECTABLE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} diff --git a/gio/gproxyaddressenumerator.h b/gio/gproxyaddressenumerator.h new file mode 100644 index 0000000..2fb1104 --- /dev/null +++ b/gio/gproxyaddressenumerator.h @@ -0,0 +1,73 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 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. + * + * Author: Nicolas Dufresne + */ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __G_PROXY_ADDRESS_ENUMERATOR_H__ +#define __G_PROXY_ADDRESS_ENUMERATOR_H__ + +#include + +G_BEGIN_DECLS + +#define G_TYPE_PROXY_ADDRESS_ENUMERATOR (g_proxy_address_enumerator_get_type ()) +#define G_PROXY_ADDRESS_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_ADDRESS_ENUMERATOR, GProxyAddressEnumerator)) +#define G_PROXY_ADDRESS_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_ADDRESS_ENUMERATOR, GProxyAddressEnumeratorClass)) +#define G_IS_PROXY_ADDRESS_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_ADDRESS_ENUMERATOR)) +#define G_IS_PROXY_ADDRESS_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_ADDRESS_ENUMERATOR)) +#define G_PROXY_ADDRESS_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_PROXY_ADDRESS_ENUMERATOR, GProxyAddressEnumeratorClass)) + +/** + * GProxyAddressEnumerator: + * + * A subclass of #GSocketAddressEnumerator that takes another address + * enumerator and wraps its results in #GProxyAddresses as + * directed by the default #GProxyResolver. + */ + +typedef struct _GProxyAddressEnumeratorClass GProxyAddressEnumeratorClass; +typedef struct _GProxyAddressEnumeratorPrivate GProxyAddressEnumeratorPrivate; + +struct _GProxyAddressEnumerator +{ + GSocketAddressEnumerator parent_instance; + GProxyAddressEnumeratorPrivate *priv; +}; + +struct _GProxyAddressEnumeratorClass +{ + GSocketAddressEnumeratorClass parent_class; + + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); + void (*_g_reserved6) (void); + void (*_g_reserved7) (void); +}; + +GType g_proxy_address_enumerator_get_type (void) G_GNUC_CONST; + +#endif /* __G_PROXY_ADDRESS_ENUMERATOR_H__ */ -- 2.7.4