[libsoup/gresolver: 1/2] Port SoupAddress to use GResolver, remove soup-dns
- From: Dan Winship <danw src gnome org>
- To: svn-commits-list gnome org
- Subject: [libsoup/gresolver: 1/2] Port SoupAddress to use GResolver, remove soup-dns
- Date: Sat, 2 May 2009 17:04:09 -0400 (EDT)
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]