diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-08-31 14:33:41 +0200 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-09-02 12:18:40 +0200 |
commit | 59027ddc49b31b60607803f992b83a13764539f2 (patch) | |
tree | a6f5e6d7ff761266df4bb0603937771e9caa82d0 | |
parent | 45d06b489dd7bffc4310f61ae88c025c69870794 (diff) | |
download | libsoup-59027ddc49b31b60607803f992b83a13764539f2.tar.gz |
http2: Handle all http2 errors on stream close
Set the data error and save thee http2 error to ensure we don't retry
the message in case of unhandled http2 error.
-rw-r--r-- | libsoup/http2/soup-client-message-io-http2.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/libsoup/http2/soup-client-message-io-http2.c b/libsoup/http2/soup-client-message-io-http2.c index b6c21adf..7e6fc64a 100644 --- a/libsoup/http2/soup-client-message-io-http2.c +++ b/libsoup/http2/soup-client-message-io-http2.c @@ -116,6 +116,7 @@ typedef struct { gpointer completion_data; SoupHTTP2IOState state; GError *error; + uint32_t http2_error; gboolean paused; guint32 stream_id; gboolean can_be_restarted; @@ -268,6 +269,20 @@ set_error_for_data (SoupHTTP2MessageData *data, } static void +set_http2_error_for_data (SoupHTTP2MessageData *data, + uint32_t error_code) +{ + h2_debug (data->io, data, "[SESSION] Error: %s", nghttp2_http2_strerror (error_code)); + + if (data->error) + return; + + data->http2_error = error_code; + data->error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, + "HTTP/2 Error: %s", nghttp2_http2_strerror (error_code)); +} + +static void set_io_error (SoupClientMessageIOHTTP2 *io, GError *error) { @@ -320,6 +335,7 @@ soup_http2_message_data_can_be_restarted (SoupHTTP2MessageData *data, !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && error->domain != G_TLS_ERROR && + data->http2_error == NGHTTP2_NO_ERROR && SOUP_METHOD_IS_IDEMPOTENT (soup_message_get_method (data->msg)); } @@ -691,8 +707,7 @@ handle_goaway (SoupClientMessageIOHTTP2 *io, if ((error_code == 0 && (int32_t)data->stream_id > last_stream_id) || data->state < STATE_READ_DONE) { /* TODO: We can restart unfinished messages */ - set_error_for_data (data, g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, - "HTTP/2 Error: %s", nghttp2_http2_strerror (error_code))); + set_http2_error_for_data (data, error_code); } } } @@ -806,10 +821,8 @@ on_frame_recv_callback (nghttp2_session *session, } break; case NGHTTP2_RST_STREAM: - if (frame->rst_stream.error_code != NGHTTP2_NO_ERROR) { - set_error_for_data (data, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, - nghttp2_http2_strerror (frame->rst_stream.error_code))); - } + if (frame->rst_stream.error_code != NGHTTP2_NO_ERROR) + set_http2_error_for_data (data, frame->rst_stream.error_code); break; case NGHTTP2_WINDOW_UPDATE: h2_debug (io, data, "[RECV] WINDOW_UPDATE: increment=%d, total=%d", frame->window_update.window_size_increment, @@ -993,6 +1006,8 @@ on_stream_close_callback (nghttp2_session *session, data->io->in_callback++; switch (error_code) { + case NGHTTP2_NO_ERROR: + break; case NGHTTP2_REFUSED_STREAM: if (data->state < STATE_READ_DATA_START) data->can_be_restarted = TRUE; @@ -1001,6 +1016,9 @@ on_stream_close_callback (nghttp2_session *session, soup_message_set_force_http_version (data->item->msg, SOUP_HTTP_1_1); data->can_be_restarted = TRUE; break; + default: + set_http2_error_for_data (data, error_code); + break; } data->io->in_callback--; |