Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/glib/gio/gsocketclient.c
Line
Count
Source (jump to first uncovered line)
1
/*  GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright © 2008, 2009 codethink
4
 * Copyright © 2009 Red Hat, Inc
5
 * Copyright © 2018 Igalia S.L.
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
 * Authors: Ryan Lortie <desrt@desrt.ca>
23
 *          Alexander Larsson <alexl@redhat.com>
24
 */
25
26
#include "config.h"
27
#include "gsocketclient.h"
28
29
#ifndef G_OS_WIN32
30
#include <netinet/in.h>
31
#endif
32
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include <gio/gioenumtypes.h>
37
#include <gio/gsocketaddressenumerator.h>
38
#include <gio/gsocketconnectable.h>
39
#include <gio/gsocketconnection.h>
40
#include <gio/gioprivate.h>
41
#include <gio/gproxyaddressenumerator.h>
42
#include <gio/gproxyaddress.h>
43
#include <gio/gtask.h>
44
#include <gio/gcancellable.h>
45
#include <gio/gioerror.h>
46
#include <gio/gsocket.h>
47
#include <gio/gnetworkaddress.h>
48
#include <gio/gnetworking.h>
49
#include <gio/gnetworkservice.h>
50
#include <gio/gproxy.h>
51
#include <gio/gproxyresolver.h>
52
#include <gio/gsocketaddress.h>
53
#include <gio/gtcpconnection.h>
54
#include <gio/gtcpwrapperconnection.h>
55
#include <gio/gtlscertificate.h>
56
#include <gio/gtlsclientconnection.h>
57
#include <gio/ginetaddress.h>
58
#include "glibintl.h"
59
#include "gmarshal-internal.h"
60
61
/* As recommended by RFC 8305 this is the time it waits
62
 * on a connection before starting another concurrent attempt.
63
 *
64
 * See https://datatracker.ietf.org/doc/html/rfc8305#section-8
65
 */
66
0
#define HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS 250
67
68
/**
69
 * GSocketClient:
70
 *
71
 * `GSocketClient` is a lightweight high-level utility class for connecting to
72
 * a network host using a connection oriented socket type.
73
 *
74
 * You create a `GSocketClient` object, set any options you want, and then
75
 * call a sync or async connect operation, which returns a
76
 * [class@Gio.SocketConnection] subclass on success.
77
 *
78
 * The type of the [class@Gio.SocketConnection] object returned depends on the
79
 * type of the underlying socket that is in use. For instance, for a TCP/IP
80
 * connection it will be a [class@Gio.TcpConnection].
81
 *
82
 * As `GSocketClient` is a lightweight object, you don't need to cache it. You
83
 * can just create a new one any time you need one.
84
 *
85
 * Since: 2.22
86
 */
87
88
89
enum
90
{
91
  EVENT,
92
  LAST_SIGNAL
93
};
94
95
static guint signals[LAST_SIGNAL] = { 0 };
96
97
enum
98
{
99
  PROP_NONE,
100
  PROP_FAMILY,
101
  PROP_TYPE,
102
  PROP_PROTOCOL,
103
  PROP_LOCAL_ADDRESS,
104
  PROP_TIMEOUT,
105
  PROP_ENABLE_PROXY,
106
  PROP_TLS,
107
  PROP_TLS_VALIDATION_FLAGS,
108
  PROP_PROXY_RESOLVER
109
};
110
111
struct _GSocketClientPrivate
112
{
113
  GSocketFamily family;
114
  GSocketType type;
115
  GSocketProtocol protocol;
116
  GSocketAddress *local_address;
117
  guint timeout;
118
  gboolean enable_proxy;
119
  GHashTable *app_proxies;
120
  gboolean tls;
121
  GTlsCertificateFlags tls_validation_flags;
122
  GProxyResolver *proxy_resolver;
123
};
124
125
G_DEFINE_TYPE_WITH_PRIVATE (GSocketClient, g_socket_client, G_TYPE_OBJECT)
126
127
static GSocket *
128
create_socket (GSocketClient  *client,
129
         GSocketAddress *dest_address,
130
         GError        **error)
131
0
{
132
0
  GSocketFamily family;
133
0
  GSocket *socket;
134
135
0
  family = client->priv->family;
136
0
  if (family == G_SOCKET_FAMILY_INVALID &&
137
0
      client->priv->local_address != NULL)
138
0
    family = g_socket_address_get_family (client->priv->local_address);
139
0
  if (family == G_SOCKET_FAMILY_INVALID)
140
0
    family = g_socket_address_get_family (dest_address);
141
142
0
  socket = g_socket_new (family,
143
0
       client->priv->type,
144
0
       client->priv->protocol,
145
0
       error);
146
0
  if (socket == NULL)
147
0
    return NULL;
148
149
0
  if (client->priv->local_address)
150
0
    {
151
0
#ifdef IP_BIND_ADDRESS_NO_PORT
152
0
      g_socket_set_option (socket, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, 1, NULL);
153
0
#endif
154
155
0
      if (!g_socket_bind (socket,
156
0
        client->priv->local_address,
157
0
        FALSE,
158
0
        error))
159
0
  {
160
0
    g_object_unref (socket);
161
0
    return NULL;
162
0
  }
163
0
    }
164
165
0
  if (client->priv->timeout)
166
0
    g_socket_set_timeout (socket, client->priv->timeout);
167
168
0
  return socket;
169
0
}
170
171
static gboolean
172
can_use_proxy (GSocketClient *client)
173
0
{
174
0
  GSocketClientPrivate *priv = client->priv;
175
176
0
  return priv->enable_proxy
177
0
          && priv->type == G_SOCKET_TYPE_STREAM;
178
0
}
179
180
static void
181
clarify_connect_error (GError             *error,
182
           GSocketConnectable *connectable,
183
           GSocketAddress     *address)
184
0
{
185
0
  const char *name;
186
0
  char *tmp_name = NULL;
187
188
0
  if (G_IS_PROXY_ADDRESS (address))
189
0
    {
190
0
      name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)));
191
192
0
      g_prefix_error (&error, _("Could not connect to proxy server %s: "), name);
193
0
    }
194
0
  else
195
0
    {
196
0
      if (G_IS_NETWORK_ADDRESS (connectable))
197
0
  name = g_network_address_get_hostname (G_NETWORK_ADDRESS (connectable));
198
0
      else if (G_IS_NETWORK_SERVICE (connectable))
199
0
  name = g_network_service_get_domain (G_NETWORK_SERVICE (connectable));
200
0
      else if (G_IS_INET_SOCKET_ADDRESS (connectable))
201
0
  name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (connectable)));
202
0
      else
203
0
  name = NULL;
204
205
0
      if (name)
206
0
  g_prefix_error (&error, _("Could not connect to %s: "), name);
207
0
      else
208
0
  g_prefix_error (&error, _("Could not connect: "));
209
0
    }
210
211
0
  g_free (tmp_name);
212
0
}
213
214
static void
215
g_socket_client_init (GSocketClient *client)
216
0
{
217
0
  client->priv = g_socket_client_get_instance_private (client);
218
0
  client->priv->type = G_SOCKET_TYPE_STREAM;
219
0
  client->priv->app_proxies = g_hash_table_new_full (g_str_hash,
220
0
                 g_str_equal,
221
0
                 g_free,
222
0
                 NULL);
223
0
}
224
225
/**
226
 * g_socket_client_new:
227
 *
228
 * Creates a new #GSocketClient with the default options.
229
 *
230
 * Returns: a #GSocketClient.
231
 *     Free the returned object with g_object_unref().
232
 *
233
 * Since: 2.22
234
 */
235
GSocketClient *
236
g_socket_client_new (void)
237
0
{
238
0
  return g_object_new (G_TYPE_SOCKET_CLIENT, NULL);
239
0
}
240
241
static void
242
g_socket_client_finalize (GObject *object)
243
0
{
244
0
  GSocketClient *client = G_SOCKET_CLIENT (object);
245
246
0
  g_clear_object (&client->priv->local_address);
247
0
  g_clear_object (&client->priv->proxy_resolver);
248
249
0
  G_OBJECT_CLASS (g_socket_client_parent_class)->finalize (object);
250
251
0
  g_hash_table_unref (client->priv->app_proxies);
252
0
}
253
254
static void
255
g_socket_client_get_property (GObject    *object,
256
            guint       prop_id,
257
            GValue     *value,
258
            GParamSpec *pspec)
259
0
{
260
0
  GSocketClient *client = G_SOCKET_CLIENT (object);
261
262
0
  switch (prop_id)
263
0
    {
264
0
      case PROP_FAMILY:
265
0
  g_value_set_enum (value, client->priv->family);
266
0
  break;
267
268
0
      case PROP_TYPE:
269
0
  g_value_set_enum (value, client->priv->type);
270
0
  break;
271
272
0
      case PROP_PROTOCOL:
273
0
  g_value_set_enum (value, client->priv->protocol);
274
0
  break;
275
276
0
      case PROP_LOCAL_ADDRESS:
277
0
  g_value_set_object (value, client->priv->local_address);
278
0
  break;
279
280
0
      case PROP_TIMEOUT:
281
0
  g_value_set_uint (value, client->priv->timeout);
282
0
  break;
283
284
0
      case PROP_ENABLE_PROXY:
285
0
  g_value_set_boolean (value, client->priv->enable_proxy);
286
0
  break;
287
288
0
      case PROP_TLS:
289
0
  g_value_set_boolean (value, g_socket_client_get_tls (client));
290
0
  break;
291
292
0
      case PROP_TLS_VALIDATION_FLAGS:
293
0
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
294
0
  g_value_set_flags (value, g_socket_client_get_tls_validation_flags (client));
295
0
G_GNUC_END_IGNORE_DEPRECATIONS
296
0
  break;
297
298
0
      case PROP_PROXY_RESOLVER:
299
0
  g_value_set_object (value, g_socket_client_get_proxy_resolver (client));
300
0
  break;
301
302
0
      default:
303
0
  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
304
0
    }
305
0
}
306
307
static void
308
g_socket_client_set_property (GObject      *object,
309
            guint         prop_id,
310
            const GValue *value,
311
            GParamSpec   *pspec)
312
0
{
313
0
  GSocketClient *client = G_SOCKET_CLIENT (object);
314
315
0
  switch (prop_id)
316
0
    {
317
0
    case PROP_FAMILY:
318
0
      g_socket_client_set_family (client, g_value_get_enum (value));
319
0
      break;
320
321
0
    case PROP_TYPE:
322
0
      g_socket_client_set_socket_type (client, g_value_get_enum (value));
323
0
      break;
324
325
0
    case PROP_PROTOCOL:
326
0
      g_socket_client_set_protocol (client, g_value_get_enum (value));
327
0
      break;
328
329
0
    case PROP_LOCAL_ADDRESS:
330
0
      g_socket_client_set_local_address (client, g_value_get_object (value));
331
0
      break;
332
333
0
    case PROP_TIMEOUT:
334
0
      g_socket_client_set_timeout (client, g_value_get_uint (value));
335
0
      break;
336
337
0
    case PROP_ENABLE_PROXY:
338
0
      g_socket_client_set_enable_proxy (client, g_value_get_boolean (value));
339
0
      break;
340
341
0
    case PROP_TLS:
342
0
      g_socket_client_set_tls (client, g_value_get_boolean (value));
343
0
      break;
344
345
0
    case PROP_TLS_VALIDATION_FLAGS:
346
0
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
347
0
      g_socket_client_set_tls_validation_flags (client, g_value_get_flags (value));
348
0
G_GNUC_END_IGNORE_DEPRECATIONS
349
0
      break;
350
351
0
    case PROP_PROXY_RESOLVER:
352
0
      g_socket_client_set_proxy_resolver (client, g_value_get_object (value));
353
0
      break;
354
355
0
    default:
356
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
357
0
    }
358
0
}
359
360
/**
361
 * g_socket_client_get_family:
362
 * @client: a #GSocketClient.
363
 *
364
 * Gets the socket family of the socket client.
365
 *
366
 * See g_socket_client_set_family() for details.
367
 *
368
 * Returns: a #GSocketFamily
369
 *
370
 * Since: 2.22
371
 */
