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