Coverage Report

Created: 2025-06-13 06:55

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