libsoup r1179 - in trunk: . libsoup tests
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1179 - in trunk: . libsoup tests
- Date: Fri, 3 Oct 2008 21:01:54 +0000 (UTC)
Author: danw
Date: Fri Oct 3 21:01:54 2008
New Revision: 1179
URL: http://svn.gnome.org/viewvc/libsoup?rev=1179&view=rev
Log:
* libsoup/soup-connection.c: Change the SoupURI properties to
SoupAddress properties.
* libsoup/soup-address.c (soup_address_resolve_async)
(soup_address_resolve_sync): Redo slightly so that multiple
simultaneous attempts to resolve the same address won't cause
problems.
(soup_address_hash_by_name, soup_address_equal_by_name):
(soup_address_hash_by_ip, soup_address_equal_by_ip): methods to
hash addresses by name or IP address
* libsoup/soup-message.c (soup_message_get_address): gets a
SoupAddress corresponding to the message's URI
* libsoup/soup-auth-manager.c (SoupAuthHost): hash hosts by
soup_address_hash_by_name() rather than by URI.
* libsoup/soup-session.c (soup_session_get_connection): pass
addresses to soup_connection_new(), not URIs.
(SoupSessionHost): hash hosts by soup_address_hash_by_ip() rather
than by URI. This requires that the addresses will have already
been resolved by the SoupSession subclasses before calling
soup_session_get_connection(), but also means that now requests
made to different virtual hosts on the same IP address can share a
connection.
* libsoup/soup-message-queue.c (SoupMessageQueueItem): add
address-resolving state
* libsoup/soup-session-sync.c (process_queue_item): resolve the
message's address before getting a connection
* libsoup/soup-session-async.c (run_queue, resolve_msg_addr)
(resolved_msg_addr): resolve the message's address before getting
a connection
(request_restarted): if the message gets requeued to a different
host, we'll need to re-resolve the address.
* libsoup/soup-uri.c (soup_uri_copy_root, soup_uri_host_hash)
(soup_uri_host_equal): No longer needed
* libsoup/soup-dns.c (do_async_callback): disconnect from the
cancellable before invoking the callback
* tests/proxy-test.c (tests): fix the 403 example; hostnames are
resolved by the session now, even when sending to a proxy, so we
need to use a hostname that actually exists
Modified:
trunk/ChangeLog
trunk/libsoup/soup-address.c
trunk/libsoup/soup-address.h
trunk/libsoup/soup-auth-manager.c
trunk/libsoup/soup-connection.c
trunk/libsoup/soup-connection.h
trunk/libsoup/soup-dns.c
trunk/libsoup/soup-message-private.h
trunk/libsoup/soup-message-queue.c
trunk/libsoup/soup-message-queue.h
trunk/libsoup/soup-message.c
trunk/libsoup/soup-message.h
trunk/libsoup/soup-session-async.c
trunk/libsoup/soup-session-sync.c
trunk/libsoup/soup-session.c
trunk/libsoup/soup-uri.c
trunk/tests/proxy-test.c
Modified: trunk/libsoup/soup-address.c
==============================================================================
--- trunk/libsoup/soup-address.c (original)
+++ trunk/libsoup/soup-address.c Fri Oct 3 21:01:54 2008
@@ -60,9 +60,6 @@
char *name, *physical;
guint port;
-
- SoupDNSLookup *lookup;
- guint timeout_id;
} SoupAddressPrivate;
#define SOUP_ADDRESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_ADDRESS, SoupAddressPrivate))
@@ -151,11 +148,6 @@
if (priv->physical)
g_free (priv->physical);
- if (priv->lookup)
- soup_dns_lookup_free (priv->lookup);
- if (priv->timeout_id)
- g_source_remove (priv->timeout_id);
-
G_OBJECT_CLASS (soup_address_parent_class)->finalize (object);
}
@@ -235,12 +227,7 @@
return NULL;
priv = SOUP_ADDRESS_GET_PRIVATE (addr);
- if (priv->name) {
- if (!priv->sockaddr)
- priv->lookup = soup_dns_lookup_name (priv->name);
- } else if (priv->sockaddr)
- priv->lookup = soup_dns_lookup_address (priv->sockaddr);
- else {
+ if (!priv->name && !priv->sockaddr) {
g_object_unref (addr);
return NULL;
}
@@ -548,6 +535,7 @@
callback (addr, status, callback_data);
g_object_unref (addr);
+ soup_dns_lookup_free (lookup);
}
/**
@@ -585,17 +573,21 @@
{
SoupAddressPrivate *priv;
SoupAddressResolveAsyncData *res_data;
+ SoupDNSLookup *lookup;
g_return_if_fail (SOUP_IS_ADDRESS (addr));
priv = SOUP_ADDRESS_GET_PRIVATE (addr);
res_data = g_new (SoupAddressResolveAsyncData, 1);
- res_data->addr = addr;
+ res_data->addr = g_object_ref (addr);
res_data->callback = callback;
res_data->callback_data = user_data;
- g_object_ref (addr);
- soup_dns_lookup_resolve_async (priv->lookup, async_context, cancellable,
+ 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);
}
@@ -618,15 +610,149 @@
soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable)
{
SoupAddressPrivate *priv;
+ SoupDNSLookup *lookup;
guint status;
g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED);
priv = SOUP_ADDRESS_GET_PRIVATE (addr);
g_object_ref (addr);
- status = soup_dns_lookup_resolve (priv->lookup, cancellable);
+ 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, priv->lookup);
+ update_address (addr, lookup);
g_object_unref (addr);
+ soup_dns_lookup_free (lookup);
return status;
}
+
+gboolean
+soup_address_is_resolved (SoupAddress *addr)
+{
+ SoupAddressPrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_ADDRESS (addr), FALSE);
+ priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+
+ return priv->sockaddr && priv->name;
+}
+
+/**
+ * soup_address_hash_by_name:
+ * @addr: a #SoupAddress
+ *
+ * A hash function (for #GHashTable) that corresponds to
+ * soup_address_equal_by_name(), qv
+ *
+ * Return value: the named-based hash value for @addr.
+ **/
+guint
+soup_address_hash_by_name (gconstpointer addr)
+{
+ SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+
+ g_return_val_if_fail (priv->name != NULL, 0);
+ return g_str_hash (priv->name);
+}
+
+/**
+ * soup_address_equal_by_name:
+ * @addr1: a #SoupAddress with a resolved name
+ * @addr2: another #SoupAddress with a resolved name
+ *
+ * Tests if @addr1 and @addr2 have the same "name". This method can be
+ * used with soup_address_hash_by_name() to create a #GHashTable that
+ * hashes on address "names".
+ *
+ * Comparing by name normally means comparing the addresses by their
+ * hostnames. But if the address was originally created using an IP
+ * address literal, then it will be compared by that instead.
+ *
+ * In particular, if "www.example.com" has the IP address 10.0.0.1,
+ * and @addr1 was created with the name "www.example.com" and @addr2
+ * was created with the name "10.0.0.1", then they will compare as
+ * unequal for purposes of soup_address_equal_by_name().
+ *
+ * This would be used to distinguish hosts in situations where
+ * different virtual hosts on the same IP address should be considered
+ * different. Eg, for purposes of HTTP authentication or cookies, two
+ * hosts with the same IP address but different names are considered
+ * to be different hosts.
+ *
+ * See also soup_address_equal_by_ip(), which compares by IP address
+ * rather than by name.
+ *
+ * Return value: whether or not @addr1 and @addr2 have the same name
+ **/
+gboolean
+soup_address_equal_by_name (gconstpointer addr1, gconstpointer addr2)
+{
+ SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
+ SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);
+
+ g_return_val_if_fail (priv1->name != NULL, FALSE);
+ g_return_val_if_fail (priv2->name != NULL, FALSE);
+ return !g_ascii_strcasecmp (priv1->name, priv2->name);
+}
+
+/**
+ * soup_address_hash_by_ip:
+ * @addr: a #SoupAddress
+ *
+ * A hash function (for #GHashTable) that corresponds to
+ * soup_address_equal_by_ip(), qv
+ *
+ * Return value: the IP-based hash value for @addr.
+ **/
+guint
+soup_address_hash_by_ip (gconstpointer addr)
+{
+ SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
+ guint hash;
+
+ g_return_val_if_fail (priv->sockaddr != NULL, 0);
+
+ memcpy (&hash, SOUP_ADDRESS_GET_DATA (priv),
+ MIN (sizeof (hash), SOUP_ADDRESS_FAMILY_DATA_SIZE (priv->sockaddr->sa_family)));
+ return hash;
+}
+
+/**
+ * soup_address_equal_by_ip:
+ * @addr1: a #SoupAddress with a resolved IP address
+ * @addr2: another #SoupAddress with a resolved IP address
+ *
+ * Tests if @addr1 and @addr2 have the same IP address. This method
+ * can be used with soup_address_hash_by_ip() to create a
+ * #GHashTable that hashes on IP address.
+ *
+ * This would be used to distinguish hosts in situations where
+ * different virtual hosts on the same IP address should be considered
+ * the same. Eg, if "www.example.com" and "www.example.net" have the
+ * same IP address, then a single #SoupConnection can be used to talk
+ * to either of them.
+ *
+ * See also soup_address_equal_by_name(), which compares by name
+ * rather than by IP address.
+ *
+ * Return value: whether or not @addr1 and @addr2 have the same IP
+ * address.
+ **/
+gboolean
+soup_address_equal_by_ip (gconstpointer addr1, gconstpointer addr2)
+{
+ SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
+ SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);
+ int size;
+
+ g_return_val_if_fail (priv1->sockaddr != NULL, FALSE);
+ g_return_val_if_fail (priv2->sockaddr != NULL, FALSE);
+
+ size = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (priv1->sockaddr->sa_family);
+ return (priv1->sockaddr->sa_family ==
+ priv2->sockaddr->sa_family &&
+ !memcmp (priv1->sockaddr, priv2->sockaddr, size));
+}
Modified: trunk/libsoup/soup-address.h
==============================================================================
--- trunk/libsoup/soup-address.h (original)
+++ trunk/libsoup/soup-address.h Fri Oct 3 21:01:54 2008
@@ -87,6 +87,15 @@
guint soup_address_get_port (SoupAddress *addr);
struct sockaddr *soup_address_get_sockaddr (SoupAddress *addr,
int *len);
+gboolean soup_address_is_resolved (SoupAddress *addr);
+
+guint soup_address_hash_by_name (gconstpointer addr);
+gboolean soup_address_equal_by_name (gconstpointer addr1,
+ gconstpointer addr2);
+guint soup_address_hash_by_ip (gconstpointer addr);
+gboolean soup_address_equal_by_ip (gconstpointer addr1,
+ gconstpointer addr2);
+
G_END_DECLS
Modified: trunk/libsoup/soup-auth-manager.c
==============================================================================
--- trunk/libsoup/soup-auth-manager.c (original)
+++ trunk/libsoup/soup-auth-manager.c Fri Oct 3 21:01:54 2008
@@ -12,6 +12,7 @@
#include <string.h>
#include "soup-auth-manager.h"
+#include "soup-address.h"
#include "soup-headers.h"
#include "soup-marshal.h"
#include "soup-message-private.h"
@@ -52,25 +53,19 @@
#define SOUP_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate))
typedef struct {
- SoupURI *root_uri;
+ SoupAddress *addr;
SoupPathMap *auth_realms; /* path -> scheme:realm */
GHashTable *auths; /* scheme:realm -> SoupAuth */
} SoupAuthHost;
-/* temporary until we fix this to index hosts by SoupAddress */
-extern guint soup_uri_host_hash (gconstpointer key);
-extern gboolean soup_uri_host_equal (gconstpointer v1,
- gconstpointer v2);
-extern SoupURI *soup_uri_copy_root (SoupURI *uri);
-
static void
soup_auth_manager_init (SoupAuthManager *manager)
{
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager);
priv->auth_types = g_ptr_array_new ();
- priv->auth_hosts = g_hash_table_new (soup_uri_host_hash,
- soup_uri_host_equal);
+ priv->auth_hosts = g_hash_table_new (soup_address_hash_by_name,
+ soup_address_equal_by_name);
}
static gboolean
@@ -83,7 +78,7 @@
if (host->auths)
g_hash_table_destroy (host->auths);
- soup_uri_free (host->root_uri);
+ g_object_unref (host->addr);
g_slice_free (SoupAuthHost, host);
return TRUE;
@@ -323,15 +318,15 @@
get_auth_host_for_message (SoupAuthManagerPrivate *priv, SoupMessage *msg)
{
SoupAuthHost *host;
- SoupURI *source = soup_message_get_uri (msg);
+ SoupAddress *addr = soup_message_get_address (msg);
- host = g_hash_table_lookup (priv->auth_hosts, source);
+ host = g_hash_table_lookup (priv->auth_hosts, addr);
if (host)
return host;
host = g_slice_new0 (SoupAuthHost);
- host->root_uri = soup_uri_copy_root (source);
- g_hash_table_insert (priv->auth_hosts, host->root_uri, host);
+ host->addr = g_object_ref (addr);
+ g_hash_table_insert (priv->auth_hosts, host->addr, host);
return host;
}
Modified: trunk/libsoup/soup-connection.c
==============================================================================
--- trunk/libsoup/soup-connection.c (original)
+++ trunk/libsoup/soup-connection.c Fri Oct 3 21:01:54 2008
@@ -36,13 +36,13 @@
typedef struct {
SoupSocket *socket;
- /* proxy_uri is the URI of the proxy server we are connected
- * to, if any. origin_uri is the URI of the origin server.
- * conn_uri is the uri of the host we are actually directly
- * connected to, which will be proxy_uri if there's a proxy
- * and origin_uri if not.
+ /* proxy_addr is the address of the proxy server we are
+ * connected to, if any. server_addr is the address of the
+ * origin server. conn_addr is the uri of the host we are
+ * actually directly connected to, which will be proxy_addr if
+ * there's a proxy and server_addr if not.
*/
- SoupURI *proxy_uri, *origin_uri, *conn_uri;
+ SoupAddress *proxy_addr, *server_addr, *conn_addr;
gpointer ssl_creds;
SoupConnectionMode mode;
@@ -71,8 +71,8 @@
enum {
PROP_0,
- PROP_ORIGIN_URI,
- PROP_PROXY_URI,
+ PROP_SERVER_ADDRESS,
+ PROP_PROXY_ADDRESS,
PROP_SSL_CREDS,
PROP_ASYNC_CONTEXT,
PROP_TIMEOUT,
@@ -101,10 +101,10 @@
{
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object);
- if (priv->proxy_uri)
- soup_uri_free (priv->proxy_uri);
- if (priv->origin_uri)
- soup_uri_free (priv->origin_uri);
+ if (priv->proxy_addr)
+ g_object_unref (priv->proxy_addr);
+ if (priv->server_addr)
+ g_object_unref (priv->server_addr);
if (priv->async_context)
g_main_context_unref (priv->async_context);
@@ -175,17 +175,19 @@
/* properties */
g_object_class_install_property (
- object_class, PROP_ORIGIN_URI,
- g_param_spec_pointer (SOUP_CONNECTION_ORIGIN_URI,
- "Origin URI",
- "The HTTP origin server to use for this connection",
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ object_class, PROP_SERVER_ADDRESS,
+ g_param_spec_object (SOUP_CONNECTION_SERVER_ADDRESS,
+ "Server address",
+ "The address of the HTTP origin server for this connection",
+ SOUP_TYPE_ADDRESS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (
- object_class, PROP_PROXY_URI,
- g_param_spec_pointer (SOUP_CONNECTION_PROXY_URI,
- "Proxy URI",
- "The HTTP Proxy to use for this connection",
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ object_class, PROP_PROXY_ADDRESS,
+ g_param_spec_object (SOUP_CONNECTION_PROXY_ADDRESS,
+ "Proxy address",
+ "The address of the HTTP Proxy to use for this connection",
+ SOUP_TYPE_ADDRESS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (
object_class, PROP_SSL_CREDS,
g_param_spec_pointer (SOUP_CONNECTION_SSL_CREDENTIALS,
@@ -220,12 +222,21 @@
* @propname1: name of first property to set
* @...: value of @propname1, followed by additional property/value pairs
*
- * Creates an HTTP connection. You must set at least one of
- * %SOUP_CONNECTION_ORIGIN_URI or %SOUP_CONNECTION_PROXY_URI. If you
- * set an origin server URI but no proxy URI, this will be a direct
- * connection. If you set a proxy URI and an https origin server URI,
- * this will be a tunnel. Otherwise it will be an http proxy
- * connection.
+ * Creates an HTTP connection. There are three possibilities:
+ *
+ * If you set %SOUP_CONNECTION_SERVER_ADDRESS and not
+ * %SOUP_CONNECTION_PROXY_ADDRESS, this will be a direct connection to
+ * the indicated origin server.
+ *
+ * If you set %SOUP_CONNECTION_PROXY_ADDRESS and not
+ * %SOUP_CONNECTION_SSL_CREDENTIALS, this will be a standard proxy
+ * connection, which can be used for requests to multiple origin
+ * servers.
+ *
+ * If you set %SOUP_CONNECTION_SERVER_ADDRESS,
+ * %SOUP_CONNECTION_PROXY_ADDRESS, and
+ * %SOUP_CONNECTION_SSL_CREDENTIALS, this will be a tunnel through the
+ * proxy to the origin server.
*
* You must call soup_connection_connect_async() or
* soup_connection_connect_sync() to connect it after creating it.
@@ -251,35 +262,33 @@
const GValue *value, GParamSpec *pspec)
{
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object);
- gpointer pval;
switch (prop_id) {
- case PROP_ORIGIN_URI:
- pval = g_value_get_pointer (value);
- priv->origin_uri = pval ? soup_uri_copy (pval) : NULL;
- goto changed_uri;
-
- case PROP_PROXY_URI:
- pval = g_value_get_pointer (value);
- priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL;
-
- changed_uri:
- if (priv->proxy_uri) {
- priv->conn_uri = priv->proxy_uri;
- if (priv->origin_uri &&
- priv->origin_uri->scheme == SOUP_URI_SCHEME_HTTPS)
+ case PROP_SERVER_ADDRESS:
+ priv->server_addr = g_value_dup_object (value);
+ goto changed_connection;
+
+ case PROP_PROXY_ADDRESS:
+ priv->proxy_addr = g_value_dup_object (value);
+ goto changed_connection;
+
+ case PROP_SSL_CREDS:
+ priv->ssl_creds = g_value_get_pointer (value);
+ goto changed_connection;
+
+ changed_connection:
+ if (priv->proxy_addr) {
+ priv->conn_addr = priv->proxy_addr;
+ if (priv->server_addr && priv->ssl_creds)
priv->mode = SOUP_CONNECTION_MODE_TUNNEL;
else
priv->mode = SOUP_CONNECTION_MODE_PROXY;
} else {
- priv->conn_uri = priv->origin_uri;
+ priv->conn_addr = priv->server_addr;
priv->mode = SOUP_CONNECTION_MODE_DIRECT;
}
break;
- case PROP_SSL_CREDS:
- priv->ssl_creds = g_value_get_pointer (value);
- break;
case PROP_ASYNC_CONTEXT:
priv->async_context = g_value_get_pointer (value);
if (priv->async_context)
@@ -304,15 +313,12 @@
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_ORIGIN_URI:
- g_value_set_pointer (value, priv->origin_uri ?
- soup_uri_copy (priv->origin_uri) :
- NULL);
- break;
- case PROP_PROXY_URI:
- g_value_set_pointer (value, priv->proxy_uri ?
- soup_uri_copy (priv->proxy_uri) :
- NULL);
+ case PROP_SERVER_ADDRESS:
+ g_value_set_object (value, priv->server_addr);
+ break;
+ case PROP_PROXY_ADDRESS:
+ g_value_set_object (value, priv->proxy_addr);
+ break;
case PROP_SSL_CREDS:
g_value_set_pointer (value, priv->ssl_creds);
break;
@@ -405,7 +411,7 @@
static inline guint
proxified_status (SoupConnectionPrivate *priv, guint status)
{
- if (!priv->proxy_uri)
+ if (!priv->proxy_addr)
return status;
if (status == SOUP_STATUS_CANT_RESOLVE)
@@ -416,6 +422,22 @@
return status;
}
+static SoupMessage *
+connect_message (SoupConnectionPrivate *priv)
+{
+ SoupURI *uri;
+ SoupMessage *msg;
+
+ uri = soup_uri_new (NULL);
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
+ soup_uri_set_host (uri, soup_address_get_name (priv->server_addr));
+ soup_uri_set_port (uri, soup_address_get_port (priv->server_addr));
+ msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri);
+ soup_uri_free (uri);
+
+ return msg;
+}
+
static void
tunnel_connect_finished (SoupMessage *msg, gpointer user_data)
{
@@ -425,9 +447,10 @@
clear_current_request (conn);
- if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
- if (soup_socket_start_proxy_ssl (priv->socket,
- priv->origin_uri->host,
+ if (SOUP_STATUS_IS_SUCCESSFUL (status) && priv->ssl_creds) {
+ const char *server_name =
+ soup_address_get_name (priv->server_addr);
+ if (soup_socket_start_proxy_ssl (priv->socket, server_name,
NULL))
priv->connected = TRUE;
else
@@ -482,7 +505,7 @@
if (!SOUP_STATUS_IS_SUCCESSFUL (status))
goto done;
- if (priv->conn_uri->scheme == SOUP_URI_SCHEME_HTTPS) {
+ if (priv->mode == SOUP_CONNECTION_MODE_DIRECT && priv->ssl_creds) {
if (!soup_socket_start_ssl (sock, NULL)) {
status = SOUP_STATUS_SSL_FAILED;
goto done;
@@ -490,10 +513,7 @@
}
if (priv->mode == SOUP_CONNECTION_MODE_TUNNEL) {
- SoupMessage *connect_msg;
-
- connect_msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT,
- priv->origin_uri);
+ SoupMessage *connect_msg = connect_message (priv);
g_signal_connect (connect_msg, "restarted",
G_CALLBACK (tunnel_connect_restarted), conn);
@@ -516,6 +536,28 @@
guint soup_signal_connect_once (gpointer instance, const char *detailed_signal,
GCallback c_handler, gpointer data);
+static void
+address_resolved (SoupAddress *addr, guint status, gpointer data)
+{
+ SoupConnection *conn = data;
+ SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
+
+ if (status != SOUP_STATUS_OK) {
+ socket_connect_result (NULL, status, conn);
+ return;
+ }
+
+ priv->socket =
+ soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
+ SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
+ SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
+ NULL);
+ soup_socket_connect_async (priv->socket, NULL,
+ socket_connect_result, conn);
+ g_signal_connect (priv->socket, "disconnected",
+ G_CALLBACK (socket_disconnected), conn);
+}
+
/**
* soup_connection_connect_async:
* @conn: the connection
@@ -530,7 +572,6 @@
gpointer user_data)
{
SoupConnectionPrivate *priv;
- SoupAddress *addr;
g_return_if_fail (SOUP_IS_CONNECTION (conn));
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
@@ -541,18 +582,8 @@
G_CALLBACK (callback), user_data);
}
- addr = soup_address_new (priv->conn_uri->host, priv->conn_uri->port);
- priv->socket =
- soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
- SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
- SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
- NULL);
- soup_socket_connect_async (priv->socket, NULL,
- socket_connect_result, conn);
- g_signal_connect (priv->socket, "disconnected",
- G_CALLBACK (socket_disconnected), conn);
-
- g_object_unref (addr);
+ soup_address_resolve_async (priv->conn_addr, priv->async_context, NULL,
+ address_resolved, conn);
}
/**
@@ -567,24 +598,24 @@
soup_connection_connect_sync (SoupConnection *conn)
{
SoupConnectionPrivate *priv;
- SoupAddress* addr;
guint status;
g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED);
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
g_return_val_if_fail (priv->socket == NULL, SOUP_STATUS_MALFORMED);
- addr = soup_address_new (priv->conn_uri->host,
- priv->conn_uri->port);
+ status = soup_address_resolve_sync (priv->conn_addr, NULL);
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
+ goto fail;
+
priv->socket =
- soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
+ soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, priv->conn_addr,
SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
SOUP_SOCKET_FLAG_NONBLOCKING, FALSE,
SOUP_SOCKET_TIMEOUT, priv->io_timeout,
NULL);
status = soup_socket_connect_sync (priv->socket, NULL);
- g_object_unref (addr);
if (!SOUP_STATUS_IS_SUCCESSFUL (status))
goto fail;
@@ -592,7 +623,7 @@
g_signal_connect (priv->socket, "disconnected",
G_CALLBACK (socket_disconnected), conn);
- if (priv->conn_uri->scheme == SOUP_URI_SCHEME_HTTPS) {
+ if (priv->mode == SOUP_CONNECTION_MODE_DIRECT && priv->ssl_creds) {
if (!soup_socket_start_ssl (priv->socket, NULL)) {
status = SOUP_STATUS_SSL_FAILED;
goto fail;
@@ -600,10 +631,8 @@
}
if (priv->mode == SOUP_CONNECTION_MODE_TUNNEL) {
- SoupMessage *connect_msg;
+ SoupMessage *connect_msg = connect_message (priv);
- connect_msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT,
- priv->origin_uri);
soup_connection_send_request (conn, connect_msg);
status = connect_msg->status_code;
@@ -620,8 +649,10 @@
g_object_unref (connect_msg);
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
+ const char *server_name =
+ soup_address_get_name (priv->server_addr);
if (!soup_socket_start_proxy_ssl (priv->socket,
- priv->origin_uri->host,
+ server_name,
NULL))
status = SOUP_STATUS_SSL_FAILED;
}
Modified: trunk/libsoup/soup-connection.h
==============================================================================
--- trunk/libsoup/soup-connection.h (original)
+++ trunk/libsoup/soup-connection.h Fri Oct 3 21:01:54 2008
@@ -45,8 +45,8 @@
gpointer data);
-#define SOUP_CONNECTION_ORIGIN_URI "origin-uri"
-#define SOUP_CONNECTION_PROXY_URI "proxy-uri"
+#define SOUP_CONNECTION_SERVER_ADDRESS "server_address"
+#define SOUP_CONNECTION_PROXY_ADDRESS "proxy-address"
#define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds"
#define SOUP_CONNECTION_ASYNC_CONTEXT "async-context"
#define SOUP_CONNECTION_TIMEOUT "timeout"
Modified: trunk/libsoup/soup-dns.c
==============================================================================
--- trunk/libsoup/soup-dns.c (original)
+++ trunk/libsoup/soup-dns.c Fri Oct 3 21:01:54 2008
@@ -520,10 +520,10 @@
SoupDNSCacheEntry *entry = lookup->entry;
GCancellable *cancellable = lookup->cancellable;
- lookup->callback (lookup, resolve_status (entry, cancellable),
- lookup->user_data);
if (cancellable)
g_signal_handlers_disconnect_by_func (cancellable, async_cancel, lookup);
+ lookup->callback (lookup, resolve_status (entry, cancellable),
+ lookup->user_data);
return FALSE;
}
Modified: trunk/libsoup/soup-message-private.h
==============================================================================
--- trunk/libsoup/soup-message-private.h (original)
+++ trunk/libsoup/soup-message-private.h Fri Oct 3 21:01:54 2008
@@ -32,6 +32,7 @@
SoupHTTPVersion http_version, orig_http_version;
SoupURI *uri;
+ SoupAddress *addr;
SoupAuth *auth, *proxy_auth;
} SoupMessagePrivate;
Modified: trunk/libsoup/soup-message-queue.c
==============================================================================
--- trunk/libsoup/soup-message-queue.c (original)
+++ trunk/libsoup/soup-message-queue.c Fri Oct 3 21:01:54 2008
@@ -79,6 +79,7 @@
item->msg = g_object_ref (msg);
item->callback = callback;
item->callback_data = user_data;
+ item->cancellable = g_cancellable_new ();
/* Note: the initial ref_count of 1 represents the caller's
* ref; the queue's own ref is indicated by the absence of the
@@ -145,6 +146,9 @@
/* And free it */
g_object_unref (item->msg);
+ g_object_unref (item->cancellable);
+ if (item->msg_addr)
+ g_object_unref (item->msg_addr);
g_slice_free (SoupMessageQueueItem, item);
}
Modified: trunk/libsoup/soup-message-queue.h
==============================================================================
--- trunk/libsoup/soup-message-queue.h (original)
+++ trunk/libsoup/soup-message-queue.h Fri Oct 3 21:01:54 2008
@@ -8,6 +8,7 @@
#define SOUP_MESSAGE_QUEUE_H 1
#include <glib.h>
+#include <gio/gio.h>
#include <libsoup/soup-message.h>
#include <libsoup/soup-session.h>
@@ -24,9 +25,14 @@
SoupSessionCallback callback;
gpointer callback_data;
+ GCancellable *cancellable;
+ SoupAddress *msg_addr;
+
+ guint resolving_msg_addr : 1;
+
/*< private >*/
guint removed : 1;
- guint ref_count : 31;
+ guint ref_count : 30;
SoupMessageQueueItem *prev, *next;
};
Modified: trunk/libsoup/soup-message.c
==============================================================================
--- trunk/libsoup/soup-message.c (original)
+++ trunk/libsoup/soup-message.c Fri Oct 3 21:01:54 2008
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
+#include "soup-address.h"
#include "soup-auth.h"
#include "soup-enum-types.h"
#include "soup-marshal.h"
@@ -145,6 +146,8 @@
if (priv->uri)
soup_uri_free (priv->uri);
+ if (priv->addr)
+ g_object_unref (priv->addr);
if (priv->auth)
g_object_unref (priv->auth);
@@ -1280,6 +1283,10 @@
if (priv->uri)
soup_uri_free (priv->uri);
+ if (priv->addr) {
+ g_object_unref (priv->addr);
+ priv->addr = NULL;
+ }
priv->uri = soup_uri_copy (uri);
g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_URI);
@@ -1302,6 +1309,31 @@
}
/**
+ * soup_message_get_address:
+ * @msg: a #SoupMessage
+ *
+ * Gets the address @msg's URI points to. After first setting the
+ * URI on a message, this will be unresolved, although the message's
+ * session will resolve it before sending the message.
+ *
+ * Return value: the address @msg's URI points to
+ **/
+SoupAddress *
+soup_message_get_address (SoupMessage *msg)
+{
+ SoupMessagePrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
+
+ priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+ if (!priv->addr) {
+ priv->addr = soup_address_new (priv->uri->host,
+ priv->uri->port);
+ }
+ return priv->addr;
+}
+
+/**
* soup_message_set_status:
* @msg: a #SoupMessage
* @status_code: an HTTP status code
Modified: trunk/libsoup/soup-message.h
==============================================================================
--- trunk/libsoup/soup-message.h (original)
+++ trunk/libsoup/soup-message.h Fri Oct 3 21:01:54 2008
@@ -98,6 +98,7 @@
SoupURI *soup_message_get_uri (SoupMessage *msg);
void soup_message_set_uri (SoupMessage *msg,
SoupURI *uri);
+SoupAddress *soup_message_get_address (SoupMessage *msg);
typedef enum {
#ifndef LIBSOUP_DISABLE_DEPRECATED
Modified: trunk/libsoup/soup-session-async.c
==============================================================================
--- trunk/libsoup/soup-session-async.c (original)
+++ trunk/libsoup/soup-session-async.c Fri Oct 3 21:01:54 2008
@@ -11,6 +11,7 @@
#include "soup-session-async.h"
#include "soup-session-private.h"
+#include "soup-address.h"
#include "soup-message-private.h"
#include "soup-misc.h"
@@ -108,6 +109,47 @@
static void
+resolved_msg_addr (SoupAddress *addr, guint status, gpointer user_data)
+{
+ SoupMessageQueueItem *item = user_data;
+ SoupSession *session = item->session;
+
+ if (item->removed) {
+ /* Message was cancelled before its address resolved */
+ soup_message_queue_item_unref (item);
+ return;
+ }
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+ soup_session_cancel_message (session, item->msg, status);
+ soup_message_queue_item_unref (item);
+ return;
+ }
+
+ item->msg_addr = g_object_ref (addr);
+ item->resolving_msg_addr = FALSE;
+
+ soup_message_queue_item_unref (item);
+
+ /* If we got here we know session still exists */
+ run_queue ((SoupSessionAsync *)session);
+}
+
+static void
+resolve_msg_addr (SoupMessageQueueItem *item)
+{
+ if (item->resolving_msg_addr)
+ return;
+ item->resolving_msg_addr = TRUE;
+
+ soup_message_queue_item_ref (item);
+ soup_address_resolve_async (soup_message_get_address (item->msg),
+ soup_session_get_async_context (item->session),
+ item->cancellable,
+ resolved_msg_addr, item);
+}
+
+static void
connection_closed (SoupConnection *conn, gpointer session)
{
/* Run the queue in case anyone was waiting for a connection
@@ -169,6 +211,11 @@
soup_message_io_in_progress (msg))
continue;
+ if (!item->msg_addr) {
+ resolve_msg_addr (item);
+ continue;
+ }
+
conn = soup_session_get_connection (session, msg,
&should_prune, &is_new);
if (!conn)
@@ -198,9 +245,17 @@
}
static void
-request_restarted (SoupMessage *req, gpointer sa)
+request_restarted (SoupMessage *req, gpointer user_data)
{
- run_queue (sa);
+ SoupMessageQueueItem *item = user_data;
+
+ if (item->msg_addr &&
+ item->msg_addr != soup_message_get_address (item->msg)) {
+ g_object_unref (item->msg_addr);
+ item->msg_addr = NULL;
+ }
+
+ run_queue ((SoupSessionAsync *)item->session);
}
static void
@@ -258,7 +313,7 @@
g_return_if_fail (item != NULL);
g_signal_connect (req, "restarted",
- G_CALLBACK (request_restarted), session);
+ G_CALLBACK (request_restarted), item);
g_signal_connect_after (req, "finished",
G_CALLBACK (final_finished), item);
Modified: trunk/libsoup/soup-session-sync.c
==============================================================================
--- trunk/libsoup/soup-session-sync.c (original)
+++ trunk/libsoup/soup-session-sync.c Fri Oct 3 21:01:54 2008
@@ -11,6 +11,7 @@
#include "soup-session-sync.h"
#include "soup-session-private.h"
+#include "soup-address.h"
#include "soup-message-private.h"
#include "soup-misc.h"
@@ -186,8 +187,19 @@
SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (item->session);
SoupMessage *msg = item->msg;
SoupConnection *conn;
+ SoupAddress *addr;
+ guint status;
do {
+ /* Resolve address */
+ addr = soup_message_get_address (msg);
+ status = soup_address_resolve_sync (addr, item->cancellable);
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+ if (status != SOUP_STATUS_CANCELLED)
+ soup_session_cancel_message (item->session, msg, status);
+ break;
+ }
+
/* Get a connection */
conn = wait_for_connection (item->session, msg);
if (!conn)
Modified: trunk/libsoup/soup-session.c
==============================================================================
--- trunk/libsoup/soup-session.c (original)
+++ trunk/libsoup/soup-session.c Fri Oct 3 21:01:54 2008
@@ -13,6 +13,7 @@
#include <string.h>
#include <stdlib.h>
+#include "soup-address.h"
#include "soup-auth.h"
#include "soup-auth-basic.h"
#include "soup-auth-digest.h"
@@ -55,17 +56,15 @@
**/
typedef struct {
- SoupURI *root_uri;
+ SoupAddress *addr;
- GSList *connections; /* CONTAINS: SoupConnection */
- guint num_conns;
-
- GHashTable *auth_realms; /* path -> scheme:realm */
- GHashTable *auths; /* scheme:realm -> SoupAuth */
+ GSList *connections; /* CONTAINS: SoupConnection */
+ guint num_conns;
} SoupSessionHost;
typedef struct {
SoupURI *proxy_uri;
+ SoupAddress *proxy_addr;
SoupAuth *proxy_auth;
char *ssl_ca_file;
@@ -78,7 +77,7 @@
GSList *features;
SoupAuthManager *auth_manager;
- GHashTable *hosts; /* SoupURI -> SoupSessionHost */
+ GHashTable *hosts; /* SoupAddress -> SoupSessionHost */
GHashTable *conns; /* SoupConnection -> SoupSessionHost */
guint num_conns;
guint max_conns, max_conns_per_host;
@@ -106,12 +105,6 @@
SoupMessage *msg, SoupAuth *auth,
gboolean retrying, gpointer user_data);
-/* temporary until we fix this to index hosts by SoupAddress */
-extern guint soup_uri_host_hash (gconstpointer key);
-extern gboolean soup_uri_host_equal (gconstpointer v1,
- gconstpointer v2);
-extern SoupURI *soup_uri_copy_root (SoupURI *uri);
-
#define SOUP_SESSION_MAX_CONNS_DEFAULT 10
#define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2
@@ -161,8 +154,8 @@
priv->queue = soup_message_queue_new (session);
priv->host_lock = g_mutex_new ();
- priv->hosts = g_hash_table_new (soup_uri_host_hash,
- soup_uri_host_equal);
+ priv->hosts = g_hash_table_new (soup_address_hash_by_ip,
+ soup_address_equal_by_ip);
priv->conns = g_hash_table_new (NULL, NULL);
priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT;
@@ -192,8 +185,8 @@
g_mutex_lock (priv->host_lock);
old_hosts = priv->hosts;
- priv->hosts = g_hash_table_new (soup_uri_host_hash,
- soup_uri_host_equal);
+ priv->hosts = g_hash_table_new (soup_address_hash_by_ip,
+ soup_address_equal_by_ip);
g_mutex_unlock (priv->host_lock);
g_hash_table_foreach_remove (old_hosts, foreach_free_host, NULL);
@@ -234,6 +227,8 @@
if (priv->proxy_uri)
soup_uri_free (priv->proxy_uri);
+ if (priv->proxy_addr)
+ g_object_unref (priv->proxy_addr);
if (priv->ssl_creds)
soup_ssl_free_client_credentials (priv->ssl_creds);
@@ -554,8 +549,13 @@
if (priv->proxy_uri)
soup_uri_free (priv->proxy_uri);
+ if (priv->proxy_addr)
+ g_object_unref (priv->proxy_addr);
priv->proxy_uri = uri ? soup_uri_copy (uri) : NULL;
+ priv->proxy_addr = uri ?
+ soup_address_new (uri->host, uri->port) :
+ NULL;
if (need_abort) {
soup_session_abort (session);
@@ -702,20 +702,12 @@
/* Hosts */
static SoupSessionHost *
-soup_session_host_new (SoupSession *session, SoupURI *source_uri)
+soup_session_host_new (SoupSession *session, SoupAddress *addr)
{
- SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
SoupSessionHost *host;
host = g_slice_new0 (SoupSessionHost);
- host->root_uri = soup_uri_copy_root (source_uri);
-
- if (host->root_uri->scheme == SOUP_URI_SCHEME_HTTPS &&
- !priv->ssl_creds) {
- priv->ssl_creds =
- soup_ssl_get_client_credentials (priv->ssl_ca_file);
- }
-
+ host->addr = g_object_ref (addr);
return host;
}
@@ -728,14 +720,14 @@
{
SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
SoupSessionHost *host;
- SoupURI *source = soup_message_get_uri (msg);
+ SoupAddress *addr = soup_message_get_address (msg);
- host = g_hash_table_lookup (priv->hosts, source);
+ host = g_hash_table_lookup (priv->hosts, addr);
if (host)
return host;
- host = soup_session_host_new (session, source);
- g_hash_table_insert (priv->hosts, host->root_uri, host);
+ host = soup_session_host_new (session, addr);
+ g_hash_table_insert (priv->hosts, host->addr, host);
return host;
}
@@ -750,7 +742,7 @@
soup_connection_disconnect (conn);
}
- soup_uri_free (host->root_uri);
+ g_object_unref (host->addr);
g_slice_free (SoupSessionHost, host);
}
@@ -1021,7 +1013,9 @@
SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
SoupConnection *conn;
SoupSessionHost *host;
+ SoupSSLCredentials *ssl_creds;
GSList *conns;
+ SoupURI *uri;
g_mutex_lock (priv->host_lock);
@@ -1054,10 +1048,18 @@
return NULL;
}
+ uri = soup_message_get_uri (msg);
+ if (uri->scheme == SOUP_URI_SCHEME_HTTPS) {
+ if (!priv->ssl_creds)
+ priv->ssl_creds = soup_ssl_get_client_credentials (priv->ssl_ca_file);
+ ssl_creds = priv->ssl_creds;
+ } else
+ ssl_creds = NULL;
+
conn = soup_connection_new (
- SOUP_CONNECTION_ORIGIN_URI, host->root_uri,
- SOUP_CONNECTION_PROXY_URI, priv->proxy_uri,
- SOUP_CONNECTION_SSL_CREDENTIALS, priv->ssl_creds,
+ SOUP_CONNECTION_SERVER_ADDRESS, host->addr,
+ SOUP_CONNECTION_PROXY_ADDRESS, priv->proxy_addr,
+ SOUP_CONNECTION_SSL_CREDENTIALS, ssl_creds,
SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
SOUP_CONNECTION_IDLE_TIMEOUT, priv->idle_timeout,
@@ -1272,6 +1274,8 @@
item = soup_message_queue_lookup (priv->queue, msg);
if (item) {
soup_message_queue_remove (priv->queue, item);
+ if (item->cancellable)
+ g_cancellable_cancel (item->cancellable);
soup_message_queue_item_unref (item);
}
Modified: trunk/libsoup/soup-uri.c
==============================================================================
--- trunk/libsoup/soup-uri.c (original)
+++ trunk/libsoup/soup-uri.c Fri Oct 3 21:01:54 2008
@@ -487,49 +487,6 @@
return dup;
}
-/* Temporarily still used by SoupSession, but no longer public */
-SoupURI *soup_uri_copy_root (SoupURI *uri);
-gboolean soup_uri_host_equal (gconstpointer v1, gconstpointer v2);
-guint soup_uri_host_hash (gconstpointer key);
-
-SoupURI *
-soup_uri_copy_root (SoupURI *uri)
-{
- SoupURI *dup;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- dup = g_slice_new0 (SoupURI);
- dup->scheme = uri->scheme;
- dup->host = g_strdup (uri->host);
- dup->port = uri->port;
-
- return dup;
-}
-
-guint
-soup_uri_host_hash (gconstpointer key)
-{
- const SoupURI *uri = key;
-
- return GPOINTER_TO_UINT (uri->scheme) + uri->port +
- soup_str_case_hash (uri->host);
-}
-
-gboolean
-soup_uri_host_equal (gconstpointer v1, gconstpointer v2)
-{
- const SoupURI *one = v1;
- const SoupURI *two = v2;
-
- if (one->scheme != two->scheme)
- return FALSE;
- if (one->port != two->port)
- return FALSE;
-
- return g_ascii_strcasecmp (one->host, two->host) == 0;
-}
-
static inline gboolean
parts_equal (const char *one, const char *two, gboolean insensitive)
{
Modified: trunk/tests/proxy-test.c
==============================================================================
--- trunk/tests/proxy-test.c (original)
+++ trunk/tests/proxy-test.c Fri Oct 3 21:01:54 2008
@@ -21,7 +21,7 @@
{ "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND },
{ "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK },
{ "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED },
- { "GET -> 403", "http://no-proxy.example.com/", SOUP_STATUS_FORBIDDEN },
+ { "GET -> 403", "http://www.example.com/", SOUP_STATUS_FORBIDDEN },
};
static int ntests = sizeof (tests) / sizeof (tests[0]);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]