summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2021-04-23 11:57:43 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2021-04-23 11:57:43 +0200
commit33cffbe5aa3952e86a4fc0eab436c46ea8e62f4b (patch)
tree1afb9e4a871e1acdd989bcb8462b559d424d0b4e
parent0a6b2555b7ca74d7b879fa5ff06daf1bd22a56f6 (diff)
downloadlibsoup-carlosgc/preconnect-stolen.tar.gz
preconnect: preconnect should never steal a connectioncarlosgc/preconnect-stolen
-rw-r--r--libsoup/soup-session.c3
-rw-r--r--tests/connection-test.c116
2 files changed, 119 insertions, 0 deletions
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 393f01f1..64adb1de 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1780,6 +1780,9 @@ steal_preconnection (SoupSession *session,
if (!item->async)
return FALSE;
+ if (item->connect_only)
+ return FALSE;
+
preconnect_item = soup_session_lookup_queue_item_by_connection (session, conn);
if (!preconnect_item)
return FALSE;
diff --git a/tests/connection-test.c b/tests/connection-test.c
index ec40bc5b..4bb13027 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -1401,6 +1401,119 @@ do_steal_connection_preconnect_fail_test (const char *uri,
soup_test_session_abort_unref (session);
}
+typedef struct {
+ GMainLoop *loop;
+ guint count;
+} StealPreconnectTestData;
+
+static void
+steal_preconnect_finished (SoupSession *session,
+ GAsyncResult *result,
+ StealPreconnectTestData *data)
+{
+ soup_session_preconnect_finish (session, result, NULL);
+ if (++data->count == 2)
+ g_main_loop_quit (data->loop);
+}
+
+static void
+steal_preconnect_send_and_read_finished (SoupSession *session,
+ GAsyncResult *result,
+ StealPreconnectTestData *data)
+{
+ GBytes *bytes;
+
+ bytes = soup_session_send_and_read_finish (session, result, NULL);
+ g_bytes_unref (bytes);
+ if (++data->count == 2)
+ g_main_loop_quit (data->loop);
+}
+
+static void
+do_steal_preconnect_connection_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ StealPreconnectTestData data = { NULL, 0 };
+ PreconnectTestData data1 = { NULL, NULL, "rRcCx", SOUP_CONNECTION_DISCONNECTED, NULL, FALSE };
+ PreconnectTestData data2 = { NULL, NULL, "rRcCx", SOUP_CONNECTION_DISCONNECTED, NULL, FALSE };
+
+ session = soup_test_session_new (NULL);
+
+ /* Preconnect requests should never steal the connection of another preconnect. */
+
+ data.loop = g_main_loop_new (NULL, FALSE);
+ msg = soup_message_new ("HEAD", HTTP_SERVER);
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (preconnection_test_message_network_event),
+ &data1);
+ soup_session_preconnect_async (session, msg, G_PRIORITY_DEFAULT, NULL,
+ (GAsyncReadyCallback)steal_preconnect_finished,
+ &data);
+ g_object_unref (msg);
+
+ msg = soup_message_new ("HEAD", HTTP_SERVER);
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (preconnection_test_message_network_event),
+ &data2);
+ soup_session_preconnect_async (session, msg, G_PRIORITY_DEFAULT, NULL,
+ (GAsyncReadyCallback)steal_preconnect_finished,
+ &data);
+ g_object_unref (msg);
+
+ g_main_loop_run (data.loop);
+ g_assert_nonnull (data1.conn);
+ g_assert_nonnull (data2.conn);
+ g_assert_false (data1.conn == data2.conn);
+ g_assert_cmpint (data1.state, ==, SOUP_CONNECTION_IDLE);
+ g_assert_cmpint (data2.state, ==, SOUP_CONNECTION_IDLE);
+
+ while (*data1.events) {
+ soup_test_assert (!*data1.events,
+ "Expected %s",
+ event_name_from_abbrev (*data1.events));
+ soup_test_assert (!*data2.events,
+ "Expected %s",
+ event_name_from_abbrev (*data2.events));
+ data1.events++;
+ data2.events++;
+ }
+
+ data.count = 0;
+ g_clear_object (&data1.conn);
+ g_clear_object (&data2.conn);
+
+ msg = soup_message_new ("GET", HTTP_SERVER);
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (preconnection_test_message_network_event),
+ &data1);
+ soup_session_send_and_read_async (session, msg, G_PRIORITY_DEFAULT, NULL,
+ (GAsyncReadyCallback)steal_preconnect_send_and_read_finished,
+ &data);
+ g_object_unref (msg);
+
+ msg = soup_message_new ("GET", HTTP_SERVER);
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (preconnection_test_message_network_event),
+ &data2);
+ soup_session_send_and_read_async (session, msg, G_PRIORITY_DEFAULT, NULL,
+ (GAsyncReadyCallback)steal_preconnect_send_and_read_finished,
+ &data);
+ g_object_unref (msg);
+
+ g_main_loop_run (data.loop);
+
+ /* connection-created hasn't been called. */
+ g_assert_null (data1.conn);
+ g_assert_null (data2.conn);
+ g_assert_cmpint (data1.state, ==, SOUP_CONNECTION_IDLE);
+ g_assert_cmpint (data2.state, ==, SOUP_CONNECTION_IDLE);
+
+ g_main_loop_unref (data.loop);
+
+ soup_test_session_abort_unref (session);
+}
+
static void
do_connection_preconnect_test (void)
{
@@ -1440,6 +1553,9 @@ do_connection_preconnect_test (void)
"r");
} else
debug_printf (1, " https -- SKIPPING\n");
+
+ debug_printf (1, " preconnect should never steal a connection\n");
+ do_steal_preconnect_connection_test ();
}
static void