372
GSocketFamily
373
g_socket_client_get_family (GSocketClient *client)
374
0
{
375
0
  return client->priv->family;
376
0
}
377
378
/**
379
 * g_socket_client_set_family:
380
 * @client: a #GSocketClient.
381
 * @family: a #GSocketFamily
382
 *
383
 * Sets the socket family of the socket client.
384
 * If this is set to something other than %G_SOCKET_FAMILY_INVALID
385
 * then the sockets created by this object will be of the specified
386
 * family.
387
 *
388
 * This might be useful for instance if you want to force the local
389
 * connection to be an ipv4 socket, even though the address might
390
 * be an ipv6 mapped to ipv4 address.
391
 *
392
 * Since: 2.22
393
 */
394
void
395
g_socket_client_set_family (GSocketClient *client,
396
          GSocketFamily  family)
397
0
{
398
0
  if (client->priv->family == family)
399
0
    return;
400
401
0
  client->priv->family = family;
402
0
  g_object_notify (G_OBJECT (client), "family");
403
0
}
404
405
/**
406
 * g_socket_client_get_socket_type:
407
 * @client: a #GSocketClient.
408
 *
409
 * Gets the socket type of the socket client.
410
 *
411
 * See g_socket_client_set_socket_type() for details.
412
 *
413
 * Returns: a #GSocketFamily
414
 *
415
 * Since: 2.22
416
 */
417
GSocketType
418
g_socket_client_get_socket_type (GSocketClient *client)
419
0
{
420
0
  return client->priv->type;
421
0
}
422
423
/**
424
 * g_socket_client_set_socket_type:
425
 * @client: a #GSocketClient.
426
 * @type: a #GSocketType
427
 *
428
 * Sets the socket type of the socket client.
429
 * The sockets created by this object will be of the specified
430
 * type.
431
 *
432
 * It doesn't make sense to specify a type of %G_SOCKET_TYPE_DATAGRAM,
433
 * as GSocketClient is used for connection oriented services.
434
 *
435
 * Since: 2.22
436
 */
437
void
438
g_socket_client_set_socket_type (GSocketClient *client,
439
         GSocketType    type)
440
0
{
441
0
  if (client->priv->type == type)
442
0
    return;
443
444
0
  client->priv->type = type;
445
0
  g_object_notify (G_OBJECT (client), "type");
446
0
}
447
448
/**
449
 * g_socket_client_get_protocol:
450
 * @client: a #GSocketClient
451
 *
452
 * Gets the protocol name type of the socket client.
453
 *
454
 * See g_socket_client_set_protocol() for details.
455
 *
456
 * Returns: a #GSocketProtocol
457
 *
458
 * Since: 2.22
459
 */
460
GSocketProtocol
461
g_socket_client_get_protocol (GSocketClient *client)
462
0
{
463
0
  return client->priv->protocol;
464
0
}
465
466
/**
467
 * g_socket_client_set_protocol:
468
 * @client: a #GSocketClient.
469
 * @protocol: a #GSocketProtocol
470
 *
471
 * Sets the protocol of the socket client.
472
 * The sockets created by this object will use of the specified
473
 * protocol.
474
 *
475
 * If @protocol is %G_SOCKET_PROTOCOL_DEFAULT that means to use the default
476
 * protocol for the socket family and type.
477
 *
478
 * Since: 2.22
479
 */
480
void
481
g_socket_client_set_protocol (GSocketClient   *client,
482
            GSocketProtocol  protocol)
483
0
{
484
0
  if (client->priv->protocol == protocol)
485
0
    return;
486
487
0
  client->priv->protocol = protocol;
488
0
  g_object_notify (G_OBJECT (client), "protocol");
489
0
}
490
491
/**
492
 * g_socket_client_get_local_address:
493
 * @client: a #GSocketClient.
494
 *
495
 * Gets the local address of the socket client.
496
 *
497
 * See g_socket_client_set_local_address() for details.
498
 *
499
 * Returns: (nullable) (transfer none): a #GSocketAddress or %NULL. Do not free.
500
 *
501
 * Since: 2.22
502
 */
503
GSocketAddress *
504
g_socket_client_get_local_address (GSocketClient *client)
505
0
{
506
0
  return client->priv->local_address;
507
0
}
508
509
/**
510
 * g_socket_client_set_local_address:
511
 * @client: a #GSocketClient.
512
 * @address: (nullable): a #GSocketAddress, or %NULL
513
 *
514
 * Sets the local address of the socket client.
515
 * The sockets created by this object will bound to the
516
 * specified address (if not %NULL) before connecting.
517
 *
518
 * This is useful if you want to ensure that the local
519
 * side of the connection is on a specific port, or on
520
 * a specific interface.
521
 *
522
 * Since: 2.22
523
 */
524
void
525
g_socket_client_set_local_address (GSocketClient  *client,
526
           GSocketAddress *address)
527
0
{
528
0
  if (address)
529
0
    g_object_ref (address);
530
531
0
  if (client->priv->local_address)
532
0
    {
533
0
      g_object_unref (client->priv->local_address);
534
0
    }
535
0
  client->priv->local_address = address;
536
0
  g_object_notify (G_OBJECT (client), "local-address");
537
0
}
538
539
/**
540
 * g_socket_client_get_timeout:
541
 * @client: a #GSocketClient
542
 *
543
 * Gets the I/O timeout time for sockets created by @client.
544
 *
545
 * See g_socket_client_set_timeout() for details.
546
 *
547
 * Returns: the timeout in seconds
548
 *
549
 * Since: 2.26
550
 */
551
guint
552
g_socket_client_get_timeout (GSocketClient *client)
553
0
{
554
0
  return client->priv->timeout;
555
0
}
556
557
558
/**
559
 * g_socket_client_set_timeout:
560
 * @client: a #GSocketClient.
561
 * @timeout: the timeout
562
 *
563
 * Sets the I/O timeout for sockets created by @client. @timeout is a
564
 * time in seconds, or 0 for no timeout (the default).
565
 *
566
 * The timeout value affects the initial connection attempt as well,
567
 * so setting this may cause calls to g_socket_client_connect(), etc,
568
 * to fail with %G_IO_ERROR_TIMED_OUT.
569
 *
570
 * Since: 2.26
571
 */
572
void
573
g_socket_client_set_timeout (GSocketClient *client,
574
           guint          timeout)
575
0
{
576
0
  if (client->priv->timeout == timeout)
577
0
    return;
578
579
0
  client->priv->timeout = timeout;
580
0
  g_object_notify (G_OBJECT (client), "timeout");
581
0
}
582
583
/**
584
 * g_socket_client_get_enable_proxy:
585
 * @client: a #GSocketClient.
586
 *
587
 * Gets the proxy enable state; see g_socket_client_set_enable_proxy()
588
 *
589
 * Returns: whether proxying is enabled
590
 *
591
 * Since: 2.26
592
 */
593
gboolean
594
g_socket_client_get_enable_proxy (GSocketClient *client)
595
0
{
596
0
  return client->priv->enable_proxy;
597
0
}
598
599
/**
600
 * g_socket_client_set_enable_proxy:
601
 * @client: a #GSocketClient.
602
 * @enable: whether to enable proxies
603
 *
604
 * Sets whether or not @client attempts to make connections via a
605
 * proxy server. When enabled (the default), #GSocketClient will use a
606
 * #GProxyResolver to determine if a proxy protocol such as SOCKS is
607
 * needed, and automatically do the necessary proxy negotiation.
608
 *
609
 * See also g_socket_client_set_proxy_resolver().
610
 *
611
 * Since: 2.26
612
 */
613
void
614
g_socket_client_set_enable_proxy (GSocketClient *client,
615
          gboolean       enable)
616
0
{
617
0
  enable = !!enable;
618
0
  if (client->priv->enable_proxy == enable)
619
0
    return;
620
621
0
  client->priv->enable_proxy = enable;
622
0
  g_object_notify (G_OBJECT (client), "enable-proxy");
623
0
}
624
625
/**
626
 * g_socket_client_get_tls:
627
 * @client: a #GSocketClient.
628
 *
629
 * Gets whether @client creates TLS connections. See
630
 * g_socket_client_set_tls() for details.
631
 *
632
 * Returns: whether @client uses TLS
633
 *
634
 * Since: 2.28
635
 */
636
gboolean
637
g_socket_client_get_tls (GSocketClient *client)
638
0
{
639
0
  return client->priv->tls;
640
0
}
641
642
/**
643
 * g_socket_client_set_tls:
644
 * @client: a #GSocketClient.
645
 * @tls: whether to use TLS
646
 *
647
 * Sets whether @client creates TLS (aka SSL) connections. If @tls is
648
 * %TRUE, @client will wrap its connections in a #GTlsClientConnection
649
 * and perform a TLS handshake when connecting.
650
 *
651
 * Note that since #GSocketClient must return a #GSocketConnection,
652
 * but #GTlsClientConnection is not a #GSocketConnection, this
653
 * actually wraps the resulting #GTlsClientConnection in a
654
 * #GTcpWrapperConnection when returning it. You can use
655
 * g_tcp_wrapper_connection_get_base_io_stream() on the return value
656
 * to extract the #GTlsClientConnection.
657
 *
658
 * If you need to modify the behavior of the TLS handshake (eg, by
659
 * setting a client-side certificate to use, or connecting to the
660
 * #GTlsConnection::accept-certificate signal), you can connect to
661
 * @client's #GSocketClient::event signal and wait for it to be
662
 * emitted with %G_SOCKET_CLIENT_TLS_HANDSHAKING, which will give you
663
 * a chance to see the #GTlsClientConnection before the handshake
664
 * starts.
665
 *
666
 * Since: 2.28
667
 */
668
void
669
g_socket_client_set_tls (GSocketClient *client,
670
       gboolean       tls)
671
0
{
672
0
  tls = !!tls;
673
0
  if (tls == client->priv->tls)
674
0
    return;
675
676
0
  client->priv->tls = tls;
677
0
  g_object_notify (G_OBJECT (client), "tls");
678
0
}
679
680
/**
681
 * g_socket_client_get_tls_validation_flags:
682
 * @client: a #GSocketClient.
683
 *
684
 * Gets the TLS validation flags used creating TLS connections via
685
 * @client.
686
 *
687
 * This function does not work as originally designed and is impossible
688
 * to use correctly. See #GSocketClient:tls-validation-flags for more
689
 * information.
690
 *
691
 * Returns: the TLS validation flags
692
 *
693
 * Since: 2.28
694
 *
695
 * Deprecated: 2.72: Do not attempt to ignore validation errors.
696
 */
697
GTlsCertificateFlags
698
g_socket_client_get_tls_validation_flags (GSocketClient *client)
699
0
{
700
0
  return client->priv->tls_validation_flags;
701
0
}
702
703
/**
704
 * g_socket_client_set_tls_validation_flags:
705
 * @client: a #GSocketClient.
706
 * @flags: the validation flags
707
 *
708
 * Sets the TLS validation flags used when creating TLS connections
709
 * via @client. The default value is %G_TLS_CERTIFICATE_VALIDATE_ALL.
710
 *
711
 * This function does not work as originally designed and is impossible
712
 * to use correctly. See #GSocketClient:tls-validation-flags for more
713
 * information.
714
 *
715
 * Since: 2.28
716
 *
717
 * Deprecated: 2.72: Do not attempt to ignore validation errors.
718
 */
719
void
720
g_socket_client_set_tls_validation_flags (GSocketClient        *client,
721
            GTlsCertificateFlags  flags)
