Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib-2.80.0/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 "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
 * GProxyAddressEnumerator:
46
 *
47
 * `GProxyAddressEnumerator` is a wrapper around
48
 * [class@Gio.SocketAddressEnumerator] which takes the [class@Gio.SocketAddress]
49
 * instances returned by the [class@Gio.SocketAddressEnumerator]
50
 * and wraps them in [class@Gio.ProxyAddress] instances, using the given
51
 * [property@Gio.ProxyAddressEnumerator:proxy-resolver].
52
 *
53
 * This enumerator will be returned (for example, by
54
 * [method@Gio.SocketConnectable.enumerate]) as appropriate when a proxy is
55
 * configured; there should be no need to manually wrap a
56
 * [class@Gio.SocketAddressEnumerator] instance 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
0
    int default_port;
162
163
0
    default_port = GLIB_PRIVATE_CALL (g_uri_get_default_scheme_port) (priv->proxy_type);
164
0
    if (default_port == -1)
165
0
      default_port = 0;
166
167
0
    connectable = g_network_address_parse_uri (priv->proxy_uri, default_port, &error);
168
0
    if (error)
169
0
      {
170
0
        g_warning ("Invalid proxy URI '%s': %s",
171
0
       priv->proxy_uri, error->message);
172
0
        g_error_free (error);
173
0
      }
174
175
0
    save_userinfo (priv, priv->proxy_uri);
176
0
  }
177
178
0
      if (connectable)
179
0
  {
180
0
    priv->addr_enum = g_socket_connectable_enumerate (connectable);
181
0
    g_object_unref (connectable);
182
0
  }
183
0
    }
184
0
}
185
186
static GSocketAddress *
187
g_proxy_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
188
         GCancellable              *cancellable,
189
         GError                   **error)
190
0
{
191
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
192
0
  GSocketAddress *result = NULL;
193
0
  GError *first_error = NULL;
194
195
0
  if (!priv->ever_enumerated)
196
0
    {
197
0
      g_assert (priv->proxies == NULL);
198
0
      priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
199
0
                 priv->dest_uri,
200
0
                 cancellable,
201
0
                 error);
202
0
      priv->next_proxy = priv->proxies;
203
204
0
      if (priv->proxies == NULL)
205
0
  {
206
0
    priv->ever_enumerated = TRUE;
207
0
    return NULL;
208
0
  }
209
0
    }
210
211
0
  while (result == NULL && (*priv->next_proxy || priv->addr_enum))
212
0
    {
213
0
      gchar *dest_hostname;
214
0
      gchar *dest_protocol;
215
0
      GInetSocketAddress *inetsaddr;
216
0
      GInetAddress *inetaddr;
217
0
      guint16 port;
218
219
0
      next_enumerator (priv);
220
221
0
      if (!priv->addr_enum)
222
0
  continue;
223
224
0
      if (priv->proxy_address == NULL)
225
0
  {
226
0
    priv->proxy_address = g_socket_address_enumerator_next (
227
0
            priv->addr_enum,
228
0
            cancellable,
229
0
            first_error ? NULL : &first_error);
230
0
  }
231
232
0
      if (priv->proxy_address == NULL)
233
0
  {
234
0
    g_object_unref (priv->addr_enum);
235
0
    priv->addr_enum = NULL;
236
237
0
    if (priv->dest_ips)
238
0
      {
239
0
        g_resolver_free_addresses (priv->dest_ips);
240
0
        priv->dest_ips = NULL;
241
0
      }
242
243
0
    continue;
244
0
  }
245
246
0
      if (strcmp ("direct", priv->proxy_type) == 0)
247
0
  {
248
0
    result = priv->proxy_address;
249
0
    priv->proxy_address = NULL;
250
0
    continue;
251
0
  }
252
253
0
      if (!priv->supports_hostname)
254
0
  {
255
0
    GInetAddress *dest_ip;
256
257
0
    if (!priv->dest_ips)
258
0
      {
259
0
        GResolver *resolver;
260
261
0
        resolver = g_resolver_get_default();
262
0
        priv->dest_ips = g_resolver_lookup_by_name (resolver,
263
0
                priv->dest_hostname,
264
0
                cancellable,
265
0
                first_error ? NULL : &first_error);
266
0
        g_object_unref (resolver);
267
268
0
        if (!priv->dest_ips)
269
0
    {
270
0
      g_object_unref (priv->proxy_address);
271
0
      priv->proxy_address = NULL;
272
0
      continue;
273
0
    }
274
0
      }
275
276
0
    if (!priv->next_dest_ip)
277
0
      priv->next_dest_ip = priv->dest_ips;
278
  
279
0
    dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
280
0
    dest_hostname = g_inet_address_to_string (dest_ip);
281
282
0
    priv->next_dest_ip = g_list_next (priv->next_dest_ip);
283
0
  }
284
0
      else
285
0
  {
286
0
    dest_hostname = g_strdup (priv->dest_hostname);
287
0
  }
288
0
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
289
          
290
0
      if (!G_IS_INET_SOCKET_ADDRESS (priv->proxy_address))
291
0
        {
292
0
    g_free (dest_hostname);
293
0
    g_free (dest_protocol);
294
0
        }
295
0
      g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address), NULL);
