[libsoup] redirect-test: add a test for accidental connection sharing



commit 5299595334a0a1081b6278d61cac958c17fe7fe6
Author: Dan Winship <danw gnome org>
Date:   Thu Sep 29 10:05:59 2011 -0400

    redirect-test: add a test for accidental connection sharing
    
    https://bugzilla.gnome.org/show_bug.cgi?id=651146

 tests/redirect-test.c |  140 +++++++++++++++++++++++++++++++++++++++++++++----
 1 files 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]