722
0
{
723
0
  if (client->priv->tls_validation_flags != flags)
724
0
    {
725
0
      client->priv->tls_validation_flags = flags;
726
0
      g_object_notify (G_OBJECT (client), "tls-validation-flags");
727
0
    }
728
0
}
729
730
/**
731
 * g_socket_client_get_proxy_resolver:
732
 * @client: a #GSocketClient.
733
 *
734
 * Gets the #GProxyResolver being used by @client. Normally, this will
735
 * be the resolver returned by g_proxy_resolver_get_default(), but you
736
 * can override it with g_socket_client_set_proxy_resolver().
737
 *
738
 * Returns: (transfer none): The #GProxyResolver being used by
739
 *   @client.
740
 *
741
 * Since: 2.36
742
 */
743
GProxyResolver *
744
g_socket_client_get_proxy_resolver (GSocketClient *client)
745
0
{
746
0
  if (client->priv->proxy_resolver)
747
0
    return client->priv->proxy_resolver;
748
0
  else
749
0
    return g_proxy_resolver_get_default ();
750
0
}
751
752
/**
753
 * g_socket_client_set_proxy_resolver:
754
 * @client: a #GSocketClient.
755
 * @proxy_resolver: (nullable): a #GProxyResolver, or %NULL for the
756
 *   default.
757
 *
758
 * Overrides the #GProxyResolver used by @client. You can call this if
759
 * you want to use specific proxies, rather than using the system
760
 * default proxy settings.
761
 *
762
 * Note that whether or not the proxy resolver is actually used
763
 * depends on the setting of #GSocketClient:enable-proxy, which is not
764
 * changed by this function (but which is %TRUE by default)
765
 *
766
 * Since: 2.36
767
 */
768
void
769
g_socket_client_set_proxy_resolver (GSocketClient  *client,
770
                                    GProxyResolver *proxy_resolver)
771
0
{
772
  /* We have to be careful to avoid calling
773
   * g_proxy_resolver_get_default() until we're sure we need it,
774
   * because trying to load the default proxy resolver module will
775
   * break some test programs that aren't expecting it (eg,
776
   * tests/gsettings).
777
   */
778
779
0
  if (client->priv->proxy_resolver)
780
0
    g_object_unref (client->priv->proxy_resolver);
781
782
0
  client->priv->proxy_resolver = proxy_resolver;
783
784
0
  if (client->priv->proxy_resolver)
785
0
    g_object_ref (client->priv->proxy_resolver);
786
0
}
787
788
static void
789
g_socket_client_class_init (GSocketClientClass *class)
790
0
{
791
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
792
793
0
  gobject_class->finalize = g_socket_client_finalize;
794
0
  gobject_class->set_property = g_socket_client_set_property;
795
0
  gobject_class->get_property = g_socket_client_get_property;
796
797
  /**
798
   * GSocketClient::event:
799
   * @client: the #GSocketClient
800
   * @event: the event that is occurring
801
   * @connectable: the #GSocketConnectable that @event is occurring on
802
   * @connection: (nullable): the current representation of the connection
803
   *
804
   * Emitted when @client's activity on @connectable changes state.
805
   * Among other things, this can be used to provide progress
806
   * information about a network connection in the UI. The meanings of
807
   * the different @event values are as follows:
808
   *
809
   * - %G_SOCKET_CLIENT_RESOLVING: @client is about to look up @connectable
810
   *   in DNS. @connection will be %NULL.
811
   *
812
   * - %G_SOCKET_CLIENT_RESOLVED:  @client has successfully resolved
813
   *   @connectable in DNS. @connection will be %NULL.
814
   *
815
   * - %G_SOCKET_CLIENT_CONNECTING: @client is about to make a connection
816
   *   to a remote host; either a proxy server or the destination server
817
   *   itself. @connection is the #GSocketConnection, which is not yet
818
   *   connected.  Since GLib 2.40, you can access the remote
819
   *   address via g_socket_connection_get_remote_address().
820
   *
821
   * - %G_SOCKET_CLIENT_CONNECTED: @client has successfully connected
822
   *   to a remote host. @connection is the connected #GSocketConnection.
823
   *
824
   * - %G_SOCKET_CLIENT_PROXY_NEGOTIATING: @client is about to negotiate
825
   *   with a proxy to get it to connect to @connectable. @connection is
826
   *   the #GSocketConnection to the proxy server.
827
   *
828
   * - %G_SOCKET_CLIENT_PROXY_NEGOTIATED: @client has negotiated a
829
   *   connection to @connectable through a proxy server. @connection is
830
   *   the stream returned from g_proxy_connect(), which may or may not
831
   *   be a #GSocketConnection.
832
   *
833
   * - %G_SOCKET_CLIENT_TLS_HANDSHAKING: @client is about to begin a TLS
834
   *   handshake. @connection is a #GTlsClientConnection.
835
   *
836
   * - %G_SOCKET_CLIENT_TLS_HANDSHAKED: @client has successfully completed
837
   *   the TLS handshake. @connection is a #GTlsClientConnection.
838
   *
839
   * - %G_SOCKET_CLIENT_COMPLETE: @client has either successfully connected
840
   *   to @connectable (in which case @connection is the #GSocketConnection
841
   *   that it will be returning to the caller) or has failed (in which
842
   *   case @connection is %NULL and the client is about to return an error).
843
   *
844
   * Each event except %G_SOCKET_CLIENT_COMPLETE may be emitted
845
   * multiple times (or not at all) for a given connectable (in
846
   * particular, if @client ends up attempting to connect to more than
847
   * one address). However, if @client emits the #GSocketClient::event
848
   * signal at all for a given connectable, then it will always emit
849
   * it with %G_SOCKET_CLIENT_COMPLETE when it is done.
850
   *
851
   * Note that there may be additional #GSocketClientEvent values in
852
   * the future; unrecognized @event values should be ignored.
853
   *
854
   * Since: 2.32
855
   */
856
0
  signals[EVENT] =
857
0
    g_signal_new (I_("event"),
858
0
      G_TYPE_FROM_CLASS (gobject_class),
859
0
      G_SIGNAL_RUN_LAST,
860
0
      G_STRUCT_OFFSET (GSocketClientClass, event),
861
0
      NULL, NULL,
862
0
      _g_cclosure_marshal_VOID__ENUM_OBJECT_OBJECT,
863
0
      G_TYPE_NONE, 3,
864
0
      G_TYPE_SOCKET_CLIENT_EVENT,
865
0
      G_TYPE_SOCKET_CONNECTABLE,
866
0
      G_TYPE_IO_STREAM);
867
0
  g_signal_set_va_marshaller (signals[EVENT],
868
0
                              G_TYPE_FROM_CLASS (class),
869
0
                              _g_cclosure_marshal_VOID__ENUM_OBJECT_OBJECTv);
870
871
  /**
872
   * GSocketClient:family:
873
   *
874
   * The address family to use for socket construction.
875
   *
876
   * Since: 2.22
877
   */
878
0
  g_object_class_install_property (gobject_class, PROP_FAMILY,
879
0
           g_param_spec_enum ("family", NULL, NULL,
880
0
                  G_TYPE_SOCKET_FAMILY,
881
0
                  G_SOCKET_FAMILY_INVALID,
882
0
                  G_PARAM_CONSTRUCT |
883
0
                                                      G_PARAM_READWRITE |
884
0
                                                      G_PARAM_STATIC_STRINGS));
885
886
  /**
887
   * GSocketClient:type:
888
   *
889
   * The type to use for socket construction.
890
   *
891
   * Since: 2.22
892
   */
893
0
  g_object_class_install_property (gobject_class, PROP_TYPE,
894
0
           g_param_spec_enum ("type", NULL, NULL,
895
0
                  G_TYPE_SOCKET_TYPE,
896
0
                  G_SOCKET_TYPE_STREAM,
897
0
                  G_PARAM_CONSTRUCT |
898
0
                                                      G_PARAM_READWRITE |
899
0
                                                      G_PARAM_STATIC_STRINGS));
900
901
  /**
902
   * GSocketClient:protocol:
903
   *
904
   * The protocol to use for socket construction, or `0` for default.
905
   *
906
   * Since: 2.22
907
   */
908
0
  g_object_class_install_property (gobject_class, PROP_PROTOCOL,
909
0
           g_param_spec_enum ("protocol", NULL, NULL,
910
0
                  G_TYPE_SOCKET_PROTOCOL,
911
0
                  G_SOCKET_PROTOCOL_DEFAULT,
912
0
                  G_PARAM_CONSTRUCT |
913
0
                                                      G_PARAM_READWRITE |
914
0
                                                      G_PARAM_STATIC_STRINGS));
915
916
  /**
917
   * GSocketClient:local-address:
918
   *
919
   * The local address constructed sockets will be bound to.
920
   *
921
   * Since: 2.22
922
   */
923
0
  g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
924
0
           g_param_spec_object ("local-address", NULL, NULL,
925
0
              G_TYPE_SOCKET_ADDRESS,
926
0
              G_PARAM_CONSTRUCT |
927
0
                                                        G_PARAM_READWRITE |
928
0
                                                        G_PARAM_STATIC_STRINGS));
929
930
  /**
931
   * GSocketClient:timeout:
932
   *
933
   * The I/O timeout for sockets, in seconds, or `0` for none.
934
   *
935
   * Since: 2.22
936
   */
937
0
  g_object_class_install_property (gobject_class, PROP_TIMEOUT,
938
0
           g_param_spec_uint ("timeout", NULL, NULL,
939
0
                  0, G_MAXUINT, 0,
940
0
                  G_PARAM_CONSTRUCT |
941
0
                                                      G_PARAM_READWRITE |
942
0
                                                      G_PARAM_STATIC_STRINGS));
943
944
  /**
945
   * GSocketClient:enable-proxy:
946
   *
947
   * Enable proxy support.
948
   *
949
   * Since: 2.22
950
   */
951
0
   g_object_class_install_property (gobject_class, PROP_ENABLE_PROXY,
952
0
            g_param_spec_boolean ("enable-proxy", NULL, NULL,
953
0
                TRUE,
954
0
                G_PARAM_CONSTRUCT |
955
0
                G_PARAM_READWRITE |
956
0
                G_PARAM_STATIC_STRINGS));
957
958
  /**
959
   * GSocketClient:tls:
960
   *
961
   * Whether to create TLS connections.
962
   *
963
   * Since: 2.22
964
   */
965
0
  g_object_class_install_property (gobject_class, PROP_TLS,
966
0
           g_param_spec_boolean ("tls", NULL, NULL,
967
0
               FALSE,
968
0
               G_PARAM_CONSTRUCT |
969
0
               G_PARAM_READWRITE |
970
0
               G_PARAM_STATIC_STRINGS));
971
972
  /**
973
   * GSocketClient:tls-validation-flags:
974
   *
975
   * The TLS validation flags used when creating TLS connections. The
976
   * default value is %G_TLS_CERTIFICATE_VALIDATE_ALL.
977
   *
978
   * GLib guarantees that if certificate verification fails, at least one
979
   * flag will be set, but it does not guarantee that all possible flags
980
   * will be set. Accordingly, you may not safely decide to ignore any
981
   * particular type of error. For example, it would be incorrect to mask
982
   * %G_TLS_CERTIFICATE_EXPIRED if you want to allow expired certificates,
983
   * because this could potentially be the only error flag set even if
984
   * other problems exist with the certificate. Therefore, there is no
985
   * safe way to use this property. This is not a horrible problem,
986
   * though, because you should not be attempting to ignore validation
987
   * errors anyway. If you really must ignore TLS certificate errors,
988
   * connect to the #GSocketClient::event signal, wait for it to be
989
   * emitted with %G_SOCKET_CLIENT_TLS_HANDSHAKING, and use that to
990
   * connect to #GTlsConnection::accept-certificate.
991
   *
992
   * Deprecated: 2.72: Do not attempt to ignore validation errors.
993
   */
