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