Gentoo Archives: gentoo-commits

From: Jory Pratt <anarchy@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/musl:master commit in: dev-libs/glib/files/
Date: Mon, 29 Jun 2020 01:01:41
Message-Id: 1593392492.c76e3a569dd4139e7f9d3d7888910a4298f9bb3c.anarchy@gentoo
1 commit: c76e3a569dd4139e7f9d3d7888910a4298f9bb3c
2 Author: Jory Pratt <anarchy <AT> gentoo <DOT> org>
3 AuthorDate: Mon Jun 29 01:01:32 2020 +0000
4 Commit: Jory Pratt <anarchy <AT> gentoo <DOT> org>
5 CommitDate: Mon Jun 29 01:01:32 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/musl.git/commit/?id=c76e3a56
7
8 dev-libs/glib: drop obsolete patches
9
10 Package-Manager: Portage-2.3.103, Repoman-2.3.23
11 Signed-off-by: Jory Pratt <anarchy <AT> gentoo.org>
12
13 dev-libs/glib/files/2.60.7-gdbus-fixes.patch | 301 -----------
14 dev-libs/glib/files/CVE-2020-6750.patch | 763 ---------------------------
15 2 files changed, 1064 deletions(-)
16
17 diff --git a/dev-libs/glib/files/2.60.7-gdbus-fixes.patch b/dev-libs/glib/files/2.60.7-gdbus-fixes.patch
18 deleted file mode 100644
19 index e2a066b..0000000
20 --- a/dev-libs/glib/files/2.60.7-gdbus-fixes.patch
21 +++ /dev/null
22 @@ -1,301 +0,0 @@
23 -From 1cfab12a28d97716ad581c30fbbf3e94e4d7f303 Mon Sep 17 00:00:00 2001
24 -From: Simon McVittie <smcv@×××××××××.com>
25 -Date: Mon, 14 Oct 2019 08:22:24 +0100
26 -Subject: [PATCH 1/3] gcredentialsprivate: Document the various private macros
27 -
28 -Signed-off-by: Simon McVittie <smcv@×××××××××.com>
29 ----
30 - gio/gcredentialsprivate.h | 59 +++++++++++++++++++++++++++++++++++++++
31 - 1 file changed, 59 insertions(+)
32 -
33 -diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h
34 -index 4d1c420a8..06f0aed19 100644
35 ---- a/gio/gcredentialsprivate.h
36 -+++ b/gio/gcredentialsprivate.h
37 -@@ -22,6 +22,65 @@
38 - #include "gio/gcredentials.h"
39 - #include "gio/gnetworking.h"
40 -
41 -+/*
42 -+ * G_CREDENTIALS_SUPPORTED:
43 -+ *
44 -+ * Defined to 1 if GCredentials works.
45 -+ */
46 -+#undef G_CREDENTIALS_SUPPORTED
47 -+
48 -+/*
49 -+ * G_CREDENTIALS_USE_LINUX_UCRED, etc.:
50 -+ *
51 -+ * Defined to 1 if GCredentials uses Linux `struct ucred`, etc.
52 -+ */
53 -+#undef G_CREDENTIALS_USE_LINUX_UCRED
54 -+#undef G_CREDENTIALS_USE_FREEBSD_CMSGCRED
55 -+#undef G_CREDENTIALS_USE_NETBSD_UNPCBID
56 -+#undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
57 -+#undef G_CREDENTIALS_USE_SOLARIS_UCRED
58 -+
59 -+/*
60 -+ * G_CREDENTIALS_NATIVE_TYPE:
61 -+ *
62 -+ * Defined to one of G_CREDENTIALS_TYPE_LINUX_UCRED, etc.
63 -+ */
64 -+#undef G_CREDENTIALS_NATIVE_TYPE
65 -+
66 -+/*
67 -+ * G_CREDENTIALS_NATIVE_SIZE:
68 -+ *
69 -+ * Defined to the size of the %G_CREDENTIALS_NATIVE_TYPE
70 -+ */
71 -+#undef G_CREDENTIALS_NATIVE_SIZE
72 -+
73 -+/*
74 -+ * G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED:
75 -+ *
76 -+ * Defined to 1 if we have a message-passing API in which credentials
77 -+ * are attached to a particular message, such as `SCM_CREDENTIALS` on Linux
78 -+ * or `SCM_CREDS` on FreeBSD.
79 -+ */
80 -+#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
81 -+
82 -+/*
83 -+ * G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED:
84 -+ *
85 -+ * Defined to 1 if we have a `getsockopt()`-style API in which one end of
86 -+ * a socket connection can directly query the credentials of the process
87 -+ * that initiated the other end, such as `getsockopt SO_PEERCRED` on Linux
88 -+ * or `getpeereid()` on multiple operating systems.
89 -+ */
90 -+#undef G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
91 -+
92 -+/*
93 -+ * G_CREDENTIALS_SPOOFING_SUPPORTED:
94 -+ *
95 -+ * Defined to 1 if privileged processes can spoof their credentials when
96 -+ * using the message-passing API.
97 -+ */
98 -+#undef G_CREDENTIALS_SPOOFING_SUPPORTED
99 -+
100 - #ifdef __linux__
101 - #define G_CREDENTIALS_SUPPORTED 1
102 - #define G_CREDENTIALS_USE_LINUX_UCRED 1
103 ---
104 -2.20.1
105 -
106 -
107 -From 5f9318af8f19756685c1b79cf8b76f3e66614d84 Mon Sep 17 00:00:00 2001
108 -From: Simon McVittie <smcv@×××××××××.com>
109 -Date: Fri, 18 Oct 2019 10:55:09 +0100
110 -Subject: [PATCH 2/3] credentials: Invalid Linux struct ucred means "no
111 - information"
112 -
113 -On Linux, if getsockopt SO_PEERCRED is used on a TCP socket, one
114 -might expect it to fail with an appropriate error like ENOTSUP or
115 -EPROTONOSUPPORT. However, it appears that in fact it succeeds, but
116 -yields a credentials structure with pid 0, uid -1 and gid -1. These
117 -are not real process, user and group IDs that can be allocated to a
118 -real process (pid 0 needs to be reserved to give kill(0) its documented
119 -special semantics, and similarly uid and gid -1 need to be reserved for
120 -setresuid() and setresgid()) so it is not meaningful to signal them to
121 -high-level API users.
122 -
123 -An API user with Linux-specific knowledge can still inspect these fields
124 -via g_credentials_get_native() if desired.
125 -
126 -Similarly, if SO_PASSCRED is used to receive a SCM_CREDENTIALS message
127 -on a receiving Unix socket, but the sending socket had not enabled
128 -SO_PASSCRED at the time that the message was sent, it is possible
129 -for it to succeed but yield a credentials structure with pid 0, uid
130 -/proc/sys/kernel/overflowuid and gid /proc/sys/kernel/overflowgid. Even
131 -if we were to read those pseudo-files, we cannot distinguish between
132 -the overflow IDs and a real process that legitimately has the same IDs
133 -(typically they are set to 'nobody' and 'nogroup', which can be used
134 -by a real process), so we detect this situation by noticing that
135 -pid == 0, and to save syscalls we do not read the overflow IDs from
136 -/proc at all.
137 -
138 -This results in a small API change: g_credentials_is_same_user() now
139 -returns FALSE if we compare two credentials structures that are both
140 -invalid. This seems like reasonable, conservative behaviour: if we cannot
141 -prove that they are the same user, we should assume they are not.
142 -
143 -(Dropped new translatable string when backporting to `glib-2-62`.)
144 -
145 -Signed-off-by: Simon McVittie <smcv@×××××××××.com>
146 ----
147 - gio/gcredentials.c | 42 +++++++++++++++++++++++++++++++++++++++---
148 - 1 file changed, 39 insertions(+), 3 deletions(-)
149 -
150 -diff --git a/gio/gcredentials.c b/gio/gcredentials.c
151 -index 57a39f2a2..ff9b7e0b8 100644
152 ---- a/gio/gcredentials.c
153 -+++ b/gio/gcredentials.c
154 -@@ -265,6 +265,35 @@ g_credentials_to_string (GCredentials *credentials)
155 -
156 - /* ---------------------------------------------------------------------------------------------------- */
157 -
158 -+#if G_CREDENTIALS_USE_LINUX_UCRED
159 -+/*
160 -+ * Check whether @native contains invalid data. If getsockopt SO_PEERCRED
161 -+ * is used on a TCP socket, it succeeds but yields a credentials structure
162 -+ * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a
163 -+ * receiving Unix socket when the sending socket did not also enable
164 -+ * SO_PASSCRED, it can succeed but yield a credentials structure with
165 -+ * pid 0, uid /proc/sys/kernel/overflowuid and gid
166 -+ * /proc/sys/kernel/overflowgid.
167 -+ */
168 -+static gboolean
169 -+linux_ucred_check_valid (struct ucred *native,
170 -+ GError **error)
171 -+{
172 -+ if (native->pid == 0
173 -+ || native->uid == -1
174 -+ || native->gid == -1)
175 -+ {
176 -+ g_set_error_literal (error,
177 -+ G_IO_ERROR,
178 -+ G_IO_ERROR_INVALID_DATA,
179 -+ "GCredentials contains invalid data");
180 -+ return FALSE;
181 -+ }
182 -+
183 -+ return TRUE;
184 -+}
185 -+#endif
186 -+
187 - /**
188 - * g_credentials_is_same_user:
189 - * @credentials: A #GCredentials.
190 -@@ -294,7 +323,8 @@ g_credentials_is_same_user (GCredentials *credentials,
191 -
192 - ret = FALSE;
193 - #if G_CREDENTIALS_USE_LINUX_UCRED
194 -- if (credentials->native.uid == other_credentials->native.uid)
195 -+ if (linux_ucred_check_valid (&credentials->native, NULL)
196 -+ && credentials->native.uid == other_credentials->native.uid)
197 - ret = TRUE;
198 - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
199 - if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
200 -@@ -453,7 +483,10 @@ g_credentials_get_unix_user (GCredentials *credentials,
201 - g_return_val_if_fail (error == NULL || *error == NULL, -1);
202 -
203 - #if G_CREDENTIALS_USE_LINUX_UCRED
204 -- ret = credentials->native.uid;
205 -+ if (linux_ucred_check_valid (&credentials->native, error))
206 -+ ret = credentials->native.uid;
207 -+ else
208 -+ ret = -1;
209 - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
210 - ret = credentials->native.cmcred_euid;
211 - #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
212 -@@ -499,7 +532,10 @@ g_credentials_get_unix_pid (GCredentials *credentials,
213 - g_return_val_if_fail (error == NULL || *error == NULL, -1);
214 -
215 - #if G_CREDENTIALS_USE_LINUX_UCRED
216 -- ret = credentials->native.pid;
217 -+ if (linux_ucred_check_valid (&credentials->native, error))
218 -+ ret = credentials->native.pid;
219 -+ else
220 -+ ret = -1;
221 - #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
222 - ret = credentials->native.cmcred_pid;
223 - #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
224 ---
225 -2.20.1
226 -
227 -
228 -From c7618cce3752e1f3681f75d0a26c7e07c15bd6a2 Mon Sep 17 00:00:00 2001
229 -From: Simon McVittie <smcv@×××××××××.com>
230 -Date: Mon, 14 Oct 2019 08:47:39 +0100
231 -Subject: [PATCH 3/3] GDBus: prefer getsockopt()-style credentials-passing APIs
232 -
233 -Closes: https://gitlab.gnome.org/GNOME/glib/issues/1831
234 ----
235 - gio/gcredentialsprivate.h | 18 ++++++++++++++++++
236 - gio/gdbusauth.c | 27 +++++++++++++++++++++++++--
237 - 2 files changed, 43 insertions(+), 2 deletions(-)
238 -
239 -diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h
240 -index 06f0aed19..e9ec09b9f 100644
241 ---- a/gio/gcredentialsprivate.h
242 -+++ b/gio/gcredentialsprivate.h
243 -@@ -81,6 +81,18 @@
244 - */
245 - #undef G_CREDENTIALS_SPOOFING_SUPPORTED
246 -
247 -+/*
248 -+ * G_CREDENTIALS_PREFER_MESSAGE_PASSING:
249 -+ *
250 -+ * Defined to 1 if the data structure transferred by the message-passing
251 -+ * API is strictly more informative than the one transferred by the
252 -+ * `getsockopt()`-style API, and hence should be preferred, even for
253 -+ * protocols like D-Bus that are defined in terms of the credentials of
254 -+ * the (process that opened the) socket, as opposed to the credentials
255 -+ * of an individual message.
256 -+ */
257 -+#undef G_CREDENTIALS_PREFER_MESSAGE_PASSING
258 -+
259 - #ifdef __linux__
260 - #define G_CREDENTIALS_SUPPORTED 1
261 - #define G_CREDENTIALS_USE_LINUX_UCRED 1
262 -@@ -100,6 +112,12 @@
263 - #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred))
264 - #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
265 - #define G_CREDENTIALS_SPOOFING_SUPPORTED 1
266 -+/* GLib doesn't implement it yet, but FreeBSD's getsockopt()-style API
267 -+ * is getpeereid(), which is not as informative as struct cmsgcred -
268 -+ * it does not tell us the PID. As a result, libdbus prefers to use
269 -+ * SCM_CREDS, and if we implement getpeereid() in future, we should
270 -+ * do the same. */
271 -+#define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1
272 -
273 - #elif defined(__NetBSD__)
274 - #define G_CREDENTIALS_SUPPORTED 1
275 -diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c
276 -index 752ec23fc..14cc5d70e 100644
277 ---- a/gio/gdbusauth.c
278 -+++ b/gio/gdbusauth.c
279 -@@ -31,6 +31,7 @@
280 - #include "gdbusutils.h"
281 - #include "gioenumtypes.h"
282 - #include "gcredentials.h"
283 -+#include "gcredentialsprivate.h"
284 - #include "gdbusprivate.h"
285 - #include "giostream.h"
286 - #include "gdatainputstream.h"
287 -@@ -969,9 +970,31 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
288 -
289 - g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
290 -
291 -- /* first read the NUL-byte */
292 -+ /* read the NUL-byte, possibly with credentials attached */
293 - #ifdef G_OS_UNIX
294 -- if (G_IS_UNIX_CONNECTION (auth->priv->stream))
295 -+#ifndef G_CREDENTIALS_PREFER_MESSAGE_PASSING
296 -+ if (G_IS_SOCKET_CONNECTION (auth->priv->stream))
297 -+ {
298 -+ GSocket *sock = g_socket_connection_get_socket (G_SOCKET_CONNECTION (auth->priv->stream));
299 -+
300 -+ local_error = NULL;
301 -+ credentials = g_socket_get_credentials (sock, &local_error);
302 -+
303 -+ if (credentials == NULL && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
304 -+ {
305 -+ g_propagate_error (error, local_error);
306 -+ goto out;
307 -+ }
308 -+ else
309 -+ {
310 -+ /* Clear the error indicator, so we can retry with
311 -+ * g_unix_connection_receive_credentials() if necessary */
312 -+ g_clear_error (&local_error);
313 -+ }
314 -+ }
315 -+#endif
316 -+
317 -+ if (credentials == NULL && G_IS_UNIX_CONNECTION (auth->priv->stream))
318 - {
319 - local_error = NULL;
320 - credentials = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (auth->priv->stream),
321 ---
322 -2.20.1
323 -
324
325 diff --git a/dev-libs/glib/files/CVE-2020-6750.patch b/dev-libs/glib/files/CVE-2020-6750.patch
326 deleted file mode 100644
327 index fe39914..0000000
328 --- a/dev-libs/glib/files/CVE-2020-6750.patch
329 +++ /dev/null
330 @@ -1,763 +0,0 @@
331 -From cc3cf6b8b2ad12d54f3474113f0ccfa7dcf66b7b Mon Sep 17 00:00:00 2001
332 -From: Michael Catanzaro <mcatanzaro@×××××.org>
333 -Date: Sat, 4 Jan 2020 20:46:25 -0600
334 -Subject: [PATCH] gsocketclient: run timeout source on the task's main context
335 -
336 -This shouldn't make any difference, because this code should only ever
337 -be running in the main context that was thread-default at the time the
338 -task was created, so it should already match the task's context. But
339 -let's make sure, just in case.
340 ----
341 - gio/gsocketclient.c | 2 +-
342 - 1 file changed, 1 insertion(+), 1 deletion(-)
343 -
344 -diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
345 -index 6adeee299..81721795b 100644
346 ---- a/gio/gsocketclient.c
347 -+++ b/gio/gsocketclient.c
348 -@@ -1794,7 +1794,7 @@ g_socket_client_enumerator_callback (GObject *object,
349 - attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
350 - attempt->timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS);
351 - g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL);
352 -- g_source_attach (attempt->timeout_source, g_main_context_get_thread_default ());
353 -+ g_source_attach (attempt->timeout_source, g_task_get_context (data->task));
354 - data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
355 -
356 - if (g_task_get_cancellable (data->task))
357 ---
358 -2.24.1
359 -
360 -From d4fcf91460696b09bb2b55c352a023f6dd71c7fe Mon Sep 17 00:00:00 2001
361 -From: Patrick Griffis <tingping@××××××××.se>
362 -Date: Thu, 23 Jan 2020 19:58:41 -0800
363 -Subject: [PATCH] Refactor g_socket_client_connect_async()
364 -
365 -This is a fairly large refactoring. The highlights are:
366 -
367 -- Removing in-progress connections/addresses from GSocketClientAsyncConnectData:
368 -
369 - This caused issues where multiple ConnectionAttempt's would step over eachother
370 - and modify shared state causing bugs like accidentally bypassing a set proxy.
371 -
372 - Fixes #1871
373 - Fixes #1989
374 - Fixes #1902
375 -
376 -- Cancelling address enumeration on error/completion
377 -
378 -- Queuing successful TCP connections and doing application layer work serially:
379 -
380 - This is more in the spirit of Happy Eyeballs but it also greatly simplifies
381 - the flow of connection handling so fewer tasks are happening in parallel
382 - when they don't need to be.
383 -
384 - The behavior also should more closely match that of g_socket_client_connect().
385 -
386 -- Better track the state of address enumeration:
387 -
388 - Previously we were over eager to treat enumeration finishing as an error.
389 -
390 - Fixes #1872
391 - See also #1982
392 -
393 -- Add more detailed documentation and logging.
394 -
395 -Closes #1995
396 ----
397 - gio/gsocketclient.c | 459 ++++++++++++++++++++++++++++----------------
398 - 1 file changed, 296 insertions(+), 163 deletions(-)
399 -
400 -diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
401 -index 81721795b..c9943309c 100644
402 ---- a/gio/gsocketclient.c
403 -+++ b/gio/gsocketclient.c
404 -@@ -1337,13 +1337,15 @@ typedef struct
405 -
406 - GSocketConnectable *connectable;
407 - GSocketAddressEnumerator *enumerator;
408 -- GProxyAddress *proxy_addr;
409 -- GSocket *socket;
410 -- GIOStream *connection;
411 -+ GCancellable *enumeration_cancellable;
412 -
413 - GSList *connection_attempts;
414 -+ GSList *successful_connections;
415 - GError *last_error;
416 -
417 -+ gboolean enumerated_at_least_once;
418 -+ gboolean enumeration_completed;
419 -+ gboolean connection_in_progress;
420 - gboolean completed;
421 - } GSocketClientAsyncConnectData;
422 -
423 -@@ -1355,10 +1357,9 @@ g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
424 - data->task = NULL;
425 - g_clear_object (&data->connectable);
426 - g_clear_object (&data->enumerator);
427 -- g_clear_object (&data->proxy_addr);
428 -- g_clear_object (&data->socket);
429 -- g_clear_object (&data->connection);
430 -+ g_clear_object (&data->enumeration_cancellable);
431 - g_slist_free_full (data->connection_attempts, connection_attempt_unref);
432 -+ g_slist_free_full (data->successful_connections, connection_attempt_unref);
433 -
434 - g_clear_error (&data->last_error);
435 -
436 -@@ -1370,6 +1371,7 @@ typedef struct
437 - GSocketAddress *address;
438 - GSocket *socket;
439 - GIOStream *connection;
440 -+ GProxyAddress *proxy_addr;
441 - GSocketClientAsyncConnectData *data; /* unowned */
442 - GSource *timeout_source;
443 - GCancellable *cancellable;
444 -@@ -1401,6 +1403,7 @@ connection_attempt_unref (gpointer pointer)
445 - g_clear_object (&attempt->socket);
446 - g_clear_object (&attempt->connection);
447 - g_clear_object (&attempt->cancellable);
448 -+ g_clear_object (&attempt->proxy_addr);
449 - if (attempt->timeout_source)
450 - {
451 - g_source_destroy (attempt->timeout_source);
452 -@@ -1418,37 +1421,59 @@ connection_attempt_remove (ConnectionAttempt *attempt)
453 - }
454 -
455 - static void
456 --g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
457 -+cancel_all_attempts (GSocketClientAsyncConnectData *data)
458 - {
459 -- g_assert (data->connection);
460 -+ GSList *l;
461 -
462 -- if (!G_IS_SOCKET_CONNECTION (data->connection))
463 -+ for (l = data->connection_attempts; l; l = g_slist_next (l))
464 - {
465 -- GSocketConnection *wrapper_connection;
466 --
467 -- wrapper_connection = g_tcp_wrapper_connection_new (data->connection, data->socket);
468 -- g_object_unref (data->connection);
469 -- data->connection = (GIOStream *)wrapper_connection;
470 -+ ConnectionAttempt *attempt_entry = l->data;
471 -+ g_cancellable_cancel (attempt_entry->cancellable);
472 -+ connection_attempt_unref (attempt_entry);
473 - }
474 -+ g_slist_free (data->connection_attempts);
475 -+ data->connection_attempts = NULL;
476 -
477 -- if (!data->completed)
478 -+ g_slist_free_full (data->successful_connections, connection_attempt_unref);
479 -+ data->successful_connections = NULL;
480 -+
481 -+ g_cancellable_cancel (data->enumeration_cancellable);
482 -+}
483 -+
484 -+static void
485 -+g_socket_client_async_connect_complete (ConnectionAttempt *attempt)
486 -+{
487 -+ GSocketClientAsyncConnectData *data = attempt->data;
488 -+ GError *error = NULL;
489 -+ g_assert (attempt->connection);
490 -+ g_assert (!data->completed);
491 -+
492 -+ if (!G_IS_SOCKET_CONNECTION (attempt->connection))
493 - {
494 -- GError *error = NULL;
495 -+ GSocketConnection *wrapper_connection;
496 -
497 -- if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
498 -- {
499 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
500 -- g_task_return_error (data->task, g_steal_pointer (&error));
501 -- }
502 -- else
503 -- {
504 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, data->connection);
505 -- g_task_return_pointer (data->task, g_steal_pointer (&data->connection), g_object_unref);
506 -- }
507 -+ wrapper_connection = g_tcp_wrapper_connection_new (attempt->connection, attempt->socket);
508 -+ g_object_unref (attempt->connection);
509 -+ attempt->connection = (GIOStream *)wrapper_connection;
510 -+ }
511 -
512 -- data->completed = TRUE;
513 -+ data->completed = TRUE;
514 -+ cancel_all_attempts (data);
515 -+
516 -+ if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
517 -+ {
518 -+ g_debug ("GSocketClient: Connection cancelled!");
519 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
520 -+ g_task_return_error (data->task, g_steal_pointer (&error));
521 -+ }
522 -+ else
523 -+ {
524 -+ g_debug ("GSocketClient: Connection successful!");
525 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, attempt->connection);
526 -+ g_task_return_pointer (data->task, g_steal_pointer (&attempt->connection), g_object_unref);
527 - }
528 -
529 -+ connection_attempt_unref (attempt);
530 - g_object_unref (data->task);
531 - }
532 -
533 -@@ -1470,59 +1495,63 @@ static void
534 - enumerator_next_async (GSocketClientAsyncConnectData *data,
535 - gboolean add_task_ref)
536 - {
537 -- /* We need to cleanup the state */
538 -- g_clear_object (&data->socket);
539 -- g_clear_object (&data->proxy_addr);
540 -- g_clear_object (&data->connection);
541 --
542 - /* Each enumeration takes a ref. This arg just avoids repeated unrefs when
543 - an enumeration starts another enumeration */
544 - if (add_task_ref)
545 - g_object_ref (data->task);
546 -
547 - g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
548 -+ g_debug ("GSocketClient: Starting new address enumeration");
549 - g_socket_address_enumerator_next_async (data->enumerator,
550 -- g_task_get_cancellable (data->task),
551 -+ data->enumeration_cancellable,
552 - g_socket_client_enumerator_callback,
553 - data);
554 - }
555 -
556 -+static void try_next_connection_or_finish (GSocketClientAsyncConnectData *, gboolean);
557 -+
558 - static void
559 - g_socket_client_tls_handshake_callback (GObject *object,
560 - GAsyncResult *result,
561 - gpointer user_data)
562 - {
563 -- GSocketClientAsyncConnectData *data = user_data;
564 -+ ConnectionAttempt *attempt = user_data;
565 -+ GSocketClientAsyncConnectData *data = attempt->data;
566 -
567 - if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object),
568 - result,
569 - &data->last_error))
570 - {
571 -- g_object_unref (data->connection);
572 -- data->connection = G_IO_STREAM (object);
573 -+ g_object_unref (attempt->connection);
574 -+ attempt->connection = G_IO_STREAM (object);
575 -
576 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, data->connection);
577 -- g_socket_client_async_connect_complete (data);
578 -+ g_debug ("GSocketClient: TLS handshake succeeded");
579 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, attempt->connection);
580 -+ g_socket_client_async_connect_complete (attempt);
581 - }
582 - else
583 - {
584 - g_object_unref (object);
585 -- enumerator_next_async (data, FALSE);
586 -+ connection_attempt_unref (attempt);
587 -+ g_debug ("GSocketClient: TLS handshake failed: %s", data->last_error->message);
588 -+ try_next_connection_or_finish (data, TRUE);
589 - }
590 - }
591 -
592 - static void
593 --g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data)
594 -+g_socket_client_tls_handshake (ConnectionAttempt *attempt)
595 - {
596 -+ GSocketClientAsyncConnectData *data = attempt->data;
597 - GIOStream *tlsconn;
598 -
599 - if (!data->client->priv->tls)
600 - {
601 -- g_socket_client_async_connect_complete (data);
602 -+ g_socket_client_async_connect_complete (attempt);
603 - return;
604 - }
605 -
606 -- tlsconn = g_tls_client_connection_new (data->connection,
607 -+ g_debug ("GSocketClient: Starting TLS handshake");
608 -+ tlsconn = g_tls_client_connection_new (attempt->connection,
609 - data->connectable,
610 - &data->last_error);
611 - if (tlsconn)
612 -@@ -1534,11 +1563,12 @@ g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data)
613 - G_PRIORITY_DEFAULT,
614 - g_task_get_cancellable (data->task),
615 - g_socket_client_tls_handshake_callback,
616 -- data);
617 -+ attempt);
618 - }
619 - else
620 - {
621 -- enumerator_next_async (data, FALSE);
622 -+ connection_attempt_unref (attempt);
623 -+ try_next_connection_or_finish (data, TRUE);
624 - }
625 - }
626 -
627 -@@ -1547,23 +1577,38 @@ g_socket_client_proxy_connect_callback (GObject *object,
628 - GAsyncResult *result,
629 - gpointer user_data)
630 - {
631 -- GSocketClientAsyncConnectData *data = user_data;
632 -+ ConnectionAttempt *attempt = user_data;
633 -+ GSocketClientAsyncConnectData *data = attempt->data;
634 -
635 -- g_object_unref (data->connection);
636 -- data->connection = g_proxy_connect_finish (G_PROXY (object),
637 -- result,
638 -- &data->last_error);
639 -- if (data->connection)
640 -+ g_object_unref (attempt->connection);
641 -+ attempt->connection = g_proxy_connect_finish (G_PROXY (object),
642 -+ result,
643 -+ &data->last_error);
644 -+ if (attempt->connection)
645 - {
646 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, data->connection);
647 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, attempt->connection);
648 - }
649 - else
650 - {
651 -- enumerator_next_async (data, FALSE);
652 -+ connection_attempt_unref (attempt);
653 -+ try_next_connection_or_finish (data, TRUE);
654 - return;
655 - }
656 -
657 -- g_socket_client_tls_handshake (data);
658 -+ g_socket_client_tls_handshake (attempt);
659 -+}
660 -+
661 -+static void
662 -+complete_connection_with_error (GSocketClientAsyncConnectData *data,
663 -+ GError *error)
664 -+{
665 -+ g_debug ("GSocketClient: Connection failed: %s", error->message);
666 -+ g_assert (!data->completed);
667 -+
668 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
669 -+ data->completed = TRUE;
670 -+ cancel_all_attempts (data);
671 -+ g_task_return_error (data->task, error);
672 - }
673 -
674 - static gboolean
675 -@@ -1577,15 +1622,114 @@ task_completed_or_cancelled (GSocketClientAsyncConnectData *data)
676 - return TRUE;
677 - else if (g_cancellable_set_error_if_cancelled (cancellable, &error))
678 - {
679 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
680 -- g_task_return_error (task, g_steal_pointer (&error));
681 -- data->completed = TRUE;
682 -+ complete_connection_with_error (data, g_steal_pointer (&error));
683 - return TRUE;
684 - }
685 - else
686 - return FALSE;
687 - }
688 -
689 -+static gboolean
690 -+try_next_successful_connection (GSocketClientAsyncConnectData *data)
691 -+{
692 -+ ConnectionAttempt *attempt;
693 -+ const gchar *protocol;
694 -+ GProxy *proxy;
695 -+
696 -+ if (data->connection_in_progress)
697 -+ return FALSE;
698 -+
699 -+ g_assert (data->successful_connections != NULL);
700 -+ attempt = data->successful_connections->data;
701 -+ g_assert (attempt != NULL);
702 -+ data->successful_connections = g_slist_remove (data->successful_connections, attempt);
703 -+ data->connection_in_progress = TRUE;
704 -+
705 -+ g_debug ("GSocketClient: Starting application layer connection");
706 -+
707 -+ if (!attempt->proxy_addr)
708 -+ {
709 -+ g_socket_client_tls_handshake (g_steal_pointer (&attempt));
710 -+ return TRUE;
711 -+ }
712 -+
713 -+ protocol = g_proxy_address_get_protocol (attempt->proxy_addr);
714 -+
715 -+ /* The connection should not be anything other than TCP,
716 -+ * but let's put a safety guard in case
717 -+ */
718 -+ if (!G_IS_TCP_CONNECTION (attempt->connection))
719 -+ {
720 -+ g_critical ("Trying to proxy over non-TCP connection, this is "
721 -+ "most likely a bug in GLib IO library.");
722 -+
723 -+ g_set_error_literal (&data->last_error,
724 -+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
725 -+ _("Proxying over a non-TCP connection is not supported."));
726 -+ }
727 -+ else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
728 -+ {
729 -+ /* Simply complete the connection, we don't want to do TLS handshake
730 -+ * as the application proxy handling may need proxy handshake first */
731 -+ g_socket_client_async_connect_complete (g_steal_pointer (&attempt));
732 -+ return TRUE;
733 -+ }
734 -+ else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
735 -+ {
736 -+ GIOStream *connection = attempt->connection;
737 -+ GProxyAddress *proxy_addr = attempt->proxy_addr;
738 -+
739 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, attempt->connection);
740 -+ g_debug ("GSocketClient: Starting proxy connection");
741 -+ g_proxy_connect_async (proxy,
742 -+ connection,
743 -+ proxy_addr,
744 -+ g_task_get_cancellable (data->task),
745 -+ g_socket_client_proxy_connect_callback,
746 -+ g_steal_pointer (&attempt));
747 -+ g_object_unref (proxy);
748 -+ return TRUE;
749 -+ }
750 -+ else
751 -+ {
752 -+ g_clear_error (&data->last_error);
753 -+
754 -+ g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
755 -+ _("Proxy protocol “%s” is not supported."),
756 -+ protocol);
757 -+ }
758 -+
759 -+ data->connection_in_progress = FALSE;
760 -+ g_clear_pointer (&attempt, connection_attempt_unref);
761 -+ return FALSE; /* All non-return paths are failures */
762 -+}
763 -+
764 -+static void
765 -+try_next_connection_or_finish (GSocketClientAsyncConnectData *data,
766 -+ gboolean end_current_connection)
767 -+{
768 -+ if (end_current_connection)
769 -+ data->connection_in_progress = FALSE;
770 -+
771 -+ if (data->connection_in_progress)
772 -+ return;
773 -+
774 -+ /* Keep trying successful connections until one works, each iteration pops one */
775 -+ while (data->successful_connections)
776 -+ {
777 -+ if (try_next_successful_connection (data))
778 -+ return;
779 -+ }
780 -+
781 -+ if (!data->enumeration_completed)
782 -+ {
783 -+ enumerator_next_async (data, FALSE);
784 -+ return;
785 -+ }
786 -+
787 -+ complete_connection_with_error (data, data->last_error);
788 -+}
789 -+
790 - static void
791 - g_socket_client_connected_callback (GObject *source,
792 - GAsyncResult *result,
793 -@@ -1593,10 +1737,7 @@ g_socket_client_connected_callback (GObject *source,
794 - {
795 - ConnectionAttempt *attempt = user_data;
796 - GSocketClientAsyncConnectData *data = attempt->data;
797 -- GSList *l;
798 - GError *error = NULL;
799 -- GProxy *proxy;
800 -- const gchar *protocol;
801 -
802 - if (task_completed_or_cancelled (data) || g_cancellable_is_cancelled (attempt->cancellable))
803 - {
804 -@@ -1618,11 +1759,12 @@ g_socket_client_connected_callback (GObject *source,
805 - {
806 - clarify_connect_error (error, data->connectable, attempt->address);
807 - set_last_error (data, error);
808 -+ g_debug ("GSocketClient: Connection attempt failed: %s", error->message);
809 - connection_attempt_remove (attempt);
810 -- enumerator_next_async (data, FALSE);
811 - connection_attempt_unref (attempt);
812 -+ try_next_connection_or_finish (data, FALSE);
813 - }
814 -- else
815 -+ else /* Silently ignore cancelled attempts */
816 - {
817 - g_clear_error (&error);
818 - g_object_unref (data->task);
819 -@@ -1632,74 +1774,21 @@ g_socket_client_connected_callback (GObject *source,
820 - return;
821 - }
822 -
823 -- data->socket = g_steal_pointer (&attempt->socket);
824 -- data->connection = g_steal_pointer (&attempt->connection);
825 --
826 -- for (l = data->connection_attempts; l; l = g_slist_next (l))
827 -- {
828 -- ConnectionAttempt *attempt_entry = l->data;
829 -- g_cancellable_cancel (attempt_entry->cancellable);
830 -- connection_attempt_unref (attempt_entry);
831 -- }
832 -- g_slist_free (data->connection_attempts);
833 -- data->connection_attempts = NULL;
834 -- connection_attempt_unref (attempt);
835 --
836 -- g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, NULL);
837 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, data->connection);
838 -+ g_socket_connection_set_cached_remote_address ((GSocketConnection*)attempt->connection, NULL);
839 -+ g_debug ("GSocketClient: TCP connection successful");
840 -+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, attempt->connection);
841 -
842 - /* wrong, but backward compatible */
843 -- g_socket_set_blocking (data->socket, TRUE);
844 -+ g_socket_set_blocking (attempt->socket, TRUE);
845 -
846 -- if (!data->proxy_addr)
847 -- {
848 -- g_socket_client_tls_handshake (data);
849 -- return;
850 -- }
851 --
852 -- protocol = g_proxy_address_get_protocol (data->proxy_addr);
853 --
854 -- /* The connection should not be anything other than TCP,
855 -- * but let's put a safety guard in case
856 -+ /* This ends the parallel "happy eyeballs" portion of connecting.
857 -+ Now that we have a successful tcp connection we will attempt to connect
858 -+ at the TLS/Proxy layer. If those layers fail we will move on to the next
859 -+ connection.
860 - */
861 -- if (!G_IS_TCP_CONNECTION (data->connection))
862 -- {
863 -- g_critical ("Trying to proxy over non-TCP connection, this is "
864 -- "most likely a bug in GLib IO library.");
865 --
866 -- g_set_error_literal (&data->last_error,
867 -- G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
868 -- _("Proxying over a non-TCP connection is not supported."));
869 --
870 -- enumerator_next_async (data, FALSE);
871 -- }
872 -- else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
873 -- {
874 -- /* Simply complete the connection, we don't want to do TLS handshake
875 -- * as the application proxy handling may need proxy handshake first */
876 -- g_socket_client_async_connect_complete (data);
877 -- }
878 -- else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
879 -- {
880 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, data->connection);
881 -- g_proxy_connect_async (proxy,
882 -- data->connection,
883 -- data->proxy_addr,
884 -- g_task_get_cancellable (data->task),
885 -- g_socket_client_proxy_connect_callback,
886 -- data);
887 -- g_object_unref (proxy);
888 -- }
889 -- else
890 -- {
891 -- g_clear_error (&data->last_error);
892 --
893 -- g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
894 -- _("Proxy protocol “%s” is not supported."),
895 -- protocol);
896 --
897 -- enumerator_next_async (data, FALSE);
898 -- }
899 -+ connection_attempt_remove (attempt);
900 -+ data->successful_connections = g_slist_append (data->successful_connections, g_steal_pointer (&attempt));
901 -+ try_next_connection_or_finish (data, FALSE);
902 - }
903 -
904 - static gboolean
905 -@@ -1707,7 +1796,11 @@ on_connection_attempt_timeout (gpointer data)
906 - {
907 - ConnectionAttempt *attempt = data;
908 -
909 -- enumerator_next_async (attempt->data, TRUE);
910 -+ if (!attempt->data->enumeration_completed)
911 -+ {
912 -+ g_debug ("GSocketClient: Timeout reached, trying another enumeration");
913 -+ enumerator_next_async (attempt->data, TRUE);
914 -+ }
915 -
916 - g_clear_pointer (&attempt->timeout_source, g_source_unref);
917 - return G_SOURCE_REMOVE;
918 -@@ -1717,9 +1810,9 @@ static void
919 - on_connection_cancelled (GCancellable *cancellable,
920 - gpointer data)
921 - {
922 -- GCancellable *attempt_cancellable = data;
923 -+ GCancellable *linked_cancellable = G_CANCELLABLE (data);
924 -
925 -- g_cancellable_cancel (attempt_cancellable);
926 -+ g_cancellable_cancel (linked_cancellable);
927 - }
928 -
929 - static void
930 -@@ -1743,39 +1836,49 @@ g_socket_client_enumerator_callback (GObject *object,
931 - result, &error);
932 - if (address == NULL)
933 - {
934 -- if (data->connection_attempts)
935 -+ if (G_UNLIKELY (data->enumeration_completed))
936 -+ return;
937 -+
938 -+ data->enumeration_completed = TRUE;
939 -+ g_debug ("GSocketClient: Address enumeration completed (out of addresses)");
940 -+
941 -+ /* As per API docs: We only care about error if its the first call,
942 -+ after that the enumerator is done.
943 -+
944 -+ Note that we don't care about cancellation errors because
945 -+ task_completed_or_cancelled() above should handle that.
946 -+
947 -+ If this fails and nothing is in progress then we will complete task here.
948 -+ */
949 -+ if ((data->enumerated_at_least_once && !data->connection_attempts && !data->connection_in_progress) ||
950 -+ !data->enumerated_at_least_once)
951 - {
952 -- g_object_unref (data->task);
953 -- return;
954 -+ g_debug ("GSocketClient: Address enumeration failed: %s", error ? error->message : NULL);
955 -+ if (data->last_error)
956 -+ {
957 -+ g_clear_error (&error);
958 -+ error = data->last_error;
959 -+ data->last_error = NULL;
960 -+ }
961 -+ else if (!error)
962 -+ {
963 -+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
964 -+ _("Unknown error on connect"));
965 -+ }
966 -+
967 -+ complete_connection_with_error (data, error);
968 - }
969 -
970 -- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
971 -- data->completed = TRUE;
972 -- if (!error)
973 -- {
974 -- if (data->last_error)
975 -- {
976 -- error = data->last_error;
977 -- data->last_error = NULL;
978 -- }
979 -- else
980 -- {
981 -- g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
982 -- _("Unknown error on connect"));
983 -- }
984 -- }
985 -- g_task_return_error (data->task, error);
986 -+ /* Enumeration should never trigger again, drop our ref */
987 - g_object_unref (data->task);
988 - return;
989 - }
990 -
991 -+ data->enumerated_at_least_once = TRUE;
992 -+ g_debug ("GSocketClient: Address enumeration succeeded");
993 - g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
994 - data->connectable, NULL);
995 -
996 -- if (G_IS_PROXY_ADDRESS (address) &&
997 -- data->client->priv->enable_proxy)
998 -- data->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
999 --
1000 - g_clear_error (&data->last_error);
1001 -
1002 - socket = create_socket (data->client, address, &data->last_error);
1003 -@@ -1793,6 +1896,10 @@ g_socket_client_enumerator_callback (GObject *object,
1004 - attempt->cancellable = g_cancellable_new ();
1005 - attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
1006 - attempt->timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS);
1007 -+
1008 -+ if (G_IS_PROXY_ADDRESS (address) && data->client->priv->enable_proxy)
1009 -+ attempt->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
1010 -+
1011 - g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL);
1012 - g_source_attach (attempt->timeout_source, g_task_get_context (data->task));
1013 - data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
1014 -@@ -1802,6 +1909,7 @@ g_socket_client_enumerator_callback (GObject *object,
1015 - g_object_ref (attempt->cancellable), g_object_unref);
1016 -
1017 - g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
1018 -+ g_debug ("GSocketClient: Starting TCP connection attempt");
1019 - g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, attempt->connection);
1020 - g_socket_connection_connect_async (G_SOCKET_CONNECTION (attempt->connection),
1021 - address,
1022 -@@ -1854,24 +1962,48 @@ g_socket_client_connect_async (GSocketClient *client,
1023 - else
1024 - data->enumerator = g_socket_connectable_enumerate (connectable);
1025 -
1026 -- /* The flow and ownership here isn't quite obvious:
1027 -- - The task starts an async attempt to connect.
1028 -- - Each attempt holds a single ref on task.
1029 -- - Each attempt may create new attempts by timing out (not a failure) so
1030 -- there are multiple attempts happening in parallel.
1031 -- - Upon failure an attempt will start a new attempt that steals its ref
1032 -- until there are no more attempts left and it drops its ref.
1033 -- - Upon success it will cancel all other attempts and continue on
1034 -- to the rest of the connection (tls, proxies, etc) which do not
1035 -- happen in parallel and at the very end drop its ref.
1036 -- - Upon cancellation an attempt drops its ref.
1037 -- */
1038 -+ /* This function tries to match the behavior of g_socket_client_connect ()
1039 -+ which is simple enough but much of it is done in parallel to be as responsive
1040 -+ as possible as per Happy Eyeballs (RFC 8305). This complicates flow quite a
1041 -+ bit but we can describe it in 3 sections:
1042 -+
1043 -+ Firstly we have address enumeration (DNS):
1044 -+ - This may be triggered multiple times by enumerator_next_async().
1045 -+ - It also has its own cancellable (data->enumeration_cancellable).
1046 -+ - Enumeration is done lazily because GNetworkAddressAddressEnumerator
1047 -+ also does work in parallel and may lazily add new addresses.
1048 -+ - If the first enumeration errors then the task errors. Otherwise all enumerations
1049 -+ will potentially be used (until task or enumeration is cancelled).
1050 -+
1051 -+ Then we start attempting connections (TCP):
1052 -+ - Each connection is independent and kept in a ConnectionAttempt object.
1053 -+ - They each hold a ref on the main task and have their own cancellable.
1054 -+ - Multiple attempts may happen in parallel as per Happy Eyeballs.
1055 -+ - Upon failure or timeouts more connection attempts are made.
1056 -+ - If no connections succeed the task errors.
1057 -+ - Upon success they are kept in a list of successful connections.
1058 -+
1059 -+ Lastly we connect at the application layer (TLS, Proxies):
1060 -+ - These are done in serial.
1061 -+ - The reasoning here is that Happy Eyeballs is about making bad connections responsive
1062 -+ at the IP/TCP layers. Issues at the application layer are generally not due to
1063 -+ connectivity issues but rather misconfiguration.
1064 -+ - Upon failure it will try the next TCP connection until it runs out and
1065 -+ the task errors.
1066 -+ - Upon success it cancels everything remaining (enumeration and connections)
1067 -+ and returns the connection.
1068 -+ */
1069 -
1070 - data->task = g_task_new (client, cancellable, callback, user_data);
1071 - g_task_set_check_cancellable (data->task, FALSE); /* We handle this manually */
1072 - g_task_set_source_tag (data->task, g_socket_client_connect_async);
1073 - g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
1074 -
1075 -+ data->enumeration_cancellable = g_cancellable_new ();
1076 -+ if (cancellable)
1077 -+ g_cancellable_connect (cancellable, G_CALLBACK (on_connection_cancelled),
1078 -+ g_object_ref (data->enumeration_cancellable), g_object_unref);
1079 -+
1080 - enumerator_next_async (data, FALSE);
1081 - }
1082 -
1083 -@@ -1990,6 +2122,7 @@ g_socket_client_connect_to_uri_async (GSocketClient *client,
1084 - }
1085 - else
1086 - {
1087 -+ g_debug("g_socket_client_connect_to_uri_async");
1088 - g_socket_client_connect_async (client,
1089 - connectable, cancellable,
1090 - callback, user_data);
1091 ---
1092 -2.24.1
1093 -