Coverage Report

Created: 2025-10-13 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rauc/subprojects/glib-2.76.5/gio/gproxyaddressenumerator.c
Line
Count
Source
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright (C) 2010 Collabora, Ltd.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
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
 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
21
 */
22
23
#include "config.h"
24
#include "gproxyaddressenumerator.h"
25
26
#include <string.h>
27
28
#include "gasyncresult.h"
29
#include "ginetaddress.h"
30
#include "gioerror.h"
31
#include "glibintl.h"
32
#include "gnetworkaddress.h"
33
#include "gnetworkingprivate.h"
34
#include "gproxy.h"
35
#include "gproxyaddress.h"
36
#include "gproxyresolver.h"
37
#include "gtask.h"
38
#include "gresolver.h"
39
#include "gsocketaddress.h"
40
#include "gsocketaddressenumerator.h"
41
#include "gsocketconnectable.h"
42
43
/**
44
 * SECTION:gproxyaddressenumerator
45
 * @short_description: Proxy wrapper enumerator for socket addresses
46
 * @include: gio/gio.h
47
 *
48
 * #GProxyAddressEnumerator is a wrapper around #GSocketAddressEnumerator which
49
 * takes the #GSocketAddress instances returned by the #GSocketAddressEnumerator
50
 * and wraps them in #GProxyAddress instances, using the given
51
 * #GProxyAddressEnumerator:proxy-resolver.
52
 *
53
 * This enumerator will be returned (for example, by
54
 * g_socket_connectable_enumerate()) as appropriate when a proxy is configured;
55
 * there should be no need to manually wrap a #GSocketAddressEnumerator instance
56
 * with one.
57
 */
58
59
0
#define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
60
61
enum
62
{
63
  PROP_0,
64
  PROP_URI,
65
  PROP_DEFAULT_PORT,
66
  PROP_CONNECTABLE,
67
  PROP_PROXY_RESOLVER
68
};
69
70
struct _GProxyAddressEnumeratorPrivate
71
{
72
  /* Destination address */
73
  GSocketConnectable *connectable;
74
  gchar              *dest_uri;
75
  guint16             default_port;
76
  gchar              *dest_hostname;
77
  guint16             dest_port;
78
  GList              *dest_ips;
79
80
  /* Proxy enumeration */
81
  GProxyResolver           *proxy_resolver;
82
  gchar                   **proxies;
83
  gchar                   **next_proxy;
84
  GSocketAddressEnumerator *addr_enum;
85
  GSocketAddress           *proxy_address;
86
  const gchar              *proxy_uri;
87
  gchar                    *proxy_type;
88
  gchar                    *proxy_username;
89
  gchar                    *proxy_password;
90
  gboolean                  supports_hostname;
91
  GList                    *next_dest_ip;
92
  GError                   *last_error;
93
94
  /* ever_enumerated is TRUE after we've returned a result for the first time
95
   * via g_proxy_address_enumerator_next() or _next_async(). If FALSE, we have
96
   * never returned yet, and should return an error if returning NULL because
97
   * it does not make sense for a proxy resolver to return NULL except on error.
98
   * (Whereas a DNS resolver would return NULL with no error to indicate "no
99
   * results", a proxy resolver would want to return "direct://" instead, so
100
   * NULL without error does not make sense for us.)
101
   *
102
   * But if ever_enumerated is TRUE, then we must not report any further errors
103
   * (except for G_IO_ERROR_CANCELLED), because this is an API contract of
104
   * GSocketAddressEnumerator.
105
   */
106
  gboolean                  ever_enumerated;
107
};
108
109
0
G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
110
0
111
0
static void
112
0
save_userinfo (GProxyAddressEnumeratorPrivate *priv,
113
0
               const gchar *proxy)
