mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-04-23 07:39:17 +02:00
threadedresolver: Cache network interface checks
This commit is contained in:
parent
fe0139ee98
commit
cce3001d5d
@ -36,6 +36,7 @@
|
|||||||
#include "gcancellable.h"
|
#include "gcancellable.h"
|
||||||
#include "ginetaddress.h"
|
#include "ginetaddress.h"
|
||||||
#include "ginetsocketaddress.h"
|
#include "ginetsocketaddress.h"
|
||||||
|
#include "gnetworkmonitorbase.h"
|
||||||
#include "gtask.h"
|
#include "gtask.h"
|
||||||
#include "gsocketaddress.h"
|
#include "gsocketaddress.h"
|
||||||
#include "gsrvtarget.h"
|
#include "gsrvtarget.h"
|
||||||
@ -90,6 +91,11 @@ struct _GThreadedResolver
|
|||||||
GResolver parent_instance;
|
GResolver parent_instance;
|
||||||
|
|
||||||
GThreadPool *thread_pool; /* (owned) */
|
GThreadPool *thread_pool; /* (owned) */
|
||||||
|
|
||||||
|
GMutex interface_mutex;
|
||||||
|
GNetworkMonitor *network_monitor; /* (owned) */
|
||||||
|
gboolean monitor_supports_caching;
|
||||||
|
int network_is_loopback_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (GThreadedResolver, g_threaded_resolver, G_TYPE_RESOLVER)
|
G_DEFINE_TYPE (GThreadedResolver, g_threaded_resolver, G_TYPE_RESOLVER)
|
||||||
@ -110,6 +116,10 @@ g_threaded_resolver_init (GThreadedResolver *self)
|
|||||||
20,
|
20,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
self->network_is_loopback_only = -1;
|
||||||
|
|
||||||
|
g_mutex_init (&self->interface_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -120,6 +130,12 @@ g_threaded_resolver_finalize (GObject *object)
|
|||||||
g_thread_pool_free (self->thread_pool, TRUE, FALSE);
|
g_thread_pool_free (self->thread_pool, TRUE, FALSE);
|
||||||
self->thread_pool = NULL;
|
self->thread_pool = NULL;
|
||||||
|
|
||||||
|
if (self->network_monitor)
|
||||||
|
g_signal_handlers_disconnect_by_data (self->network_monitor, object);
|
||||||
|
|
||||||
|
g_clear_object (&self->network_monitor);
|
||||||
|
g_mutex_clear (&self->interface_mutex);
|
||||||
|
|
||||||
G_OBJECT_CLASS (g_threaded_resolver_parent_class)->finalize (object);
|
G_OBJECT_CLASS (g_threaded_resolver_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +276,7 @@ lookup_data_free (LookupData *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
only_has_loopback_interfaces (void)
|
check_only_has_loopback_interfaces (void)
|
||||||
{
|
{
|
||||||
#if HAVE_GETIFADDRS
|
#if HAVE_GETIFADDRS
|
||||||
struct ifaddrs *addrs;
|
struct ifaddrs *addrs;
|
||||||
@ -305,12 +321,42 @@ only_has_loopback_interfaces (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
network_changed_cb (GNetworkMonitor *monitor,
|
||||||
|
gboolean network_available,
|
||||||
|
GThreadedResolver *resolver)
|
||||||
|
{
|
||||||
|
g_mutex_lock (&resolver->interface_mutex);
|
||||||
|
resolver->network_is_loopback_only = -1;
|
||||||
|
g_mutex_unlock (&resolver->interface_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
only_has_loopback_interfaces_cached (GThreadedResolver *resolver)
|
||||||
|
{
|
||||||
|
g_mutex_lock (&resolver->interface_mutex);
|
||||||
|
|
||||||
|
if (!resolver->network_monitor)
|
||||||
|
{
|
||||||
|
resolver->network_monitor = g_object_ref (g_network_monitor_get_default ());
|
||||||
|
resolver->monitor_supports_caching = G_TYPE_FROM_INSTANCE (resolver->network_monitor) != G_TYPE_NETWORK_MONITOR_BASE;
|
||||||
|
g_signal_connect_object (resolver->network_monitor, "network-changed", G_CALLBACK (network_changed_cb), resolver, G_CONNECT_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolver->monitor_supports_caching || resolver->network_is_loopback_only == -1)
|
||||||
|
resolver->network_is_loopback_only = check_only_has_loopback_interfaces ();
|
||||||
|
|
||||||
|
g_mutex_unlock (&resolver->interface_mutex);
|
||||||
|
|
||||||
|
return resolver->network_is_loopback_only;
|
||||||
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
do_lookup_by_name (const gchar *hostname,
|
do_lookup_by_name (GThreadedResolver *resolver,
|
||||||
int address_family,
|
const gchar *hostname,
|
||||||
GCancellable *cancellable,
|
int address_family,
|
||||||
GError **error)
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
struct addrinfo *res = NULL;
|
struct addrinfo *res = NULL;
|
||||||
GList *addresses;
|
GList *addresses;
|
||||||
@ -320,7 +366,7 @@ do_lookup_by_name (const gchar *hostname,
|
|||||||
/* In general we only want IPs for valid interfaces.
|
/* In general we only want IPs for valid interfaces.
|
||||||
* However this will return nothing if you only have loopback interfaces.
|
* However this will return nothing if you only have loopback interfaces.
|
||||||
* Instead in this case we will manually filter out invalid IPs. */
|
* Instead in this case we will manually filter out invalid IPs. */
|
||||||
gboolean only_loopback = only_has_loopback_interfaces ();
|
gboolean only_loopback = only_has_loopback_interfaces_cached (resolver);
|
||||||
|
|
||||||
#ifdef AI_ADDRCONFIG
|
#ifdef AI_ADDRCONFIG
|
||||||
if (!only_loopback)
|
if (!only_loopback)
|
||||||
@ -1630,13 +1676,15 @@ threaded_resolver_worker_cb (gpointer task_data,
|
|||||||
GTask *task = G_TASK (g_steal_pointer (&task_data));
|
GTask *task = G_TASK (g_steal_pointer (&task_data));
|
||||||
LookupData *data = g_task_get_task_data (task);
|
LookupData *data = g_task_get_task_data (task);
|
||||||
GCancellable *cancellable = g_task_get_cancellable (task);
|
GCancellable *cancellable = g_task_get_cancellable (task);
|
||||||
|
GThreadedResolver *resolver = G_THREADED_RESOLVER (user_data);
|
||||||
GError *local_error = NULL;
|
GError *local_error = NULL;
|
||||||
gboolean should_return;
|
gboolean should_return;
|
||||||
|
|
||||||
switch (data->lookup_type) {
|
switch (data->lookup_type) {
|
||||||
case LOOKUP_BY_NAME:
|
case LOOKUP_BY_NAME:
|
||||||
{
|
{
|
||||||
GList *addresses = do_lookup_by_name (data->lookup_by_name.hostname,
|
GList *addresses = do_lookup_by_name (resolver,
|
||||||
|
data->lookup_by_name.hostname,
|
||||||
data->lookup_by_name.address_family,
|
data->lookup_by_name.address_family,
|
||||||
cancellable,
|
cancellable,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user