From d0f981d4761fb088ebbcbc2a1c387c209ce0c243 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 3 Oct 2008 21:01:54 +0000 Subject: [PATCH] Change the SoupURI properties to SoupAddress properties. * 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 --- ChangeLog | 50 ++++++++++ libsoup/soup-address.c | 164 +++++++++++++++++++++++++++++---- libsoup/soup-address.h | 9 ++ libsoup/soup-auth-manager.c | 23 ++--- libsoup/soup-connection.c | 205 ++++++++++++++++++++++++----------------- libsoup/soup-connection.h | 4 +- libsoup/soup-dns.c | 4 +- libsoup/soup-message-private.h | 1 + libsoup/soup-message-queue.c | 4 + libsoup/soup-message-queue.h | 8 +- libsoup/soup-message.c | 32 +++++++ libsoup/soup-message.h | 1 + libsoup/soup-session-async.c | 61 +++++++++++- libsoup/soup-session-sync.c | 12 +++ libsoup/soup-session.c | 74 ++++++++------- libsoup/soup-uri.c | 43 --------- tests/proxy-test.c | 2 +- 17 files changed, 490 insertions(+), 207 deletions(-) diff --git a/ChangeLog b/ChangeLog index 32945ae..9d72460 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,55 @@ 2008-10-03 Dan Winship + * 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 + * 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 diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 69bbe98..4a24569 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -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)); +} diff --git a/libsoup/soup-address.h b/libsoup/soup-address.h index 90c133e..8c4e7f9 100644 --- a/libsoup/soup-address.h +++ b/libsoup/soup-address.h @@ -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 diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index df8dddf..181658b 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -12,6 +12,7 @@ #include #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; } diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index cdc9ea9..e38f777 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -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; } diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 548cb32..180ab28 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -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" diff --git a/libsoup/soup-dns.c b/libsoup/soup-dns.c index 3866523..cb4cee5 100644 --- a/libsoup/soup-dns.c +++ b/libsoup/soup-dns.c @@ -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; } diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 8392c50..f47251a 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -32,6 +32,7 @@ typedef struct { SoupHTTPVersion http_version, orig_http_version; SoupURI *uri; + SoupAddress *addr; SoupAuth *auth, *proxy_auth; } SoupMessagePrivate; diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index b616b77..1a7abb8 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -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); } diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 1061581..3a4f344 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -8,6 +8,7 @@ #define SOUP_MESSAGE_QUEUE_H 1 #include +#include #include #include @@ -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; }; diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index c5890ce..2aa0473 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -8,6 +8,7 @@ #include #include +#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 diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 7a9d940..1b850be 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -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 diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index d3f229b..34c0a43 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -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); diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 9ecac2a..3be2054 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -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) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 417591c..2b9e5eb 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -13,6 +13,7 @@ #include #include +#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 @@ 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); } diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 4ecf931..668a753 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -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) { diff --git a/tests/proxy-test.c b/tests/proxy-test.c index e4e9581..e512e86 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -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]); -- 2.7.4