114
0
{
115
0
  g_clear_pointer (&priv->proxy_username, g_free);
116
0
  g_clear_pointer (&priv->proxy_password, g_free);
117
118
0
  g_uri_split_with_user (proxy, G_URI_FLAGS_HAS_PASSWORD, NULL,
119
0
                         &priv->proxy_username, &priv->proxy_password,
120
0
                         NULL, NULL, NULL, NULL, NULL, NULL, NULL);
121
0
}
122
123
static void
124
next_enumerator (GProxyAddressEnumeratorPrivate *priv)
125
0
{
126
0
  if (priv->proxy_address)
127
0
    return;
128
129
0
  while (priv->addr_enum == NULL && *priv->next_proxy)
130
0
    {
131
0
      GSocketConnectable *connectable = NULL;
132
0
      GProxy *proxy;
133
134
0
      priv->proxy_uri = *priv->next_proxy++;
135
0
      g_free (priv->proxy_type);
136
0
      priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);
137
138
0
      if (priv->proxy_type == NULL)
139
0
  continue;
140
141
      /* Assumes hostnames are supported for unknown protocols */
142
0
      priv->supports_hostname = TRUE;
143
0
      proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
144
0
      if (proxy)
145
0
        {
146
0
    priv->supports_hostname = g_proxy_supports_hostname (proxy);
147
0
    g_object_unref (proxy);
148
0
        }
149
150
0
      if (strcmp ("direct", priv->proxy_type) == 0)
151
0
  {
152
0
    if (priv->connectable)
153
0
      connectable = g_object_ref (priv->connectable);
154
0
    else
155
0
      connectable = g_network_address_new (priv->dest_hostname,
156
0
             priv->dest_port);
157
0
  }
158
0
      else
159
0
  {
160
0
    GError *error = NULL;
161
162
0
    connectable = g_network_address_parse_uri (priv->proxy_uri, 0, &error);
163
164
0
    if (error)
165
0
      {
166
0
        g_warning ("Invalid proxy URI '%s': %s",
167
0
       priv->proxy_uri, error->message);
168
0
        g_error_free (error);
169
0
      }
170
171
0
    save_userinfo (priv, priv->proxy_uri);
172
0
  }
173
174
0
      if (connectable)
175
0
  {
176
0
    priv->addr_enum = g_socket_connectable_enumerate (connectable);
177
0
    g_object_unref (connectable);
178
0
  }
179
0
    }
180
0
}
181
182
static GSocketAddress *
183
g_proxy_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
184
         GCancellable              *cancellable,
185
         GError                   **error)
186
0
{
187
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
188
0
  GSocketAddress *result = NULL;
189
0
  GError *first_error = NULL;
190
191
0
  if (!priv->ever_enumerated)
192
0
    {
193
0
      g_assert (priv->proxies == NULL);
194
0
      priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
195
0
                 priv->dest_uri,
196
0
                 cancellable,
197
0
                 error);
198
0
      priv->next_proxy = priv->proxies;
199
200
0
      if (priv->proxies == NULL)
201
0
  {
202
0
    priv->ever_enumerated = TRUE;
203
0
    return NULL;
204
0
  }
205
0
    }
206
207
0
  while (result == NULL && (*priv->next_proxy || priv->addr_enum))
208
0
    {
209
0
      gchar *dest_hostname;
210
0
      gchar *dest_protocol;
211
0
      GInetSocketAddress *inetsaddr;
212
0
      GInetAddress *inetaddr;
213
0
      guint16 port;
214
215
0
      next_enumerator (priv);
216
217
0
      if (!priv->addr_enum)
218
0
  continue;
219
220
0
      if (priv->proxy_address == NULL)
221
0
  {
222
0
    priv->proxy_address = g_socket_address_enumerator_next (
223
0
            priv->addr_enum,
224
0
            cancellable,
225
0
            first_error ? NULL : &first_error);
226
0
  }
227
228
0
      if (priv->proxy_address == NULL)
229
0
  {
230
0
    g_object_unref (priv->addr_enum);
231
0
    priv->addr_enum = NULL;
232
233
0
    if (priv->dest_ips)
234
0
      {
235
0
        g_resolver_free_addresses (priv->dest_ips);
236
0
        priv->dest_ips = NULL;
237
0
      }
238
239
0
    continue;
240
0
  }
241
242
0
      if (strcmp ("direct", priv->proxy_type) == 0)
243
0
  {
244
0
    result = priv->proxy_address;
245
0
    priv->proxy_address = NULL;
246
0
    continue;
247
0
  }
248
249
0
      if (!priv->supports_hostname)
250
0
  {
251
0
    GInetAddress *dest_ip;
252
253
0
    if (!priv->dest_ips)
254
0
      {
255
0
        GResolver *resolver;
256
257
0
        resolver = g_resolver_get_default();
258
0
        priv->dest_ips = g_resolver_lookup_by_name (resolver,
259
0
                priv->dest_hostname,
260
0
                cancellable,
261
0
                first_error ? NULL : &first_error);
262
0
        g_object_unref (resolver);
263
264
0
        if (!priv->dest_ips)
265
0
    {
266
0
      g_object_unref (priv->proxy_address);
267
0
      priv->proxy_address = NULL;
268
0
      continue;
269
0
    }
270
0
      }
271
272
0
    if (!priv->next_dest_ip)
273
0
      priv->next_dest_ip = priv->dest_ips;
274
  
275
0
    dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
276
0
    dest_hostname = g_inet_address_to_string (dest_ip);
277
278
0
    priv->next_dest_ip = g_list_next (priv->next_dest_ip);
279
0
  }
280
0
      else
281
0
  {
282
0
    dest_hostname = g_strdup (priv->dest_hostname);
283
0
  }
284
0
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
285
          
286
0
      if (!G_IS_INET_SOCKET_ADDRESS (priv->proxy_address))
287
0
        {
288
0
    g_free (dest_hostname);
289
0
    g_free (dest_protocol);
290
0
        }
291
0
      g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address), NULL);
