[glib] GNetworkAddress: drop cached addresses on resolver reload
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] GNetworkAddress: drop cached addresses on resolver reload
- Date: Wed, 20 Feb 2013 12:34:25 +0000 (UTC)
commit c6c11665668c47841011258e5dbca07ad3d8aba0
Author: Dan Winship <danw gnome org>
Date: Tue Feb 19 15:19:22 2013 -0500
GNetworkAddress: drop cached addresses on resolver reload
If the resolver reloads (ie, if /etc/resolv.conf changes),
GNetworkAddress needs to re-resolve its addresses the next time it's
enumerated. Otherwise hosts that have different IP addresses inside
and outside a VPN won't work correctly if you hold on to a
GNetworkAddress for them for a long time.
https://bugzilla.gnome.org/show_bug.cgi?id=694181
gio/gnetworkaddress.c | 70 +++++++++++++++++++++++++++++++++------------
gio/gnetworkingprivate.h | 2 +
gio/gresolver.c | 14 +++++++++
3 files changed, 67 insertions(+), 19 deletions(-)
---
diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c
index 1335d94..2e4042c 100644
--- a/gio/gnetworkaddress.c
+++ b/gio/gnetworkaddress.c
@@ -65,6 +65,8 @@ struct _GNetworkAddressPrivate {
guint16 port;
GList *sockaddrs;
gchar *scheme;
+
+ gint64 resolver_serial;
};
enum {
@@ -226,7 +228,8 @@ g_network_address_get_property (GObject *object,
static void
g_network_address_set_addresses (GNetworkAddress *addr,
- GList *addresses)
+ GList *addresses,
+ guint64 resolver_serial)
{
GList *a;
GSocketAddress *sockaddr;
@@ -241,6 +244,8 @@ g_network_address_set_addresses (GNetworkAddress *addr,
}
g_list_free (addresses);
addr->priv->sockaddrs = g_list_reverse (addr->priv->sockaddrs);
+
+ addr->priv->resolver_serial = resolver_serial;
}
static gboolean
@@ -846,26 +851,39 @@ g_network_address_address_enumerator_next (GSocketAddressEnumerator *enumerator
if (addr_enum->addresses == NULL)
{
- if (!addr_enum->addr->priv->sockaddrs)
- g_network_address_parse_sockaddr (addr_enum->addr);
- if (!addr_enum->addr->priv->sockaddrs)
+ GNetworkAddress *addr = addr_enum->addr;
+ GResolver *resolver = g_resolver_get_default ();
+ gint64 serial = g_resolver_get_serial (resolver);
+
+ if (addr->priv->resolver_serial != 0 &&
+ addr->priv->resolver_serial != serial)
+ {
+ /* Resolver has reloaded, discard cached addresses */
+ g_list_free_full (addr->priv->sockaddrs, g_object_unref);
+ addr->priv->sockaddrs = NULL;
+ }
+
+ if (!addr->priv->sockaddrs)
+ g_network_address_parse_sockaddr (addr);
+ if (!addr->priv->sockaddrs)
{
- GResolver *resolver = g_resolver_get_default ();
GList *addresses;
addresses = g_resolver_lookup_by_name (resolver,
- addr_enum->addr->priv->hostname,
+ addr->priv->hostname,
cancellable, error);
- g_object_unref (resolver);
-
if (!addresses)
- return NULL;
+ {
+ g_object_unref (resolver);
+ return NULL;
+ }
- g_network_address_set_addresses (addr_enum->addr, addresses);
+ g_network_address_set_addresses (addr, addresses, serial);
}
- addr_enum->addresses = addr_enum->addr->priv->sockaddrs;
+ addr_enum->addresses = addr->priv->sockaddrs;
addr_enum->next = addr_enum->addresses;
+ g_object_unref (resolver);
}
if (addr_enum->next == NULL)
@@ -916,7 +934,10 @@ got_addresses (GObject *source_object,
addresses = g_resolver_lookup_by_name_finish (resolver, result, &error);
if (!error)
- g_network_address_set_addresses (addr_enum->addr, addresses);
+ {
+ g_network_address_set_addresses (addr_enum->addr, addresses,
+ g_resolver_get_serial (resolver));
+ }
}
have_addresses (addr_enum, task, error);
}
@@ -936,25 +957,36 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum
if (addr_enum->addresses == NULL)
{
- if (!addr_enum->addr->priv->sockaddrs)
+ GNetworkAddress *addr = addr_enum->addr;
+ GResolver *resolver = g_resolver_get_default ();
+ gint64 serial = g_resolver_get_serial (resolver);
+
+ if (addr->priv->resolver_serial != 0 &&
+ addr->priv->resolver_serial != serial)
+ {
+ /* Resolver has reloaded, discard cached addresses */
+ g_list_free_full (addr->priv->sockaddrs, g_object_unref);
+ addr->priv->sockaddrs = NULL;
+ }
+
+ if (!addr->priv->sockaddrs)
{
- if (g_network_address_parse_sockaddr (addr_enum->addr))
+ if (g_network_address_parse_sockaddr (addr))
have_addresses (addr_enum, task, NULL);
else
{
- GResolver *resolver = g_resolver_get_default ();
-
g_resolver_lookup_by_name_async (resolver,
- addr_enum->addr->priv->hostname,
+ addr->priv->hostname,
cancellable,
got_addresses, task);
- g_object_unref (resolver);
}
+ g_object_unref (resolver);
return;
}
- addr_enum->addresses = addr_enum->addr->priv->sockaddrs;
+ addr_enum->addresses = addr->priv->sockaddrs;
addr_enum->next = addr_enum->addresses;
+ g_object_unref (resolver);
}
if (addr_enum->next)
diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h
index 1a299c9..4341dc7 100644
--- a/gio/gnetworkingprivate.h
+++ b/gio/gnetworkingprivate.h
@@ -34,6 +34,8 @@ gchar * _g_uri_from_authority (const gchar *protocol,
guint port,
const gchar *userinfo);
+guint64 g_resolver_get_serial (GResolver *resolver);
+
gint g_socket (gint domain,
gint type,
gint protocol,
diff --git a/gio/gresolver.c b/gio/gresolver.c
index 589e324..5549e4f 100644
--- a/gio/gresolver.c
+++ b/gio/gresolver.c
@@ -846,6 +846,20 @@ g_resolver_lookup_records_finish (GResolver *resolver,
lookup_records_finish (resolver, result, error);
}
+guint64
+g_resolver_get_serial (GResolver *resolver)
+{
+ g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
+
+ g_resolver_maybe_reload (resolver);
+
+#ifdef G_OS_UNIX
+ return (guint64) resolver->priv->resolv_conf_timestamp;
+#else
+ return 1;
+#endif
+}
+
/**
* g_resolver_error_quark:
*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]