296
297
0
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
298
0
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
299
0
      port = g_inet_socket_address_get_port (inetsaddr);
300
301
0
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
302
0
           "address", inetaddr,
303
0
           "port", port,
304
0
           "protocol", priv->proxy_type,
305
0
           "destination-protocol", dest_protocol,
306
0
           "destination-hostname", dest_hostname,
307
0
           "destination-port", priv->dest_port,
308
0
           "username", priv->proxy_username,
309
0
           "password", priv->proxy_password,
310
0
           "uri", priv->proxy_uri,
311
0
           NULL);
312
0
      g_free (dest_hostname);
313
0
      g_free (dest_protocol);
314
315
0
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
316
0
  {
317
0
    g_object_unref (priv->proxy_address);
318
0
    priv->proxy_address = NULL;
319
0
  }
320
0
    }
321
322
0
  if (result == NULL && first_error && (!priv->ever_enumerated || g_error_matches (first_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
323
0
    g_propagate_error (error, first_error);
324
0
  else if (first_error)
325
0
    g_error_free (first_error);
326
327
0
  if (result == NULL && error != NULL && *error == NULL && !priv->ever_enumerated)
328
0
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
329
330
0
  priv->ever_enumerated = TRUE;
331
332
0
  return result;
333
0
}
334
335
static void
336
complete_async (GTask *task)
337
0
{
338
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
339
340
0
  if (priv->last_error && (!priv->ever_enumerated || g_error_matches (priv->last_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
341
0
    {
342
0
      g_task_return_error (task, priv->last_error);
343
0
      priv->last_error = NULL;
344
0
    }
345
0
  else if (!priv->ever_enumerated)
346
0
    {
347
0
      g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED,
348
0
                                       _("Unspecified proxy lookup failure"));
349
0
    }
350
0
  else
351
0
    {
352
0
      g_task_return_pointer (task, NULL, NULL);
353
0
    }
354
355
0
  priv->ever_enumerated = TRUE;
356
357
0
  g_clear_error (&priv->last_error);
358
0
  g_object_unref (task);
359
0
}
360
361
static void
362
return_result (GTask *task)
363
0
{
364
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
365
0
  GSocketAddress *result;
366
0
  gboolean is_inet_socket_address;
367
368
0
  if (strcmp ("direct", priv->proxy_type) == 0)
369
0
    {
370
0
      result = priv->proxy_address;
371
0
      priv->proxy_address = NULL;
372
0
    }
373
0
  else
374
0
    {
375
0
      gchar *dest_hostname, *dest_protocol;
376
0
      GInetSocketAddress *inetsaddr;
377
0
      GInetAddress *inetaddr;
378
0
      guint16 port;
379
380
0
      if (!priv->supports_hostname)
381
0
  {
382
0
    GInetAddress *dest_ip;
383
384
0
    if (!priv->next_dest_ip)
385
0
      priv->next_dest_ip = priv->dest_ips;
386
387
0
    dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
388
0
    dest_hostname = g_inet_address_to_string (dest_ip);
389
390
0
    priv->next_dest_ip = g_list_next (priv->next_dest_ip);
391
0
  }
392
0
      else
393
0
  {
394
0
    dest_hostname = g_strdup (priv->dest_hostname);
395
0
  }
396
0
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
397
398
0
      is_inet_socket_address = G_IS_INET_SOCKET_ADDRESS (priv->proxy_address);
399
0
      if (!is_inet_socket_address)
400
0
        {
401
0
    g_free (dest_hostname);
402
0
    g_free (dest_protocol);
403
0
        }
404
0
      g_return_if_fail (is_inet_socket_address);
405
406
0
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
407
0
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
408
0
      port = g_inet_socket_address_get_port (inetsaddr);
409
410
0
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
411
0
           "address", inetaddr,
412
0
           "port", port,
413
0
           "protocol", priv->proxy_type,
414
0
           "destination-protocol", dest_protocol,
415
0
           "destination-hostname", dest_hostname,
416
0
           "destination-port", priv->dest_port,
417
0
           "username", priv->proxy_username,
418
0
           "password", priv->proxy_password,
419
0
           "uri", priv->proxy_uri,
420
0
           NULL);
421
0
      g_free (dest_hostname);
422
0
      g_free (dest_protocol);
423
424
0
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
425
0
  {
426
0
    g_object_unref (priv->proxy_address);
427
0
    priv->proxy_address = NULL;
428
0
  }
429
0
    }
430
431
0
  priv->ever_enumerated = TRUE;
432
0
  g_task_return_pointer (task, result, g_object_unref);
433
0
  g_object_unref (task);
434
0
}
435
436
static void address_enumerate_cb (GObject      *object,
437
          GAsyncResult *result,
438
          gpointer  user_data);
439
440
static void
441
next_proxy (GTask *task)
442
0
{
443
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
444
445
0
  if (*priv->next_proxy)
446
0
    {
447
0
      g_object_unref (priv->addr_enum);
448
0
      priv->addr_enum = NULL;
449
450
0
      if (priv->dest_ips)
451
0
  {
452
0
    g_resolver_free_addresses (priv->dest_ips);
453
0
    priv->dest_ips = NULL;
454
0
  }
455
456
0
      next_enumerator (priv);
457
458
0
      if (priv->addr_enum)
459
0
  {
460
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
461
0
              g_task_get_cancellable (task),
462
0
              address_enumerate_cb,
463
0
              task);
464
0
    return;
465
0
  }
466
0
    }
467
468
0
  complete_async (task);
469
0
}
470
471
static void
472
dest_hostname_lookup_cb (GObject           *object,
473
       GAsyncResult      *result,
474
       gpointer           user_data)
475
0
{
476
0
  GTask *task = user_data;
477
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
478
479
0
  g_clear_error (&priv->last_error);
480
0
  priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
481
0
                 result,
482
0
                 &priv->last_error);
483
0
  if (priv->dest_ips)
484
0
    return_result (task);
485
0
  else
486
0
    {
487
0
      g_clear_object (&priv->proxy_address);
488
0
      next_proxy (task);
489
0
    }
490
0
}
491
492
static void
493
address_enumerate_cb (GObject    *object,
494
          GAsyncResult *result,
495
          gpointer      user_data)
496
0
{
497
0
  GTask *task = user_data;
498
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
499
500
0
  g_clear_error (&priv->last_error);
501
0
  priv->proxy_address =
502
0
    g_socket_address_enumerator_next_finish (priv->addr_enum,
503
0
               result,
504
0
               &priv->last_error);
505
0
  if (priv->proxy_address)
506
0
    {
507
0
      if (!priv->supports_hostname && !priv->dest_ips)
508
0
  {
509
0
    GResolver *resolver;
510
0
    resolver = g_resolver_get_default();
511
0
    g_resolver_lookup_by_name_async (resolver,
512
0
             priv->dest_hostname,
513
0
             g_task_get_cancellable (task),
514
0
             dest_hostname_lookup_cb,
515
0
             task);
516
0
    g_object_unref (resolver);
517
0
    return;
518
0
  }
519
520
0
      return_result (task);
521
0
    }
522
0
  else
523
0
    next_proxy (task);
524
0
}
525
526
static void
527
proxy_lookup_cb (GObject      *object,
528
     GAsyncResult *result,
529
     gpointer      user_data)
530
0
{
531
0
  GTask *task = user_data;
532
0
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
533
534
0
  g_clear_error (&priv->last_error);
535
0
  priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
536
0
              result,
537
0
              &priv->last_error);
538
0
  priv->next_proxy = priv->proxies;
539
540
0
  if (priv->last_error)
541
0
    {
542
0
      complete_async (task);
543
0
      return;
544
0
    }
545
0
  else
546
0
    {
547
0
      next_enumerator (priv);
548
0
      if (priv->addr_enum)
549
0
  {
550
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
551
0
              g_task_get_cancellable (task),
552
0
              address_enumerate_cb,
553
0
              task);
554
0
    return;
555
0
  }
556
0
    }