994
0
  g_object_class_install_property (gobject_class, PROP_TLS_VALIDATION_FLAGS,
995
0
           g_param_spec_flags ("tls-validation-flags", NULL, NULL,
996
0
                   G_TYPE_TLS_CERTIFICATE_FLAGS,
997
0
                   G_TLS_CERTIFICATE_VALIDATE_ALL,
998
0
                   G_PARAM_CONSTRUCT |
999
0
                   G_PARAM_READWRITE |
1000
0
                   G_PARAM_STATIC_STRINGS |
1001
0
                   G_PARAM_DEPRECATED));
1002
1003
  /**
1004
   * GSocketClient:proxy-resolver:
1005
   *
1006
   * The proxy resolver to use
1007
   *
1008
   * Since: 2.36
1009
   */
1010
0
  g_object_class_install_property (gobject_class, PROP_PROXY_RESOLVER,
1011
0
                                   g_param_spec_object ("proxy-resolver", NULL, NULL,
1012
0
                                                        G_TYPE_PROXY_RESOLVER,
1013
0
                                                        G_PARAM_CONSTRUCT |
1014
0
                                                        G_PARAM_READWRITE |
1015
0
                                                        G_PARAM_STATIC_STRINGS));
1016
0
}
1017
1018
static void
1019
g_socket_client_emit_event (GSocketClient       *client,
1020
          GSocketClientEvent   event,
1021
          GSocketConnectable  *connectable,
1022
          GIOStream           *connection)
1023
0
{
1024
0
  g_signal_emit (client, signals[EVENT], 0,
1025
0
     event, connectable, connection);
1026
0
}
1027
1028
/* Originally, GSocketClient returned whatever error occurred last. Turns
1029
 * out this doesn't work well in practice. Consider the following case:
1030
 * DNS returns an IPv4 and IPv6 address. First we'll connect() to the
1031
 * IPv4 address, and say that succeeds, but TLS is enabled and the TLS
1032
 * handshake fails. Then we try the IPv6 address and receive ENETUNREACH
1033
 * because IPv6 isn't supported. We wind up returning NETWORK_UNREACHABLE
1034
 * even though the address can be pinged and a TLS error would be more
1035
 * appropriate. So instead, we now try to return the error corresponding
1036
 * to the latest attempted GSocketClientEvent in the connection process.
1037
 * TLS errors take precedence over proxy errors, which take precedence
1038
 * over connect() errors, which take precedence over DNS errors.
1039
 *
1040
 * Note that the example above considers a sync codepath, but this is an
1041
 * issue for the async codepath too, where events and errors may occur
1042
 * in confusing orders.
1043
 */
1044
typedef struct
1045
{
1046
  GError *tmp_error;
1047
  GError *best_error;
1048
  GSocketClientEvent best_error_event;
1049
} SocketClientErrorInfo;
1050
1051
static SocketClientErrorInfo *
1052
socket_client_error_info_new (void)
1053
0
{
1054
0
  return g_new0 (SocketClientErrorInfo, 1);
1055
0
}
1056
1057
static void
1058
socket_client_error_info_free (SocketClientErrorInfo *info)
1059
0
{
1060
0
  g_assert (info->tmp_error == NULL);
1061
0
  g_clear_error (&info->best_error);
1062
0
  g_free (info);
1063
0
}
1064
1065
static void
1066
consider_tmp_error (SocketClientErrorInfo *info,
1067
                    GSocketClientEvent     event)
1068
0
{
1069
0
  if (info->tmp_error == NULL)
1070
0
    return;
1071
1072
  /* If we ever add more GSocketClientEvents in the future, then we'll
1073
   * no longer be able to use >= for this comparison, because future
1074
   * events will compare greater than G_SOCKET_CLIENT_COMPLETE. Until
1075
   * then, this is convenient. Note G_SOCKET_CLIENT_RESOLVING is 0 so we
1076
   * need to use >= here or those errors would never be set. That means
1077
   * if we get two errors on the same GSocketClientEvent, we wind up
1078
   * preferring the last one, which is fine.
1079
   */
1080
0
  g_assert (event <= G_SOCKET_CLIENT_COMPLETE);
1081
0
  if (event >= info->best_error_event)
1082
0
    {
1083
0
      g_clear_error (&info->best_error);
1084
0
      info->best_error = info->tmp_error;
1085
0
      info->tmp_error = NULL;
1086
0
      info->best_error_event = event;
1087
0
    }
1088
0
  else
1089
0
    {
1090
0
      g_clear_error (&info->tmp_error);
1091
0
    }
1092
0
}
1093
1094
/**
1095
 * g_socket_client_connect:
1096
 * @client: a #GSocketClient.
1097
 * @connectable: a #GSocketConnectable specifying the remote address.
1098
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
1099
 * @error: #GError for error reporting, or %NULL to ignore.
1100
 *
1101
 * Tries to resolve the @connectable and make a network connection to it.
1102
 *
1103
 * Upon a successful connection, a new #GSocketConnection is constructed
1104
 * and returned.  The caller owns this new object and must drop their
1105
 * reference to it when finished with it.
1106
 *
1107
 * The type of the #GSocketConnection object returned depends on the type of
1108
 * the underlying socket that is used. For instance, for a TCP/IP connection
1109
 * it will be a #GTcpConnection.
1110
 *
1111
 * The socket created will be the same family as the address that the
1112
 * @connectable resolves to, unless family is set with g_socket_client_set_family()
1113
 * or indirectly via g_socket_client_set_local_address(). The socket type
1114
 * defaults to %G_SOCKET_TYPE_STREAM but can be set with
1115
 * g_socket_client_set_socket_type().
1116
 *
1117
 * If a local address is specified with g_socket_client_set_local_address() the
1118
 * socket will be bound to this address before connecting.
1119
 *
1120
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
1121
 *
1122
 * Since: 2.22
1123
 */
1124
GSocketConnection *
1125
g_socket_client_connect (GSocketClient       *client,
1126
       GSocketConnectable  *connectable,
1127
       GCancellable        *cancellable,
1128
       GError             **error)
1129
0
{
1130
0
  GIOStream *connection = NULL;
1131
0
  GSocketAddressEnumerator *enumerator = NULL;
1132
0
  SocketClientErrorInfo *error_info;
1133
0
  gboolean ever_resolved = FALSE;
1134
1135
0
  error_info = socket_client_error_info_new ();
1136
1137
0
  if (can_use_proxy (client))
1138
0
    {
1139
0
      enumerator = g_socket_connectable_proxy_enumerate (connectable);
1140
0
      if (client->priv->proxy_resolver &&
1141
0
          G_IS_PROXY_ADDRESS_ENUMERATOR (enumerator))
1142
0
        {
1143
0
          g_object_set (G_OBJECT (enumerator),
1144
0
                        "proxy-resolver", client->priv->proxy_resolver,
1145
0
                        NULL);
1146
0
        }
1147
0
    }
1148
0
  else
1149
0
    enumerator = g_socket_connectable_enumerate (connectable);
1150
1151
0
  while (connection == NULL)
1152
0
    {
1153
0
      GSocketAddress *address = NULL;
1154
0
      gboolean application_proxy = FALSE;
1155
0
      GSocket *socket;
1156
0
      gboolean using_proxy;
1157
1158
0
      if (g_cancellable_is_cancelled (cancellable))
1159
0
  {
1160
0
    g_clear_error (&error_info->best_error);
1161
0
    g_cancellable_set_error_if_cancelled (cancellable, &error_info->best_error);
1162
0
    break;
1163
0
  }
1164
1165
0
      if (!ever_resolved)
1166
0
  {
1167
0
    g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING,
1168
0
              connectable, NULL);
1169
0
  }
1170
0
      address = g_socket_address_enumerator_next (enumerator, cancellable,
1171
0
              &error_info->tmp_error);
1172
0
      consider_tmp_error (error_info, G_SOCKET_CLIENT_RESOLVING);
1173
0
      if (!ever_resolved)
1174
0
  {
1175
0
    g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED,
1176
0
              connectable, NULL);
1177
0
    ever_resolved = TRUE;
1178
0
  }
1179
1180
0
      if (address == NULL)
1181
0
  {
1182
          /* Enumeration is finished. */
1183
0
          g_assert (&error_info->best_error != NULL);
1184
0
    break;
1185
0
  }
1186
1187
0
      using_proxy = (G_IS_PROXY_ADDRESS (address) &&
1188
0
         client->priv->enable_proxy);
1189
1190
0
      socket = create_socket (client, address, &error_info->tmp_error);
1191
0
      consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING);
1192
0
      if (socket == NULL)
1193
0
  {
1194
0
    g_object_unref (address);
1195
0
    continue;
1196
0
  }
1197
1198
0
      connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
1199
0
      g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, address);
1200
0
      g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTING, connectable, connection);
1201
1202
0
      if (g_socket_connection_connect (G_SOCKET_CONNECTION (connection),
1203
0
               address, cancellable, &error_info->tmp_error))
1204
0
  {
1205
0
          g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, NULL);
1206
0
    g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTED, connectable, connection);
1207
0
  }
1208
0
      else
1209
0
  {
1210
0
    clarify_connect_error (error_info->tmp_error, connectable, address);
1211
0
          consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING);
1212
0
    g_object_unref (connection);
1213
0
    connection = NULL;
1214
0
  }
1215
1216
0
      if (connection && using_proxy)
1217
0
  {
1218
0
    GProxyAddress *proxy_addr = G_PROXY_ADDRESS (address);
1219
0
    const gchar *protocol;
1220
0
    GProxy *proxy;
1221
1222
0
    protocol = g_proxy_address_get_protocol (proxy_addr);
1223
1224
          /* The connection should not be anything else then TCP Connection,
1225
           * but let's put a safety guard in case
1226
     */
1227
0
          if (!G_IS_TCP_CONNECTION (connection))
1228
0
            {
1229
0
              g_critical ("Trying to proxy over non-TCP connection, this is "
1230
0
                          "most likely a bug in GLib IO library.");
1231
1232
0
              g_set_error_literal (&error_info->tmp_error,
1233
0
                  G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1234
0
                  _("Proxying over a non-TCP connection is not supported."));
1235
0
              consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1236
1237
0
        g_object_unref (connection);
1238
0
        connection = NULL;
1239
0
            }
1240
0
    else if (g_hash_table_contains (client->priv->app_proxies, protocol))
1241
0
      {
1242
0
        application_proxy = TRUE;
1243
0
      }
1244
0
          else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
1245
0
      {
1246
0
        GIOStream *proxy_connection;
1247
1248
0
        g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, connectable, connection);
1249
0
        proxy_connection = g_proxy_connect (proxy,
1250
0
              connection,
1251
0
              proxy_addr,
1252
0
              cancellable,
1253
0
              &error_info->tmp_error);
1254
0
        consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1255
1256
0
        g_object_unref (connection);
1257
0
        connection = proxy_connection;
1258
0
        g_object_unref (proxy);
1259
1260
0
        if (connection)
1261
0
    g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, connectable, connection);
1262
0
      }
1263
0
    else
1264
0
      {
1265
0
        g_set_error (&error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1266
0
         _("Proxy protocol “%s” is not supported."),
1267
0
         protocol);
1268
0
        consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1269
0
        g_object_unref (connection);
1270
0
        connection = NULL;
1271
0
      }
1272
0
  }
1273
1274
0
      if (!application_proxy && connection && client->priv->tls)
1275
0
  {
1276
0
    GIOStream *tlsconn;
1277
1278
0
    tlsconn = g_tls_client_connection_new (connection, connectable, &error_info->tmp_error);
1279
0
    g_object_unref (connection);
1280
0
    connection = tlsconn;
1281
1282
0
    if (tlsconn)
1283
0
      {
1284
0
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1285
0
        g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
1286
0
                                                            client->priv->tls_validation_flags);
1287
0
G_GNUC_END_IGNORE_DEPRECATIONS
1288
0
        g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKING, connectable, connection);
1289
0
        if (g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn),
1290
0
                cancellable, &error_info->tmp_error))
1291
0
    {
1292
0
      g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKED, connectable, connection);
1293
0
    }
1294
0
        else
