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 |
- |