Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/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
 * 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
0
{
95
0
  GNetworkService *srv = G_NETWORK_SERVICE (object);
96
97
0
  g_free (srv->priv->service);
98
0
  g_free (srv->priv->protocol);
99
0
  g_free (srv->priv->domain);
100
0
  g_free (srv->priv->scheme);
101
102
0
  if (srv->priv->targets)
103
0
    g_resolver_free_targets (srv->priv->targets);
104
105
0
  G_OBJECT_CLASS (g_network_service_parent_class)->finalize (object);
106
0
}
107
108
static void
109
g_network_service_class_init (GNetworkServiceClass *klass)
110
0
{
111
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
112
113
0
  gobject_class->set_property = g_network_service_set_property;
114
0
  gobject_class->get_property = g_network_service_get_property;
115
0
  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
0
  g_object_class_install_property (gobject_class, PROP_SERVICE,
125
0
                                   g_param_spec_string ("service", NULL, NULL,
126
0
                                                        NULL,
127
0
                                                        G_PARAM_READWRITE |
128
0
                                                        G_PARAM_CONSTRUCT_ONLY |
129
0
                                                        G_PARAM_STATIC_STRINGS));
130
131
  /**
132
   * GNetworkService:protocol:
133
   *
134
   * Network protocol, for example `tcp`.
135
   *
136
   * Since: 2.22
137
   */
138
0
  g_object_class_install_property (gobject_class, PROP_PROTOCOL,
139
0
                                   g_param_spec_string ("protocol", NULL, NULL,
140
0
                                                        NULL,
141
0
                                                        G_PARAM_READWRITE |
142
0
                                                        G_PARAM_CONSTRUCT_ONLY |
143
0
                                                        G_PARAM_STATIC_STRINGS));
144
145
  /**
146
   * GNetworkService:domain:
147
   *
148
   * Network domain, for example `example.com`.
149
   *
150
   * Since: 2.22
151
   */
152
0
  g_object_class_install_property (gobject_class, PROP_DOMAIN,
153
0
                                   g_param_spec_string ("domain", NULL, NULL,
154
0
                                                        NULL,
155
0
                                                        G_PARAM_READWRITE |
156
0
                                                        G_PARAM_CONSTRUCT_ONLY |
157
0
                                                        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
0
  g_object_class_install_property (gobject_class, PROP_DOMAIN,
167
0
                                   g_param_spec_string ("scheme", NULL, NULL,
168
0
                                                        NULL,
169
0
                                                        G_PARAM_READWRITE |
170
0
                                                        G_PARAM_STATIC_STRINGS));
171
172
0
}
173
174
static void
175
g_network_service_connectable_iface_init (GSocketConnectableIface *connectable_iface)
176
0
{
177
0
  connectable_iface->enumerate = g_network_service_connectable_enumerate;
178
0
  connectable_iface->proxy_enumerate = g_network_service_connectable_proxy_enumerate;
179
0
  connectable_iface->to_string = g_network_service_connectable_to_string;
180
0
}
181
182
static void
183
g_network_service_init (GNetworkService *srv)
184
0
{
185
0
  srv->priv = g_network_service_get_instance_private (srv);
186
0
}
187
188
static void
189
g_network_service_set_property (GObject      *object,
190
                                guint         prop_id,
191
                                const GValue *value,
192
                                GParamSpec   *pspec)
193
0
{
194
0
  GNetworkService *srv = G_NETWORK_SERVICE (object);
195
196
0
  switch (prop_id)
197
0
    {
198
0
    case PROP_SERVICE:
199
0
      srv->priv->service = g_value_dup_string (value);
200
0
      break;
201
202
0
    case PROP_PROTOCOL:
203
0
      srv->priv->protocol = g_value_dup_string (value);
204
0
      break;
205
206
0
    case PROP_DOMAIN:
207
0
      srv->priv->domain = g_value_dup_string (value);
208
0
      break;
209
210
0
    case PROP_SCHEME:
211
0
      g_network_service_set_scheme (srv, g_value_get_string (value));
212
0
      break;
213
214
0
    default:
215
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216
0
      break;
217
0
    }
218
0
}
219
220
static void
221
g_network_service_get_property (GObject    *object,
222
                                guint       prop_id,
223
                                GValue     *value,
224
                                GParamSpec *pspec)
225
0
{
226
0
  GNetworkService *srv = G_NETWORK_SERVICE (object);
227
228
0
  switch (prop_id)
229
0
    {
230
0
    case PROP_SERVICE:
231
0
      g_value_set_string (value, g_network_service_get_service (srv));
232
0
      break;
233
234
0
    case PROP_PROTOCOL:
235
0
      g_value_set_string (value, g_network_service_get_protocol (srv));
236
0
      break;
237
238
0
    case PROP_DOMAIN:
239
0
      g_value_set_string (value, g_network_service_get_domain (srv));
240
0
      break;
241
242
0
    case PROP_SCHEME:
243
0
      g_value_set_string (value, g_network_service_get_scheme (srv));
244
0
      break;
245
246
0
    default:
247
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248
0
      break;
249
0
    }
250
0
}
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
0
{
271
0
  return g_object_new (G_TYPE_NETWORK_SERVICE,
272
0
                       "service", service,
273
0
                       "protocol", protocol,
274
0
                       "domain", domain,
275
0
                       NULL);
276
0
}
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
0
{
291
0
  g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
292
293
0
  return srv->priv->service;
294
0
}
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
0
{
309
0
  g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
310
311
0
  return srv->priv->protocol;
312
0
}
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
0
{
328
0
  g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
329
330
0
  return srv->priv->domain;
331
0
}
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
0
{
347
0
  g_return_val_if_fail (G_IS_NETWORK_SERVICE (srv), NULL);
348
349
0
  if (srv->priv->scheme)
350
0
    return srv->priv->scheme;
351
0
  else
352
0
    return srv->priv->service;
353
0
}
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
0
{
369
0
  g_return_if_fail (G_IS_NETWORK_SERVICE (srv));
370
371
0
  g_free (srv->priv->scheme);
372
0
  srv->priv->scheme = g_strdup (scheme);
373
374
0
  g_object_notify (G_OBJECT (srv), "scheme");
375
0
}
376
377
static GList *
378
g_network_service_fallback_targets (GNetworkService *srv)
379
0
{
380
0
  GSrvTarget *target;
381
0
  gboolean has_port;
382
0
  guint16 port;
383
384
0
  has_port = g_getservbyname_ntohs (srv->priv->service, "tcp", &port);
385
386
0
#ifdef HAVE_ENDSERVENT
387
0
  endservent ();
388
0
#endif
389
390
0
  if (!has_port)
391
0
    return NULL;
392
393
0
  target = g_srv_target_new (srv->priv->domain, port, 0, 0);
394
0
  return g_list_append (NULL, target);
395
0
}
396
397
0
#define G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR (_g_network_service_address_enumerator_get_type ())
398
0
#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
0
{
426
0
  GNetworkServiceAddressEnumerator *srv_enum =
427
0
    G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator);
428
0
  GSocketAddress *ret = NULL;
429
430
  /* If we haven't yet resolved srv, do that */
431
0
  if (!srv_enum->srv->priv->targets)
432
0
    {
433
0
      GList *targets;
434
0
      GError *my_error = NULL;
435
436
0
      targets = g_resolver_lookup_service (srv_enum->resolver,
437
0
                                           srv_enum->srv->priv->service,
438
0
                                           srv_enum->srv->priv->protocol,
439
0
                                           srv_enum->srv->priv->domain,
440
0
                                           cancellable, &my_error);
441
0
      if (!targets && g_error_matches (my_error, G_RESOLVER_ERROR,
442
0
                                       G_RESOLVER_ERROR_NOT_FOUND))
443
0
        {
444
0
          targets = g_network_service_fallback_targets (srv_enum->srv);
445
0
          if (targets)
446
0
            g_clear_error (&my_error);
447
0
        }
448
449
0
      if (my_error)
450
0
        {
451
0
          g_propagate_error (error, my_error);
452
0
          return NULL;
453
0
        }
454
455
0
      srv_enum->srv->priv->targets = targets;
456
0
      srv_enum->t = srv_enum->srv->priv->targets;
457
0
    }
458
459
  /* Delegate to GNetworkAddress */
460
0
  do
461
0
    {
462
0
      if (srv_enum->addr_enum == NULL && srv_enum->t)
463
0
        {
464
0
          GError *my_error = NULL;
465
0
          gchar *uri;
466
0
          gchar *hostname;
467
0
          GSocketConnectable *addr;
468
0
          GSrvTarget *target = srv_enum->t->data;
469
470
0
          srv_enum->t = g_list_next (srv_enum->t);
471
472
0
          hostname = g_hostname_to_ascii (g_srv_target_get_hostname (target));
473
474
0
          if (hostname == NULL)
475
0
            {
476
0
              if (srv_enum->error == NULL)
477
0
                srv_enum->error =
478
0
                  g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
479
0
                               "Received invalid hostname '%s' from GSrvTarget",
480
0
                               g_srv_target_get_hostname (target));
481
0
              continue;
482
0
            }
483
484
0
          uri = g_uri_join (G_URI_FLAGS_NONE,
485
0
                            g_network_service_get_scheme (srv_enum->srv),
486
0
                            NULL,
487
0
                            hostname,
488
0
                            g_srv_target_get_port (target),
489
0
                            "",
490
0
                            NULL,
491
0
                            NULL);
492
0
          g_free (hostname);
493
494
0
          addr = g_network_address_parse_uri (uri,
495
0
                                              g_srv_target_get_port (target),
496
0
                                              &my_error);
497
0
          g_free (uri);
498
499
0
          if (addr == NULL)
500
0
            {
501
0
              if (srv_enum->error == NULL)
502
0
                srv_enum->error = my_error;
503
0
              else
504
0
                g_error_free (my_error);
505
0
              continue;
506
0
            }
507
508
0
          if (srv_enum->use_proxy)
509
0
            srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr);
510
0
          else
511
0
            srv_enum->addr_enum = g_socket_connectable_enumerate (addr);
512
0
          g_object_unref (addr);
513
0
        }
514
515
0
      if (srv_enum->addr_enum)
516
0
        {
517
0
          GError *my_error = NULL;
518
519
0
          ret = g_socket_address_enumerator_next (srv_enum->addr_enum,
520
0
                                                  cancellable,
521
0
                                                  &my_error);
522
523
0
          if (my_error)
524
0
            {
525
0
              if (srv_enum->error == NULL)
526
0
                srv_enum->error = my_error;
527
0
              else
528
0
                g_error_free (my_error);
529
0
            }
530
531
0
          if (!ret)
532
0
            {
533
0
              g_object_unref (srv_enum->addr_enum);
534
0
              srv_enum->addr_enum = NULL;
535
0
            }
536
0
        }
537
0
    }