1295
0
    {
1296
0
      consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
1297
0
      g_object_unref (tlsconn);
1298
0
      connection = NULL;
1299
0
    }
1300
0
      }
1301
0
          else
1302
0
            {
1303
0
              consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
1304
0
            }
1305
0
  }
1306
1307
0
      if (connection && !G_IS_SOCKET_CONNECTION (connection))
1308
0
  {
1309
0
    GSocketConnection *wrapper_connection;
1310
1311
0
    wrapper_connection = g_tcp_wrapper_connection_new (connection, socket);
1312
0
    g_object_unref (connection);
1313
0
    connection = (GIOStream *)wrapper_connection;
1314
0
  }
1315
1316
0
      g_object_unref (socket);
1317
0
      g_object_unref (address);
1318
0
    }
1319
0
  g_object_unref (enumerator);
1320
1321
0
  if (!connection)
1322
0
    g_propagate_error (error, g_steal_pointer (&error_info->best_error));
1323
0
  socket_client_error_info_free (error_info);
1324
1325
0
  g_socket_client_emit_event (client, G_SOCKET_CLIENT_COMPLETE, connectable, connection);
1326
0
  return G_SOCKET_CONNECTION (connection);
1327
0
}
1328
1329
/**
1330
 * g_socket_client_connect_to_host:
1331
 * @client: a #GSocketClient
1332
 * @host_and_port: the name and optionally port of the host to connect to
1333
 * @default_port: the default port to connect to
1334
 * @cancellable: (nullable): a #GCancellable, or %NULL
1335
 * @error: a pointer to a #GError, or %NULL
1336
 *
1337
 * This is a helper function for g_socket_client_connect().
1338
 *
1339
 * Attempts to create a TCP connection to the named host.
1340
 *
1341
 * @host_and_port may be in any of a number of recognized formats; an IPv6
1342
 * address, an IPv4 address, or a domain name (in which case a DNS
1343
 * lookup is performed).  Quoting with [] is supported for all address
1344
 * types.  A port override may be specified in the usual way with a
1345
 * colon.  Ports may be given as decimal numbers or symbolic names (in
1346
 * which case an /etc/services lookup is performed).
1347
 *
1348
 * If no port override is given in @host_and_port then @default_port will be
1349
 * used as the port number to connect to.
1350
 *
1351
 * In general, @host_and_port is expected to be provided by the user (allowing
1352
 * them to give the hostname, and a port override if necessary) and
1353
 * @default_port is expected to be provided by the application.
1354
 *
1355
 * In the case that an IP address is given, a single connection
1356
 * attempt is made.  In the case that a name is given, multiple
1357
 * connection attempts may be made, in turn and according to the
1358
 * number of address records in DNS, until a connection succeeds.
1359
 *
1360
 * Upon a successful connection, a new #GSocketConnection is constructed
1361
 * and returned.  The caller owns this new object and must drop their
1362
 * reference to it when finished with it.
1363
 *
1364
 * In the event of any failure (DNS error, service not found, no hosts
1365
 * connectable) %NULL is returned and @error (if non-%NULL) is set
1366
 * accordingly.
1367
 *
1368
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
1369
 *
1370
 * Since: 2.22
1371
 */
1372
GSocketConnection *
1373
g_socket_client_connect_to_host (GSocketClient  *client,
1374
         const gchar    *host_and_port,
1375
         guint16         default_port,
1376
         GCancellable   *cancellable,
1377
         GError        **error)
1378
0
{
1379
0
  GSocketConnectable *connectable;
1380
0
  GSocketConnection *connection;
1381
1382
0
  connectable = g_network_address_parse (host_and_port, default_port, error);
1383
0
  if (connectable == NULL)
1384
0
    return NULL;
1385
1386
0
  connection = g_socket_client_connect (client, connectable,
1387
0
          cancellable, error);
1388
0
  g_object_unref (connectable);
1389
1390
0
  return connection;
1391
0
}
1392
1393
/**
1394
 * g_socket_client_connect_to_service:
1395
 * @client: a #GSocketConnection
1396
 * @domain: a domain name
1397
 * @service: the name of the service to connect to
1398
 * @cancellable: (nullable): a #GCancellable, or %NULL
1399
 * @error: a pointer to a #GError, or %NULL
1400
 *
1401
 * Attempts to create a TCP connection to a service.
1402
 *
1403
 * This call looks up the SRV record for @service at @domain for the
1404
 * "tcp" protocol.  It then attempts to connect, in turn, to each of
1405
 * the hosts providing the service until either a connection succeeds
1406
 * or there are no hosts remaining.
1407
 *
1408
 * Upon a successful connection, a new #GSocketConnection is constructed
1409
 * and returned.  The caller owns this new object and must drop their
1410
 * reference to it when finished with it.
1411
 *
1412
 * In the event of any failure (DNS error, service not found, no hosts
1413
 * connectable) %NULL is returned and @error (if non-%NULL) is set
1414
 * accordingly.
1415
 *
1416
 * Returns: (transfer full): a #GSocketConnection if successful, or %NULL on error
1417
 */
1418
GSocketConnection *
1419
g_socket_client_connect_to_service (GSocketClient  *client,
1420
            const gchar    *domain,
1421
            const gchar    *service,
1422
            GCancellable   *cancellable,
1423
            GError        **error)
1424
0
{
1425
0
  GSocketConnectable *connectable;
1426
0
  GSocketConnection *connection;
1427
1428
0
  connectable = g_network_service_new (service, "tcp", domain);
1429
0
  connection = g_socket_client_connect (client, connectable,
1430
0
          cancellable, error);
1431
0
  g_object_unref (connectable);
1432
1433
0
  return connection;
1434
0
}
1435
1436
/**
1437
 * g_socket_client_connect_to_uri:
1438
 * @client: a #GSocketClient
1439
 * @uri: A network URI
1440
 * @default_port: the default port to connect to
1441
 * @cancellable: (nullable): a #GCancellable, or %NULL
1442
 * @error: a pointer to a #GError, or %NULL
1443
 *
1444
 * This is a helper function for g_socket_client_connect().
1445
 *
1446
 * Attempts to create a TCP connection with a network URI.
1447
 *
1448
 * @uri may be any valid URI containing an "authority" (hostname/port)
1449
 * component. If a port is not specified in the URI, @default_port
1450
 * will be used. TLS will be negotiated if #GSocketClient:tls is %TRUE.
1451
 * (#GSocketClient does not know to automatically assume TLS for
1452
 * certain URI schemes.)
1453
 *
1454
 * Using this rather than g_socket_client_connect() or
1455
 * g_socket_client_connect_to_host() allows #GSocketClient to
1456
 * determine when to use application-specific proxy protocols.
1457
 *
1458
 * Upon a successful connection, a new #GSocketConnection is constructed
1459
 * and returned.  The caller owns this new object and must drop their
1460
 * reference to it when finished with it.
1461
 *
1462
 * In the event of any failure (DNS error, service not found, no hosts
1463
 * connectable) %NULL is returned and @error (if non-%NULL) is set
1464
 * accordingly.
1465
 *
1466
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
1467
 *
1468
 * Since: 2.26
1469
 */
1470
GSocketConnection *
1471
g_socket_client_connect_to_uri (GSocketClient  *client,
1472
        const gchar    *uri,
1473
        guint16         default_port,
1474
        GCancellable   *cancellable,
1475
        GError        **error)
1476
0
{
1477
0
  GSocketConnectable *connectable;
1478
0
  GSocketConnection *connection;
1479
1480
0
  connectable = g_network_address_parse_uri (uri, default_port, error);
1481
0
  if (connectable == NULL)
1482
0
    return NULL;
1483
1484
0
  connection = g_socket_client_connect (client, connectable,
1485
0
          cancellable, error);
1486
0
  g_object_unref (connectable);
1487
1488
0
  return connection;
1489
0
}
1490
1491
typedef struct
1492
{
1493
  GTask *task; /* unowned */
1494
  GSocketClient *client;
1495
1496
  GSocketConnectable *connectable;
1497
  GSocketAddressEnumerator *enumerator;
1498
  GCancellable *enumeration_cancellable;
1499
  GCancellable *enumeration_parent_cancellable;  /* (nullable) (owned) */
1500
  gulong enumeration_cancelled_id;
1501
1502
  GSList *connection_attempts;  /* (element-type ConnectionAttempt) (owned) */
1503
  GSList *successful_connections;
1504
  SocketClientErrorInfo *error_info;
1505
1506
  /* Number of times g_socket_address_enumerator_next_async() has successfully
1507
   * returned an address. */
1508
  guint n_addresses_enumerated;
1509
1510
  gboolean enumeration_completed;
1511
  gboolean connection_in_progress;
1512
  gboolean completed;
1513
} GSocketClientAsyncConnectData;
1514
1515
static void connection_attempt_unref (gpointer attempt);
1516
1517
static void
1518
g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
1519
0
{
1520
0
  data->task = NULL;
1521
0
  g_clear_object (&data->connectable);
1522
0
  g_clear_object (&data->enumerator);
1523
1524
0
  g_cancellable_disconnect (data->enumeration_parent_cancellable, data->enumeration_cancelled_id);
1525
0
  g_clear_object (&data->enumeration_parent_cancellable);
1526
0
  data->enumeration_cancelled_id = 0;
1527
0
  g_clear_object (&data->enumeration_cancellable);
1528
1529
0
  g_slist_free_full (data->connection_attempts, connection_attempt_unref);
1530
0
  g_slist_free_full (data->successful_connections, connection_attempt_unref);
1531
1532
0
  g_clear_pointer (&data->error_info, socket_client_error_info_free);
1533
1534
0
  g_slice_free (GSocketClientAsyncConnectData, data);
1535
0
}
1536
1537
typedef struct
1538
{
1539
  GSocketAddress *address;
1540
  GSocket *socket;
1541
  GIOStream *connection;
1542
  GProxyAddress *proxy_addr;
1543
  GSocketClientAsyncConnectData *data; /* unowned */
1544
  GSource *delay_timeout_source;  /* (owned) */
1545
  gboolean delay_reached;
1546
  GCancellable *cancellable;
1547
  GCancellable *task_cancellable;  /* (owned); this is equal to g_task_get_cancellable (ConnectionAttempt.data->task), but with a longer lifetime */
1548
  gulong cancelled_id;
1549
  grefcount ref;
1550
} ConnectionAttempt;
1551
1552
static ConnectionAttempt *
1553
connection_attempt_new (void)
1554
0
{
1555
0
  ConnectionAttempt *attempt = g_new0 (ConnectionAttempt, 1);
1556
0
  g_ref_count_init (&attempt->ref);
1557
0
  return attempt;
1558
0
}
1559
1560
static ConnectionAttempt *
1561
connection_attempt_ref (ConnectionAttempt *attempt)
1562
0
{
1563
0
  g_ref_count_inc (&attempt->ref);
1564
0
  return attempt;
1565
0
}
1566
1567
static void
1568
connection_attempt_unref (gpointer pointer)
1569
0
{
1570
0
  ConnectionAttempt *attempt = pointer;
1571
0
  if (g_ref_count_dec (&attempt->ref))
1572
0
    {
1573
0
      g_clear_object (&attempt->address);
1574
0
      g_clear_object (&attempt->socket);
1575
0
      g_clear_object (&attempt->connection);
1576
0
      g_cancellable_disconnect (attempt->task_cancellable, attempt->cancelled_id);
1577
0
      g_clear_object (&attempt->task_cancellable);
1578
0
      attempt->cancelled_id = 0;
1579
0
      g_clear_object (&attempt->cancellable);
1580
0
      g_clear_object (&attempt->proxy_addr);
1581
0
      if (attempt->delay_timeout_source)
1582
0
        {
1583
0
          g_source_destroy (attempt->delay_timeout_source);
1584
0
          g_source_unref (attempt->delay_timeout_source);
1585
0
        }
1586
0
      g_free (attempt);
1587
0
    }
1588
0
}
1589
1590
static void
1591
connection_attempt_remove (ConnectionAttempt *attempt)
1592
0
{
1593
0
  GSList *attempt_link = g_slist_find (attempt->data->connection_attempts, attempt);
1594
0
  if (attempt_link != NULL)
1595
0
    {
1596
0
      attempt->data->connection_attempts = g_slist_delete_link (attempt->data->connection_attempts, attempt_link);
1597
0
      connection_attempt_unref (attempt);
1598
0
    }
1599
0
}
1600
1601
static void
1602
cancel_all_attempts (GSocketClientAsyncConnectData *data)
1603
0
{
1604
0
  GSList *l;
1605
1606
0
  for (l = data->connection_attempts; l; l = g_slist_next (l))
1607
0
    {
1608
0
      ConnectionAttempt *attempt_entry = l->data;
1609
0
      g_cancellable_cancel (attempt_entry->cancellable);
1610
0
      connection_attempt_unref (attempt_entry);
1611
0
    }
1612
0
  g_slist_free (data->connection_attempts);
1613
0
  data->connection_attempts = NULL;
1614
1615
0
  g_slist_free_full (data->successful_connections, connection_attempt_unref);
1616
0
  data->successful_connections = NULL;
1617
1618
0
  g_cancellable_cancel (data->enumeration_cancellable);
1619
0
}
1620
1621
static void
1622
g_socket_client_async_connect_complete (ConnectionAttempt *attempt)
1623
0
{
1624
0
  GSocketClientAsyncConnectData *data = attempt->data;
1625
0
  GError *error = NULL;
1626
0
  g_assert (attempt->connection);
1627
0
  g_assert (!data->completed);
1628
1629
0
  if (!G_IS_SOCKET_CONNECTION (attempt->connection))
1630
0
    {
1631
0
      GSocketConnection *wrapper_connection;
1632
1633
0
      wrapper_connection = g_tcp_wrapper_connection_new (attempt->connection, attempt->socket);
1634
0
      g_object_unref (attempt->connection);
1635
0
      attempt->connection = (GIOStream *)wrapper_connection;
1636
0
    }
1637
1638
0
  data->completed = TRUE;
1639
0
  cancel_all_attempts (data);
1640
1641
0
  if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
1642
0
    {
1643
0
      g_debug ("GSocketClient: Connection cancelled!");
1644
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
1645
0
      g_task_return_error (data->task, g_steal_pointer (&error));
1646
0
    }
1647
0
  else
1648
0
    {
1649
0
      g_debug ("GSocketClient: Connection successful!");
1650
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, attempt->connection);
1651
0
      g_task_return_pointer (data->task, g_steal_pointer (&attempt->connection), g_object_unref);
1652
0
    }
