• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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