538
0
  while (srv_enum->addr_enum == NULL && srv_enum->t);
539
540
0
  if (ret == NULL && srv_enum->error)
541
0
    {
542
0
      g_propagate_error (error, srv_enum->error);
543
0
      srv_enum->error = NULL;
544
0
    }
545
546
0
  return ret;
547
0
}
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
0
{
563
0
  GNetworkServiceAddressEnumerator *srv_enum =
564
0
    G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (enumerator);
565
0
  GTask *task;
566
567
0
  task = g_task_new (enumerator, cancellable, callback, user_data);
568
0
  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
0
  if (!srv_enum->srv->priv->targets)
572
0
    {
573
0
      g_resolver_lookup_service_async (srv_enum->resolver,
574
0
                                       srv_enum->srv->priv->service,
575
0
                                       srv_enum->srv->priv->protocol,
576
0
                                       srv_enum->srv->priv->domain,
577
0
                                       cancellable,
578
0
                                       next_async_resolved_targets,
579
0
                                       task);
580
0
    }
581
0
  else
582
0
    next_async_have_targets (task);
583
0
}
584
585
static void
586
next_async_resolved_targets (GObject      *source_object,
587
                             GAsyncResult *result,
588
                             gpointer      user_data)
589
0
{
590
0
  GTask *task = user_data;
591
0
  GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
592
0
  GError *error = NULL;
593
0
  GList *targets;
594
595
0
  targets = g_resolver_lookup_service_finish (srv_enum->resolver,
596
0
                                              result, &error);
597
598
0
  if (!targets && g_error_matches (error, G_RESOLVER_ERROR,
599
0
                                   G_RESOLVER_ERROR_NOT_FOUND))
600
0
    {
601
0
      targets = g_network_service_fallback_targets (srv_enum->srv);
602
0
      if (targets)
603
0
        g_clear_error (&error);
604
0
    }
605
606
0
  if (error)
607
0
    {
608
0
      g_task_return_error (task, error);
609
0
      g_object_unref (task);
610
0
    }
611
0
  else
612
0
    {
613
0
      srv_enum->t = srv_enum->srv->priv->targets = targets;
614
0
      next_async_have_targets (task);
615
0
    }
616
0
}
617
618
static void
619
next_async_have_targets (GTask *task)
620
0
{
621
0
  GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
622
623
  /* Delegate to GNetworkAddress */
624
0
  if (srv_enum->addr_enum == NULL && srv_enum->t)
625
0
    {
626
0
      GSocketConnectable *addr;
627
0
      GSrvTarget *target = srv_enum->t->data;
628
629
0
      srv_enum->t = g_list_next (srv_enum->t);
630
0
      addr = g_network_address_new (g_srv_target_get_hostname (target),
631
0
                                    (guint16) g_srv_target_get_port (target));
632
633
0
      if (srv_enum->use_proxy)
634
0
        srv_enum->addr_enum = g_socket_connectable_proxy_enumerate (addr);
635
0
      else
636
0
        srv_enum->addr_enum = g_socket_connectable_enumerate (addr);
637
638
0
      g_object_unref (addr);
639
0
    }
640
641
0
  if (srv_enum->addr_enum)
642
0
    {
643
0
      g_socket_address_enumerator_next_async (srv_enum->addr_enum,
644
0
                                              g_task_get_cancellable (task),
645
0
                                              next_async_have_address,
646
0
                                              task);
647
0
    }
648
0
  else
649
0
    {
650
0
      if (srv_enum->error)
651
0
        {
652
0
          g_task_return_error (task, srv_enum->error);
653
0
          srv_enum->error = NULL;
654
0
        }
655
0
      else
656
0
        g_task_return_pointer (task, NULL, NULL);
657
658
0
      g_object_unref (task);
659
0
    }
660
0
}
661
662
static void
663
next_async_have_address (GObject      *source_object,
664
                         GAsyncResult *result,
665
                         gpointer      user_data)
