From 5299595334a0a1081b6278d61cac958c17fe7fe6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 29 Sep 2011 10:05:59 -0400 Subject: [PATCH] redirect-test: add a test for accidental connection sharing https://bugzilla.gnome.org/show_bug.cgi?id=651146 --- tests/redirect-test.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 129 insertions(+), 11 deletions(-) diff --git a/tests/redirect-test.c b/tests/redirect-test.c index f99d9c7..c953f03 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -226,12 +226,125 @@ do_redirect_tests (SoupURI *base_uri) soup_test_session_abort_unref (session); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - debug_printf (1, "Sync session\n"); + debug_printf (1, "\nSync session\n"); for (n = 0; n < n_tests; n++) do_test (session, base_uri, n); soup_test_session_abort_unref (session); } +typedef struct { + SoupSession *session; + SoupMessage *msg1, *msg2; + SoupURI *uri1, *uri2; + SoupSocket *sock1, *sock2; +} ConnectionTestData; + +static void +msg2_finished (SoupSession *session, SoupMessage *msg2, gpointer user_data) +{ + if (!SOUP_STATUS_IS_SUCCESSFUL (msg2->status_code)) { + debug_printf (1, " msg2 failed: %d %s\n", + msg2->status_code, msg2->reason_phrase); + errors++; + } +} + +static void +unpause_msg1 (SoupMessage *msg2, gpointer user_data) +{ + ConnectionTestData *data = user_data; + + if (!data->sock1) { + debug_printf (1, " msg1 has no connection?\n"); + errors++; + } else if (!data->sock2) { + debug_printf (1, " msg2 has no connection?\n"); + errors++; + } else if (data->sock1 == data->sock2) { + debug_printf (1, " Both messages sharing the same connection\n"); + errors++; + } + + soup_session_unpause_message (data->session, data->msg1); +} + +static gboolean +msg1_just_restarted (gpointer user_data) +{ + ConnectionTestData *data = user_data; + + soup_session_pause_message (data->session, data->msg1); + + data->msg2 = soup_message_new_from_uri ("GET", data->uri2); + + g_signal_connect (data->msg2, "got_body", + G_CALLBACK (unpause_msg1), data); + + soup_session_queue_message (data->session, data->msg2, msg2_finished, data); + return FALSE; +} + +static void +msg1_about_to_restart (SoupMessage *msg1, gpointer user_data) +{ + ConnectionTestData *data = user_data; + + /* Do nothing when loading the redirected-to resource */ + if (!SOUP_STATUS_IS_REDIRECTION (data->msg1->status_code)) + return; + + /* We have to pause msg1 after the I/O finishes, but before + * the queue runs again. + */ + g_idle_add_full (G_PRIORITY_HIGH, msg1_just_restarted, data, NULL); +} + +static void +request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + ConnectionTestData *data = user_data; + + if (msg == data->msg1) + data->sock1 = socket; + else if (msg == data->msg2) + data->sock2 = socket; + else + g_warn_if_reached (); +} + +static void +do_connection_test (SoupURI *base_uri) +{ + ConnectionTestData data; + + debug_printf (1, "\nConnection reuse\n"); + memset (&data, 0, sizeof (data)); + + data.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (data.session, "request-started", + G_CALLBACK (request_started), &data); + + data.uri1 = soup_uri_new_with_base (base_uri, "/301"); + data.uri2 = soup_uri_new_with_base (base_uri, "/"); + data.msg1 = soup_message_new_from_uri ("GET", data.uri1); + + g_signal_connect (data.msg1, "got-body", + G_CALLBACK (msg1_about_to_restart), &data); + soup_session_send_message (data.session, data.msg1); + + if (!SOUP_STATUS_IS_SUCCESSFUL (data.msg1->status_code)) { + debug_printf (1, " msg1 failed: %d %s\n", + data.msg1->status_code, data.msg1->reason_phrase); + errors++; + } + g_object_unref (data.msg1); + soup_uri_free (data.uri1); + soup_uri_free (data.uri2); + + soup_test_session_abort_unref (data.session); +} + static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, @@ -240,6 +353,14 @@ server_callback (SoupServer *server, SoupMessage *msg, char *remainder; guint status_code; + /* Make sure that a HTTP/1.0 redirect doesn't cause an + * HTTP/1.0 re-request. (#521848) + */ + if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + if (g_str_has_prefix (path, "/bad")) { if (!strcmp (path, "/bad")) { soup_message_set_status (msg, SOUP_STATUS_FOUND); @@ -280,14 +401,6 @@ server_callback (SoupServer *server, SoupMessage *msg, return; } - /* Make sure that a HTTP/1.0 redirect doesn't cause an - * HTTP/1.0 re-request. (#521848) - */ - if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) { - soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); - return; - } - soup_message_set_status (msg, SOUP_STATUS_OK); /* FIXME: this is wrong, though it doesn't matter for @@ -310,8 +423,12 @@ server_callback (SoupServer *server, SoupMessage *msg, return; } - /* See above comment re bug 521848. */ - soup_message_set_http_version (msg, SOUP_HTTP_1_0); + /* See above comment re bug 521848. We only test this on the + * double-redirects so that we get connection-reuse testing + * the rest of the time. + */ + if (*remainder == '/') + soup_message_set_http_version (msg, SOUP_HTTP_1_0); soup_message_set_status (msg, status_code); if (*remainder) { @@ -367,6 +484,7 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1"); soup_uri_set_port (base_uri, port); do_redirect_tests (base_uri); + do_connection_test (base_uri); soup_uri_free (base_uri); } else { printf ("Listening on port %d\n", port); -- 2.7.4