summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2022-11-10 12:50:19 +0100
committerCarlos Garcia Campos <cgarcia@igalia.com>2022-11-10 12:50:19 +0100
commitab3767f07a075c9e1e847ac45559924eed9b4a3e (patch)
tree78b337fe847ab522f11df235bff9fe492b94865b
parentd20c6601664624116f3dc43f21c7ec4a186cf8d3 (diff)
downloadlibsoup-ab3767f07a075c9e1e847ac45559924eed9b4a3e.tar.gz
server: close http/2 connection after io error or goaway received
-rw-r--r--libsoup/server/http2/soup-server-message-io-http2.c44
-rw-r--r--tests/server-test.c13
2 files changed, 43 insertions, 14 deletions
diff --git a/libsoup/server/http2/soup-server-message-io-http2.c b/libsoup/server/http2/soup-server-message-io-http2.c
index e9e2fbfb..f782dcef 100644
--- a/libsoup/server/http2/soup-server-message-io-http2.c
+++ b/libsoup/server/http2/soup-server-message-io-http2.c
@@ -364,12 +364,18 @@ io_write_ready (GObject *stream,
return G_SOURCE_CONTINUE;
}
- if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io)
- h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+ if (soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) {
+ if (error)
+ h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+
+ g_clear_pointer (&io->write_source, g_source_unref);
+
+ if (error || (!nghttp2_session_want_read (io->session) && !nghttp2_session_want_write (io->session)))
+ soup_server_connection_disconnect (conn);
+ }
g_clear_error (&error);
g_object_unref (conn);
- g_clear_pointer (&io->write_source, g_source_unref);
return G_SOURCE_REMOVE;
}
@@ -388,16 +394,21 @@ io_try_write (SoupServerMessageIOHTTP2 *io)
while (!error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io && !io->in_callback && nghttp2_session_want_write (io->session))
io_write (io, &error);
- if (io->in_callback || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
- g_clear_error (&error);
- io->write_source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (io->ostream), NULL);
- g_source_set_name (io->write_source, "Soup server HTTP/2 write source");
- g_source_set_callback (io->write_source, (GSourceFunc)io_write_ready, io, NULL);
- g_source_attach (io->write_source, g_main_context_get_thread_default ());
- }
+ if (soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) {
+ if (io->in_callback || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
+ g_clear_error (&error);
+ io->write_source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (io->ostream), NULL);
+ g_source_set_name (io->write_source, "S oup server HTTP/2 write source");
+ g_source_set_callback (io->write_source, (GSourceFunc)io_write_ready, io, NULL);
+ g_source_attach (io->write_source, g_main_context_get_thread_default ());
+ }
- if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io)
- h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+ if (error)
+ h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+
+ if (error || (!nghttp2_session_want_read (io->session) && !nghttp2_session_want_write (io->session)))
+ soup_server_connection_disconnect (conn);
+ }
g_clear_error (&error);
g_object_unref (conn);
@@ -450,8 +461,13 @@ io_read_ready (GObject *stream,
return G_SOURCE_CONTINUE;
}
- if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io)
- h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+ if (soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) {
+ if (error)
+ h2_debug (io, NULL, "[SESSION] IO error: %s", error->message);
+
+ if (error || (!nghttp2_session_want_read (io->session) && !nghttp2_session_want_write (io->session)))
+ soup_server_connection_disconnect (conn);
+ }
g_clear_error (&error);
g_object_unref (conn);
diff --git a/tests/server-test.c b/tests/server-test.c
index 12bfd980..8d0c38bb 100644
--- a/tests/server-test.c
+++ b/tests/server-test.c
@@ -1325,6 +1325,8 @@ do_idle_connection_closed_test (ServerData *sd, gconstpointer test_data)
GError *error = NULL;
GSList *clients;
+ soup_server_set_http2_enabled (sd->server, tls_available);
+
session = soup_test_session_new (NULL);
msg = soup_message_new_from_uri ("GET", sd->base_uri);
@@ -1336,6 +1338,17 @@ do_idle_connection_closed_test (ServerData *sd, gconstpointer test_data)
clients = soup_server_get_clients (sd->server);
g_assert_cmpuint (g_slist_length (clients), ==, 1);
+ if (tls_available) {
+ msg = soup_message_new_from_uri ("GET", sd->ssl_base_uri);
+ body = soup_session_send_and_read (session, msg, NULL, &error);
+ g_assert_no_error (error);
+ g_bytes_unref (body);
+ g_object_unref (msg);
+
+ clients = soup_server_get_clients (sd->server);
+ g_assert_cmpuint (g_slist_length (clients), ==, 2);
+ }
+
soup_test_session_abort_unref (session);
while (soup_server_get_clients (sd->server))