666
0
{
667
0
  GTask *task = user_data;
668
0
  GNetworkServiceAddressEnumerator *srv_enum = g_task_get_source_object (task);
669
0
  GSocketAddress *address;
670
0
  GError *error = NULL;
671
  
672
0
  address = g_socket_address_enumerator_next_finish (srv_enum->addr_enum,
673
0
                                                     result,
674
0
                                                     &error);
675
676
0
  if (error)
677
0
    {
678
0
      if (srv_enum->error == NULL)
679
0
        srv_enum->error = error;
680
0
      else
681
0
        g_error_free (error);
682
0
    }
683
684
0
  if (!address)
685
0
    {
686
0
      g_object_unref (srv_enum->addr_enum);
687
0
      srv_enum->addr_enum = NULL;
688
689
0
      next_async_have_targets (task);
690
0
    }
691
0
  else
692
0
    {
693
0
      g_task_return_pointer (task, address, g_object_unref);
694
0
      g_object_unref (task);
695
0
    }
696
0
}
697
698
static GSocketAddress *
699
g_network_service_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
700
                                                  GAsyncResult              *result,
701
                                                  GError                   **error)
702
0
{
703
0
  return g_task_propagate_pointer (G_TASK (result), error);
704
0
}
705
706
static void
707
_g_network_service_address_enumerator_init (GNetworkServiceAddressEnumerator *enumerator)
708
0
{
709
0
}
710
711
static void
712
g_network_service_address_enumerator_finalize (GObject *object)
713
0
{
714
0
  GNetworkServiceAddressEnumerator *srv_enum =
715
0
    G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (object);
716
717
0
  if (srv_enum->srv)
718
0
    g_object_unref (srv_enum->srv);
719
720
0
  if (srv_enum->addr_enum)
721
0
    g_object_unref (srv_enum->addr_enum);
722
723
0
  if (srv_enum->resolver)
724
0
    g_object_unref (srv_enum->resolver);
725
726
0
  if (srv_enum->error)
727
0
    g_error_free (srv_enum->error);
728
729
0
  G_OBJECT_CLASS (_g_network_service_address_enumerator_parent_class)->finalize (object);
730
0
}
731
732
static void
733
_g_network_service_address_enumerator_class_init (GNetworkServiceAddressEnumeratorClass *srvenum_class)
734
0
{
735
0
  GObjectClass *object_class = G_OBJECT_CLASS (srvenum_class);
736
0
  GSocketAddressEnumeratorClass *enumerator_class =
737
0
    G_SOCKET_ADDRESS_ENUMERATOR_CLASS (srvenum_class);
738
739
0
  enumerator_class->next        = g_network_service_address_enumerator_next;
740
0
  enumerator_class->next_async  = g_network_service_address_enumerator_next_async;
741
0
  enumerator_class->next_finish = g_network_service_address_enumerator_next_finish;
742
743
0
  object_class->finalize = g_network_service_address_enumerator_finalize;
744
0
}
745
746
static GSocketAddressEnumerator *
747
g_network_service_connectable_enumerate (GSocketConnectable *connectable)
748
0
{
749
0
  GNetworkServiceAddressEnumerator *srv_enum;
750
751
0
  srv_enum = g_object_new (G_TYPE_NETWORK_SERVICE_ADDRESS_ENUMERATOR, NULL);
752
0
  srv_enum->srv = g_object_ref (G_NETWORK_SERVICE (connectable));
753
0
  srv_enum->resolver = g_resolver_get_default ();
754
0
  srv_enum->use_proxy = FALSE;
755
756
0
  return G_SOCKET_ADDRESS_ENUMERATOR (srv_enum);
757
0
}
758
759
static GSocketAddressEnumerator *
760
g_network_service_connectable_proxy_enumerate (GSocketConnectable *connectable)
761
0
{
762
0
  GSocketAddressEnumerator *addr_enum;
763
0
  GNetworkServiceAddressEnumerator *srv_enum;
764
765
0
  addr_enum = g_network_service_connectable_enumerate (connectable);
766
0
  srv_enum = G_NETWORK_SERVICE_ADDRESS_ENUMERATOR (addr_enum);
767
0
  srv_enum->use_proxy = TRUE;
768
769
0
  return addr_enum;
770
0
}
771
772
static gchar *
773
g_network_service_connectable_to_string (GSocketConnectable *connectable)
774
0
{
775
0
  GNetworkService *service;
776
777
0
  service = G_NETWORK_SERVICE (connectable);
778
779
0
  return g_strdup_printf ("(%s, %s, %s, %s)", service->priv->service,
780
0
                          service->priv->protocol, service->priv->domain,
781
0
                          service->priv->scheme);
782
0
}