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