mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 01:58:54 +01:00 
			
		
		
		
	threadedresolver: Cache network interface checks
This commit is contained in:
		@@ -36,6 +36,7 @@
 | 
			
		||||
#include "gcancellable.h"
 | 
			
		||||
#include "ginetaddress.h"
 | 
			
		||||
#include "ginetsocketaddress.h"
 | 
			
		||||
#include "gnetworkmonitorbase.h"
 | 
			
		||||
#include "gtask.h"
 | 
			
		||||
#include "gsocketaddress.h"
 | 
			
		||||
#include "gsrvtarget.h"
 | 
			
		||||
@@ -90,6 +91,11 @@ struct _GThreadedResolver
 | 
			
		||||
  GResolver parent_instance;
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
@@ -110,6 +116,10 @@ g_threaded_resolver_init (GThreadedResolver *self)
 | 
			
		||||
                                              20,
 | 
			
		||||
                                              FALSE,
 | 
			
		||||
                                              NULL);
 | 
			
		||||
 | 
			
		||||
  self->network_is_loopback_only = -1;
 | 
			
		||||
 | 
			
		||||
  g_mutex_init (&self->interface_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -120,6 +130,12 @@ g_threaded_resolver_finalize (GObject *object)
 | 
			
		||||
  g_thread_pool_free (self->thread_pool, TRUE, FALSE);
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -260,7 +276,7 @@ lookup_data_free (LookupData *data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
only_has_loopback_interfaces (void)
 | 
			
		||||
check_only_has_loopback_interfaces (void)
 | 
			
		||||
{
 | 
			
		||||
#if HAVE_GETIFADDRS
 | 
			
		||||
  struct ifaddrs *addrs;
 | 
			
		||||
@@ -305,9 +321,39 @@ only_has_loopback_interfaces (void)
 | 
			
		||||
#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 *
 | 
			
		||||
do_lookup_by_name (const gchar   *hostname,
 | 
			
		||||
do_lookup_by_name (GThreadedResolver  *resolver,
 | 
			
		||||
                   const gchar        *hostname,
 | 
			
		||||
                   int                 address_family,
 | 
			
		||||
                   GCancellable       *cancellable,
 | 
			
		||||
                   GError            **error)
 | 
			
		||||
@@ -320,7 +366,7 @@ do_lookup_by_name (const gchar   *hostname,
 | 
			
		||||
  /* In general we only want IPs for valid interfaces.
 | 
			
		||||
   * However this will return nothing if you only have loopback interfaces.
 | 
			
		||||
   * 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
 | 
			
		||||
  if (!only_loopback)
 | 
			
		||||
@@ -1630,13 +1676,15 @@ threaded_resolver_worker_cb (gpointer task_data,
 | 
			
		||||
  GTask *task = G_TASK (g_steal_pointer (&task_data));
 | 
			
		||||
  LookupData *data = g_task_get_task_data (task);
 | 
			
		||||
  GCancellable *cancellable = g_task_get_cancellable (task);
 | 
			
		||||
  GThreadedResolver *resolver = G_THREADED_RESOLVER (user_data);
 | 
			
		||||
  GError *local_error = NULL;
 | 
			
		||||
  gboolean should_return;
 | 
			
		||||
 | 
			
		||||
  switch (data->lookup_type) {
 | 
			
		||||
  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,
 | 
			
		||||
                                            cancellable,
 | 
			
		||||
                                            &local_error);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user