[libsoup] io-http2: ensure we always finish the stream



commit c8d96bb31481e8027146e823a25bd629b8521f12
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Thu May 20 14:28:59 2021 +0200

    io-http2: ensure we always finish the stream
    
    In case of cancellation, we destroy the io data for the message but the
    session keeps processing the stream.

 libsoup/http2/soup-client-message-io-http2.c |  5 ++--
 tests/http2-test.c                           | 42 ++++++++++++++++++++++------
 2 files changed, 36 insertions(+), 11 deletions(-)
---
diff --git a/libsoup/http2/soup-client-message-io-http2.c b/libsoup/http2/soup-client-message-io-http2.c
index 8979592d..1fec42ab 100644
--- a/libsoup/http2/soup-client-message-io-http2.c
+++ b/libsoup/http2/soup-client-message-io-http2.c
@@ -918,9 +918,6 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
 
         h2_debug (io, data, "Finished: %s", completion == SOUP_MESSAGE_IO_COMPLETE ? "completed" : 
"interrupted");
 
-        // int ret;
-        // ret = nghttp2_submit_rst_stream (io->session, NGHTTP2_FLAG_NONE, data->stream_id, 
NGHTTP2_STREAM_CLOSED);
-        // g_assert (ret == 0);
         // ret = nghttp2_session_terminate_session (io->session, NGHTTP2_NO_ERROR);
         // g_assert (ret == 0);
 
@@ -929,6 +926,8 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
 
        g_object_ref (msg);
 
+        NGCHECK (nghttp2_submit_rst_stream (io->session, NGHTTP2_FLAG_NONE, data->stream_id,
+                                            completion == SOUP_MESSAGE_IO_COMPLETE ? NGHTTP2_NO_ERROR : 
NGHTTP2_CANCEL));
         nghttp2_session_set_stream_user_data (io->session, data->stream_id, NULL);
         if (!g_hash_table_remove (io->messages, msg))
                 g_warn_if_reached ();
diff --git a/tests/http2-test.c b/tests/http2-test.c
index c12f86a0..26d2b5c9 100644
--- a/tests/http2-test.c
+++ b/tests/http2-test.c
@@ -173,28 +173,44 @@ do_multi_message_async_test (Test *test, gconstpointer data)
 
 
 static void
-on_send_and_read_complete (GObject *source, GAsyncResult *res, gpointer user_data)
+on_send_and_read_cancelled_complete (SoupSession  *session,
+                                     GAsyncResult *result,
+                                     gboolean     *done)
 {
-        SoupSession *sess = SOUP_SESSION (source);
-        gboolean *done = user_data;
         GError *error = NULL;
-        GBytes *response = soup_session_send_and_read_finish (sess, res, &error);
+        GBytes *response = soup_session_send_and_read_finish (session, result, &error);
 
         g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
         g_assert_null (response);
+        g_error_free (error);
+        *done = TRUE;
+}
+
+static void
+on_send_and_read_complete (SoupSession  *session,
+                           GAsyncResult *result,
+                           gboolean     *done)
+{
+        GError *error = NULL;
+        GBytes *response = soup_session_send_and_read_finish (session, result, &error);
+
+        g_assert_no_error (error);
+        g_assert_nonnull (response);
+        g_bytes_unref (response);
         *done = TRUE;
 }
 
 static void
 do_cancellation_test (Test *test, gconstpointer data)
 {
-        test->msg = soup_message_new (SOUP_METHOD_GET, "https://127.0.0.1:5000/large";);
+        SoupMessage *msg;
         GMainContext *async_context = g_main_context_ref_thread_default ();
         GCancellable *cancellable = g_cancellable_new ();
         gboolean done = FALSE;
 
-        soup_session_send_and_read_async (test->session, test->msg, G_PRIORITY_DEFAULT, cancellable,
-                                          on_send_and_read_complete, &done);
+        msg = soup_message_new (SOUP_METHOD_GET, "https://127.0.0.1:5000/large";);
+        soup_session_send_and_read_async (test->session, msg, G_PRIORITY_DEFAULT, cancellable,
+                                          (GAsyncReadyCallback)on_send_and_read_cancelled_complete, &done);
 
         /* Just iterate until a partial read is happening */
         for (guint i = 100000; i; i--)
@@ -206,7 +222,17 @@ do_cancellation_test (Test *test, gconstpointer data)
         while (!done)
                 g_main_context_iteration (async_context, FALSE);
 
-        g_object_unref (test->msg);
+        g_object_unref (msg);
+
+        done = FALSE;
+        msg = soup_message_new (SOUP_METHOD_GET, "https://127.0.0.1:5000/large";);
+        soup_session_send_and_read_async (test->session, msg, G_PRIORITY_DEFAULT, NULL,
+                                          (GAsyncReadyCallback)on_send_and_read_complete, &done);
+
+        while (!done)
+                g_main_context_iteration (async_context, FALSE);
+
+        g_object_unref (msg);
         g_object_unref (cancellable);
         g_main_context_unref (async_context);
 }


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