summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2022-08-31 14:33:41 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2022-08-31 14:33:41 +0200
commita31e1744191b88d0da4dcdc4d95cc78f37c2609a (patch)
treeed28aea145ac8c9dd6b1c196d4daff48743858ee
parentfb7cad1a928c062c811bc5782630138265f295c2 (diff)
downloadlibsoup-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.c30
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--;