1653
1654
0
  connection_attempt_unref (attempt);
1655
0
  g_object_unref (data->task);
1656
0
}
1657
1658
1659
static void
1660
g_socket_client_enumerator_callback (GObject      *object,
1661
             GAsyncResult *result,
1662
             gpointer      user_data);
1663
1664
static void
1665
enumerator_next_async (GSocketClientAsyncConnectData *data,
1666
                       gboolean                       add_task_ref)
1667
0
{
1668
  /* Each enumeration takes a ref. This arg just avoids repeated unrefs when
1669
     an enumeration starts another enumeration */
1670
0
  if (add_task_ref)
1671
0
    g_object_ref (data->task);
1672
1673
0
  if (data->n_addresses_enumerated == 0)
1674
0
    g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
1675
0
  g_debug ("GSocketClient: Starting new address enumeration");
1676
0
  g_socket_address_enumerator_next_async (data->enumerator,
1677
0
            data->enumeration_cancellable,
1678
0
            g_socket_client_enumerator_callback,
1679
0
            data);
1680
0
}
1681
1682
static void try_next_connection_or_finish (GSocketClientAsyncConnectData *, gboolean);
1683
1684
static void
1685
g_socket_client_tls_handshake_callback (GObject      *object,
1686
          GAsyncResult *result,
1687
          gpointer      user_data)
1688
0
{
1689
0
  ConnectionAttempt *attempt = user_data;
1690
0
  GSocketClientAsyncConnectData *data = attempt->data;
1691
1692
0
  if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object),
1693
0
           result,
1694
0
           &data->error_info->tmp_error))
1695
0
    {
1696
0
      g_object_unref (attempt->connection);
1697
0
      attempt->connection = G_IO_STREAM (object);
1698
1699
0
      g_debug ("GSocketClient: TLS handshake succeeded");
1700
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, attempt->connection);
1701
0
      g_socket_client_async_connect_complete (attempt);
1702
0
    }
1703
0
  else
1704
0
    {
1705
0
      g_object_unref (object);
1706
0
      connection_attempt_unref (attempt);
1707
1708
0
      g_debug ("GSocketClient: TLS handshake failed: %s", data->error_info->tmp_error->message);
1709
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
1710
0
      try_next_connection_or_finish (data, TRUE);
1711
0
    }
1712
0
}
1713
1714
static void
1715
g_socket_client_tls_handshake (ConnectionAttempt *attempt)
1716
0
{
1717
0
  GSocketClientAsyncConnectData *data = attempt->data;
1718
0
  GIOStream *tlsconn;
1719
1720
0
  if (!data->client->priv->tls)
1721
0
    {
1722
0
      g_socket_client_async_connect_complete (attempt);
1723
0
      return;
1724
0
    }
1725
1726
0
  g_debug ("GSocketClient: Starting TLS handshake");
1727
0
  tlsconn = g_tls_client_connection_new (attempt->connection,
1728
0
           data->connectable,
1729
0
           &data->error_info->tmp_error);
1730
0
  if (tlsconn)
1731
0
    {
1732
0
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1733
0
      g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn),
1734
0
                                                    data->client->priv->tls_validation_flags);
1735
0
G_GNUC_END_IGNORE_DEPRECATIONS
1736
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKING, data->connectable, G_IO_STREAM (tlsconn));
1737
1738
      /* This operation will time out if the underlying #GSocket times out on
1739
       * any part of the TLS handshake. It does not have a higher-level
1740
       * timeout. */
1741
0
      g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn),
1742
0
          G_PRIORITY_DEFAULT,
1743
0
          g_task_get_cancellable (data->task),
1744
0
          g_socket_client_tls_handshake_callback,
1745
0
          attempt);
1746
0
    }
1747
0
  else
1748
0
    {
1749
0
      connection_attempt_unref (attempt);
1750
1751
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING);
1752
0
      try_next_connection_or_finish (data, TRUE);
1753
0
    }
1754
0
}
1755
1756
static void
1757
g_socket_client_proxy_connect_callback (GObject      *object,
1758
          GAsyncResult *result,
1759
          gpointer      user_data)
1760
0
{
1761
0
  ConnectionAttempt *attempt = user_data;
1762
0
  GSocketClientAsyncConnectData *data = attempt->data;
1763
1764
0
  g_object_unref (attempt->connection);
1765
0
  attempt->connection = g_proxy_connect_finish (G_PROXY (object),
1766
0
                                                result,
1767
0
                                                &data->error_info->tmp_error);
1768
0
  if (attempt->connection)
1769
0
    {
1770
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, attempt->connection);
1771
0
      g_socket_client_tls_handshake (attempt);
1772
0
    }
1773
0
  else
1774
0
    {
1775
0
      connection_attempt_unref (attempt);
1776
1777
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1778
0
      try_next_connection_or_finish (data, TRUE);
1779
0
    }
1780
0
}
1781
1782
static void
1783
complete_connection_with_error (GSocketClientAsyncConnectData *data,
1784
                                GError                        *error)
1785
0
{
1786
0
  g_debug ("GSocketClient: Connection failed: %s", error->message);
1787
0
  g_assert (!data->completed);
1788
1789
0
  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
1790
0
  data->completed = TRUE;
1791
0
  cancel_all_attempts (data);
1792
0
  g_task_return_error (data->task, error);
1793
0
}
1794
1795
static gboolean
1796
task_completed_or_cancelled (GSocketClientAsyncConnectData *data)
1797
0
{
1798
0
  GTask *task = data->task;
1799
0
  GCancellable *cancellable = g_task_get_cancellable (task);
1800
0
  GError *error = NULL;
1801
1802
0
  if (data->completed)
1803
0
    return TRUE;
1804
0
  else if (g_cancellable_set_error_if_cancelled (cancellable, &error))
1805
0
    {
1806
0
      complete_connection_with_error (data, g_steal_pointer (&error));
1807
0
      return TRUE;
1808
0
    }
1809
0
  else
1810
0
    return FALSE;
1811
0
}
1812
1813
/* Returns %TRUE if it’s popped a connection of data->successful_connections and
1814
 * successfully started the next ongoing async operation for that connection. */
1815
static gboolean
1816
try_next_successful_connection (GSocketClientAsyncConnectData *data)
1817
0
{
1818
0
  ConnectionAttempt *attempt;
1819
0
  const gchar *protocol;
1820
0
  GProxy *proxy;
1821
1822
0
  if (data->connection_in_progress)
1823
0
    return FALSE;
1824
1825
0
  g_assert (data->successful_connections != NULL);
1826
0
  attempt = data->successful_connections->data;
1827
0
  g_assert (attempt != NULL);
1828
0
  data->successful_connections = g_slist_remove (data->successful_connections, attempt);
1829
0
  data->connection_in_progress = TRUE;
1830
1831
0
  g_debug ("GSocketClient: Starting application layer connection");
1832
1833
0
  if (!attempt->proxy_addr)
1834
0
    {
1835
0
      g_socket_client_tls_handshake (g_steal_pointer (&attempt));
1836
0
      return TRUE;
1837
0
    }
1838
1839
0
  protocol = g_proxy_address_get_protocol (attempt->proxy_addr);
1840
1841
  /* The connection should not be anything other than TCP,
1842
   * but let's put a safety guard in case
1843
   */
1844
0
  if (!G_IS_TCP_CONNECTION (attempt->connection))
1845
0
    {
1846
0
      g_critical ("Trying to proxy over non-TCP connection, this is "
1847
0
          "most likely a bug in GLib IO library.");
1848
1849
0
      g_set_error_literal (&data->error_info->tmp_error,
1850
0
          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1851
0
          _("Proxying over a non-TCP connection is not supported."));
1852
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1853
0
    }
1854
0
  else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
1855
0
    {
1856
      /* Simply complete the connection, we don't want to do TLS handshake
1857
       * as the application proxy handling may need proxy handshake first */
1858
0
      g_socket_client_async_connect_complete (g_steal_pointer (&attempt));
1859
0
      return TRUE;
1860
0
    }
1861
0
  else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
1862
0
    {
1863
0
      GIOStream *connection = attempt->connection;
1864
0
      GProxyAddress *proxy_addr = attempt->proxy_addr;
1865
1866
0
      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, attempt->connection);
1867
0
      g_debug ("GSocketClient: Starting proxy connection");
1868
1869
      /* FIXME: The #GProxy implementations do not have well-defined timeout
1870
       * behaviour, so this operation may theoretically never complete or time
1871
       * out. In practice, all #GProxy implementations use a #GSocket and a
1872
       * default timeout on that will eventually be hit. But there is no
1873
       * higher-level timeout. */
1874
0
      g_proxy_connect_async (proxy,
1875
0
                             connection,
1876
0
                             proxy_addr,
1877
0
                             g_task_get_cancellable (data->task),
1878
0
                             g_socket_client_proxy_connect_callback,
1879
0
                             g_steal_pointer (&attempt));
1880
0
      g_object_unref (proxy);
1881
0
      return TRUE;
1882
0
    }
1883
0
  else
1884
0
    {
1885
0
      g_set_error (&data->error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1886
0
          _("Proxy protocol “%s” is not supported."),
1887
0
          protocol);
1888
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING);
1889
0
    }
1890
1891
0
  data->connection_in_progress = FALSE;
1892
0
  g_clear_pointer (&attempt, connection_attempt_unref);
1893
0
  return FALSE; /* All non-return paths are failures */
