X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgnetworkservice.c;h=497d6fd35bec575981ded89e6a08f6ea796cfe4f;hb=33b9935efc82f8cc4747dfea2743129dfc418d19;hp=54d64fd79a37bf82c349bdaa0386c0c2adecb6cb;hpb=7498049a1683db50805b9a9a580b62bb748918f4;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gnetworkservice.c b/gio/gnetworkservice.c index 54d64fd..497d6fd 100644 --- a/gio/gnetworkservice.c +++ b/gio/gnetworkservice.c @@ -15,9 +15,7 @@ * 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. + * Public License along with this library; if not, see . */ #include "config.h" @@ -25,11 +23,15 @@ #include "glibintl.h" #include "gnetworkservice.h" + #include "gcancellable.h" #include "ginetaddress.h" #include "ginetsocketaddress.h" +#include "gioerror.h" +#include "gnetworkaddress.h" +#include "gnetworkingprivate.h" #include "gresolver.h" -#include "gsimpleasyncresult.h" +#include "gtask.h" #include "gsocketaddressenumerator.h" #include "gsocketconnectable.h" #include "gsrvtarget.h" @@ -37,11 +39,10 @@ #include #include -#include "gioalias.h" /** * SECTION:gnetworkservice - * @short_description: a #GSocketConnectable for resolving SRV records + * @short_description: A GSocketConnectable for resolving SRV records * @include: gio/gio.h * * Like #GNetworkAddress does with hostnames, #GNetworkService @@ -53,18 +54,18 @@ * See #GSrvTarget for more information about SRV records, and see * #GSocketConnectable for and example of using the connectable * interface. - **/ + */ /** * GNetworkService: * * A #GSocketConnectable for resolving a SRV record and connecting to * that service. - **/ + */ struct _GNetworkServicePrivate { - gchar *service, *protocol, *domain; + gchar *service, *protocol, *domain, *scheme; GList *targets; }; @@ -73,6 +74,7 @@ enum { PROP_SERVICE, PROP_PROTOCOL, PROP_DOMAIN, + PROP_SCHEME }; static void g_network_service_set_property (GObject *object, @@ -84,10 +86,12 @@ 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_ADD_PRIVATE (GNetworkService) G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, g_network_service_connectable_iface_init)) @@ -99,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); @@ -111,8 +116,6 @@ g_network_service_class_init (GNetworkServiceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (GNetworkServicePrivate)); - gobject_class->set_property = g_network_service_set_property; gobject_class->get_property = g_network_service_get_property; gobject_class->finalize = g_network_service_finalize; @@ -122,32 +125,46 @@ g_network_service_class_init (GNetworkServiceClass *klass) P_("Service"), P_("Service name, eg \"ldap\""), NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_PROTOCOL, g_param_spec_string ("protocol", P_("Protocol"), P_("Network protocol, eg \"tcp\""), NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DOMAIN, g_param_spec_string ("domain", - P_("domain"), + P_("Domain"), P_("Network domain, eg, \"example.com\""), NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + 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 g_network_service_init (GNetworkService *srv) { - srv->priv = G_TYPE_INSTANCE_GET_PRIVATE (srv, G_TYPE_NETWORK_SERVICE, - GNetworkServicePrivate); + srv->priv = g_network_service_get_instance_private (srv); } static void @@ -158,7 +175,7 @@ g_network_service_set_property (GObject *object, { GNetworkService *srv = G_NETWORK_SERVICE (object); - switch (prop_id) + switch (prop_id) { case PROP_SERVICE: srv->priv->service = g_value_dup_string (value); @@ -172,11 +189,14 @@ 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; } - } static void @@ -188,7 +208,7 @@ g_network_service_get_property (GObject *object, GNetworkService *srv = G_NETWORK_SERVICE (object); switch (prop_id) - { + { case PROP_SERVICE: g_value_set_string (value, g_network_service_get_service (srv)); break; @@ -201,11 +221,14 @@ 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; } - } /** @@ -218,10 +241,10 @@ g_network_service_get_property (GObject *object, * @protocol, and @domain. This will initially be unresolved; use the * #GSocketConnectable interface to resolve it. * - * Return value: a new #GNetworkService + * Returns: (transfer full) (type GNetworkService): a new #GNetworkService * * Since: 2.22 - **/ + */ GSocketConnectable * g_network_service_new (const gchar *service, const gchar *protocol, @@ -240,10 +263,10 @@ g_network_service_new (const gchar *service, * * Gets @srv's service name (eg, "ldap"). * - * Return value: @srv's service name + * Returns: @srv's service name * * Since: 2.22 - **/ + */ const gchar * g_network_service_get_service (GNetworkService *srv) { @@ -258,10 +281,10 @@ g_network_service_get_service (GNetworkService *srv) * * Gets @srv's protocol name (eg, "tcp"). * - * Return value: @srv's protocol name + * Returns: @srv's protocol name * * Since: 2.22 - **/ + */ const gchar * g_network_service_get_protocol (GNetworkService *srv) { @@ -277,10 +300,10 @@ g_network_service_get_protocol (GNetworkService *srv) * Gets the domain that @srv serves. This might be either UTF-8 or * ASCII-encoded, depending on what @srv was created with. * - * Return value: @srv's domain name + * Returns: @srv's domain name * * Since: 2.22 - **/ + */ const gchar * g_network_service_get_domain (GNetworkService *srv) { @@ -289,6 +312,70 @@ 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. + * + * Returns: @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 + * @scheme: a URI scheme + * + * 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)); + + g_free (srv->priv->scheme); + srv->priv->scheme = g_strdup (scheme); + + g_object_notify (G_OBJECT (srv), "scheme"); +} + +static GList * +g_network_service_fallback_targets (GNetworkService *srv) +{ + GSrvTarget *target; + struct servent *entry; + guint16 port; + + entry = getservbyname (srv->priv->service, "tcp"); + port = entry ? g_ntohs (entry->s_port) : 0; +#ifdef HAVE_ENDSERVENT + endservent (); +#endif + + if (entry == NULL) + return NULL; + + target = g_srv_target_new (srv->priv->domain, port, 0, 0); + return g_list_append (NULL, target); +} + #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)) @@ -297,13 +384,12 @@ typedef struct { GResolver *resolver; GNetworkService *srv; - GList *addrs, *a, *t; + GSocketAddressEnumerator *addr_enum; + GList *t; + gboolean use_proxy; GError *error; - /* For async operation */ - GCancellable *cancellable; - GSimpleAsyncResult *result; } GNetworkServiceAddressEnumerator; typedef struct { @@ -311,31 +397,9 @@ typedef struct { } GNetworkServiceAddressEnumeratorClass; +static GType _g_network_service_address_enumerator_get_type (void); 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, @@ -343,107 +407,129 @@ 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) { GList *targets; + GError *my_error = NULL; targets = g_resolver_lookup_service (srv_enum->resolver, srv_enum->srv->priv->service, srv_enum->srv->priv->protocol, srv_enum->srv->priv->domain, - cancellable, error); - if (!targets) - return NULL; + cancellable, &my_error); + if (!targets && g_error_matches (my_error, G_RESOLVER_ERROR, + G_RESOLVER_ERROR_NOT_FOUND)) + { + targets = g_network_service_fallback_targets (srv_enum->srv); + if (targets) + g_clear_error (&my_error); + } + + if (my_error) + { + g_propagate_error (error, my_error); + 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; + + uri = _g_uri_from_authority (g_network_service_get_scheme (srv_enum->srv), + hostname, + g_srv_target_get_port (target), + NULL); + g_free (hostname); + + addr = g_network_address_parse_uri (uri, + g_srv_target_get_port (target), + &error); + g_free (uri); + + if (addr == 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); } - target = srv_enum->t->data; - /* If we haven't resolved the addrs for the current target, do that */ - if (!srv_enum->addrs) + if (srv_enum->addr_enum) { - GError **error_p; + GError *error = NULL; - 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; + ret = g_socket_address_enumerator_next (srv_enum->addr_enum, + cancellable, + &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; - } + if (srv_enum->error == NULL) + srv_enum->error = error; + else + g_error_free (error); } - else + + if (!ret) { - /* Try the next target */ - srv_enum->t = srv_enum->t->next; + 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, - 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 next_async_resolved_targets (GObject *source_object, + GAsyncResult *result, + gpointer user_data); +static void next_async_have_targets (GTask *srv_enum); +static void next_async_have_address (GObject *source_object, + GAsyncResult *result, + gpointer user_data); + static void g_network_service_address_enumerator_next_async (GSocketAddressEnumerator *enumerator, GCancellable *cancellable, @@ -452,13 +538,9 @@ g_network_service_address_enumerator_next_async (GSocketAddressEnumerator *enum { GNetworkServiceAddressEnumerator *srv_enum = G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator); + GTask *task; - g_return_if_fail (srv_enum->result == NULL); - - 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; + task = g_task_new (enumerator, cancellable, callback, user_data); /* If we haven't yet resolved srv, do that */ if (!srv_enum->srv->priv->targets) @@ -469,10 +551,10 @@ g_network_service_address_enumerator_next_async (GSocketAddressEnumerator *enum srv_enum->srv->priv->domain, cancellable, next_async_resolved_targets, - srv_enum); + task); } else - next_async_have_targets (srv_enum); + next_async_have_targets (task); } static void @@ -480,136 +562,112 @@ next_async_resolved_targets (GObject *source_object, GAsyncResult *result, gpointer user_data) { - GNetworkServiceAddressEnumerator *srv_enum = user_data; - GList *targets; + GTask *task = user_data; + GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task); GError *error = NULL; + GList *targets; - targets = g_resolver_lookup_service_finish (srv_enum->resolver, result, &error); - if (!srv_enum->srv->priv->targets) - { - if (error) - { - 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; - } + targets = g_resolver_lookup_service_finish (srv_enum->resolver, + result, &error); - srv_enum->srv->priv->targets = targets; - srv_enum->t = srv_enum->srv->priv->targets; + if (!targets && g_error_matches (error, G_RESOLVER_ERROR, + G_RESOLVER_ERROR_NOT_FOUND)) + { + targets = g_network_service_fallback_targets (srv_enum->srv); + if (targets) + g_clear_error (&error); } - next_async_have_targets (srv_enum); + if (error) + { + g_task_return_error (task, error); + g_object_unref (task); + } + else + { + srv_enum->t = srv_enum->srv->priv->targets = targets; + next_async_have_targets (task); + } } static void -next_async_have_targets (GNetworkServiceAddressEnumerator *srv_enum) +next_async_have_targets (GTask *task) { - GSrvTarget *target; + GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task); - /* 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) { - if (srv_enum->error) - { - g_simple_async_result_set_from_error (srv_enum->result, 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; + 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); } - target = srv_enum->t->data; - /* If we haven't resolved the addrs for the current target, do that */ - if (!srv_enum->addrs) + if (srv_enum->addr_enum) { - 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_socket_address_enumerator_next_async (srv_enum->addr_enum, + g_task_get_cancellable (task), + next_async_have_address, + task); } else - next_async_have_addresses (srv_enum); -} - -static void -next_async_resolved_addresses (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GNetworkServiceAddressEnumerator *srv_enum = user_data; - GError *error = NULL; - - srv_enum->addrs = g_resolver_lookup_by_name_finish (srv_enum->resolver, result, &error); - if (srv_enum->addrs) { - srv_enum->a = srv_enum->addrs; if (srv_enum->error) { - g_error_free (srv_enum->error); + g_task_return_error (task, srv_enum->error); srv_enum->error = NULL; } - next_async_have_addresses (srv_enum); - } - else - { - if (g_cancellable_is_cancelled (srv_enum->cancellable)) - { - 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); + g_task_return_pointer (task, NULL, NULL); - /* Try the next target */ - srv_enum->t = srv_enum->t->next; - next_async_have_targets (srv_enum); - } + g_object_unref (task); } } static void -next_async_have_addresses (GNetworkServiceAddressEnumerator *srv_enum) +next_async_have_address (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - 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) + GTask *task = user_data; + GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task); + GSocketAddress *address; + GError *error = NULL; + + address = g_socket_address_enumerator_next_finish (srv_enum->addr_enum, + result, + &error); + + if (error) { - g_list_free (srv_enum->addrs); - srv_enum->addrs = NULL; - srv_enum->t = srv_enum->t->next; + if (srv_enum->error == NULL) + srv_enum->error = error; + else + g_error_free (error); } - 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); + if (!address) + { + g_object_unref (srv_enum->addr_enum); + srv_enum->addr_enum = NULL; + + next_async_have_targets (task); + } + else + { + g_task_return_pointer (task, address, g_object_unref); + g_object_unref (task); + } } static GSocketAddress * @@ -617,14 +675,7 @@ g_network_service_address_enumerator_next_finish (GSocketAddressEnumerator *enu GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - GSocketAddress *sockaddr; - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - sockaddr = g_simple_async_result_get_op_res_gpointer (simple); - return sockaddr ? g_object_ref (sockaddr) : NULL; + return g_task_propagate_pointer (G_TASK (result), error); } static void @@ -633,15 +684,37 @@ _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) +{ + GNetworkServiceAddressEnumerator *srv_enum = + G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (object); + + 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->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 (addrenum_class); + GObjectClass *object_class = G_OBJECT_CLASS (srvenum_class); GSocketAddressEnumeratorClass *enumerator_class = - G_SOCKET_ADDRESS_ENUMERATOR_CLASS (addrenum_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 = 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; } @@ -653,9 +726,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); } -#define __G_NETWORK_SERVICE_C__ -#include "gioaliasdef.c" +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; +}