557
558
0
  complete_async (task);
559
0
}
560
561
static void
562
g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
563
               GCancellable             *cancellable,
564
               GAsyncReadyCallback       callback,
565
               gpointer                  user_data)
566
0
{
567
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
568
0
  GTask *task;
569
570
0
  task = g_task_new (enumerator, cancellable, callback, user_data);
571
0
  g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
572
0
  g_task_set_task_data (task, priv, NULL);
573
574
0
  if (priv->proxies == NULL)
575
0
    {
576
0
      g_proxy_resolver_lookup_async (priv->proxy_resolver,
577
0
             priv->dest_uri,
578
0
             cancellable,
579
0
             proxy_lookup_cb,
580
0
             task);
581
0
      return;
582
0
    }
583
584
0
  if (priv->addr_enum)
585
0
    {
586
0
      if (priv->proxy_address)
587
0
  {
588
0
    return_result (task);
589
0
    return;
590
0
  }
591
0
      else
592
0
  {
593
0
    g_socket_address_enumerator_next_async (priv->addr_enum,
594
0
              cancellable,
595
0
              address_enumerate_cb,
596
0
              task);
597
0
    return;
598
0
  }
599
0
    }
600
601
0
  complete_async (task);
602
0
}
603
604
static GSocketAddress *
605
g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
606
          GAsyncResult              *result,
