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