glib2/backport-gsocketclient-emit-RESOLVING-RESOLVED-events-only-once.patch
shirely16 a3d31ddf3c synchronous community patch
(cherry picked from commit 5fb95aa15490a21b390e53a88c1b8b052971e504)
2021-05-21 15:56:45 +08:00

119 lines
4.7 KiB
Diff

From f0a7b147806e852e2090eeda6e4e38f7d3f52b52 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@gnome.org>
Date: Tue, 6 Oct 2020 15:39:45 -0500
Subject: [PATCH 0989/1095] gsocketclient: emit RESOLVING/RESOLVED events only
once
GSocketAddressEnumerator encapsulates the details of how DNS happens, so
we don't have to think about it. But we may have taken encapsulation a
bit too far, here. Usually, we resolve a domain name to a list of IPv4
and IPv6 addresses. Then we go through each address in the list and try
to connect to it. Name resolution happens exactly once, at the start.
It doesn't happen each time we enumerate the enumerator. In theory, it
*could*, because we've designed these APIs to be agnostic of underlying
implementation details like DNS and network protocols. But in practice,
we know that's not really what's happening. It's weird to say that we
are RESOLVING what we know to be the same name multiple times. Behind
the scenes, we're not doing that.
This also fixes #1994, where enumeration can end with a RESOLVING event,
even though this is supposed to be the first event rather than the last.
I thought this would be hard to fix, even requiring new public API in
GSocketAddressEnumerator to peek ahead to see if the next enumeration is
going to return NULL. Then I decided we should just fake it: always emit
both RESOLVING and RESOLVED at the same time right after each
enumeration. Finally, I realized we can emit them at the correct time if
we simply assume resolving only happens the first time. This seems like
the most elegant of the possible solutions.
Now, this is a behavior change, and arguably an API break, but it should
align better with reasonable expectations of how GSocketClientEvent
ought to work. I don't expect it to break anything besides tests that
check which order GSocketClientEvent events are emitted in. (Currently,
libsoup has such tests, which will need to be updated.) Ideally we would
have GLib-level tests as well, but in a concession to pragmatism, it's a
lot easier to keep network tests in libsoup.
reason:emit RESOLVING/RESOLVED events only once
Conflict:NA
Reference:https://github.com/GNOME/glib/commit/f0a7b147806e852e2090eeda6e4e38f7d3f52b52
---
gio/gsocketclient.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index 8a663c3..9df8f29 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -991,6 +991,7 @@ g_socket_client_connect (GSocketClient *client,
{
GIOStream *connection = NULL;
GSocketAddressEnumerator *enumerator = NULL;
+ gboolean ever_resolved = FALSE;
GError *last_error, *tmp_error;
last_error = NULL;
@@ -1025,10 +1026,20 @@ g_socket_client_connect (GSocketClient *client,
}
tmp_error = NULL;
- g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING,
- connectable, NULL);
+
+ if (!ever_resolved)
+ {
+ g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING,
+ connectable, NULL);
+ }
address = g_socket_address_enumerator_next (enumerator, cancellable,
&tmp_error);
+ if (!ever_resolved)
+ {
+ g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED,
+ connectable, NULL);
+ ever_resolved = TRUE;
+ }
if (address == NULL)
{
@@ -1046,8 +1057,6 @@ g_socket_client_connect (GSocketClient *client,
_("Unknown error on connect"));
break;
}
- g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED,
- connectable, NULL);
using_proxy = (G_IS_PROXY_ADDRESS (address) &&
client->priv->enable_proxy);
@@ -1509,7 +1518,8 @@ enumerator_next_async (GSocketClientAsyncConnectData *data,
if (add_task_ref)
g_object_ref (data->task);
- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
+ if (!data->enumerated_at_least_once)
+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
g_debug ("GSocketClient: Starting new address enumeration");
g_socket_address_enumerator_next_async (data->enumerator,
data->enumeration_cancellable,
@@ -1883,10 +1893,13 @@ g_socket_client_enumerator_callback (GObject *object,
return;
}
- data->enumerated_at_least_once = TRUE;
g_debug ("GSocketClient: Address enumeration succeeded");
- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
- data->connectable, NULL);
+ if (!data->enumerated_at_least_once)
+ {
+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
+ data->connectable, NULL);
+ data->enumerated_at_least_once = TRUE;
+ }
g_clear_error (&data->last_error);
--
1.8.3.1