[libsoup/gresolver: 1/2] Port SoupAddress to use GResolver, remove soup-dns



commit b2a57e6bd90c5bedc4c88ad82807aff66e1bac2a
Author: Dan Winship <danw gnome org>
Date:   Sat Sep 27 18:55:35 2008 -0400

    Port SoupAddress to use GResolver, remove soup-dns
    
    This is just a quick port that does not yet fix SoupSocket to try
    multiple IP addresses.
---
 libsoup/Makefile.am                  |    2 -
 libsoup/soup-address.c               |  264 ++++++++++---
 libsoup/soup-cookie.c                |    5 +-
 libsoup/soup-dns.c                   |  731 ----------------------------------
 libsoup/soup-dns.h                   |   39 --
 libsoup/soup-proxy-resolver-gnome.c  |    1 -
 libsoup/soup-proxy-resolver-static.c |    1 -
 libsoup/soup-session.c               |    9 +
 8 files changed, 229 insertions(+), 823 deletions(-)

diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index dc9ff55..9f4fbaf 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -122,8 +122,6 @@ libsoup_2_4_la_SOURCES =		\
 	soup-cookie-jar.c		\
 	soup-cookie-jar-text.c		\
 	soup-date.c			\
-	soup-dns.h			\
-	soup-dns.c			\
 	soup-form.c			\
 	soup-gnutls.c			\
 	soup-headers.c			\
diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c
index 2041580..3daff04 100644
--- a/libsoup/soup-address.c
+++ b/libsoup/soup-address.c
@@ -16,8 +16,9 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include <gio/gio.h>
+
 #include "soup-address.h"
-#include "soup-dns.h"
 #include "soup-enum-types.h"
 #include "soup-marshal.h"
 #include "soup-misc.h"
@@ -156,8 +157,6 @@ soup_address_class_init (SoupAddressClass *address_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (address_class);
 
-	soup_dns_init ();
-
 	g_type_class_add_private (address_class, sizeof (SoupAddressPrivate));
 
 	/* virtual method override */
@@ -478,10 +477,23 @@ soup_address_get_sockaddr (SoupAddress *addr, int *len)
 
 	if (priv->sockaddr && len)
 		*len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv));
-
 	return priv->sockaddr;
 }
 
