Coverage Report

Created: 2025-07-01 07:09

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