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 /libsoup | |
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.
Diffstat (limited to 'libsoup')
-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--; |