1894
0
}
1895
1896
static void
1897
try_next_connection_or_finish (GSocketClientAsyncConnectData *data,
1898
                               gboolean                       end_current_connection)
1899
0
{
1900
0
  if (end_current_connection)
1901
0
    data->connection_in_progress = FALSE;
1902
1903
0
  if (data->connection_in_progress)
1904
0
    return;
1905
1906
  /* Try to pop and make progress on the next successful_connection. */
1907
0
  while (data->successful_connections)
1908
0
    {
1909
0
      if (try_next_successful_connection (data))
1910
0
        return;
1911
0
    }
1912
1913
  /* If there are no more successful_connections which we can make progress on,
1914
   * try the next address enumeration. */
1915
0
  if (!data->enumeration_completed)
1916
0
    {
1917
0
      enumerator_next_async (data, FALSE);
1918
0
      return;
1919
0
    }
1920
1921
0
  complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error));
1922
0
  g_object_unref (data->task);
1923
0
}
1924
1925
static void
1926
g_socket_client_connected_callback (GObject      *source,
1927
            GAsyncResult *result,
1928
            gpointer      user_data)
1929
0
{
1930
0
  ConnectionAttempt *attempt = g_steal_pointer (&user_data);
1931
0
  GSocketClientAsyncConnectData *data = attempt->data;
1932
1933
0
  if (task_completed_or_cancelled (data) || g_cancellable_is_cancelled (attempt->cancellable))
1934
0
    {
1935
0
      connection_attempt_remove (attempt);
1936
0
      connection_attempt_unref (attempt);
1937
0
      g_object_unref (data->task);
1938
0
      return;
1939
0
    }
1940
1941
0
  if (attempt->delay_timeout_source)
1942
0
    {
1943
0
      g_source_destroy (attempt->delay_timeout_source);
1944
0
      g_clear_pointer (&attempt->delay_timeout_source, g_source_unref);
1945
0
    }
1946
1947
0
  if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source),
1948
0
             result, &data->error_info->tmp_error))
1949
0
    {
1950
0
      if (!g_cancellable_is_cancelled (attempt->cancellable))
1951
0
        {
1952
0
          g_debug ("GSocketClient: Connection attempt failed: %s", data->error_info->tmp_error->message);
1953
0
          clarify_connect_error (data->error_info->tmp_error, data->connectable, attempt->address);
1954
0
          consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING);
1955
0
          connection_attempt_remove (attempt);
1956
0
          connection_attempt_unref (attempt);
1957
0
          try_next_connection_or_finish (data, FALSE);
1958
0
        }
1959
0
      else /* Silently ignore cancelled attempts */
1960
0
        {
1961
0
          g_clear_error (&data->error_info->tmp_error);
1962
0
          g_object_unref (data->task);
1963
0
          connection_attempt_unref (attempt);
1964
0
        }
1965
1966
0
      return;
1967
0
    }
1968
1969
0
  g_socket_connection_set_cached_remote_address ((GSocketConnection*)attempt->connection, NULL);
1970
0
  g_debug ("GSocketClient: TCP connection successful");
1971
0
  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, attempt->connection);
1972
1973
  /* wrong, but backward compatible */
1974
0
  g_socket_set_blocking (attempt->socket, TRUE);
1975
1976
  /* This ends the parallel "happy eyeballs" portion of connecting.
1977
     Now that we have a successful tcp connection we will attempt to connect
1978
     at the TLS/Proxy layer. If those layers fail we will move on to the next
1979
     connection.
1980
   */
1981
0
  connection_attempt_remove (attempt);
1982
0
  data->successful_connections = g_slist_append (data->successful_connections, g_steal_pointer (&attempt));
1983
0
  try_next_connection_or_finish (data, FALSE);
1984
0
}
1985
1986
static gboolean
1987
on_connection_attempt_delay_reached (gpointer data)
1988
0
{
1989
0
  ConnectionAttempt *attempt = data;
1990
1991
0
  g_assert (!attempt->delay_reached);
1992
0
  attempt->delay_reached = TRUE;
1993
1994
0
  if (!attempt->data->enumeration_completed)
1995
0
    {
1996
0
      g_debug ("GSocketClient: Connection attempt delay reached, trying another enumeration");
1997
0
      enumerator_next_async (attempt->data, TRUE);
1998
0
    }
1999
2000
0
  g_clear_pointer (&attempt->delay_timeout_source, g_source_unref);
2001
0
  return G_SOURCE_REMOVE;
2002
0
}
2003
2004
static void
2005
on_connection_cancelled (GCancellable *cancellable,
2006
                         gpointer      data)
2007
0
{
2008
0
  GCancellable *linked_cancellable = G_CANCELLABLE (data);
2009
2010
0
  g_cancellable_cancel (linked_cancellable);
2011
0
}
2012
2013
static void
2014
g_socket_client_enumerator_callback (GObject      *object,
2015
             GAsyncResult *result,
2016
             gpointer      user_data)
2017
0
{
2018
0
  GSocketClientAsyncConnectData *data = user_data;
2019
0
  GSocketAddress *address = NULL;
2020
0
  GSocket *socket;
2021
0
  ConnectionAttempt *attempt;
2022
2023
0
  if (task_completed_or_cancelled (data))
2024
0
    {
2025
0
      g_object_unref (data->task);
2026
0
      return;
2027
0
    }
2028
2029
0
  address = g_socket_address_enumerator_next_finish (data->enumerator,
2030
0
                 result, &data->error_info->tmp_error);
2031
0
  if (address == NULL)
2032
0
    {
2033
0
      if (G_UNLIKELY (data->enumeration_completed))
2034
0
        return;
2035
2036
0
      data->enumeration_completed = TRUE;
2037
0
      g_debug ("GSocketClient: Address enumeration completed (out of addresses)");
2038
2039
      /* As per API docs: We only care about error if it's the first call,
2040
         after that the enumerator is done.
2041
2042
         Note that we don't care about cancellation errors because
2043
         task_completed_or_cancelled() above should handle that.
2044
2045
         If this fails and nothing is in progress then we will complete task here.
2046
       */
2047
0
      if ((data->n_addresses_enumerated > 0 && !data->connection_attempts && !data->connection_in_progress) ||
2048
0
          data->n_addresses_enumerated == 0)
2049
0
        {
2050
0
          g_debug ("GSocketClient: Address enumeration failed: %s",
2051
0
                   data->error_info->tmp_error ? data->error_info->tmp_error->message : NULL);
2052
0
          consider_tmp_error (data->error_info, G_SOCKET_CLIENT_RESOLVING);
2053
0
          g_assert (data->error_info->best_error);
2054
0
          complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error));
2055
0
        }
2056
2057
      /* Enumeration should never trigger again, drop our ref */
2058
0
      g_object_unref (data->task);
2059
0
      return;
2060
0
    }
2061
2062
0
  g_debug ("GSocketClient: Address enumeration succeeded");
2063
0
  if (data->n_addresses_enumerated == 0)
2064
0
    g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
2065
0
                                data->connectable, NULL);
2066
2067
0
  data->n_addresses_enumerated++;
2068
2069
0
  socket = create_socket (data->client, address, &data->error_info->tmp_error);
2070
0
  if (socket == NULL)
2071
0
    {
2072
0
      g_object_unref (address);
2073
0
      consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING);
2074
0
      enumerator_next_async (data, FALSE);
2075
0
      return;
2076
0
    }
2077
2078
0
  attempt = connection_attempt_new ();
2079
0
  attempt->data = data;
2080
0
  attempt->socket = socket;
2081
0
  attempt->address = address;
2082
0
  attempt->cancellable = g_cancellable_new ();
2083
0
  attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
2084
0
  attempt->delay_timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS);
2085
2086
0
  g_debug ("%s: starting connection attempt %p for GSocketClientAsyncConnectData %p",
2087
0
           G_STRFUNC, attempt, data);
2088
2089
0
  if (G_IS_PROXY_ADDRESS (address) && data->client->priv->enable_proxy)
2090
0
    attempt->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
2091
2092
0
  g_source_set_callback (attempt->delay_timeout_source, on_connection_attempt_delay_reached, attempt, NULL);
2093
0
  g_source_attach (attempt->delay_timeout_source, g_task_get_context (data->task));
2094
0
  data->connection_attempts = g_slist_append (data->connection_attempts, connection_attempt_ref (attempt));
2095
2096
0
  if (g_task_get_cancellable (data->task))
2097
0
    {
2098
0
      attempt->task_cancellable = g_object_ref (g_task_get_cancellable (data->task));
2099
0
      attempt->cancelled_id =
2100
0
          g_cancellable_connect (attempt->task_cancellable, G_CALLBACK (on_connection_cancelled),
2101
0
                                 g_object_ref (attempt->cancellable), g_object_unref);
2102
0
    }
2103
2104
0
  g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
2105
0
  g_debug ("GSocketClient: Starting TCP connection attempt");
2106
0
  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, attempt->connection);
2107
2108
  /* If client->priv->timeout is set, this async operation will time out after
2109
   * then. Otherwise it will continue until the kernel timeouts for a
2110
   * non-blocking connect() call (if any) are hit. */
2111
0
  g_socket_connection_connect_async (G_SOCKET_CONNECTION (attempt->connection),
2112
0
             address,
2113
0
             attempt->cancellable,
2114
0
             g_socket_client_connected_callback, attempt  /* transfer full */);
2115
0
}
2116
2117
/**
2118
 * g_socket_client_connect_async:
2119
 * @client: a #GSocketClient
2120
 * @connectable: a #GSocketConnectable specifying the remote address.
2121
 * @cancellable: (nullable): a #GCancellable, or %NULL
2122
 * @callback: (scope async): a #GAsyncReadyCallback
2123
 * @user_data: user data for the callback
2124
 *
2125
 * This is the asynchronous version of g_socket_client_connect().
2126
 *
2127
 * You may wish to prefer the asynchronous version even in synchronous
2128
 * command line programs because, since 2.60, it implements
2129
 * [RFC 8305](https://tools.ietf.org/html/rfc8305) "Happy Eyeballs"
2130
 * recommendations to work around long connection timeouts in networks
2131
 * where IPv6 is broken by performing an IPv4 connection simultaneously
2132
 * without waiting for IPv6 to time out, which is not supported by the
2133
 * synchronous call. (This is not an API guarantee, and may change in
2134
 * the future.)
2135
 *
2136
 * When the operation is finished @callback will be
2137
 * called. You can then call g_socket_client_connect_finish() to get
2138
 * the result of the operation.
2139
 *
2140
 * Since: 2.22
2141
 */
2142
void
2143
g_socket_client_connect_async (GSocketClient       *client,
2144
             GSocketConnectable  *connectable,
2145
             GCancellable        *cancellable,
2146
             GAsyncReadyCallback  callback,
2147
             gpointer             user_data)