607
          GError                   **error)
608
0
{
609
0
  g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
610
611
0
  return g_task_propagate_pointer (G_TASK (result), error);
612
0
}
613
614
static void
615
g_proxy_address_enumerator_constructed (GObject *object)
616
0
{
617
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
618
0
  GSocketConnectable *conn;
619
0
  guint port;
620
621
0
  if (priv->dest_uri)
622
0
    {
623
0
      conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
624
0
      if (conn)
625
0
        {
626
0
          g_object_get (conn,
627
0
                        "hostname", &priv->dest_hostname,
628
0
                        "port", &port,
629
0
                        NULL);
630
0
          priv->dest_port = port;
631
632
0
          g_object_unref (conn);
633
0
        }
634
0
      else
635
0
        g_warning ("Invalid URI '%s'", priv->dest_uri);
636
0
    }
637
638
0
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
639
0
}
640
641
static void
642
g_proxy_address_enumerator_get_property (GObject        *object,
643
                                         guint           property_id,
644
                                         GValue         *value,
645
                                         GParamSpec     *pspec)
646
0
{
647
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
648
0
  switch (property_id)
649
0
    {
650
0
    case PROP_URI:
651
0
      g_value_set_string (value, priv->dest_uri);
652
0
      break;
653
654
0
    case PROP_DEFAULT_PORT:
655
0
      g_value_set_uint (value, priv->default_port);
656
0
      break;
657
658
0
    case PROP_CONNECTABLE:
659
0
      g_value_set_object (value, priv->connectable);
660
0
      break;
661
662
0
    case PROP_PROXY_RESOLVER:
663
0
      g_value_set_object (value, priv->proxy_resolver);
664
0
      break;
665
666
0
    default:
667
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
668
0
    }
669
0
}
670
671
static void
672
g_proxy_address_enumerator_set_property (GObject        *object,
673
                                         guint           property_id,
674
                                         const GValue   *value,
675
                                         GParamSpec     *pspec)