292
293
0
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
294
0
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
295
0
      port = g_inet_socket_address_get_port (inetsaddr);
296
297
0
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
298
0
           "address", inetaddr,
299
0
           "port", port,
300
0
           "protocol", priv->proxy_type,
301
0
           "destination-protocol", dest_protocol,
302
0
           "destination-hostname", dest_hostname,
303
0
           "destination-port", priv->dest_port,
304
0
           "username", priv->proxy_username,
305
0
           "password", priv->proxy_password,
306
0
           "uri", priv->proxy_uri,
307
0
           NULL);
308
0
      g_free (dest_hostname);
309
0
      g_free (dest_protocol);
310
311
0
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
312
0
  {
313
0
    g_object_unref (priv->proxy_address);
314
0
    priv->proxy_address = NULL;
315
0
  }
316
0
    }
317
318
0
  if (result == NULL && first_error && (!priv->ever_enumerated || g_error_matches (first_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
319
0
    g_propagate_error (error, first_error);
320
0
  else if (first_error)
321
0
    g_error_free (first_error);
322
323
0
  if (result == NULL && error != NULL && *error == NULL && !priv->ever_enumerated)
324
0
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
325
326
0
  priv->ever_enumerated = TRUE;
327
328
0
  return result;
329
0
}
330
331
static void
332
complete_async (GTask *task)
333
0
{
334
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
335
336
0
  if (priv->last_error && (!priv->ever_enumerated || g_error_matches (priv->last_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
337
0
    {
338
0
      g_task_return_error (task, priv->last_error);
339
0
      priv->last_error = NULL;
340
0
    }
341
0
  else if (!priv->ever_enumerated)
342
0
    g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
343
0
  else
344
0
    g_task_return_pointer (task, NULL, NULL);
345
346
0
  priv->ever_enumerated = TRUE;
347
348
0
  g_clear_error (&priv->last_error);
349
0
  g_object_unref (task);
350
0
}
351
352
static void
353
return_result (GTask *task)
354
0
{
355
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
356
0
  GSocketAddress *result;
357
0
  gboolean is_inet_socket_address;
358
359
0
  if (strcmp ("direct", priv->proxy_type) == 0)
360
0
    {
361
0
      result = priv->proxy_address;
362
0
      priv->proxy_address = NULL;
363
0
    }
364
0
  else
365
0
    {
366
0
      gchar *dest_hostname, *dest_protocol;
367
0
      GInetSocketAddress *inetsaddr;
368
0
      GInetAddress *inetaddr;
369
0
      guint16 port;
370
371
0
      if (!priv->supports_hostname)
372
0
  {
373
0
    GInetAddress *dest_ip;
374
375
0
    if (!priv->next_dest_ip)
376
0
      priv->next_dest_ip = priv->dest_ips;
377
378
0
    dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
379
0
    dest_hostname = g_inet_address_to_string (dest_ip);
380
381
0
    priv->next_dest_ip = g_list_next (priv->next_dest_ip);
382
0
  }
383
0
      else
384
0
  {
385
0
    dest_hostname = g_strdup (priv->dest_hostname);
386
0
  }
387
0
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
388
389
0
      is_inet_socket_address = G_IS_INET_SOCKET_ADDRESS (priv->proxy_address);
390
0
      if (!is_inet_socket_address)
391
0
        {
392
0
    g_free (dest_hostname);
393
0
    g_free (dest_protocol);
394
0
        }
395
0
      g_return_if_fail (is_inet_socket_address);
396
397
0
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
398
0
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
399
0
      port = g_inet_socket_address_get_port (inetsaddr);
400
401
0
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
402
0
           "address", inetaddr,
403
0
           "port", port,
404
0
           "protocol", priv->proxy_type,
405
0
           "destination-protocol", dest_protocol,
406
0
           "destination-hostname", dest_hostname,
407
0
           "destination-port", priv->dest_port,
408
0
           "username", priv->proxy_username,
409
0
           "password", priv->proxy_password,
410
0
           "uri", priv->proxy_uri,
411
0
           NULL);
412
0
      g_free (dest_hostname);
413
0
      g_free (dest_protocol);
414
415
0
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
416
0
  {
417
0
    g_object_unref (priv->proxy_address);
418
0
    priv->proxy_address = NULL;
419
0
  }
420
0
    }
421
422
0
  priv->ever_enumerated = TRUE;
423
0
  g_task_return_pointer (task, result, g_object_unref);
424
0
  g_object_unref (task);
425
0
}
426
427
static void address_enumerate_cb (GObject      *object,
428
          GAsyncResult *result,
429
          gpointer  user_data);
430
431
static void
432
next_proxy (GTask *task)
433
0
{
434
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
435
436
0
  if (*priv->next_proxy)
437
0
    {
438
0
      g_object_unref (priv->addr_enum);
439
0
      priv->addr_enum = NULL;
440
441
0
      if (priv->dest_ips)
442
0
  {
443
0
    g_resolver_free_addresses (priv->dest_ips);
444
0
    priv->dest_ips = NULL;
445
0
  }
446
447
0
      next_enumerator (priv);
448
449
0
      if (priv->addr_enum)
450
0
  {
451
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
452
0
              g_task_get_cancellable (task),
453
0
              address_enumerate_cb,
454
0
              task);
455
0
    return;
456
0
  }
457
0
    }
458
459
0
  complete_async (task);
460
0
}
461
462
static void
463
dest_hostname_lookup_cb (GObject           *object,
464
       GAsyncResult      *result,
465
       gpointer           user_data)
466
0
{
467
0
  GTask *task = user_data;
468
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
469
470
0
  g_clear_error (&priv->last_error);
471
0
  priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
472
0
                 result,
473
0
                 &priv->last_error);
474
0
  if (priv->dest_ips)
475
0
    return_result (task);
476
0
  else
477
0
    {
478
0
      g_clear_object (&priv->proxy_address);
479
0
      next_proxy (task);
480
0
    }
481
0
}
482
483
static void
484
address_enumerate_cb (GObject    *object,
485
          GAsyncResult *result,
486
          gpointer      user_data)
487
0
{
488
0
  GTask *task = user_data;
489
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
490
491
0
  g_clear_error (&priv->last_error);
492
0
  priv->proxy_address =
493
0
    g_socket_address_enumerator_next_finish (priv->addr_enum,
494
0
               result,
495
0
               &priv->last_error);
496
0
  if (priv->proxy_address)
497
0
    {
498
0
      if (!priv->supports_hostname && !priv->dest_ips)
499
0
  {
500
0
    GResolver *resolver;
501
0
    resolver = g_resolver_get_default();
502
0
    g_resolver_lookup_by_name_async (resolver,
503
0
             priv->dest_hostname,
504
0
             g_task_get_cancellable (task),
505
0
             dest_hostname_lookup_cb,
506
0
             task);
507
0
    g_object_unref (resolver);
508
0
    return;
509
0
  }
510
511
0
      return_result (task);
512
0
    }
513
0
  else
514
0
    next_proxy (task);
515
0
}
516
517
static void
518
proxy_lookup_cb (GObject      *object,
519
     GAsyncResult *result,
520
     gpointer      user_data)
521
0
{
522
0
  GTask *task = user_data;
523
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
524
525
0
  g_clear_error (&priv->last_error);
526
0
  priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
527
0
              result,
528
0
              &priv->last_error);
529
0
  priv->next_proxy = priv->proxies;
530
531
0
  if (priv->last_error)
532
0
    {
533
0
      complete_async (task);
534
0
      return;
535
0
    }
536
0
  else
537
0
    {
538
0
      next_enumerator (priv);
539
0
      if (priv->addr_enum)
540
0
  {
541
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
542
0
              g_task_get_cancellable (task),
543
0
              address_enumerate_cb,
544
0
              task);
545
0
    return;
546
0
  }
547
0
    }
548
549
0
  complete_async (task);
550
0
}
551
552
static void
553
g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
554
               GCancellable             *cancellable,
