Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libsoup for openSUSE:Factory checked in at 2022-11-08 10:53:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libsoup (Old) and /work/SRC/openSUSE:Factory/.libsoup.new.1597 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libsoup" Tue Nov 8 10:53:19 2022 rev:139 rq:1034156 version:3.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/libsoup/libsoup.changes 2022-10-18 12:44:41.973682710 +0200 +++ /work/SRC/openSUSE:Factory/.libsoup.new.1597/libsoup.changes 2022-11-08 10:53:24.429404784 +0100 @@ -1,0 +2,10 @@ +Thu Nov 3 11:06:38 UTC 2022 - Bj??rn Lie <bjorn....@gmail.com> + +- Update to version 3.2.2: + + Various HTTP/2 Fixes: + - Fix `content-sniffed` not being emitted for resources without + content. + - Fix leak of SoupServerConnection when stolen. +- Enable tests on 32-bit again, fixed upstream. + +------------------------------------------------------------------- Old: ---- libsoup-3.2.1.tar.xz New: ---- libsoup-3.2.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libsoup.spec ++++++ --- /var/tmp/diff_new_pack.gvLcpk/_old 2022-11-08 10:53:24.953407903 +0100 +++ /var/tmp/diff_new_pack.gvLcpk/_new 2022-11-08 10:53:24.961407950 +0100 @@ -18,7 +18,7 @@ %define api_version 3.0 Name: libsoup -Version: 3.2.1 +Version: 3.2.2 Release: 0 Summary: HTTP client/server library for GNOME License: LGPL-2.1-or-later @@ -138,13 +138,9 @@ mv %{buildroot}%{_datadir}/doc/%{name}-%{api_version} %{buildroot}%{_docdir} %check -# Disable tests on 32-bit while waiting for -# https://gitlab.gnome.org/GNOME/libsoup/-/issues/309 -%ifnarch %ix86 %arm32 ppc # Run the regression tests using GnuTLS NORMAL priority export G_TLS_GNUTLS_PRIORITY=NORMAL %meson_test -%endif %ldconfig_scriptlets 3_0-0 ++++++ libsoup-3.2.1.tar.xz -> libsoup-3.2.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/NEWS new/libsoup-3.2.2/NEWS --- old/libsoup-3.2.1/NEWS 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/NEWS 2022-11-02 20:46:22.000000000 +0100 @@ -1,3 +1,9 @@ +Changes in libsoup from 3.2.1 to 3.2.2: + +* Various HTTP/2 Fixes: [Carlos Garcia Campos] + * Fix `content-sniffed` not being emitted for resources without content + * Fix leak of SoupServerConnection when stolen + Changes in libsoup from 3.2.0 to 3.2.1: * When built against nghttp2 1.50.0+ be relaxed about header whitespace [Carlos Garcia Campos] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/libsoup/http2/soup-client-message-io-http2.c new/libsoup-3.2.2/libsoup/http2/soup-client-message-io-http2.c --- old/libsoup-3.2.1/libsoup/http2/soup-client-message-io-http2.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/libsoup/http2/soup-client-message-io-http2.c 2022-11-02 20:46:22.000000000 +0100 @@ -77,6 +77,7 @@ GTask *close_task; gboolean session_terminated; gboolean goaway_sent; + gboolean ever_used; guint in_callback; } SoupClientMessageIOHTTP2; @@ -234,6 +235,7 @@ return TRUE; return data->state < STATE_READ_DATA_START && + data->io->ever_used && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && @@ -724,12 +726,15 @@ g_assert_not_reached (); } + soup_message_got_headers (data->msg); + if (soup_message_get_status (data->msg) == SOUP_STATUS_NO_CONTENT || frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { h2_debug (io, data, "Stream done"); - advance_state_from (data, STATE_READ_HEADERS, STATE_READ_DATA); + advance_state_from (data, STATE_READ_HEADERS, STATE_READ_DATA_START); + if (soup_message_has_content_sniffer (data->msg)) + soup_message_content_sniffed (data->msg, "text/plain", NULL); + advance_state_from (data, STATE_READ_DATA_START, STATE_READ_DATA); } - soup_message_got_headers (data->msg); - break; } case NGHTTP2_DATA: @@ -1072,7 +1077,16 @@ nghttp2_data_source *source, void *user_data) { + SoupClientMessageIOHTTP2 *io = user_data; SoupHTTP2MessageData *data = nghttp2_session_get_stream_user_data (session, stream_id); + + h2_debug (io, data, "[SEND_BODY] stream_id=%u, paused=%d", stream_id, data ? data->paused : 0); + + if (!data) { + /* This can happen in case of cancellation */ + return 0; + } + data->io->in_callback++; if (!data->item->async) { @@ -1414,6 +1428,7 @@ gpointer completion_data; SoupMessageIOCompletion completion; gboolean is_closed; + SoupConnection *conn; data = get_data_for_message (io, msg); @@ -1429,9 +1444,9 @@ is_closed = nghttp2_session_get_stream_user_data (io->session, data->stream_id) == NULL; nghttp2_session_set_stream_user_data (io->session, data->stream_id, NULL); - if (!io->is_shutdown && !is_closed) { - SoupConnection *conn; + conn = g_weak_ref_get (&io->conn); + if (!io->is_shutdown && !is_closed) { NGCHECK (nghttp2_submit_rst_stream (io->session, NGHTTP2_FLAG_NONE, data->stream_id, completion == SOUP_MESSAGE_IO_COMPLETE ? NGHTTP2_NO_ERROR : NGHTTP2_CANCEL)); soup_http2_message_data_close (data); @@ -1441,11 +1456,8 @@ if (!g_hash_table_add (io->closed_messages, data)) g_warn_if_reached (); - conn = g_weak_ref_get (&io->conn); - if (conn) { + if (conn) soup_connection_set_in_use (conn, TRUE); - g_object_unref (conn); - } io_try_write (io, !io->async); } else { @@ -1460,6 +1472,8 @@ if (io->is_shutdown) soup_client_message_io_http2_terminate_session (io); + + g_clear_object (&conn); } static void @@ -1563,6 +1577,7 @@ h2_debug (io, data, "Client stream EOF"); soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_END); advance_state_from (data, STATE_READ_DATA, STATE_READ_DONE); + io->ever_used = TRUE; g_signal_handlers_disconnect_by_func (stream, client_stream_eof, msg); soup_message_got_body (data->msg); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/libsoup/server/http1/soup-server-message-io-http1.c new/libsoup-3.2.2/libsoup/server/http1/soup-server-message-io-http1.c --- old/libsoup-3.2.1/libsoup/server/http1/soup-server-message-io-http1.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/libsoup/server/http1/soup-server-message-io-http1.c 2022-11-02 20:46:22.000000000 +0100 @@ -925,6 +925,14 @@ SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, &error); + + if (soup_server_message_get_io_data (msg) != (SoupServerMessageIO *)server_io) { + g_object_unref (msg); + g_clear_error (&error); + + return; + } + server_io->in_io_run = FALSE; if (success) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/libsoup/server/soup-server-connection.c new/libsoup-3.2.2/libsoup/server/soup-server-connection.c --- old/libsoup-3.2.1/libsoup/server/soup-server-connection.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/libsoup/server/soup-server-connection.c 2022-11-02 20:46:22.000000000 +0100 @@ -108,10 +108,12 @@ SoupServerConnection *conn = SOUP_SERVER_CONNECTION (object); SoupServerConnectionPrivate *priv = soup_server_connection_get_instance_private (conn); - if (priv->conn) + if (priv->conn) { disconnect_internal (conn); - - g_clear_pointer (&priv->io_data, soup_server_message_io_destroy); + } else { + g_clear_object (&priv->socket); + g_clear_pointer (&priv->io_data, soup_server_message_io_destroy); + } g_clear_object (&priv->iostream); @@ -549,9 +551,10 @@ priv = soup_server_connection_get_instance_private (conn); stream = priv->io_data ? soup_server_message_io_steal (priv->io_data) : NULL; - if (stream) { + if (stream && priv->socket) { g_object_set_data_full (G_OBJECT (stream), "GSocket", - priv->socket, g_object_unref); + g_object_ref (priv->socket), + g_object_unref); } /* Cache local and remote address */ @@ -562,6 +565,8 @@ g_clear_object (&priv->conn); g_clear_object (&priv->iostream); + g_signal_emit (conn, signals[DISCONNECTED], 0); + return stream; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/libsoup/server/soup-server-message.c new/libsoup-3.2.2/libsoup/server/soup-server-message.c --- old/libsoup-3.2.1/libsoup/server/soup-server-message.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/libsoup/server/soup-server-message.c 2022-11-02 20:46:22.000000000 +0100 @@ -1105,7 +1105,6 @@ g_object_ref (msg); stream = soup_server_connection_steal (msg->conn); g_signal_handlers_disconnect_by_data (msg, msg->conn); - connection_disconnected (msg); g_object_unref (msg); return stream; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/libsoup/soup-session.c new/libsoup-3.2.2/libsoup/soup-session.c --- old/libsoup-3.2.1/libsoup/soup-session.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/libsoup/soup-session.c 2022-11-02 20:46:22.000000000 +0100 @@ -69,8 +69,6 @@ **/ typedef struct { - gboolean disposed; - GTlsDatabase *tlsdb; GTlsInteraction *tls_interaction; gboolean tlsdb_use_default; @@ -88,6 +86,7 @@ GQueue *queue; GMutex queue_sources_mutex; GHashTable *queue_sources; + gint num_async_items; guint in_async_run_queue; gboolean needs_queue_sort; @@ -169,7 +168,7 @@ typedef struct { GSource source; - SoupSession* session; + GWeakRef session; guint num_items; } SoupMessageQueueSource; @@ -178,18 +177,33 @@ GSourceFunc callback, gpointer user_data) { - SoupSession *session = ((SoupMessageQueueSource *)source)->session; + SoupMessageQueueSource *queue_source = (SoupMessageQueueSource *)source; + SoupSession *session = g_weak_ref_get (&queue_source->session); + + if (!session) + return G_SOURCE_REMOVE; g_source_set_ready_time (source, -1); async_run_queue (session); + g_object_unref (session); + return G_SOURCE_CONTINUE; } +static void +queue_finalize (GSource *source) +{ + SoupMessageQueueSource *queue_source = (SoupMessageQueueSource *)source; + + g_weak_ref_clear (&queue_source->session); +} + static GSourceFuncs queue_source_funcs = { NULL, //queue_prepare, NULL, //queue_check, queue_dispatch, - NULL, NULL, NULL + queue_finalize, + NULL, NULL }; static void @@ -199,13 +213,16 @@ SoupSessionPrivate *priv = soup_session_get_instance_private (session); SoupMessageQueueSource *queue_source; + if (!priv->queue_sources) + priv->queue_sources = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_source_unref); + queue_source = g_hash_table_lookup (priv->queue_sources, context); if (!queue_source) { GSource *source; source = g_source_new (&queue_source_funcs, sizeof (SoupMessageQueueSource)); queue_source = (SoupMessageQueueSource *)source; - queue_source->session = session; + g_weak_ref_init (&queue_source->session, session); queue_source->num_items = 0; g_source_set_name (source, "SoupMessageQueue"); g_source_set_can_recurse (source, TRUE); @@ -214,7 +231,6 @@ } queue_source->num_items++; - } static void @@ -223,7 +239,7 @@ { SoupSessionPrivate *priv = soup_session_get_instance_private (session); - if (item->context == priv->context) + if (!item->async) return; g_mutex_lock (&priv->queue_sources_mutex); @@ -255,6 +271,9 @@ { SoupSessionPrivate *priv = soup_session_get_instance_private (session); + if (!item->async) + return; + if (item->context == priv->context) return; @@ -273,8 +292,6 @@ g_mutex_init (&priv->queue_mutex); priv->queue = g_queue_new (); g_mutex_init (&priv->queue_sources_mutex); - priv->queue_sources = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_source_unref); - soup_session_add_queue_source (session, priv->context); priv->io_timeout = priv->idle_timeout = 60; @@ -313,14 +330,14 @@ SoupSession *session = SOUP_SESSION (object); SoupSessionPrivate *priv = soup_session_get_instance_private (session); - priv->disposed = TRUE; soup_session_abort (session); g_warn_if_fail (soup_connection_manager_get_num_conns (priv->conn_manager) == 0); while (priv->features) soup_session_remove_feature (session, priv->features->data); - g_hash_table_foreach (priv->queue_sources, (GHFunc)destroy_queue_source, NULL); + if (priv->queue_sources) + g_hash_table_foreach (priv->queue_sources, (GHFunc)destroy_queue_source, NULL); G_OBJECT_CLASS (soup_session_parent_class)->dispose (object); } @@ -334,7 +351,7 @@ g_warn_if_fail (g_queue_is_empty (priv->queue)); g_queue_free (priv->queue); g_mutex_clear (&priv->queue_mutex); - g_hash_table_destroy (priv->queue_sources); + g_clear_pointer (&priv->queue_sources, g_hash_table_destroy); g_mutex_clear (&priv->queue_sources_mutex); g_main_context_unref (priv->context); @@ -1322,6 +1339,9 @@ soup_session_add_queue_source_for_item (session, item); + if (async) + g_atomic_int_inc (&priv->num_async_items); + if (!soup_message_query_flags (msg, SOUP_MESSAGE_NO_REDIRECT)) { soup_message_add_header_handler ( msg, "got_body", "Location", @@ -1410,6 +1430,9 @@ soup_session_remove_queue_source_for_item (session, item); + if (item->async) + g_atomic_int_dec_and_test (&priv->num_async_items); + /* g_signal_handlers_disconnect_by_func doesn't work if you * have a metamarshal, meaning it doesn't work with * soup_message_add_header_handler() @@ -1817,7 +1840,6 @@ GList *items = NULL; GList *i; - g_object_ref (session); g_atomic_int_inc (&priv->in_async_run_queue); soup_connection_manager_cleanup (priv->conn_manager, FALSE); @@ -1840,8 +1862,6 @@ g_mutex_unlock (&priv->queue_mutex); g_atomic_int_set (&priv->needs_queue_sort, FALSE); } - - g_object_unref (session); } /** @@ -1898,8 +1918,12 @@ { SoupSessionPrivate *priv = soup_session_get_instance_private (session); + if (g_atomic_int_get (&priv->num_async_items) <= 0) + return; + g_mutex_lock (&priv->queue_sources_mutex); - g_hash_table_foreach (priv->queue_sources, (GHFunc)kick_queue_source, NULL); + if (priv->queue_sources) + g_hash_table_foreach (priv->queue_sources, (GHFunc)kick_queue_source, NULL); g_mutex_unlock (&priv->queue_sources_mutex); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/meson.build new/libsoup-3.2.2/meson.build --- old/libsoup-3.2.1/meson.build 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/meson.build 2022-11-02 20:46:22.000000000 +0100 @@ -1,5 +1,5 @@ project('libsoup', 'c', - version: '3.2.1', + version: '3.2.2', meson_version : '>= 0.54', license : 'LGPL-2.0-or-later', default_options : [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/tests/context-test.c new/libsoup-3.2.2/tests/context-test.c --- old/libsoup-3.2.1/tests/context-test.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/tests/context-test.c 2022-11-02 20:46:22.000000000 +0100 @@ -130,11 +130,11 @@ GAsyncResult *result, GMainContext *async_context) { - GInputStream *stream; + GBytes *body; g_assert_true (async_context == g_main_context_get_thread_default ()); - stream = soup_session_send_finish (session, result, NULL); - g_clear_object (&stream); + body = soup_session_send_and_read_finish (session, result, NULL); + g_clear_pointer (&body, g_bytes_unref); } static void @@ -176,9 +176,9 @@ msg = soup_message_new ("GET", uri); loop = g_main_loop_new (async_context, FALSE); g_signal_connect (msg, "finished", G_CALLBACK (message_finished), loop); - soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback)message_send_cb, - async_context); + soup_session_send_and_read_async (session, msg, G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)message_send_cb, + async_context); g_main_loop_run (loop); /* We need one more iteration, because SoupMessage::finished is emitted * right before the message is unqueued. @@ -215,7 +215,7 @@ SoupSession *session; char *uri; SoupMessage *msg; - GInputStream *stream; + GBytes *body; GMainLoop *loop; idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL); @@ -229,18 +229,18 @@ debug_printf (1, " send_message\n"); msg = soup_message_new ("GET", uri); - stream = soup_session_send (session, msg, NULL, NULL); + body = soup_session_send_and_read (session, msg, NULL, NULL); soup_test_assert_message_status (msg, SOUP_STATUS_OK); - g_object_unref (stream); + g_bytes_unref (body); g_object_unref (msg); debug_printf (1, " queue_message\n"); msg = soup_message_new ("GET", uri); loop = g_main_loop_new (async_context, FALSE); g_signal_connect (msg, "finished", G_CALLBACK (message_finished), loop); - soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, - (GAsyncReadyCallback)message_send_cb, - async_context); + soup_session_send_and_read_async (session, msg, G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)message_send_cb, + async_context); g_main_loop_run (loop); /* We need one more iteration, because SoupMessage::finished is emitted * right before the message is unqueued. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libsoup-3.2.1/tests/http2-test.c new/libsoup-3.2.2/tests/http2-test.c --- old/libsoup-3.2.1/tests/http2-test.c 2022-10-11 20:11:57.000000000 +0200 +++ new/libsoup-3.2.2/tests/http2-test.c 2022-11-02 20:46:22.000000000 +0100 @@ -23,6 +23,7 @@ #include "soup-message-headers-private.h" #include "soup-server-message-private.h" #include "soup-body-input-stream-http2.h" +#include <gio/gnetworking.h> static GUri *base_uri; @@ -1014,13 +1015,12 @@ static void content_sniffed (SoupMessage *msg, - char *content_type, - GHashTable *params) + const char *content_type, + GHashTable *params, + char **sniffed_type) { - soup_test_assert (g_object_get_data (G_OBJECT (msg), "got-chunk") == NULL, - "got-chunk got emitted before content-sniffed"); - g_object_set_data (G_OBJECT (msg), "content-sniffed", GINT_TO_POINTER (TRUE)); + *sniffed_type = g_strdup (content_type); } static void @@ -1055,12 +1055,13 @@ SoupMessage *msg; GInputStream *stream = NULL; GBytes *bytes; + char *sniffed_type = NULL; uri = g_uri_parse_relative (base_uri, path, SOUP_HTTP_URI_FLAGS, NULL); msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); g_object_connect (msg, "signal::got-headers", got_headers, NULL, - "signal::content-sniffed", content_sniffed, NULL, + "signal::content-sniffed", content_sniffed, &sniffed_type, NULL); if (async_context) { soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, @@ -1080,14 +1081,17 @@ if (should_sniff) { soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") != NULL, "content-sniffed did not get emitted"); + g_assert_cmpstr (sniffed_type, ==, "text/plain"); } else { soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL, "content-sniffed got emitted without a sniffer"); + g_assert_null (sniffed_type); } bytes = read_stream_to_bytes_sync (stream); g_assert_cmpuint (g_bytes_get_size (bytes), ==, expected_size); + g_free (sniffed_type); g_object_unref (stream); g_bytes_unref (bytes); g_object_unref (msg); @@ -1098,12 +1102,14 @@ do_sniffer_async_test (Test *test, gconstpointer data) { GMainContext *async_context = g_main_context_ref_thread_default (); + gboolean should_content_sniff = GPOINTER_TO_INT (data); - soup_session_add_feature_by_type (test->session, SOUP_TYPE_CONTENT_SNIFFER); + if (should_content_sniff) + soup_session_add_feature_by_type (test->session, SOUP_TYPE_CONTENT_SNIFFER); - do_one_sniffer_test (test->session, "/", 11, TRUE, async_context); - do_one_sniffer_test (test->session, "/large", (LARGE_N_CHARS * LARGE_CHARS_REPEAT) + 1, TRUE, async_context); - do_one_sniffer_test (test->session, "/no-content", 0, FALSE, async_context); + do_one_sniffer_test (test->session, "/", 11, should_content_sniff, async_context); + do_one_sniffer_test (test->session, "/large", (LARGE_N_CHARS * LARGE_CHARS_REPEAT) + 1, should_content_sniff, async_context); + do_one_sniffer_test (test->session, "/no-content", 0, should_content_sniff, async_context); while (g_main_context_pending (async_context)) g_main_context_iteration (async_context, FALSE); @@ -1114,11 +1120,14 @@ static void do_sniffer_sync_test (Test *test, gconstpointer data) { - soup_session_add_feature_by_type (test->session, SOUP_TYPE_CONTENT_SNIFFER); + gboolean should_content_sniff = GPOINTER_TO_INT (data); + + if (should_content_sniff) + soup_session_add_feature_by_type (test->session, SOUP_TYPE_CONTENT_SNIFFER); - do_one_sniffer_test (test->session, "/", 11, TRUE, NULL); - do_one_sniffer_test (test->session, "/large", (LARGE_N_CHARS * LARGE_CHARS_REPEAT) + 1, TRUE, NULL); - do_one_sniffer_test (test->session, "/no-content", 0, FALSE, NULL); + do_one_sniffer_test (test->session, "/", 11, should_content_sniff, NULL); + do_one_sniffer_test (test->session, "/large", (LARGE_N_CHARS * LARGE_CHARS_REPEAT) + 1, should_content_sniff, NULL); + do_one_sniffer_test (test->session, "/no-content", 0, should_content_sniff, NULL); } static void @@ -1143,6 +1152,24 @@ g_main_context_iteration (NULL, FALSE); } +static void +do_connection_closed_test (Test *test, gconstpointer data) +{ + GUri *uri; + SoupMessage *msg; + GInputStream *stream; + GError *error = NULL; + + uri = g_uri_parse_relative (base_uri, "/close", SOUP_HTTP_URI_FLAGS, NULL); + msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); + stream = soup_session_send (test->session, msg, NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT); + g_clear_error (&error); + g_clear_object (&stream); + g_object_unref (msg); + g_uri_unref (uri); +} + static gboolean unpause_message (SoupServerMessage *msg) { @@ -1246,6 +1273,21 @@ SOUP_MEMORY_STATIC, "Success!", 8); soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); + } else if (strcmp (path, "/close") == 0) { + SoupServerConnection *conn; + int fd; + + conn = soup_server_message_get_connection (msg); + fd = g_socket_get_fd (soup_server_connection_get_socket (conn)); +#ifdef G_OS_WIN32 + shutdown (fd, SD_SEND); +#else + shutdown (fd, SHUT_WR); +#endif + + soup_server_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "Success!", 8); } } @@ -1391,11 +1433,19 @@ do_invalid_header_rfc9113_received_test, teardown_session); #endif - g_test_add ("/http2/sniffer/async", Test, NULL, + g_test_add ("/http2/sniffer/with-sniffer/async", Test, GINT_TO_POINTER (TRUE), + setup_session, + do_sniffer_async_test, + teardown_session); + g_test_add ("/http2/sniffer/no-sniffer/async", Test, GINT_TO_POINTER (FALSE), setup_session, do_sniffer_async_test, teardown_session); - g_test_add ("/http2/sniffer/sync", Test, NULL, + g_test_add ("/http2/sniffer/with-sniffer/sync", Test, GINT_TO_POINTER (TRUE), + setup_session, + do_sniffer_sync_test, + teardown_session); + g_test_add ("/http2/sniffer/no-sniffer/sync", Test, GINT_TO_POINTER (FALSE), setup_session, do_sniffer_sync_test, teardown_session); @@ -1403,6 +1453,10 @@ setup_session, do_timeout_test, teardown_session); + g_test_add ("/http2/connection-closed", Test, NULL, + setup_session, + do_connection_closed_test, + teardown_session); ret = g_test_run ();