2148
0
{
2149
0
  GSocketClientAsyncConnectData *data;
2150
2151
0
  g_return_if_fail (G_IS_SOCKET_CLIENT (client));
2152
2153
0
  data = g_slice_new0 (GSocketClientAsyncConnectData);
2154
0
  data->client = client;
2155
0
  data->connectable = g_object_ref (connectable);
2156
0
  data->error_info = socket_client_error_info_new ();
2157
2158
0
  if (can_use_proxy (client))
2159
0
    {
2160
0
      data->enumerator = g_socket_connectable_proxy_enumerate (connectable);
2161
0
      if (client->priv->proxy_resolver &&
2162
0
          G_IS_PROXY_ADDRESS_ENUMERATOR (data->enumerator))
2163
0
        {
2164
0
          g_object_set (G_OBJECT (data->enumerator),
2165
0
                        "proxy-resolver", client->priv->proxy_resolver,
2166
0
                        NULL);
2167
0
        }
2168
0
    }
2169
0
  else
2170
0
    data->enumerator = g_socket_connectable_enumerate (connectable);
2171
2172
  /* This function tries to match the behavior of g_socket_client_connect ()
2173
     which is simple enough but much of it is done in parallel to be as responsive
2174
     as possible as per Happy Eyeballs (RFC 8305). This complicates flow quite a
2175
     bit but we can describe it in 3 sections:
2176
2177
     Firstly we have address enumeration (DNS):
2178
       - This may be triggered multiple times by enumerator_next_async().
2179
       - It also has its own cancellable (data->enumeration_cancellable).
2180
       - Enumeration is done lazily because GNetworkAddressAddressEnumerator
2181
         also does work in parallel and may lazily add new addresses.
2182
       - If the first enumeration errors then the task errors. Otherwise all enumerations
2183
         will potentially be used (until task or enumeration is cancelled).
2184
2185
      Then we start attempting connections (TCP):
2186
        - Each connection is independent and kept in a ConnectionAttempt object.
2187
          - They each hold a ref on the main task and have their own cancellable.
2188
        - Multiple attempts may happen in parallel as per Happy Eyeballs.
2189
        - Upon failure or attempt delays being reached more connection attempts are made.
2190
          - If no connections succeed the task errors.
2191
        - Upon success they are kept in a list of successful connections.
2192
2193
      Lastly we connect at the application layer (TLS, Proxies):
2194
        - These are done in serial.
2195
          - The reasoning here is that Happy Eyeballs is about making bad connections responsive
2196
            at the IP/TCP layers. Issues at the application layer are generally not due to
2197
            connectivity issues but rather misconfiguration.
2198
        - Upon failure it will try the next TCP connection until it runs out and
2199
          the task errors.
2200
        - Upon success it cancels everything remaining (enumeration and connections)
2201
          and returns the connection.
2202
  */
2203
2204
0
  data->task = g_task_new (client, cancellable, callback, user_data);
2205
0
  g_task_set_check_cancellable (data->task, FALSE); /* We handle this manually */
2206
0
  g_task_set_source_tag (data->task, g_socket_client_connect_async);
2207
0
  g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
2208
2209
0
  data->enumeration_cancellable = g_cancellable_new ();
2210
0
  if (cancellable)
2211
0
    {
2212
0
      data->enumeration_parent_cancellable = g_object_ref (cancellable);
2213
0
      data->enumeration_cancelled_id =
2214
0
          g_cancellable_connect (cancellable, G_CALLBACK (on_connection_cancelled),
2215
0
                                 g_object_ref (data->enumeration_cancellable), g_object_unref);
2216
0
    }
2217
2218
0
  g_debug ("%s: starting new g_socket_client_connect_async() with GTask %p "
2219
0
           "and GSocketClientAsyncConnectData %p",
2220
0
           G_STRFUNC, data->task, data);
2221
2222
0
  enumerator_next_async (data, FALSE);
2223
0
}
2224
2225
/**
2226
 * g_socket_client_connect_to_host_async:
2227
 * @client: a #GSocketClient
2228
 * @host_and_port: the name and optionally the port of the host to connect to
2229
 * @default_port: the default port to connect to
2230
 * @cancellable: (nullable): a #GCancellable, or %NULL
2231
 * @callback: (scope async): a #GAsyncReadyCallback
2232
 * @user_data: user data for the callback
2233
 *
2234
 * This is the asynchronous version of g_socket_client_connect_to_host().
2235
 *
2236
 * When the operation is finished @callback will be
2237
 * called. You can then call g_socket_client_connect_to_host_finish() to get
2238
 * the result of the operation.
2239
 *
2240
 * Since: 2.22
2241
 */
2242
void
2243
g_socket_client_connect_to_host_async (GSocketClient        *client,
2244
               const gchar          *host_and_port,
2245
               guint16               default_port,
2246
               GCancellable         *cancellable,
2247
               GAsyncReadyCallback   callback,
2248
               gpointer              user_data)
2249
0
{
2250
0
  GSocketConnectable *connectable;
2251
0
  GError *error;
2252
2253
0
  error = NULL;
2254
0
  connectable = g_network_address_parse (host_and_port, default_port,
2255
0
           &error);
2256
0
  if (connectable == NULL)
2257
0
    {
2258
0
      g_task_report_error (client, callback, user_data,
2259
0
                           g_socket_client_connect_to_host_async,
2260
0
                           error);
2261
0
    }
2262
0
  else
2263
0
    {
2264
0
      g_socket_client_connect_async (client,
2265
0
             connectable, cancellable,
2266
0
             callback, user_data);
2267
0
      g_object_unref (connectable);
2268
0
    }
2269
0
}
2270
2271
/**
2272
 * g_socket_client_connect_to_service_async:
2273
 * @client: a #GSocketClient
2274
 * @domain: a domain name
2275
 * @service: the name of the service to connect to
2276
 * @cancellable: (nullable): a #GCancellable, or %NULL
2277
 * @callback: (scope async): a #GAsyncReadyCallback
2278
 * @user_data: user data for the callback
2279
 *
2280
 * This is the asynchronous version of
2281
 * g_socket_client_connect_to_service().
2282
 *
2283
 * Since: 2.22
2284
 */
2285
void
2286
g_socket_client_connect_to_service_async (GSocketClient       *client,
2287
            const gchar         *domain,
2288
            const gchar         *service,
2289
            GCancellable        *cancellable,
2290
            GAsyncReadyCallback  callback,
2291
            gpointer             user_data)
2292
0
{
2293
0
  GSocketConnectable *connectable;
2294
2295
0
  connectable = g_network_service_new (service, "tcp", domain);
2296
0
  g_socket_client_connect_async (client,
2297
0
         connectable, cancellable,
2298
0
         callback, user_data);
2299
0
  g_object_unref (connectable);
2300
0
}
2301
2302
/**
2303
 * g_socket_client_connect_to_uri_async:
2304
 * @client: a #GSocketClient
2305
 * @uri: a network uri
2306
 * @default_port: the default port to connect to
2307
 * @cancellable: (nullable): a #GCancellable, or %NULL
2308
 * @callback: (scope async): a #GAsyncReadyCallback
2309
 * @user_data: user data for the callback
2310
 *
2311
 * This is the asynchronous version of g_socket_client_connect_to_uri().
2312
 *
2313
 * When the operation is finished @callback will be
2314
 * called. You can then call g_socket_client_connect_to_uri_finish() to get
2315
 * the result of the operation.
2316
 *
2317
 * Since: 2.26
2318
 */
2319
void
2320
g_socket_client_connect_to_uri_async (GSocketClient        *client,
2321
              const gchar          *uri,
2322
              guint16               default_port,
2323
              GCancellable         *cancellable,
2324
              GAsyncReadyCallback   callback,
2325
              gpointer              user_data)
2326
0
{
2327
0
  GSocketConnectable *connectable;
2328
0
  GError *error;
2329
2330
0
  error = NULL;
2331
0
  connectable = g_network_address_parse_uri (uri, default_port, &error);
2332
0
  if (connectable == NULL)
2333
0
    {
2334
0
      g_task_report_error (client, callback, user_data,
2335
0
                           g_socket_client_connect_to_uri_async,
2336
0
                           error);
2337
0
    }
2338
0
  else
2339
0
    {
2340
0
      g_debug("g_socket_client_connect_to_uri_async");
2341
0
      g_socket_client_connect_async (client,
2342
0
             connectable, cancellable,
2343
0
             callback, user_data);
2344
0
      g_object_unref (connectable);
2345
0
    }
2346
0
}
2347
2348
2349
/**
2350
 * g_socket_client_connect_finish:
2351
 * @client: a #GSocketClient.
2352
 * @result: a #GAsyncResult.
2353
 * @error: a #GError location to store the error occurring, or %NULL to
2354
 * ignore.
2355
 *
2356
 * Finishes an async connect operation. See g_socket_client_connect_async()
2357
 *
2358
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
2359
 *
2360
 * Since: 2.22
2361
 */
2362
GSocketConnection *
2363
g_socket_client_connect_finish (GSocketClient  *client,
2364
        GAsyncResult   *result,
2365
        GError        **error)
2366
0
{
2367
0
  g_return_val_if_fail (g_task_is_valid (result, client), NULL);
2368
2369
0
  return g_task_propagate_pointer (G_TASK (result), error);
2370
0
}
2371
2372
/**
2373
 * g_socket_client_connect_to_host_finish:
2374
 * @client: a #GSocketClient.
2375
 * @result: a #GAsyncResult.
2376
 * @error: a #GError location to store the error occurring, or %NULL to
2377
 * ignore.
2378
 *
2379
 * Finishes an async connect operation. See g_socket_client_connect_to_host_async()
2380
 *
2381
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
2382
 *
2383
 * Since: 2.22
2384
 */
2385
GSocketConnection *
2386
g_socket_client_connect_to_host_finish (GSocketClient  *client,
2387
          GAsyncResult   *result,
2388
          GError        **error)
2389
0
{
2390
0
  return g_socket_client_connect_finish (client, result, error);
2391
0
}
2392
2393
/**
2394
 * g_socket_client_connect_to_service_finish:
2395
 * @client: a #GSocketClient.
2396
 * @result: a #GAsyncResult.
2397
 * @error: a #GError location to store the error occurring, or %NULL to
2398
 * ignore.
2399
 *
2400
 * Finishes an async connect operation. See g_socket_client_connect_to_service_async()
2401
 *
2402
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
2403
 *
2404
 * Since: 2.22
2405
 */
2406
GSocketConnection *
2407
g_socket_client_connect_to_service_finish (GSocketClient  *client,
2408
             GAsyncResult   *result,
2409
             GError        **error)
2410
0
{
2411
0
  return g_socket_client_connect_finish (client, result, error);
2412
0
}
2413
2414
/**
2415
 * g_socket_client_connect_to_uri_finish:
2416
 * @client: a #GSocketClient.
2417
 * @result: a #GAsyncResult.
2418
 * @error: a #GError location to store the error occurring, or %NULL to
2419
 * ignore.
2420
 *
2421
 * Finishes an async connect operation. See g_socket_client_connect_to_uri_async()
2422
 *
2423
 * Returns: (transfer full): a #GSocketConnection on success, %NULL on error.
2424
 *
2425
 * Since: 2.26
2426
 */
2427
GSocketConnection *
2428
g_socket_client_connect_to_uri_finish (GSocketClient  *client,
2429
               GAsyncResult   *result,
2430
               GError        **error)
2431
0
{
2432
0
  return g_socket_client_connect_finish (client, result, error);
2433
0
}
2434
2435
/**
2436
 * g_socket_client_add_application_proxy:
2437
 * @client: a #GSocketClient
2438
 * @protocol: The proxy protocol
2439
 *
2440
 * Enable proxy protocols to be handled by the application. When the
2441
 * indicated proxy protocol is returned by the #GProxyResolver,
2442
 * #GSocketClient will consider this protocol as supported but will
2443
 * not try to find a #GProxy instance to handle handshaking. The
2444
 * application must check for this case by calling
2445
 * g_socket_connection_get_remote_address() on the returned
2446
 * #GSocketConnection, and seeing if it's a #GProxyAddress of the
2447
 * appropriate type, to determine whether or not it needs to handle
2448
 * the proxy handshaking itself.
2449
 *
2450
 * This should be used for proxy protocols that are dialects of
2451
 * another protocol such as HTTP proxy. It also allows cohabitation of
2452
 * proxy protocols that are reused between protocols. A good example
2453
 * is HTTP. It can be used to proxy HTTP, FTP and Gopher and can also
2454
 * be use as generic socket proxy through the HTTP CONNECT method.
2455
 *
2456
 * When the proxy is detected as being an application proxy, TLS handshake
2457
 * will be skipped. This is required to let the application do the proxy
2458
 * specific handshake.
2459
 */
2460
void
2461
g_socket_client_add_application_proxy (GSocketClient *client,
2462
                     const gchar   *protocol)
2463
0
{
2464
0
  g_hash_table_add (client->priv->app_proxies, g_strdup (protocol));
2465
0
}