diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-08-31 14:33:41 +0200 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-08-31 14:33:41 +0200 |
commit | a31e1744191b88d0da4dcdc4d95cc78f37c2609a (patch) | |
tree | ed28aea145ac8c9dd6b1c196d4daff48743858ee | |
parent | fb7cad1a928c062c811bc5782630138265f295c2 (diff) | |
download | libsoup-a31e1744191b88d0da4dcdc4d95cc78f37c2609a.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 6a5b2265..6f7dd747 100644 --- a/libsoup/http2/soup-client-message-io-http2.c +++ b/libsoup/http2/soup-client-message-io-http2.c @@ -106,6 +106,7 @@ typedef struct { gpointer completion_data; SoupHTTP2IOState state; GError *error; + uint32_t http2_error; gboolean paused; guint32 stream_id; gboolean can_be_restarted; @@ -171,6 +172,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) { @@ -223,6 +238,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)); } @@ -600,8 +616,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); } } } @@ -715,10 +730,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, @@ -938,6 +951,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; @@ -946,6 +961,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--; |