(root)/
glib-2.79.0/
gio/
gnetworkservice.c
       1  /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
       2  
       3  /* GIO - GLib Input, Output and Streaming Library
       4   *
       5   * Copyright (C) 2008 Red Hat, Inc.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   *
       9   * This library is free software; you can redistribute it and/or
      10   * modify it under the terms of the GNU Lesser General Public
      11   * License as published by the Free Software Foundation; either
      12   * version 2.1 of the License, or (at your option) any later version.
      13   *
      14   * This library is distributed in the hope that it will be useful,
      15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17   * Lesser General Public License for more details.
      18   *
      19   * You should have received a copy of the GNU Lesser General
      20   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      21   */
      22  
      23  #include "config.h"
      24  #include <glib.h>
      25  #include "glibintl.h"
      26  
      27  #include "gnetworkservice.h"
      28  
      29  #include "gcancellable.h"
      30  #include "ginetaddress.h"
      31  #include "ginetsocketaddress.h"
      32  #include "gioerror.h"
      33  #include "gnetworkaddress.h"
      34  #include "gnetworkingprivate.h"
      35  #include "gresolver.h"
      36  #include "gtask.h"
      37  #include "gsocketaddressenumerator.h"
      38  #include "gsocketconnectable.h"
      39  #include "gsrvtarget.h"
      40  
      41  #include <stdlib.h>
      42  #include <string.h>
      43  
      44  
      45  /**
      46   * GNetworkService:
      47   *
      48   * Like [class@Gio.NetworkAddress] does with hostnames, `GNetworkService`
      49   * provides an easy way to resolve a SRV record, and then attempt to
      50   * connect to one of the hosts that implements that service, handling
      51   * service priority/weighting, multiple IP addresses, and multiple
      52   * address families.
      53   *
      54   * See [struct@Gio.SrvTarget] for more information about SRV records, and see
      55   * [iface@Gio.SocketConnectable] for an example of using the connectable
      56   * interface.
      57   */
      58  
      59  struct _GNetworkServicePrivate
      60  {
      61    gchar *service, *protocol, *domain, *scheme;
      62    GList *targets;
      63  };
      64  
      65  enum {
      66    PROP_0,
      67    PROP_SERVICE,
      68    PROP_PROTOCOL,
      69    PROP_DOMAIN,
      70    PROP_SCHEME
      71  };
      72  
      73  static void g_network_service_set_property (GObject      *object,
      74                                              guint         prop_id,
      75                                              const GValue *value,
      76                                              GParamSpec   *pspec);
      77  static void g_network_service_get_property (GObject      *object,
      78                                              guint         prop_id,
      79                                              GValue       *value,
      80                                              GParamSpec   *pspec);
      81  
      82  static void                      g_network_service_connectable_iface_init       (GSocketConnectableIface *iface);
      83  static GSocketAddressEnumerator *g_network_service_connectable_enumerate        (GSocketConnectable      *connectable);
      84  static GSocketAddressEnumerator *g_network_service_connectable_proxy_enumerate  (GSocketConnectable      *connectable);
      85  static gchar                    *g_network_service_connectable_to_string        (GSocketConnectable      *connectable);
      86  
      87  G_DEFINE_TYPE_WITH_CODE (GNetworkService, g_network_service, G_TYPE_OBJECT,
      88                           G_ADD_PRIVATE (GNetworkService)
      89                           G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
      90                                                  g_network_service_connectable_iface_init))
      91  
      92  static void
      93  g_network_service_finalize (GObject *object)
      94  {
      95    GNetworkService *srv = G_NETWORK_SERVICE (object);
      96  
      97    g_free (srv->priv->service);
      98    g_free (srv->priv->protocol);
      99    g_free (srv->priv->domain);
     100    g_free (srv->priv->scheme);
     101  
     102    if (srv->priv->targets)
     103      g_resolver_free_targets (srv->priv->targets);
     104  
     105    G_OBJECT_CLASS (g_network_service_parent_class)->finalize (object);
     106  }
     107  
     108  static void
     109  g_network_service_class_init (GNetworkServiceClass *klass)
     110  {
     111    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     112  
     113    gobject_class->set_property = g_network_service_set_property;
     114    gobject_class->get_property = g_network_service_get_property;
     115    gobject_class->finalize = g_network_service_finalize;
     116  
     117    /**
     118     * GNetworkService:service:
     119     *
     120     * Service name, for example `ldap`.
     121     *
     122     * Since: 2.22
     123     */
     124    g_object_class_install_property (gobject_class, PROP_SERVICE,
     125                                     g_param_spec_string ("service", NULL, NULL,
     126                                                          NULL,
     127                                                          G_PARAM_READWRITE |
     128                                                          G_PARAM_CONSTRUCT_ONLY |
     129                                                          G_PARAM_STATIC_STRINGS));
     130  
     131    /**
     132     * GNetworkService:protocol:
     133     *
     134     * Network protocol, for example `tcp`.
     135     *
     136     * Since: 2.22
     137     */
     138    g_object_class_install_property (gobject_class, PROP_PROTOCOL,
     139                                     g_param_spec_string ("protocol", NULL, NULL,
     140                                                          NULL,
     141                                                          G_PARAM_READWRITE |
     142                                                          G_PARAM_CONSTRUCT_ONLY |
     143                                                          G_PARAM_STATIC_STRINGS));
     144  
     145    /**
     146     * GNetworkService:domain:
     147     *
     148     * Network domain, for example `example.com`.
     149     *
     150     * Since: 2.22
     151     */
     152    g_object_class_install_property (gobject_class, PROP_DOMAIN,
     153                                     g_param_spec_string ("domain", NULL, NULL,
     154                                                          NULL,
     155                                                          G_PARAM_READWRITE |
     156                                                          G_PARAM_CONSTRUCT_ONLY |
     157                                                          G_PARAM_STATIC_STRINGS));
     158  
     159    /**
     160     * GNetworkService:scheme:
     161     *
     162     * Network scheme (default is to use service).
     163     *
     164     * Since: 2.22
     165     */
     166    g_object_class_install_property (gobject_class, PROP_DOMAIN,
     167                                     g_param_spec_string ("scheme", NULL, NULL,
     168                                                          NULL,
     169                                                          G_PARAM_READWRITE |
     170                                                          G_PARAM_STATIC_STRINGS));
     171  
     172  }
     173  
     174  static void
     175  g_network_service_connectable_iface_init (GSocketConnectableIface *connectable_iface)
     176  {
     177    connectable_iface->enumerate = g_network_service_connectable_enumerate;
     178    connectable_iface->proxy_enumerate = g_network_service_connectable_proxy_enumerate;
     179    connectable_iface->to_string = g_network_service_connectable_to_string;
     180  }
     181  
     182  static void
     183  g_network_service_init (GNetworkService *srv)
     184  {
     185    srv->priv = g_network_service_get_instance_private (srv);
     186  }
     187  
     188  static void
     189  g_network_service_set_property (GObject      *object,
     190                                  guint         prop_id,
     191                                  const GValue *value,
     192                                  GParamSpec   *pspec)
     193  {
     194    GNetworkService *srv = G_NETWORK_SERVICE (object);
     195  
     196    switch (prop_id)
     197      {
     198      case PROP_SERVICE:
     199        srv->priv->service = g_value_dup_string (value);
     200        break;
     201  
     202      case PROP_PROTOCOL:
     203        srv->priv->protocol = g_value_dup_string (value);
     204        break;
     205  
     206      case PROP_DOMAIN:
     207        srv->priv->domain = g_value_dup_string (value);
     208        break;
     209  
     210      case PROP_SCHEME:
     211        g_network_service_set_scheme (srv, g_value_get_string (value));
     212        break;
     213  
     214      default:
     215        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     216        break;
     217      }
     218  }
     219  
     220  static void
     221  g_network_service_get_property (GObject    *object,
     222                                  guint       prop_id,
     223                                  GValue     *value,
     224                                  GParamSpec *pspec)
     225  {
     226    GNetworkService *srv = G_NETWORK_SERVICE (object);
     227  
     228    switch (prop_id)
     229      {
     230      case PROP_SERVICE:
     231        g_value_set_string (value, g_network_service_get_service (srv));
     232        break;
     233  
     234      case PROP_PROTOCOL:
     235        g_value_set_string (value, g_network_service_get_protocol (srv));
     236        break;
     237  
     238      case PROP_DOMAIN:
     239        g_value_set_string (value, g_network_service_get_domain (srv));
     240        break;
     241  
     242      case PROP_SCHEME:
     243        g_value_set_string (value, g_network_service_get_scheme (srv));
     244        break;
     245  
     246      default:
     247        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     248        break;
     249      }
     250  }
     251  
     252  /**
     253   * g_network_service_new:
     254   * @service: the service type to look up (eg, "ldap")
     255   * @protocol: the networking protocol to use for @service (eg, "tcp")
     256   * @domain: the DNS domain to look up the service in
     257   *
     258   * Creates a new #GNetworkService representing the given @service,
     259   * @protocol, and @domain. This will initially be unresolved; use the
     260   * #GSocketConnectable interface to resolve it.
     261   *
     262   * Returns: (transfer full) (type GNetworkService): a new #GNetworkService
     263   *
     264   * Since: 2.22
     265   */
     266  GSocketConnectable *
     267  g_network_service_new (const gchar *service,
     268                         const gchar *protocol,
     269                         const gchar *domain)
     270  {
     271    return g_object_new (G_TYPE_NETWORK_SERVICE,
     272                         "service", service,
     273                         "protocol", protocol,
     274                         "domain", domain,
     275                         NULL);
     276  }
     277  
     278  /**
     279   * g_network_service_get_service:
     280   * @srv: a #GNetworkService
     281   *
     282   * Gets @srv's service name (eg, "ldap").
     283   *
     284   * Returns: @srv's service name
     285   *
     286   * Since: 2.22
     287   */
     288  const gchar *
     289  g_network_service_get_service (GNetworkService *srv)
     290  {
     291    g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
     292  
     293    return srv->priv->service;
     294  }
     295  
     296  /**
     297   * g_network_service_get_protocol:
     298   * @srv: a #GNetworkService
     299   *
     300   * Gets @srv's protocol name (eg, "tcp").
     301   *
     302   * Returns: @srv's protocol name
     303   *
     304   * Since: 2.22
     305   */
     306  const gchar *
     307  g_network_service_get_protocol (GNetworkService *srv)
     308  {
     309    g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
     310  
     311    return srv->priv->protocol;
     312  }
     313  
     314  /**
     315   * g_network_service_get_domain:
     316   * @srv: a #GNetworkService
     317   *
     318   * Gets the domain that @srv serves. This might be either UTF-8 or
     319   * ASCII-encoded, depending on what @srv was created with.
     320   *
     321   * Returns: @srv's domain name
     322   *
     323   * Since: 2.22
     324   */
     325  const gchar *
     326  g_network_service_get_domain (GNetworkService *srv)
     327  {
     328    g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
     329  
     330    return srv->priv->domain;
     331  }
     332  
     333  /**
     334   * g_network_service_get_scheme:
     335   * @srv: a #GNetworkService
     336   *
     337   * Gets the URI scheme used to resolve proxies. By default, the service name
     338   * is used as scheme.
     339   *
     340   * Returns: @srv's scheme name
     341   *
     342   * Since: 2.26
     343   */
     344  const gchar *
     345  g_network_service_get_scheme (GNetworkService *srv)
     346  {
     347    g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
     348  
     349    if (srv->priv->scheme)
     350      return srv->priv->scheme;
     351    else
     352      return srv->priv->service;
     353  }
     354  
     355  /**
     356   * g_network_service_set_scheme:
     357   * @srv: a #GNetworkService
     358   * @scheme: a URI scheme
     359   *
     360   * Set's the URI scheme used to resolve proxies. By default, the service name
     361   * is used as scheme.
     362   *
     363   * Since: 2.26
     364   */
     365  void
     366  g_network_service_set_scheme (GNetworkService *srv,
     367                                const gchar     *scheme)
     368  {
     369    g_return_if_fail (G_IS_NETWORK_SERVICE (srv));
     370  
     371    g_free (srv->priv->scheme);
     372    srv->priv->scheme = g_strdup (scheme);
     373  
     374    g_object_notify (G_OBJECT (srv), "scheme");
     375  }
     376  
     377  static GList *
     378  g_network_service_fallback_targets (GNetworkService *srv)
     379  {
     380    GSrvTarget *target;
     381    gboolean has_port;
     382    guint16 port;
     383  
     384    has_port = g_getservbyname_ntohs (srv->priv->service, "tcp", &port);
     385  
     386  #ifdef HAVE_ENDSERVENT
     387    endservent ();
     388  #endif
     389  
     390    if (!has_port)
     391      return NULL;
     392  
     393    target = g_srv_target_new (srv->priv->domain, port, 0, 0);
     394    return g_list_append (NULL, target);
     395  }
     396  
     397  #define G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR (_g_network_service_address_enumerator_get_type ())
     398  #define G_NETWORK_SERVICE_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, GNetworkServiceAddressEnumerator))
     399  
     400  typedef struct {
     401    GSocketAddressEnumerator parent_instance;
     402  
     403    GResolver *resolver;
     404    GNetworkService *srv;
     405    GSocketAddressEnumerator *addr_enum;
     406    GList *t;
     407    gboolean use_proxy;
     408  
     409    GError *error;
     410  
     411  } GNetworkServiceAddressEnumerator;
     412  
     413  typedef struct {
     414    GSocketAddressEnumeratorClass parent_class;
     415  
     416  } GNetworkServiceAddressEnumeratorClass;
     417  
     418  static GType _g_network_service_address_enumerator_get_type (void);
     419  G_DEFINE_TYPE (GNetworkServiceAddressEnumerator, _g_network_service_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
     420  
     421  static GSocketAddress *
     422  g_network_service_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
     423                                             GCancellable              *cancellable,
     424                                             GError                   **error)
     425  {
     426    GNetworkServiceAddressEnumerator *srv_enum =
     427      G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator);
     428    GSocketAddress *ret = NULL;
     429  
     430    /* If we haven't yet resolved srv, do that */
     431    if (!srv_enum->srv->priv->targets)
     432      {
     433        GList *targets;
     434        GError *my_error = NULL;
     435  
     436        targets = g_resolver_lookup_service (srv_enum->resolver,
     437                                             srv_enum->srv->priv->service,
     438                                             srv_enum->srv->priv->protocol,
     439                                             srv_enum->srv->priv->domain,
     440                                             cancellable, &my_error);
     441        if (!targets && g_error_matches (my_error, G_RESOLVER_ERROR,
     442                                         G_RESOLVER_ERROR_NOT_FOUND))
     443          {
     444            targets = g_network_service_fallback_targets (srv_enum->srv);
     445            if (targets)
     446              g_clear_error (&my_error);
     447          }
     448  
     449        if (my_error)
     450          {
     451            g_propagate_error (error, my_error);
     452            return NULL;
     453          }
     454  
     455        srv_enum->srv->priv->targets = targets;
     456        srv_enum->t = srv_enum->srv->priv->targets;
     457      }
     458  
     459    /* Delegate to GNetworkAddress */
     460    do
     461      {
     462        if (srv_enum->addr_enum == NULL && srv_enum->t)
     463          {
     464            GError *my_error = NULL;
     465            gchar *uri;
     466            gchar *hostname;
     467            GSocketConnectable *addr;
     468            GSrvTarget *target = srv_enum->t->data;
     469  
     470            srv_enum->t = g_list_next (srv_enum->t);
     471  
     472            hostname = g_hostname_to_ascii (g_srv_target_get_hostname (target));
     473  
     474            if (hostname == NULL)
     475              {
     476                if (srv_enum->error == NULL)
     477                  srv_enum->error =
     478                    g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
     479                                 "Received invalid hostname '%s' from GSrvTarget",
     480                                 g_srv_target_get_hostname (target));
     481                continue;
     482              }
     483  
     484            uri = g_uri_join (G_URI_FLAGS_NONE,
     485                              g_network_service_get_scheme (srv_enum->srv),
     486                              NULL,
     487                              hostname,
     488                              g_srv_target_get_port (target),
     489                              "",
     490                              NULL,
     491                              NULL);
     492            g_free (hostname);
     493  
     494            addr = g_network_address_parse_uri (uri,
     495                                                g_srv_target_get_port (target),
     496                                                &my_error);
     497            g_free (uri);
     498  
     499            if (addr == NULL)
     500              {
     501                if (srv_enum->error == NULL)
     502                  srv_enum->error = my_error;
     503                else
     504                  g_error_free (my_error);
     505                continue;
     506              }
     507  
     508            if (srv_enum->use_proxy)
     509              srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr);
     510            else
     511              srv_enum->addr_enum = g_socket_connectable_enumerate (addr);
     512            g_object_unref (addr);
     513          }
     514  
     515        if (srv_enum->addr_enum)
     516          {
     517            GError *my_error = NULL;
     518  
     519            ret = g_socket_address_enumerator_next (srv_enum->addr_enum,
     520                                                    cancellable,
     521                                                    &my_error);
     522  
     523            if (my_error)
     524              {
     525                if (srv_enum->error == NULL)
     526                  srv_enum->error = my_error;
     527                else
     528                  g_error_free (my_error);
     529              }
     530  
     531            if (!ret)
     532              {
     533                g_object_unref (srv_enum->addr_enum);
     534                srv_enum->addr_enum = NULL;
     535              }
     536          }
     537      }
     538    while (srv_enum->addr_enum == NULL && srv_enum->t);
     539  
     540    if (ret == NULL && srv_enum->error)
     541      {
     542        g_propagate_error (error, srv_enum->error);
     543        srv_enum->error = NULL;
     544      }
     545  
     546    return ret;
     547  }
     548  
     549  static void next_async_resolved_targets   (GObject      *source_object,
     550                                             GAsyncResult *result,
     551                                             gpointer      user_data);
     552  static void next_async_have_targets       (GTask        *srv_enum);
     553  static void next_async_have_address       (GObject      *source_object,
     554                                             GAsyncResult *result,
     555                                             gpointer      user_data);
     556  
     557  static void
     558  g_network_service_address_enumerator_next_async (GSocketAddressEnumerator  *enumerator,
     559                                                   GCancellable              *cancellable,
     560                                                   GAsyncReadyCallback        callback,
     561                                                   gpointer                   user_data)
     562  {
     563    GNetworkServiceAddressEnumerator *srv_enum =
     564      G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator);
     565    GTask *task;
     566  
     567    task = g_task_new (enumerator, cancellable, callback, user_data);
     568    g_task_set_source_tag (task, g_network_service_address_enumerator_next_async);
     569  
     570    /* If we haven't yet resolved srv, do that */
     571    if (!srv_enum->srv->priv->targets)
     572      {
     573        g_resolver_lookup_service_async (srv_enum->resolver,
     574                                         srv_enum->srv->priv->service,
     575                                         srv_enum->srv->priv->protocol,
     576                                         srv_enum->srv->priv->domain,
     577                                         cancellable,
     578                                         next_async_resolved_targets,
     579                                         task);
     580      }
     581    else
     582      next_async_have_targets (task);
     583  }
     584  
     585  static void
     586  next_async_resolved_targets (GObject      *source_object,
     587                               GAsyncResult *result,
     588                               gpointer      user_data)
     589  {
     590    GTask *task = user_data;
     591    GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
     592    GError *error = NULL;
     593    GList *targets;
     594  
     595    targets = g_resolver_lookup_service_finish (srv_enum->resolver,
     596                                                result, &error);
     597  
     598    if (!targets && g_error_matches (error, G_RESOLVER_ERROR,
     599                                     G_RESOLVER_ERROR_NOT_FOUND))
     600      {
     601        targets = g_network_service_fallback_targets (srv_enum->srv);
     602        if (targets)
     603          g_clear_error (&error);
     604      }
     605  
     606    if (error)
     607      {
     608        g_task_return_error (task, error);
     609        g_object_unref (task);
     610      }
     611    else
     612      {
     613        srv_enum->t = srv_enum->srv->priv->targets = targets;
     614        next_async_have_targets (task);
     615      }
     616  }
     617  
     618  static void
     619  next_async_have_targets (GTask *task)
     620  {
     621    GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
     622  
     623    /* Delegate to GNetworkAddress */
     624    if (srv_enum->addr_enum == NULL && srv_enum->t)
     625      {
     626        GSocketConnectable *addr;
     627        GSrvTarget *target = srv_enum->t->data;
     628  
     629        srv_enum->t = g_list_next (srv_enum->t);
     630        addr = g_network_address_new (g_srv_target_get_hostname (target),
     631                                      (guint16) g_srv_target_get_port (target));
     632  
     633        if (srv_enum->use_proxy)
     634          srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr);
     635        else
     636          srv_enum->addr_enum = g_socket_connectable_enumerate (addr);
     637  
     638        g_object_unref (addr);
     639      }
     640  
     641    if (srv_enum->addr_enum)
     642      {
     643        g_socket_address_enumerator_next_async (srv_enum->addr_enum,
     644                                                g_task_get_cancellable (task),
     645                                                next_async_have_address,
     646                                                task);
     647      }
     648    else
     649      {
     650        if (srv_enum->error)
     651          {
     652            g_task_return_error (task, srv_enum->error);
     653            srv_enum->error = NULL;
     654          }
     655        else
     656          g_task_return_pointer (task, NULL, NULL);
     657  
     658        g_object_unref (task);
     659      }
     660  }
     661  
     662  static void
     663  next_async_have_address (GObject      *source_object,
     664                           GAsyncResult *result,
     665                           gpointer      user_data)
     666  {
     667    GTask *task = user_data;
     668    GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
     669    GSocketAddress *address;
     670    GError *error = NULL;
     671    
     672    address = g_socket_address_enumerator_next_finish (srv_enum->addr_enum,
     673                                                       result,
     674                                                       &error);
     675  
     676    if (error)
     677      {
     678        if (srv_enum->error == NULL)
     679          srv_enum->error = error;
     680        else
     681          g_error_free (error);
     682      }
     683  
     684    if (!address)
     685      {
     686        g_object_unref (srv_enum->addr_enum);
     687        srv_enum->addr_enum = NULL;
     688  
     689        next_async_have_targets (task);
     690      }
     691    else
     692      {
     693        g_task_return_pointer (task, address, g_object_unref);
     694        g_object_unref (task);
     695      }
     696  }
     697  
     698  static GSocketAddress *
     699  g_network_service_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
     700                                                    GAsyncResult              *result,
     701                                                    GError                   **error)
     702  {
     703    return g_task_propagate_pointer (G_TASK (result), error);
     704  }
     705  
     706  static void
     707  _g_network_service_address_enumerator_init (GNetworkServiceAddressEnumerator *enumerator)
     708  {
     709  }
     710  
     711  static void
     712  g_network_service_address_enumerator_finalize (GObject *object)
     713  {
     714    GNetworkServiceAddressEnumerator *srv_enum =
     715      G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (object);
     716  
     717    if (srv_enum->srv)
     718      g_object_unref (srv_enum->srv);
     719  
     720    if (srv_enum->addr_enum)
     721      g_object_unref (srv_enum->addr_enum);
     722  
     723    if (srv_enum->resolver)
     724      g_object_unref (srv_enum->resolver);
     725  
     726    if (srv_enum->error)
     727      g_error_free (srv_enum->error);
     728  
     729    G_OBJECT_CLASS (_g_network_service_address_enumerator_parent_class)->finalize (object);
     730  }
     731  
     732  static void
     733  _g_network_service_address_enumerator_class_init (GNetworkServiceAddressEnumeratorClass *srvenum_class)
     734  {
     735    GObjectClass *object_class = G_OBJECT_CLASS (srvenum_class);
     736    GSocketAddressEnumeratorClass *enumerator_class =
     737      G_SOCKET_ADDRESS_ENUMERATOR_CLASS (srvenum_class);
     738  
     739    enumerator_class->next        = g_network_service_address_enumerator_next;
     740    enumerator_class->next_async  = g_network_service_address_enumerator_next_async;
     741    enumerator_class->next_finish = g_network_service_address_enumerator_next_finish;
     742  
     743    object_class->finalize = g_network_service_address_enumerator_finalize;
     744  }
     745  
     746  static GSocketAddressEnumerator *
     747  g_network_service_connectable_enumerate (GSocketConnectable *connectable)
     748  {
     749    GNetworkServiceAddressEnumerator *srv_enum;
     750  
     751    srv_enum = g_object_new (G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, NULL);
     752    srv_enum->srv = g_object_ref (G_NETWORK_SERVICE (connectable));
     753    srv_enum->resolver = g_resolver_get_default ();
     754    srv_enum->use_proxy = FALSE;
     755  
     756    return G_SOCKET_ADDRESS_ENUMERATOR (srv_enum);
     757  }
     758  
     759  static GSocketAddressEnumerator *
     760  g_network_service_connectable_proxy_enumerate (GSocketConnectable *connectable)
     761  {
     762    GSocketAddressEnumerator *addr_enum;
     763    GNetworkServiceAddressEnumerator *srv_enum;
     764  
     765    addr_enum = g_network_service_connectable_enumerate (connectable);
     766    srv_enum = G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (addr_enum);
     767    srv_enum->use_proxy = TRUE;
     768  
     769    return addr_enum;
     770  }
     771  
     772  static gchar *
     773  g_network_service_connectable_to_string (GSocketConnectable *connectable)
     774  {
     775    GNetworkService *service;
     776  
     777    service = G_NETWORK_SERVICE (connectable);
     778  
     779    return g_strdup_printf ("(%s, %s, %s, %s)", service->priv->service,
     780                            service->priv->protocol, service->priv->domain,
     781                            service->priv->scheme);
     782  }