+static GInetAddress *
+soup_address_make_inet_address (SoupAddress *addr)
+{
+	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+	GSocketAddress *gsa;
+	GInetAddress *gia;
+
+	gsa = g_socket_address_new_from_native (priv->sockaddr,
+						SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)));
+	gia = g_inet_socket_address_get_address ((GInetSocketAddress *)gsa);
+	g_object_unref (gsa);
+	return gia;
+}
+
 /**
  * soup_address_get_physical:
  * @addr: a #SoupAddress
@@ -502,8 +514,13 @@ soup_address_get_physical (SoupAddress *addr)
 	if (!priv->sockaddr)
 		return NULL;
 
-	if (!priv->physical)
-		priv->physical = soup_dns_ntop (priv->sockaddr);
+	if (!priv->physical) {
+		GInetAddress *gia;
+
+		gia = soup_address_make_inet_address (addr);
+		priv->physical = g_inet_address_to_string (gia);
+		g_object_unref (gia);
+	}
 
 	return priv->physical;
 }
@@ -525,47 +542,153 @@ soup_address_get_port (SoupAddress *addr)
 }
 
 
-static void
-update_address (SoupAddress *addr, SoupDNSLookup *lookup)
+static guint
+update_addrs (SoupAddress *addr, GList *addrs, GError *error)
 {
 	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+	GInetAddress *gia;
+	GSocketAddress *gsa;
+	gsize len;
+
+	if (error) {
+		if (error->domain == G_IO_ERROR &&
+		    error->code == G_IO_ERROR_CANCELLED)
+			return SOUP_STATUS_CANCELLED;
+		else
+			return SOUP_STATUS_CANT_RESOLVE;
+	} else if (!addrs)
+		return SOUP_STATUS_CANT_RESOLVE;
+	else if (priv->sockaddr)
+		return SOUP_STATUS_OK;
 
-	if (!priv->name)
-		priv->name = soup_dns_lookup_get_hostname (lookup);
+	gia = addrs->data;
+	gsa = g_inet_socket_address_new (gia, priv->port);
 
-	if (!priv->sockaddr) {
-		priv->sockaddr = soup_dns_lookup_get_address (lookup);
-		SOUP_ADDRESS_SET_PORT (priv, htons (priv->port));
-	}
+	len = g_socket_address_get_native_size (gsa);
+	priv->sockaddr = g_malloc (len);
+	g_socket_address_to_native (gsa, priv->sockaddr, len);
+
+	return SOUP_STATUS_OK;
+}
+
+static guint
+update_name (SoupAddress *addr, const char *name, GError *error)
+{
+	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+
+	if (error) {
+		if (error->domain == G_IO_ERROR &&
+		    error->code == G_IO_ERROR_CANCELLED)
+			return SOUP_STATUS_CANCELLED;
+		else
+			return SOUP_STATUS_CANT_RESOLVE;
+	} else if (!name)
+		return SOUP_STATUS_CANT_RESOLVE;
+	else if (priv->name)
+		return SOUP_STATUS_OK;
+
+	priv->name = g_strdup (name);
+	return SOUP_STATUS_OK;
 }
 
 typedef struct {
 	SoupAddress         *addr;
 	SoupAddressCallback  callback;
 	gpointer             callback_data;
+	gboolean             lookup_name;
+
+	GMainContext        *async_context;
+	GCancellable        *cancellable;
+	guint                status;
 } SoupAddressResolveAsyncData;
 
 static void
-lookup_resolved (SoupDNSLookup *lookup, guint status, gpointer user_data)
+complete_resolve_async (SoupAddressResolveAsyncData *res_data)
+{
+	SoupAddress *addr = res_data->addr;
+	SoupAddressCallback callback = res_data->callback;
+	gpointer callback_data = res_data->callback_data;
+
+	if (callback)
+		callback (addr, res_data->status, callback_data);
+
+	if (res_data->async_context)
+		g_main_context_unref (res_data->async_context);
+	if (res_data->cancellable)
+		g_object_unref (res_data->cancellable);
+
+	g_object_unref (addr);
+	g_slice_free (SoupAddressResolveAsyncData, res_data);
+}
+
+static void
+lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data)
 {
+	GResolver *resolver = G_RESOLVER (source);
 	SoupAddressResolveAsyncData *res_data = user_data;
-	SoupAddress *addr;
-	SoupAddressCallback callback;
-	gpointer callback_data;
+	SoupAddress *addr = res_data->addr;
+	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+	GError *error = NULL;
 
-	addr = res_data->addr;
-	callback = res_data->callback;
-	callback_data = res_data->callback_data;
-	g_free (res_data);
+	if (!priv->sockaddr) {
+		GList *addrs;
+
+		addrs = g_resolver_lookup_by_name_finish (resolver, result,
+							  &error);
+		res_data->status = update_addrs (addr, addrs, error);
+		g_resolver_free_addresses (addrs);
+	} else if (!priv->name) {
+		char *name;
+
+		name = g_resolver_lookup_by_address_finish (resolver, result,
+							    &error);
+		res_data->status = update_name (addr, name, error);
+		g_free (name);
+	} else
+		res_data->status = SOUP_STATUS_OK;
+
+	if (error)
+		g_error_free (error);
+
+	complete_resolve_async (res_data);
+}
 
-	if (status == SOUP_STATUS_OK)
-		update_address (addr, lookup);
+static gboolean
+idle_complete_resolve (gpointer res_data)
+{
+	complete_resolve_async (res_data);
+	return FALSE;
+}
 
-	if (callback)
-		callback (addr, status, callback_data);
+static void
+resolve_for_context (gpointer thread_data, gpointer pool_data)
+{
+	SoupAddressResolveAsyncData *res_data = thread_data;
 
-	g_object_unref (addr);
-	soup_dns_lookup_free (lookup);
+	res_data->status =
+		soup_address_resolve_sync (res_data->addr,
+					   res_data->cancellable);
+	soup_add_completion (res_data->async_context,
+			     idle_complete_resolve, res_data);
+}
+
+static void
+resolve_in_thread (SoupAddressResolveAsyncData *res_data,
+		   GMainContext *async_context, GCancellable *cancellable)
+{
+	static volatile GThreadPool *thread_pool = NULL;
+
+	if (g_once_init_enter ((gsize *)&thread_pool)) {
+		GThreadPool *pool = g_thread_pool_new (resolve_for_context,
+						       NULL, -1, FALSE, NULL);
+		g_once_init_leave ((gsize *)&thread_pool,
+				   GPOINTER_TO_SIZE (pool));
+	}
+
+	res_data->async_context = g_main_context_ref (async_context);
+	if (cancellable)
+		res_data->cancellable = g_object_ref (cancellable);
+	g_thread_pool_push ((GThreadPool *)thread_pool, res_data, NULL);
 }
 
 /**
@@ -603,22 +726,51 @@ soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context,
 {
 	SoupAddressPrivate *priv;
 	SoupAddressResolveAsyncData *res_data;
-	SoupDNSLookup *lookup;
+	GResolver *resolver;
 
 	g_return_if_fail (SOUP_IS_ADDRESS (addr));
 	priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+	g_return_if_fail (priv->name || priv->sockaddr);
 
-	res_data = g_new (SoupAddressResolveAsyncData, 1);
+	res_data = g_slice_new0 (SoupAddressResolveAsyncData);
 	res_data->addr          = g_object_ref (addr);
 	res_data->callback      = callback;
 	res_data->callback_data = user_data;
 
-	if (priv->name)
-		lookup = soup_dns_lookup_name (priv->name);
-	else
-		lookup = soup_dns_lookup_address (priv->sockaddr);
-	soup_dns_lookup_resolve_async (lookup, async_context, cancellable,
-				       lookup_resolved, res_data);
+	if (priv->name && priv->sockaddr) {
+		res_data->status = SOUP_STATUS_OK;
+		soup_add_completion (async_context, idle_complete_resolve, res_data);
+		return;
+	}
+
+	/* GResolver doesn't (yet!) do non-default contexts, so to
+	 * support that we need to synchronously resolve in another
+	 * thread and then send the answer back to the right context.
+	 */
+	if (async_context && async_context != g_main_context_default ()) {
+		resolve_in_thread (res_data, async_context, cancellable);
+		return;
+	}
+
+	resolver = g_resolver_get_default ();
+
+	if (priv->name) {
+		res_data->lookup_name = TRUE;
+		g_resolver_lookup_by_name_async (resolver, priv->name,
+						 cancellable,
+						 lookup_resolved, res_data);
+	} else {
+		GInetAddress *gia;
+
+		res_data->lookup_name = FALSE;
+		gia = soup_address_make_inet_address (addr);
+		g_resolver_lookup_by_address_async (resolver, gia,
+						    cancellable,
+						    lookup_resolved, res_data);
+		g_object_unref (gia);
+	}
+
+	g_object_unref (resolver);
 }
 
 /**
@@ -640,22 +792,40 @@ guint
 soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable)
 {
 	SoupAddressPrivate *priv;
-	SoupDNSLookup *lookup;
+	GResolver *resolver;
+	GError *error = NULL;
 	guint status;
 
 	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED);
 	priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+	g_return_val_if_fail (priv->name || priv->sockaddr, SOUP_STATUS_MALFORMED);
+
+	resolver = g_resolver_get_default ();
+
+	if (!priv->sockaddr) {
+		GList *addrs;
+
+		addrs = g_resolver_lookup_by_name (resolver, priv->name,
+						   cancellable, &error);
+		status = update_addrs (addr, addrs, error);
+		g_resolver_free_addresses (addrs);
+	} else if (!priv->name) {
+		GInetAddress *gia;
+		char *name;
+
+		gia = soup_address_make_inet_address (addr);
+		name = g_resolver_lookup_by_address (resolver, gia,
+						     cancellable, &error);
+		g_object_unref (gia);
+		status = update_name (addr, name, error);
+		g_free (name);
+	} else
+		status = SOUP_STATUS_OK;
+
+	if (error)
+		g_error_free (error);
+	g_object_unref (resolver);
 
-	g_object_ref (addr);
-	if (priv->name)
-		lookup = soup_dns_lookup_name (priv->name);
-	else
-		lookup = soup_dns_lookup_address (priv->sockaddr);
-	status = soup_dns_lookup_resolve (lookup, cancellable);
-	if (status == SOUP_STATUS_OK)
-		update_address (addr, lookup);
-	g_object_unref (addr);
-	soup_dns_lookup_free (lookup);
 	return status;
 }
 
diff --git a/libsoup/soup-cookie.c b/libsoup/soup-cookie.c
index 5e18bd0..227f1c8 100644
--- a/libsoup/soup-cookie.c
+++ b/libsoup/soup-cookie.c
@@ -12,9 +12,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <gio/gio.h>
+
 #include "soup-cookie.h"
 #include "soup-date.h"
-#include "soup-dns.h"
 #include "soup-headers.h"
 #include "soup-message.h"
 #include "soup-message-headers.h"
@@ -359,7 +360,7 @@ parse_one_cookie (const char **header_p, SoupURI *origin)
 		/* If the domain string isn't an IP addr, and doesn't
 		 * start with a '.', prepend one.
 		 */
