From 23a4d6df38d4a4a49838bb14a9c53042c8664d2d Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 16 Jul 2025 11:01:31 -0400 Subject: [PATCH] http: h2 client handle GOAWAY NO_ERROR Type: improvement Change-Id: I244528cdab03c3f17d17f98fd9182399b2ac6a17 Signed-off-by: Matus Fabian --- src/plugins/http/http2/http2.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/plugins/http/http2/http2.c b/src/plugins/http/http2/http2.c index 9060a73bb11..f10113e80e4 100644 --- a/src/plugins/http/http2/http2.c +++ b/src/plugins/http/http2/http2.c @@ -104,6 +104,7 @@ typedef struct http2_conn_ctx_ u8 *unparsed_headers; /* temporary storing rx fragmented headers */ u8 *unsent_headers; /* temporary storing tx fragmented headers */ u32 unsent_headers_offset; + u32 client_req_index; } http2_conn_ctx_t; typedef struct http2_worker_ctx_ @@ -403,11 +404,17 @@ http2_connection_error (http_conn_t *hc, http2_error_t error, http_io_ts_write (hc, response, vec_len (response), sp); http_io_ts_after_write (hc, 1); - hash_foreach (stream_id, req_index, h2c->req_by_stream_id, ({ - req = http2_req_get (req_index, hc->c_thread_index); - if (req->stream_state != HTTP2_STREAM_STATE_CLOSED) - session_transport_reset_notify (&req->base.connection); - })); + if (hc->flags & HTTP_CONN_F_IS_SERVER) + hash_foreach (stream_id, req_index, h2c->req_by_stream_id, ({ + req = http2_req_get (req_index, hc->c_thread_index); + if (req->stream_state != HTTP2_STREAM_STATE_CLOSED) + session_transport_reset_notify (&req->base.connection); + })); + else + { + req = http2_req_get (h2c->client_req_index, hc->c_thread_index); + session_transport_reset_notify (&req->base.connection); + } if (clib_llist_elt_is_linked (h2c, sched_list)) clib_llist_remove (wrk->conn_pool, sched_list, h2c); http_shutdown_transport (hc); @@ -2248,6 +2255,8 @@ http2_handle_settings_frame (http_conn_t *hc, http2_frame_header_t *fh) h2c->flags &= ~HTTP2_CONN_F_EXPECT_SERVER_SETTINGS; /* client connection is now established */ req = http2_conn_alloc_req (hc); + h2c->client_req_index = + ((http_req_handle_t) req->base.hr_req_handle).req_index; http_req_state_change (&req->base, HTTP_REQ_STATE_WAIT_APP_METHOD); if (http_conn_established (hc, &req->base)) return HTTP2_ERROR_INTERNAL_ERROR; @@ -2351,9 +2360,17 @@ http2_handle_goaway_frame (http_conn_t *hc, http2_frame_header_t *fh) HTTP_DBG (1, "received GOAWAY %U, last stream id %u", format_http2_error, error_code, last_stream_id); + h2c = http2_conn_ctx_get_w_thread (hc); if (error_code == HTTP2_ERROR_NO_ERROR) { - /* TODO: graceful shutdown (no new streams) */ + /* graceful shutdown (no new streams for client) */ + if (!(hc->flags & HTTP_CONN_F_IS_SERVER)) + { + req = http2_req_get (h2c->client_req_index, hc->c_thread_index); + if (!req) + return HTTP2_ERROR_NO_ERROR; + session_transport_closed_notify (&req->base.connection); + } } else { @@ -2362,7 +2379,6 @@ http2_handle_goaway_frame (http_conn_t *hc, http2_frame_header_t *fh) rx_buf + HTTP2_GOAWAY_MIN_SIZE, fh->length - HTTP2_GOAWAY_MIN_SIZE); /* connection error */ - h2c = http2_conn_ctx_get_w_thread (hc); hash_foreach (stream_id, req_index, h2c->req_by_stream_id, ({ req = http2_req_get (req_index, hc->c_thread_index); session_transport_reset_notify (&req->base.connection); @@ -2921,8 +2937,11 @@ http2_conn_cleanup_callback (http_conn_t *hc) HTTP_DBG (1, "hc [%u]%x", hc->c_thread_index, hc->hc_hc_index); h2c = http2_conn_ctx_get_w_thread (hc); - hash_foreach (stream_id, req_index, h2c->req_by_stream_id, - ({ vec_add1 (req_indices, req_index); })); + if (hc->flags & HTTP_CONN_F_IS_SERVER) + hash_foreach (stream_id, req_index, h2c->req_by_stream_id, + ({ vec_add1 (req_indices, req_index); })); + else + vec_add1 (req_indices, h2c->client_req_index); vec_foreach (req_index_p, req_indices) { -- 2.16.6