diff options
author | Patrick Griffis <tingping@tingping.se> | 2019-11-23 11:42:16 -0800 |
---|---|---|
committer | Patrick Griffis <tingping@tingping.se> | 2019-11-23 12:01:45 -0800 |
commit | e1c762dcc454ed3218403967f6479858d6bb8982 (patch) | |
tree | 01c9210d18de7e7c19253d2e4af66a0d711dc833 | |
parent | e825a98845334e1ce79b08d978594cca9b37152f (diff) | |
download | glib-wip/tingping/gsocket-unknown-error.tar.gz |
gnetworkaddress: Properly handle DNS returning no ipv6 addresseswip/tingping/gsocket-unknown-error
If the ipv6 addresses returned is empty it should wait on ipv4.
-rw-r--r-- | gio/gnetworkaddress.c | 6 | ||||
-rw-r--r-- | gio/tests/gsocketclient.c | 56 | ||||
-rw-r--r-- | gio/tests/meson.build | 1 |
3 files changed, 61 insertions, 2 deletions
diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index f12f93585..bc5cda33d 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -1238,11 +1238,13 @@ got_ipv6_addresses (GObject *source_object, GNetworkAddressAddressEnumerator *addr_enum = user_data; GResolver *resolver = G_RESOLVER (source_object); GList *addresses; + gboolean got_addresses; GError *error = NULL; addr_enum->state ^= RESOLVE_STATE_WAITING_ON_IPV6; addresses = g_resolver_lookup_by_name_with_flags_finish (resolver, result, &error); + got_addresses = addresses != NULL; if (!error) g_network_address_address_enumerator_add_addresses (addr_enum, g_steal_pointer (&addresses), resolver); else @@ -1255,11 +1257,11 @@ got_ipv6_addresses (GObject *source_object, g_clear_pointer (&addr_enum->wait_source, g_source_unref); } - /* If we got an error before ipv4 then let its response handle it. + /* If we got an error or no addresses before ipv4 then let its response handle it. * If we get ipv6 response first or error second then * immediately complete the task. */ - if (error != NULL && !addr_enum->last_error && (addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV4)) + if ((error != NULL || !got_addresses) && !addr_enum->last_error && (addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV4)) { /* ipv6 lookup failed, but ipv4 is still outstanding. wait. */ addr_enum->last_error = g_steal_pointer (&error); diff --git a/gio/tests/gsocketclient.c b/gio/tests/gsocketclient.c new file mode 100644 index 000000000..7537fb8e1 --- /dev/null +++ b/gio/tests/gsocketclient.c @@ -0,0 +1,56 @@ +#include "config.h" +#include "mock-resolver.h" + +#include <gio/gio.h> + +static void +on_connected (GObject *client, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GSocketConnection *connection = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), res, &error); + g_main_loop_quit (user_data); + + /* We want to make sure we made it to the point of conencting to a socket */ + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED); + g_assert_null (connection); +} + +static void +test_no_ipv6_addresses (void) +{ + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + GSocketClient *client = g_socket_client_new (); + GSocketConnectable *connectable = g_network_address_new ("gnome.fake", 1234); + GResolver *original_resolver = g_resolver_get_default (); + MockResolver *mock_resolver = mock_resolver_new (); + GList *ipv4_results = NULL; + + /* This tests that the client sucessfully attempts an ipv4 address when no ipv6 address is returned */ + + g_resolver_set_default (G_RESOLVER (mock_resolver)); + ipv4_results = g_list_append (ipv4_results, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4)); + mock_resolver_set_ipv4_results (mock_resolver, ipv4_results); + mock_resolver_set_ipv4_delay_ms (mock_resolver, 100); + + g_socket_client_set_timeout (client, 5); + g_socket_client_connect_async (client, connectable, NULL, on_connected, loop); + g_main_loop_run (loop); + + g_resolver_set_default (original_resolver); + g_list_free_full (ipv4_results, (GDestroyNotify) g_object_unref); + g_object_unref (original_resolver); + g_object_unref (mock_resolver); + g_object_unref (client); + g_object_unref (connectable); + g_main_loop_unref (loop); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/"); + + g_test_add_func ("/socket-client/no-ipv6-addresses", test_no_ipv6_addresses); + return g_test_run (); +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 8b5d105f5..32f10e294 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -79,6 +79,7 @@ gio_tests = { 'tls-interaction' : {'extra_sources' : ['gtesttlsbackend.c']}, 'tls-database' : {'extra_sources' : ['gtesttlsbackend.c']}, 'gdbus-address-get-session' : {}, + 'gsocketclient' : {'extra_sources' : ['mock-resolver.c']}, } test_extra_programs = { |