Change the SoupURI properties to SoupAddress properties.
authorDan Winship <danw@src.gnome.org>
Fri, 3 Oct 2008 21:01:54 +0000 (21:01 +0000)
committerDan Winship <danw@src.gnome.org>
Fri, 3 Oct 2008 21:01:54 +0000 (21:01 +0000)
* 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

svn path=/trunk/; revision=1179

17 files changed:
ChangeLog
libsoup/soup-address.c
libsoup/soup-address.h
libsoup/soup-auth-manager.c
libsoup/soup-connection.c
libsoup/soup-connection.h
libsoup/soup-dns.c
libsoup/soup-message-private.h
libsoup/soup-message-queue.c
libsoup/soup-message-queue.h
libsoup/soup-message.c
libsoup/soup-message.h
libsoup/soup-session-async.c
libsoup/soup-session-sync.c
libsoup/soup-session.c
libsoup/soup-uri.c
tests/proxy-test.c

index 32945ae..9d72460 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,55 @@
 2008-10-03  Dan Winship  <danw@gnome.org>
 
+       * 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
+
+2008-10-03  Dan Winship  <danw@gnome.org>
+
        * libsoup/soup-message-queue.c: Make this more complicated, with a
        SoupMessageQueueItem to keep track of the session's per-message
        state. (Part of the process of moving session-related state out of
index 69bbe98..4a24569 100644 (file)
@@ -60,9 +60,6 @@ typedef struct {
 
        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 @@ finalize (GObject *object)
        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 @@ constructor (GType                  type,
                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 @@ lookup_resolved (SoupDNSLookup *lookup, guint status, gpointer user_data)
                callback (addr, status, callback_data);
 
        g_object_unref (addr);
+       soup_dns_lookup_free (lookup);
 }
 
 /**
@@ -585,17 +573,21 @@ soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context,
 {
        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 @@ guint
 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));
+}
index 90c133e..8c4e7f9 100644 (file)
@@ -87,6 +87,15 @@ const char      *soup_address_get_physical       (SoupAddress         *addr);
 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
 
index df8dddf..181658b 100644 (file)
@@ -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 @@ typedef struct {
 #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 @@ foreach_free_host (gpointer key, gpointer value, gpointer data)
        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 @@ static SoupAuthHost *
 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;
 }
index cdc9ea9..e38f777 100644 (file)
@@ -36,13 +36,13 @@ typedef enum {
 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 @@ static guint signals[LAST_SIGNAL] = { 0 };
 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 @@ finalize (GObject *object)
 {
        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 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
 
        /* 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 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
  * @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 @@ set_property (GObject *object, guint prop_id,
              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 @@ get_property (GObject *object, guint prop_id,
        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);
+       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_PROXY_URI:
-               g_value_set_pointer (value, priv->proxy_uri ?
-                                    soup_uri_copy (priv->proxy_uri) :
-                                    NULL);
        case PROP_SSL_CREDS:
                g_value_set_pointer (value, priv->ssl_creds);
                break;
@@ -405,7 +411,7 @@ socket_disconnected (SoupSocket *sock, gpointer conn)
 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 @@ proxified_status (SoupConnectionPrivate *priv, guint status)
                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 @@ tunnel_connect_finished (SoupMessage *msg, gpointer user_data)
 
        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 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
        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 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
        }
 
        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 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
 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 @@ soup_connection_connect_async (SoupConnection *conn,
                               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 @@ soup_connection_connect_async (SoupConnection *conn,
                                          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 @@ guint
 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 @@ soup_connection_connect_sync (SoupConnection *conn)
        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 @@ soup_connection_connect_sync (SoupConnection *conn)
        }
 
        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 @@ soup_connection_connect_sync (SoupConnection *conn)
                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;
                }
index 548cb32..180ab28 100644 (file)
@@ -45,8 +45,8 @@ typedef void  (*SoupConnectionCallback)        (SoupConnection   *conn,
                                                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"
index 3866523..cb4cee5 100644 (file)
@@ -520,10 +520,10 @@ do_async_callback (gpointer user_data)
        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;
 }
index 8392c50..f47251a 100644 (file)
@@ -32,6 +32,7 @@ typedef struct {
        SoupHTTPVersion    http_version, orig_http_version;
 
        SoupURI           *uri;
+       SoupAddress       *addr;
 
        SoupAuth          *auth, *proxy_auth;
 } SoupMessagePrivate;
index b616b77..1a7abb8 100644 (file)
@@ -79,6 +79,7 @@ soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg,
        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 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item)
 
        /* 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);
 }
 
index 1061581..3a4f344 100644 (file)
@@ -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 @@ struct SoupMessageQueueItem {
        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;
 };
 
index c5890ce..2aa0473 100644 (file)
@@ -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 @@ finalize (GObject *object)
 
        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 @@ soup_message_set_uri (SoupMessage *msg, SoupURI *uri)
 
        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_uri (SoupMessage *msg)
 }
 
 /**
+ * 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
index 7a9d940..1b850be 100644 (file)
@@ -98,6 +98,7 @@ gboolean         soup_message_is_keepalive        (SoupMessage       *msg);
 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
index d3f229b..34c0a43 100644 (file)
@@ -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 @@ soup_session_async_new_with_options (const char *optname1, ...)
 
 
 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 @@ run_queue (SoupSessionAsync *sa)
                    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 @@ run_queue (SoupSessionAsync *sa)
 }
 
 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 @@ queue_message (SoupSession *session, SoupMessage *req,
        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);
 
index 9ecac2a..3be2054 100644 (file)
@@ -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 @@ process_queue_item (SoupMessageQueueItem *item)
        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)
index 417591c..2b9e5eb 100644 (file)
@@ -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"
  **/
 
 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 @@ typedef struct {
        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 @@ static void auth_manager_authenticate (SoupAuthManager *manager,
                                       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 @@ soup_session_init (SoupSession *session)
        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 @@ cleanup_hosts (SoupSessionPrivate *priv)
 
        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 @@ finalize (GObject *object)
 
        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 @@ set_property (GObject *object, guint prop_id,
 
                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 @@ soup_session_get_async_context (SoupSession *session)
 /* 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 @@ get_host_for_message (SoupSession *session, SoupMessage *msg)
 {
        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 @@ free_host (SoupSessionHost *host)
                soup_connection_disconnect (conn);
        }
 
-       soup_uri_free (host->root_uri);
+       g_object_unref (host->addr);
        g_slice_free (SoupSessionHost, host);
 }      
 
@@ -1021,7 +1013,9 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg,
        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 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg,
                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 @@ cancel_message (SoupSession *session, SoupMessage *msg, guint status_code)
        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);
        }
 
index 4ecf931..668a753 100644 (file)
@@ -487,49 +487,6 @@ soup_uri_copy (SoupURI *uri)
        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)
 {
index e4e9581..e512e86 100644 (file)
@@ -21,7 +21,7 @@ static SoupProxyTest tests[] = {
        { "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]);