676
0
{
677
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
678
0
  switch (property_id)
679
0
    {
680
0
    case PROP_URI:
681
0
      priv->dest_uri = g_value_dup_string (value);
682
0
      break;
683
684
0
    case PROP_DEFAULT_PORT:
685
0
      priv->default_port = g_value_get_uint (value);
686
0
      break;
687
688
0
    case PROP_CONNECTABLE:
689
0
      priv->connectable = g_value_dup_object (value);
690
0
      break;
691
692
0
    case PROP_PROXY_RESOLVER:
693
0
      if (priv->proxy_resolver)
694
0
        g_object_unref (priv->proxy_resolver);
695
0
      priv->proxy_resolver = g_value_get_object (value);
696
0
      if (!priv->proxy_resolver)
697
0
        priv->proxy_resolver = g_proxy_resolver_get_default ();
698
0
      g_object_ref (priv->proxy_resolver);
699
0
      break;
700
701
0
    default:
702
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
703
0
    }
704
0
}
705
706
static void
707
g_proxy_address_enumerator_finalize (GObject *object)
708
0
{
709
0
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
710
711
0
  if (priv->connectable)
712
0
    g_object_unref (priv->connectable);
713
714
0
  if (priv->proxy_resolver)
715
0
    g_object_unref (priv->proxy_resolver);
716
717
0
  g_free (priv->dest_uri);
718
0
  g_free (priv->dest_hostname);
719
720
0
  if (priv->dest_ips)
721
0
    g_resolver_free_addresses (priv->dest_ips);
722
723
0
  g_strfreev (priv->proxies);
724
725
0
  if (priv->addr_enum)
726
0
    g_object_unref (priv->addr_enum);
727
728
0
  g_free (priv->proxy_type);
729
0
  g_free (priv->proxy_username);
730
0
  g_free (priv->proxy_password);
731
732
0
  g_clear_error (&priv->last_error);
733
734
0
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
735
0
}
736
737
static void
738
g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
739
0
{
740
0
  self->priv = g_proxy_address_enumerator_get_instance_private (self);
741
0
}
742
743
static void
744
g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
745
0
{
746
0
  GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
747
0
  GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
748
749
0
  object_class->constructed = g_proxy_address_enumerator_constructed;
750
0
  object_class->set_property = g_proxy_address_enumerator_set_property;
751
0
  object_class->get_property = g_proxy_address_enumerator_get_property;
752
0
  object_class->finalize = g_proxy_address_enumerator_finalize;
753
754
0
  enumerator_class->next = g_proxy_address_enumerator_next;
755
0
  enumerator_class->next_async = g_proxy_address_enumerator_next_async;
756
0
  enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
757
758
  /**
759
   * GProxyAddressEnumerator:uri:
760
   *
761
   * The destination URI. Use `none://` for a generic socket.
762
   */
763
0
  g_object_class_install_property (object_class,
764
0
           PROP_URI,
765
0
           g_param_spec_string ("uri", NULL, NULL,
766
0
              NULL,
767
0
              G_PARAM_READWRITE |
768
0
              G_PARAM_CONSTRUCT_ONLY |
769
0
              G_PARAM_STATIC_STRINGS));
770
771
  /**
772
   * GProxyAddressEnumerator:default-port:
773
   *
774
   * The default port to use if #GProxyAddressEnumerator:uri does not
775
   * specify one.
776
   *
777
   * Since: 2.38
778
   */
779
0
  g_object_class_install_property (object_class,
780
0
           PROP_DEFAULT_PORT,
781
0
           g_param_spec_uint ("default-port", NULL, NULL,
782
0
                                                      0, 65535, 0,
783
0
                                                      G_PARAM_READWRITE |
784
0
                                                      G_PARAM_CONSTRUCT_ONLY |
785
0
                                                      G_PARAM_STATIC_STRINGS));
786
787
  /**
788
   * GProxyAddressEnumerator:connectable:
789
   *
790
   * The connectable being enumerated.
791
   */
792
0
  g_object_class_install_property (object_class,
793
0
           PROP_CONNECTABLE,
794
0
           g_param_spec_object ("connectable", NULL, NULL,
795
0
              G_TYPE_SOCKET_CONNECTABLE,
796
0
              G_PARAM_READWRITE |
797
0
              G_PARAM_CONSTRUCT_ONLY |
798
0
              G_PARAM_STATIC_STRINGS));
799
800
  /**
801
   * GProxyAddressEnumerator:proxy-resolver:
802
   *
803
   * The proxy resolver to use.
804
   *
805
   * Since: 2.36
806
   */
807
0
  g_object_class_install_property (object_class,
808
0
                                   PROP_PROXY_RESOLVER,
809
0
                                   g_param_spec_object ("proxy-resolver", NULL, NULL,
810
0
                                                        G_TYPE_PROXY_RESOLVER,
811
0
                                                        G_PARAM_READWRITE |
812
0
                                                        G_PARAM_CONSTRUCT |
813
0
                                                        G_PARAM_STATIC_STRINGS));
814
0
}