555
               GAsyncReadyCallback       callback,
556
               gpointer                  user_data)
557
0
{
558
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
559
0
  GTask *task;
560
561
0
  task = g_task_new (enumerator, cancellable, callback, user_data);
562
0
  g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
563
0
  g_task_set_task_data (task, priv, NULL);
564
565
0
  if (priv->proxies == NULL)
566
0
    {
567
0
      g_proxy_resolver_lookup_async (priv->proxy_resolver,
568
0
             priv->dest_uri,
569
0
             cancellable,
570
0
             proxy_lookup_cb,
571
0
             task);
572
0
      return;
573
0
    }
574
575
0
  if (priv->addr_enum)
576
0
    {
577
0
      if (priv->proxy_address)
578
0
  {
579
0
    return_result (task);
580
0
    return;
581
0
  }
582
0
      else
583
0
  {
584
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
585
0
              cancellable,
586
0
              address_enumerate_cb,
587
0
              task);
588
0
    return;
589
0
  }
590
0
    }
591
592
0
  complete_async (task);
593
0
}
594
595
static GSocketAddress *
596
g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
597
          GAsyncResult              *result,
598
          GError                   **error)
599
0
{
600
0
  g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
601
602
0
  return g_task_propagate_pointer (G_TASK (result), error);
603
0
}
604
605
static void
606
g_proxy_address_enumerator_constructed (GObject *object)
607
0
{
608
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
609
0
  GSocketConnectable *conn;
610
0
  guint port;
611
612
0
  if (priv->dest_uri)
613
0
    {
614
0
      conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
615
0
      if (conn)
616
0
        {
617
0
          g_object_get (conn,
618
0
                        "hostname", &priv->dest_hostname,
619
0
                        "port", &port,
620
0
                        NULL);
621
0
          priv->dest_port = port;
622
623
0
          g_object_unref (conn);
624
0
        }
625
0
      else
626
0
        g_warning ("Invalid URI '%s'", priv->dest_uri);
627
0
    }
628
629
0
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
630
0
}
631
632
static void
633
g_proxy_address_enumerator_get_property (GObject        *object,
634
                                         guint           property_id,
635
                                         GValue         *value,
636
                                         GParamSpec     *pspec)
