GSource *keep_alive_src;
SoupSession *session;
} SoupSessionHost;
+static guint soup_host_uri_hash (gconstpointer key);
+gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2);
typedef struct {
GTlsDatabase *tlsdb;
GSList *features;
GHashTable *features_cache;
- GHashTable *hosts; /* char* -> SoupSessionHost */
+ GHashTable *http_hosts, *https_hosts; /* char* -> SoupSessionHost */
GHashTable *conns; /* SoupConnection -> SoupSessionHost */
guint num_conns;
guint max_conns, max_conns_per_host;
priv->queue = soup_message_queue_new (session);
g_mutex_init (&priv->host_lock);
- priv->hosts = g_hash_table_new_full (soup_uri_host_hash,
- soup_uri_host_equal,
- NULL, (GDestroyNotify)free_host);
+ priv->http_hosts = g_hash_table_new_full (soup_host_uri_hash,
+ soup_host_uri_equal,
+ NULL, (GDestroyNotify)free_host);
+ priv->https_hosts = g_hash_table_new_full (soup_host_uri_hash,
+ soup_host_uri_equal,
+ NULL, (GDestroyNotify)free_host);
priv->conns = g_hash_table_new (NULL, NULL);
priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT;
soup_message_queue_destroy (priv->queue);
g_mutex_clear (&priv->host_lock);
- g_hash_table_destroy (priv->hosts);
+ g_hash_table_destroy (priv->http_hosts);
+ g_hash_table_destroy (priv->https_hosts);
g_hash_table_destroy (priv->conns);
g_free (priv->user_agent);
static void
set_aliases (char ***variable, char **value)
{
- int len = g_strv_length (value), i;
+ int len, i;
if (*variable)
g_free (*variable);
- *variable = g_new (char *, len);
+ if (!value) {
+ *variable = NULL;
+ return;
+ }
+
+ len = g_strv_length (value);
+ *variable = g_new (char *, len + 1);
for (i = 0; i < len; i++)
(*variable)[i] = (char *)g_intern_string (value[i]);
(*variable)[i] = NULL;
/* Hosts */
+static guint
+soup_host_uri_hash (gconstpointer key)
+{
+ const SoupURI *uri = key;
+
+ g_return_val_if_fail (uri != NULL && uri->host != NULL, 0);
+
+ return uri->port + soup_str_case_hash (uri->host);
+}
+
+gboolean
+soup_host_uri_equal (gconstpointer v1, gconstpointer v2)
+{
+ const SoupURI *one = v1;
+ const SoupURI *two = v2;
+
+ g_return_val_if_fail (one != NULL && two != NULL, one == two);
+ g_return_val_if_fail (one->host != NULL && two->host != NULL, one->host == two->host);
+
+ if (one->port != two->port)
+ return FALSE;
+
+ return g_ascii_strcasecmp (one->host, two->host) == 0;
+}
+
+
static SoupSessionHost *
soup_session_host_new (SoupSession *session, SoupURI *uri)
{
host = g_slice_new0 (SoupSessionHost);
host->uri = soup_uri_copy_host (uri);
+ if (host->uri->scheme != SOUP_URI_SCHEME_HTTP &&
+ host->uri->scheme != SOUP_URI_SCHEME_HTTPS) {
+ SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+
+ if (uri_is_https (priv, host->uri))
+ host->uri->scheme = SOUP_URI_SCHEME_HTTPS;
+ else
+ host->uri->scheme = SOUP_URI_SCHEME_HTTP;
+ }
+
host->addr = soup_address_new (host->uri->host, host->uri->port);
host->keep_alive_src = NULL;
host->session = session;
SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
SoupSessionHost *host;
- host = g_hash_table_lookup (priv->hosts, uri);
+ if (uri_is_https (priv, uri))
+ host = g_hash_table_lookup (priv->https_hosts, uri);
+ else
+ host = g_hash_table_lookup (priv->http_hosts, uri);
if (host)
return host;
host = soup_session_host_new (session, uri);
- g_hash_table_insert (priv->hosts, host->uri, host);
+
+ if (uri_is_https (priv, uri))
+ g_hash_table_insert (priv->https_hosts, host->uri, host);
+ else
+ g_hash_table_insert (priv->http_hosts, host->uri, host);
return host;
}
/* This will free the host in addition to removing it from the
* hash table
*/
- g_hash_table_remove (priv->hosts, host->uri);
+ if (host->uri->scheme == SOUP_URI_SCHEME_HTTPS)
+ g_hash_table_remove (priv->https_hosts, host->uri);
+ else
+ g_hash_table_remove (priv->http_hosts, host->uri);
g_mutex_unlock (&priv->host_lock);
return FALSE;
#include "test-utils.h"
-SoupServer *server;
-SoupURI *base_uri;
+SoupServer *server, *ssl_server;
+SoupURI *base_uri, *ssl_base_uri;
GMutex server_mutex;
static gboolean
SoupClientContext *context, gpointer data)
{
SoupURI *uri = soup_message_get_uri (msg);
+ const char *server_protocol = data;
/* The way this gets used in the tests, we don't actually
* need to hold it through the whole function, so it's simpler
return;
}
+ if (!strcmp (path, "/alias-redirect")) {
+ SoupURI *redirect_uri;
+ char *redirect_string;
+ const char *redirect_protocol;
+
+ redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol");
+
+ redirect_uri = soup_uri_copy (uri);
+ soup_uri_set_scheme (redirect_uri, "foo");
+ if (!g_strcmp0 (redirect_protocol, "https"))
+ soup_uri_set_port (redirect_uri, ssl_base_uri->port);
+ else
+ soup_uri_set_port (redirect_uri, base_uri->port);
+ soup_uri_set_path (redirect_uri, "/alias-redirected");
+ redirect_string = soup_uri_to_string (redirect_uri, FALSE);
+
+ soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string);
+ g_free (redirect_string);
+ soup_uri_free (redirect_uri);
+ return;
+ } else if (!strcmp (path, "/alias-redirected")) {
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_headers_append (msg->response_headers,
+ "X-Redirected-Protocol",
+ server_protocol);
+ return;
+ }
+
if (g_str_has_prefix (path, "/content-length/")) {
gboolean too_long = strcmp (path, "/content-length/long") == 0;
gboolean no_close = strcmp (path, "/content-length/noclose") == 0;
soup_test_session_abort_unref (session);
}
+static void
+do_aliases_test_for_session (SoupSession *session,
+ const char *redirect_protocol)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+ const char *redirected_protocol;
+
+ uri = soup_uri_new_with_base (base_uri, "/alias-redirect");
+ msg = soup_message_new_from_uri ("GET", uri);
+ if (redirect_protocol)
+ soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol);
+ soup_uri_free (uri);
+ soup_session_send_message (session, msg);
+
+ redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol");
+
+ if (g_strcmp0 (redirect_protocol, redirected_protocol)) {
+ debug_printf (1, " redirect went to %s, should have gone to %s!\n",
+ redirected_protocol ? redirected_protocol : "(none)",
+ redirect_protocol ? redirect_protocol : "(none)");
+ errors++;
+ } else if (redirect_protocol && !SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ debug_printf (1, " msg failed? (%d %s)\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ } else if (!redirect_protocol && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ debug_printf (1, " msg succeeded? (%d %s)\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ }
+
+ g_object_unref (msg);
+}
+
+static void
+do_aliases_test (void)
+{
+ SoupSession *session;
+ char *aliases[] = { "foo", NULL };
+
+ debug_printf (1, "\nhttp-aliases / https-aliases\n");
+
+ debug_printf (1, " Default behavior\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_aliases_test_for_session (session, "http");
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " foo-means-https\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTPS_ALIASES, aliases,
+ NULL);
+ do_aliases_test_for_session (session, "https");
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " foo-means-nothing\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTP_ALIASES, NULL,
+ NULL);
+ do_aliases_test_for_session (session, NULL);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
test_init (argc, argv, NULL);
server = soup_test_server_new (TRUE);
- soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ soup_server_add_handler (server, NULL, server_callback, "http", NULL);
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
soup_server_add_auth_domain (server, auth_domain);
g_object_unref (auth_domain);
+ ssl_server = soup_test_server_new_ssl (TRUE);
+ soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL);
+ ssl_base_uri = soup_uri_new ("https://127.0.0.1/");
+ soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server));
+
do_host_test ();
do_callback_unref_test ();
do_msg_reuse_test ();
do_persistent_connection_timeout_test ();
do_max_conns_test ();
do_cancel_while_reading_test ();
+ do_aliases_test ();
soup_uri_free (base_uri);
+ soup_uri_free (ssl_base_uri);
soup_test_server_quit_unref (server);
+ soup_test_server_quit_unref (ssl_server);
test_cleanup ();
return errors != 0;