-		if (!soup_dns_is_ip_address (cookie->domain) &&
+		if (!g_hostname_is_ip_address (cookie->domain) &&
 		    cookie->domain[0] != '.') {
 			char *tmp = g_strdup_printf (".%s", cookie->domain);
 			g_free (cookie->domain);
diff --git a/libsoup/soup-dns.c b/libsoup/soup-dns.c
deleted file mode 100644
index cb4cee5..0000000
--- a/libsoup/soup-dns.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-dns.c: Async DNS code
- *
- * Copyright (C) 2000-2003, Ximian, Inc.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include "soup-dns.h"
-#include "soup-misc.h"
-#include "soup-status.h"
-
-#ifndef INET_ADDRSTRLEN
-#  define INET_ADDRSTRLEN 16
-#  define INET6_ADDRSTRLEN 46
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE -1
-#endif
-
-#ifdef HAVE_IPV6
-#define SOUP_DNS_SOCKADDR_LEN(sa) \
-	(sa->sa_family == AF_INET ? sizeof (struct sockaddr_in) : \
-				    sizeof (struct sockaddr_in6))
-#else
-#define SOUP_DNS_SOCKADDR_LEN(sa) sizeof (struct sockaddr_in)
-#endif
-
-#ifdef G_OS_WIN32
-
-static int
-inet_pton(int af, const char* src, void* dst)
-{
-	int address_length;
-	struct sockaddr_storage sa;
-	struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
-	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
-
-	switch (af) {
-	case AF_INET:
-		address_length = sizeof (struct sockaddr_in);
-		break;
-		
-	case AF_INET6:
-		address_length = sizeof (struct sockaddr_in6);
-		break;
-		
-	default:
-		return -1;
-	}
-	
-	if (WSAStringToAddress ((LPTSTR) src, af, NULL, (LPSOCKADDR) &sa, &address_length) == 0) {
-		switch (af) {
-		case AF_INET:
-			memcpy (dst, &sin->sin_addr, sizeof (struct in_addr));
-			break;
-
-		case AF_INET6:
-			memcpy (dst, &sin6->sin6_addr, sizeof (struct in6_addr));
-			break;
-		}
-		return 1;
-	}
-	
-	return 0;
-}
-
-static const char* 
-inet_ntop(int af, const void* src, char* dst, size_t size)
-{
-	int address_length;
-	DWORD string_length = size;
-	struct sockaddr_storage sa;
-	struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
-	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
-	
-	memset (&sa, 0, sizeof (sa));
-	switch (af) {
-	case AF_INET:
-		address_length = sizeof (struct sockaddr_in);
-		sin->sin_family = af;
-		memcpy (&sin->sin_addr, src, sizeof (struct in_addr));
-		break;
-		
-	case AF_INET6:
-		address_length = sizeof (struct sockaddr_in6);
-		sin6->sin6_family = af;
-		memcpy (&sin6->sin6_addr, src, sizeof (struct in6_addr));
-		break;
-		
-	default:
-		return NULL;
-	}
-	
-	if (WSAAddressToString ((LPSOCKADDR) &sa, address_length, NULL,
-				dst, &string_length) == 0)
-		return dst;
-	
-	return NULL;
-}
-
-#endif
-
-typedef struct {
-	char *entry_name;
-	guint ref_count;
-	time_t expires;
-
-	char *hostname;
-	struct sockaddr *sockaddr;
-
-	gboolean resolved;
-	GThread *resolver_thread;
-	GSList *async_lookups;
-} SoupDNSCacheEntry;
-
-static GHashTable *soup_dns_cache;
-#define SOUP_DNS_CACHE_MAX 20
-
-struct SoupDNSLookup {
-	SoupDNSCacheEntry *entry;
-
-	GMainContext *async_context;
-	GCancellable *cancellable;
-	SoupDNSCallback callback;
-	gpointer user_data;
-};
-
-static GMutex *soup_dns_lock;
-static GCond *soup_dns_cond;
-
-#if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GETNAMEINFO)
-static GMutex *soup_gethost_lock;
-#endif
-
-/**
- * soup_dns_init:
- *
- * Initializes the libsoup DNS system. Must be called before any other
- * soup_dns method is called. Normally this gets called automatically
- * by #SoupAddress's class_init function.
- **/
-void
-soup_dns_init (void)
-{
-	static volatile gsize inited_dns = 0;
-
-	if (g_once_init_enter (&inited_dns)) {
-		soup_dns_cache = g_hash_table_new (soup_str_case_hash, soup_str_case_equal);
-		soup_dns_lock = g_mutex_new ();
-		soup_dns_cond = g_cond_new ();
-#if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GETNAMEINFO)
-		soup_gethost_lock = g_mutex_new ();
-#endif
-
-		g_once_init_leave (&inited_dns, TRUE);
-	}
-}
-
-static void
-prune_cache_cb (gpointer key, gpointer value, gpointer data)
-{
-	SoupDNSCacheEntry *entry = value, **prune_entry = data; 
-
-	if (!*prune_entry || (*prune_entry)->expires > entry->expires)
-		*prune_entry = entry;
-}
-
-static void
-soup_dns_cache_entry_set_from_phys (SoupDNSCacheEntry *entry)
-{
-	struct sockaddr_in sin;
-#ifdef HAVE_IPV6
-	struct sockaddr_in6 sin6;
-#endif
-
-#ifdef HAVE_IPV6
-	memset (&sin6, 0, sizeof (struct sockaddr_in6));
-	if (inet_pton (AF_INET6, entry->entry_name, &sin6.sin6_addr) != 0) {
-		entry->sockaddr = g_memdup (&sin6, sizeof (struct sockaddr_in6));
-		entry->sockaddr->sa_family = AF_INET6;
-		return;
-	}
-#endif /* HAVE_IPV6 */
-
-	memset (&sin, 0, sizeof (struct sockaddr_in));
-	if (
-#if defined(HAVE_INET_PTON)
-		inet_pton (AF_INET, entry->entry_name, &sin.sin_addr) != 0
-#elif defined(HAVE_INET_ATON)
-		inet_aton (entry->entry_name, &sin.sin_addr) != 0
-#else
-		(sin.sin_addr.s_addr = inet_addr (entry->entry_name)) &&
-		(sin.sin_addr.s_addr != INADDR_NONE)
-#endif
-		) {
-		entry->sockaddr = g_memdup (&sin, sizeof (struct sockaddr_in));
-		entry->sockaddr->sa_family = AF_INET;
-		return;
-	}
-}
-
-static void
-soup_dns_cache_entry_ref (SoupDNSCacheEntry *entry)
-{
-	entry->ref_count++;
-}
-
-static void
-soup_dns_cache_entry_unref (SoupDNSCacheEntry *entry)
-{
-	if (--entry->ref_count == 0) {
-		g_free (entry->entry_name);
-		g_free (entry->hostname);
-		g_free (entry->sockaddr);
-
-		/* If there were lookups pending, ref_count couldn't
-		 * have reached zero. So no cleanup needed there.
-		 */
-
-		g_slice_free (SoupDNSCacheEntry, entry);
-	}
-}
-
-static SoupDNSCacheEntry *
-soup_dns_cache_entry_new (const char *name)
-{
-	SoupDNSCacheEntry *entry;
-
-	entry = g_slice_new0 (SoupDNSCacheEntry);
-	entry->entry_name = g_strdup (name);
-	entry->ref_count = 2; /* One for the caller, one for the cache */
-	soup_dns_cache_entry_set_from_phys (entry);
-
-	if (g_hash_table_size (soup_dns_cache) == SOUP_DNS_CACHE_MAX) {
-		SoupDNSCacheEntry *prune_entry = NULL;
-
-		g_hash_table_foreach (soup_dns_cache, prune_cache_cb, &prune_entry);
-		if (prune_entry) {
-			g_hash_table_remove (soup_dns_cache, prune_entry->entry_name);
-			soup_dns_cache_entry_unref (prune_entry);
-		}
-	}
-
-	entry->expires = time (0) + 60 * 60;
-	g_hash_table_insert (soup_dns_cache, entry->entry_name, entry);
-
-	return entry;
-}
-
-/**
- * soup_dns_ntop:
- * @sa: pointer to a #sockaddr
- *
- * Converts @sa's address into textual form (eg, "141.213.8.59"), like
- * the standard library function inet_ntop(), except that the returned
- * string must be freed.
- *
- * Return value: the text form or @sa, which must be freed.
- **/
-char *
-soup_dns_ntop (struct sockaddr *sa)
-{
-	switch (sa->sa_family) {
-	case AF_INET:
-	{
-		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-#ifdef HAVE_INET_NTOP
-		char buffer[INET_ADDRSTRLEN];
-
-		inet_ntop (AF_INET, &sin->sin_addr, buffer, sizeof (buffer));
-		return g_strdup (buffer);
-#else
-		return g_strdup (inet_ntoa (sin->sin_addr));
-#endif
-	}
-
-#ifdef HAVE_IPV6
-	case AF_INET6:
-	{
-		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
-		char buffer[INET6_ADDRSTRLEN];
-
-		inet_ntop (AF_INET6, &sin6->sin6_addr, buffer, sizeof (buffer));
-		return g_strdup (buffer);
-	}
-#endif
-
-	default:
-		return NULL;
-	}
-}
-
-gboolean
-soup_dns_is_ip_address (const char *name)
-{
-	struct sockaddr_in sin;
-#ifdef HAVE_IPV6
-	struct sockaddr_in6 sin6;
-
-	if (inet_pton (AF_INET, name, &sin.sin_addr) > 0 ||
-	    inet_pton (AF_INET6, name, &sin6.sin6_addr) > 0)
-		return TRUE;
-#else /* !HAVE_IPV6 */
-#if defined(HAVE_INET_PTON)
-	if (inet_pton (AF_INET, name, &sin.sin_addr) > 0)
-		return TRUE;
-#elif defined(HAVE_INET_ATON)
-	if (inet_aton (name, &sin.sin_addr) != 0)
-		return TRUE;
-#else
-	if (inet_addr (name) != INADDR_NONE)
-		return TRUE;
-#endif
-#endif /* HAVE_IPV6 */
-	return FALSE;
-}
-
-static void
-resolve_address (SoupDNSCacheEntry *entry)
-{
-#if defined (HAVE_GETADDRINFO)
-
-	struct addrinfo hints, *res;
-	int retval;
-
-	memset (&hints, 0, sizeof (struct addrinfo));
-#  ifdef AI_ADDRCONFIG
-	hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
-#  else
-	hints.ai_flags = AI_CANONNAME;
-#  endif
-	hints.ai_family = PF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_protocol = IPPROTO_TCP;
-
-	retval = getaddrinfo (entry->hostname, NULL, &hints, &res);
-	if (retval == 0) {
-		entry->sockaddr = g_memdup (res->ai_addr, res->ai_addrlen);
-		entry->resolved = TRUE;
-		freeaddrinfo (res);
-	}
-
-#else /* !HAVE_GETADDRINFO */
-
-	struct hostent *h;
-
-	g_mutex_lock (soup_gethost_lock);
-
-	h = gethostbyname (entry->hostname);
-	if (h && h->h_addrtype == AF_INET) {
-		struct sockaddr_in sin;
-		memset (&sin, 0, sizeof (struct sockaddr_in));
-		sin.sin_family = AF_INET;
-		memcpy (&sin.sin_addr, h->h_addr_list[0], sizeof (struct in_addr));
-		entry->sockaddr = g_memdup (&sin, sizeof (struct sockaddr_in));
-		entry->resolved = TRUE;
-	}
-
-	g_mutex_unlock (soup_gethost_lock);
-
-#endif
-}
-
-static void
-resolve_name (SoupDNSCacheEntry *entry)
-{
-#ifdef HAVE_GETNAMEINFO
-	int retval, len = 0;
-	char *name = NULL;
-
-	do {
-		len += 128;
-		name = g_realloc (name, len);
-		retval = getnameinfo (entry->sockaddr, SOUP_DNS_SOCKADDR_LEN (entry->sockaddr),
-				      name, len, NULL, 0, NI_NAMEREQD);
-	} while (
-#ifdef EAI_OVERFLOW
-		retval == EAI_OVERFLOW
-#else
-		strlen (name) == len - 1
-#endif
-		);
-
-	if (retval == 0) {
-		entry->hostname = name;
-		entry->resolved = TRUE;
-	} else
-		g_free (name);
-
-#else /* !HAVE_GETNAMEINFO */
-
-	struct sockaddr_in *sin = (struct sockaddr_in *)entry->sockaddr;
-	struct hostent *h;
-
-	g_mutex_lock (soup_gethost_lock);
-
-	if (sin->sin_family == AF_INET) {
-		h = gethostbyaddr (&sin->sin_addr, sizeof (sin->sin_addr), AF_INET);
-		if (h) {
-			entry->hostname = g_strdup (h->h_name);
-			entry->resolved = TRUE;
-		}
-	}
-
-	g_mutex_unlock (soup_gethost_lock);
-
-#endif /* HAVE_GETNAMEINFO */
-}
-
-/* Assumes soup_dns_lock is held */
-static SoupDNSCacheEntry *
-soup_dns_cache_entry_lookup (const char *name)
-{
-	SoupDNSCacheEntry *entry;
-
-	entry = g_hash_table_lookup (soup_dns_cache, name);
-	if (entry)
-		soup_dns_cache_entry_ref (entry);
-	return entry;
-}
-
-/**
- * soup_dns_lookup_name:
- * @name: a hostname (eg, "www.gnome.org") or physical address
- * (eg, "12.107.209.247").
- *
- * Creates a #SoupDNSLookup for @name. This should be passed to
- * soup_dns_lookup_resolve() or soup_dns_lookup_resolve_async().
- *
- * Returns: a #SoupDNSLookup, which should eventually be freed with
- * soup_dns_lookup_free().
- **/
-SoupDNSLookup *
-soup_dns_lookup_name (const char *name)
-{
-	SoupDNSCacheEntry *entry;
-	SoupDNSLookup *lookup;
-
-	g_mutex_lock (soup_dns_lock);
-
-	entry = soup_dns_cache_entry_lookup (name);
-	if (!entry) {
-		entry = soup_dns_cache_entry_new (name);
-		entry->hostname = g_strdup (name);
-		if (entry->sockaddr)
-			entry->resolved = TRUE;
-	}
-
-	lookup = g_slice_new0 (SoupDNSLookup);
-	lookup->entry = entry;
-	g_mutex_unlock (soup_dns_lock);
-
-	return lookup;
-}
-
-/**
- * soup_dns_lookup_address:
- * @sockaddr: pointer to a #sockaddr
- *
- * Creates a #SoupDNSLookup for @sockaddr. This should be passed to
- * soup_dns_lookup_resolve() or soup_dns_lookup_resolve_async().
- *
- * Returns: a #SoupDNSLookup, which should eventually be freed with
- * soup_dns_lookup_free()
- **/
-SoupDNSLookup *
-soup_dns_lookup_address (struct sockaddr *sockaddr)
-{
-	SoupDNSCacheEntry *entry;
-	SoupDNSLookup *lookup;
-	char *name;
-
-	name = soup_dns_ntop (sockaddr);
-	g_return_val_if_fail (name != NULL, NULL);
-
-	g_mutex_lock (soup_dns_lock);
-
-	entry = soup_dns_cache_entry_lookup (name);
-	if (!entry)
-		entry = soup_dns_cache_entry_new (name); /* FIXME */
-	g_free (name);
-
-	lookup = g_slice_new0 (SoupDNSLookup);
-	lookup->entry = entry;
-	g_mutex_unlock (soup_dns_lock);
-
-	return lookup;
-}
-
-static inline guint
-resolve_status (SoupDNSCacheEntry *entry, GCancellable *cancellable)
-{
-	if (entry->hostname && entry->sockaddr)
-		return SOUP_STATUS_OK;
-	else if (g_cancellable_is_cancelled (cancellable))
-		return SOUP_STATUS_CANCELLED;
-	else
-		return SOUP_STATUS_CANT_RESOLVE;
-}
-
-static void async_cancel (GCancellable *cancellable, gpointer user_data);
-
-static gboolean
-do_async_callback (gpointer user_data)
-{
-	SoupDNSLookup *lookup = user_data;
-	SoupDNSCacheEntry *entry = lookup->entry;
-	GCancellable *cancellable = lookup->cancellable;
-
-	if (cancellable)
-		g_signal_handlers_disconnect_by_func (cancellable, async_cancel, lookup);
-	lookup->callback (lookup, resolve_status (entry, cancellable),
-			  lookup->user_data);
-
-	return FALSE;
-}
-
-static gpointer
-resolver_thread (gpointer user_data)
-{
-	SoupDNSCacheEntry *entry = user_data;
-	GSList *async_lookups;
-	SoupDNSLookup *lookup;
-
-	if (entry->hostname == NULL)
-		resolve_name (entry);
-	else if (entry->sockaddr == NULL)
-		resolve_address (entry);
-
-	g_mutex_lock (soup_dns_lock);
-	entry->resolver_thread = NULL;
-
-	async_lookups = entry->async_lookups;
-	entry->async_lookups = NULL;
-	g_mutex_unlock (soup_dns_lock);
-
-	g_cond_broadcast (soup_dns_cond);
-
-	while (async_lookups) {
-		lookup = async_lookups->data;
-		async_lookups = g_slist_remove (async_lookups, lookup);
-
-		soup_add_completion (lookup->async_context, do_async_callback, lookup);
-	}
-
-	soup_dns_cache_entry_unref (entry);
-	return NULL;
-}
-
-static void
-sync_cancel (GCancellable *cancellable, gpointer user_data)
-{
-	/* We can't actually cancel the resolver thread. So we just
-	 * wake up the blocking thread, which will see that
-	 * @cancellable has been cancelled and then stop waiting for
-	 * the result. If the resolver thread eventually finishes,
-	 * its result will make it to the cache.
-	 */
-	g_cond_broadcast (soup_dns_cond);
-}
-
-/**
- * soup_dns_lookup_resolve:
- * @lookup: a #SoupDNSLookup
- * @cancellable: a #GCancellable, or %NULL
- *
- * Synchronously resolves @lookup.
- *
- * Return value: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
- * %SOUP_STATUS_CANCELLED
- **/
-guint
-soup_dns_lookup_resolve (SoupDNSLookup *lookup, GCancellable *cancellable)
-{
-	SoupDNSCacheEntry *entry = lookup->entry;
-	guint cancel_id = 0;
-
-	g_mutex_lock (soup_dns_lock);
-
-	if (!entry->resolved) {
-		if (!entry->resolver_thread) {
-			soup_dns_cache_entry_ref (entry);
-			entry->resolver_thread =
-				g_thread_create (resolver_thread, entry,
-						 FALSE, NULL);
-		}
-
-		if (cancellable) {
-			cancel_id = g_signal_connect (cancellable, "cancelled",
-						      G_CALLBACK (sync_cancel),
-						      NULL);
-		}
-	}
-
-	while (entry->resolver_thread &&
-	       !g_cancellable_is_cancelled (cancellable))
-		g_cond_wait (soup_dns_cond, soup_dns_lock);
-
-	if (cancel_id)
-		g_signal_handler_disconnect (cancellable, cancel_id);
-
-	g_mutex_unlock (soup_dns_lock);
-
-	return resolve_status (entry, cancellable);
-}
-
-static void
-async_cancel (GCancellable *cancellable, gpointer user_data)
-{
-	SoupDNSLookup *lookup = user_data;
-	SoupDNSCacheEntry *entry = lookup->entry;
-
-	/* We can't actually cancel the resolver thread. So we just
-	 * remove @lookup from the list of pending async lookups and
-	 * invoke its callback now. If the resolver thread eventually
-	 * finishes, its result will make it to the cache.
-	 */
-	g_mutex_lock (soup_dns_lock);
-
-	if (g_slist_find (entry->async_lookups, lookup)) {
-		entry->async_lookups = g_slist_remove (entry->async_lookups,
-						       lookup);
-		soup_add_completion (lookup->async_context, do_async_callback, lookup);
-	}
-
-	g_mutex_unlock (soup_dns_lock);
-}
-
-/**
- * soup_dns_lookup_resolve_async:
- * @lookup: a #SoupDNSLookup
- * @async_context: #GMainContext to call @callback in
- * @cancellable: a #GCancellable, or %NULL
- * @callback: callback to call when @lookup is resolved
- * @user_data: data to pass to @callback;
- *
- * Tries to asynchronously resolve @lookup. Invokes @callback when it
- * has succeeded or failed.
- **/
-void
-soup_dns_lookup_resolve_async (SoupDNSLookup *lookup,
-			       GMainContext *async_context,
-			       GCancellable *cancellable,
-			       SoupDNSCallback callback, gpointer user_data)
-{
-	SoupDNSCacheEntry *entry = lookup->entry;
-
-	g_mutex_lock (soup_dns_lock);
-
-	lookup->async_context = async_context;
-	lookup->cancellable = cancellable;
-	lookup->callback = callback;
-	lookup->user_data = user_data;
-
-	if (!entry->resolved) {
-		entry->async_lookups = g_slist_prepend (entry->async_lookups,
-							lookup);
-		if (cancellable) {
-			g_signal_connect (cancellable, "cancelled",
-					  G_CALLBACK (async_cancel), lookup);
-		}
-
-		if (!entry->resolver_thread) {
-			soup_dns_cache_entry_ref (entry);
-			entry->resolver_thread =
-				g_thread_create (resolver_thread, entry,
-						 FALSE, NULL);
-		}
-	} else
-		soup_add_completion (lookup->async_context, do_async_callback, lookup);
-
-	g_mutex_unlock (soup_dns_lock);
-}
-
-/**
- * soup_dns_lookup_get_hostname:
- * @lookup: a #SoupDNSLookup
- *
- * Gets the hostname of @lookup.
- *
- * Return value: the hostname, which the caller owns and must free, or
- * %NULL if @lookup has not been completely resolved.
- **/
-char *
-soup_dns_lookup_get_hostname (SoupDNSLookup *lookup)
-{
-	return g_strdup (lookup->entry->hostname);
-}
-
-/**
- * soup_dns_lookup_get_address:
- * @lookup: a #SoupDNSLookup
- *
- * Gets the address of @lookup.
- *
- * Return value: the address, which the caller owns and must free, or
- * %NULL if @lookup has not been completely resolved.
- **/
-struct sockaddr *
-soup_dns_lookup_get_address (SoupDNSLookup *lookup)
-{
-	return g_memdup (lookup->entry->sockaddr,
-			 SOUP_DNS_SOCKADDR_LEN (lookup->entry->sockaddr));
-}
-
-/**
- * soup_dns_lookup_free:
- * @lookup: a #SoupDNSLookup
- *
- * Frees @lookup. It is an error to cancel a lookup while it is
- * running.
- **/
-void
-soup_dns_lookup_free (SoupDNSLookup *lookup)
-{
-	soup_dns_cache_entry_unref (lookup->entry);
-	g_slice_free (SoupDNSLookup, lookup);
-}
diff --git a/libsoup/soup-dns.h b/libsoup/soup-dns.h
deleted file mode 100644
index 5e5584a..0000000
--- a/libsoup/soup-dns.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2000-2003, Ximian, Inc.
- */
-
-#ifndef SOUP_DNS_H
-#define SOUP_DNS_H
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <sys/types.h>
-
-#include <libsoup/soup-portability.h>
-
-void             soup_dns_init                 (void);
-char            *soup_dns_ntop                 (struct sockaddr *sa);
-gboolean         soup_dns_is_ip_address        (const char *name);
-
-typedef struct SoupDNSLookup SoupDNSLookup;
-
-SoupDNSLookup   *soup_dns_lookup_name          (const char  *name);
-SoupDNSLookup   *soup_dns_lookup_address       (struct sockaddr *sockaddr);
-void             soup_dns_lookup_free          (SoupDNSLookup   *lookup);
-
-typedef void (*SoupDNSCallback) (SoupDNSLookup *lookup, guint status, gpointer user_data);
-
-guint            soup_dns_lookup_resolve       (SoupDNSLookup   *lookup,
-						GCancellable    *cancellable);
-void             soup_dns_lookup_resolve_async (SoupDNSLookup   *lookup,
-						GMainContext    *async_context,
-						GCancellable    *cancellable,
-						SoupDNSCallback  callback,
-						gpointer         user_data);
-
-char            *soup_dns_lookup_get_hostname  (SoupDNSLookup   *lookup);
-struct sockaddr *soup_dns_lookup_get_address   (SoupDNSLookup   *lookup);
-
-
-#endif /* SOUP_DNS_H */
diff --git a/libsoup/soup-proxy-resolver-gnome.c b/libsoup/soup-proxy-resolver-gnome.c
index 4371d5a..619cc11 100644
--- a/libsoup/soup-proxy-resolver-gnome.c
+++ b/libsoup/soup-proxy-resolver-gnome.c
@@ -14,7 +14,6 @@
 
 #include "soup-proxy-resolver-gnome.h"
 #include "soup-address.h"
-#include "soup-dns.h"
 #include "soup-message.h"
 #include "soup-misc.h"
 #include "soup-session-feature.h"
diff --git a/libsoup/soup-proxy-resolver-static.c b/libsoup/soup-proxy-resolver-static.c
index 575eac1..cf1fd29 100644
--- a/libsoup/soup-proxy-resolver-static.c
+++ b/libsoup/soup-proxy-resolver-static.c
@@ -13,7 +13,6 @@
 
 #include "soup-proxy-resolver-static.h"
 #include "soup-address.h"
-#include "soup-dns.h"
 #include "soup-message.h"
 #include "soup-misc.h"
 #include "soup-session-feature.h"
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index cbaa42d..d4774f3 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -89,6 +89,8 @@ typedef struct {
 	GMutex *host_lock;
 
 	GMainContext *async_context;
+
+	GResolver *resolver;
 } SoupSessionPrivate;
 #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate))
 
@@ -168,6 +170,11 @@ soup_session_init (SoupSession *session)
 	soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_BASIC);
 	soup_auth_manager_add_type (priv->auth_manager, SOUP_TYPE_AUTH_DIGEST);
 	soup_session_add_feature (session, SOUP_SESSION_FEATURE (priv->auth_manager));
+
+	/* We'll be doing DNS continuously-ish while the session is active,
+	 * so hold a ref on the default GResolver.
+	 */
+	priv->resolver = g_resolver_get_default ();
 }
 
 static gboolean
@@ -230,6 +237,8 @@ finalize (GObject *object)
 	if (priv->async_context)
 		g_main_context_unref (priv->async_context);
 
+	g_object_unref (priv->resolver);
+
 	G_OBJECT_CLASS (soup_session_parent_class)->finalize (object);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]