637
0
{
638
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
639
0
  switch (property_id)
640
0
    {
641
0
    case PROP_URI:
642
0
      g_value_set_string (value, priv->dest_uri);
643
0
      break;
644
645
0
    case PROP_DEFAULT_PORT:
646
0
      g_value_set_uint (value, priv->default_port);
647
0
      break;
648
649
0
    case PROP_CONNECTABLE:
650
0
      g_value_set_object (value, priv->connectable);
651
0
      break;
652
653
0
    case PROP_PROXY_RESOLVER:
654
0
      g_value_set_object (value, priv->proxy_resolver);
655
0
      break;
656
657
0
    default:
658
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
659
0
    }
660
0
}
661
662
static void
663
g_proxy_address_enumerator_set_property (GObject        *object,
664
                                         guint           property_id,
665
                                         const GValue   *value,
666
                                         GParamSpec     *pspec)
667
0
{
668
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
669
0
  switch (property_id)
670
0
    {
671
0
    case PROP_URI:
672
0
      priv->dest_uri = g_value_dup_string (value);
673
0
      break;
674
675
0
    case PROP_DEFAULT_PORT:
676
0
      priv->default_port = g_value_get_uint (value);
677
0
      break;
678
679
0
    case PROP_CONNECTABLE:
680
0
      priv->connectable = g_value_dup_object (value);
681
0
      break;
682
683
0
    case PROP_PROXY_RESOLVER:
684
0
      if (priv->proxy_resolver)
685
0
        g_object_unref (priv->proxy_resolver);
686
0
      priv->proxy_resolver = g_value_get_object (value);
687
0
      if (!priv->proxy_resolver)
688
0
        priv->proxy_resolver = g_proxy_resolver_get_default ();
689
0
      g_object_ref (priv->proxy_resolver);
690
0
      break;
691
692
0
    default:
693
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
694
0
    }
695
0
}
696
697
static void
698
g_proxy_address_enumerator_finalize (GObject *object)
699
0
{
700
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
701
702
0
  if (priv->connectable)
703
0
    g_object_unref (priv->connectable);
704
705
0
  if (priv->proxy_resolver)
706
0
    g_object_unref (priv->proxy_resolver);
707
708
0
  g_free (priv->dest_uri);
709
0
  g_free (priv->dest_hostname);
710
711
0
  if (priv->dest_ips)
712
0
    g_resolver_free_addresses (priv->dest_ips);
713
714
0
  g_strfreev (priv->proxies);
715
716
0
  if (priv->addr_enum)
717
0
    g_object_unref (priv->addr_enum);
718
719
0
  g_free (priv->proxy_type);
720
0
  g_free (priv->proxy_username);
721
0
  g_free (priv->proxy_password);
722
723
0
  g_clear_error (&priv->last_error);
724
725
0
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
726
0
}
727
728
static void
729
g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
730
0
{
731
0
  self->priv = g_proxy_address_enumerator_get_instance_private (self);
732
0
}
733
734
static void
735
g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
736
0
{
737
0
  GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
738
0
  GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
739
740
0
  object_class->constructed = g_proxy_address_enumerator_constructed;
741
0
  object_class->set_property = g_proxy_address_enumerator_set_property;
742
0
  object_class->get_property = g_proxy_address_enumerator_get_property;
743
0
  object_class->finalize = g_proxy_address_enumerator_finalize;
744
745
0
  enumerator_class->next = g_proxy_address_enumerator_next;
746
0
  enumerator_class->next_async = g_proxy_address_enumerator_next_async;
747
0
  enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
748
749
0
  g_object_class_install_property (object_class,
750
0
           PROP_URI,
751
0
           g_param_spec_string ("uri",
752
0
              P_("URI"),
753
0
              P_("The destination URI, use none:// for generic socket"),
754
0
              NULL,
755
0
              G_PARAM_READWRITE |
756
0
              G_PARAM_CONSTRUCT_ONLY |
757
0
              G_PARAM_STATIC_STRINGS));
758
759
  /**
760
   * GProxyAddressEnumerator:default-port:
761
   *
762
   * The default port to use if #GProxyAddressEnumerator:uri does not
763
   * specify one.
764
   *
765
   * Since: 2.38
766
   */
767
0
  g_object_class_install_property (object_class,
768
0
           PROP_DEFAULT_PORT,
769
0
           g_param_spec_uint ("default-port",
770
0
                                                      P_("Default port"),
771
0
                                                      P_("The default port to use if uri does not specify one"),
772
0
                                                      0, 65535, 0,
773
0
                                                      G_PARAM_READWRITE |
774
0
                                                      G_PARAM_CONSTRUCT_ONLY |
775
0
                                                      G_PARAM_STATIC_STRINGS));
776
777
0
  g_object_class_install_property (object_class,
778
0
           PROP_CONNECTABLE,
779
0
           g_param_spec_object ("connectable",
780
0
              P_("Connectable"),
781
0
              P_("The connectable being enumerated."),
782
0
              G_TYPE_SOCKET_CONNECTABLE,
783
0
              G_PARAM_READWRITE |
784
0
              G_PARAM_CONSTRUCT_ONLY |
785
0
              G_PARAM_STATIC_STRINGS));
786
787
  /**
788
   * GProxyAddressEnumerator:proxy-resolver:
789
   *
790
   * The proxy resolver to use.
791
   *
792
   * Since: 2.36
793
   */
794
0
  g_object_class_install_property (object_class,
795
0
                                   PROP_PROXY_RESOLVER,
796
0
                                   g_param_spec_object ("proxy-resolver",
797
0
                                                        P_("Proxy resolver"),
798
0
                                                        P_("The proxy resolver to use."),
799
0
                                                        G_TYPE_PROXY_RESOLVER,
800
0
                                                        G_PARAM_READWRITE |
801
0
                                                        G_PARAM_CONSTRUCT |
802
0
                                                        G_PARAM_STATIC_STRINGS));
803
0
}