From 9a5afa1533d58643c66ae296728f79235468038e Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 22 Oct 2025 01:29:30 -0400 Subject: [PATCH] http: start closing parent connection if no streams If h2 connection is without streams on transport close, start closing parent req Type: fix Change-Id: I3f8c537387d474372d812f0c4989b615f7344125 Signed-off-by: Florin Coras Signed-off-by: Matus Fabian --- src/plugins/http/http.c | 7 ++++--- src/plugins/http/http2/http2.c | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index 5e6672cd7dc..1ec48ef7213 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -419,9 +419,10 @@ http_conn_timeout_cb (void *hc_handlep) } /* in case nothing received on cleartext connection before timeout */ - if (PREDICT_FALSE (hc->version != HTTP_VERSION_NA)) + if (PREDICT_TRUE (hc->version != HTTP_VERSION_NA)) http_vfts[hc->version].transport_close_callback (hc); - http_disconnect_transport (hc); + if (hc->state != HTTP_CONN_STATE_CLOSED) + http_disconnect_transport (hc); http_stats_connections_timeout_inc (hs_handle >> 24); } @@ -725,7 +726,7 @@ http_ts_cleanup_callback (session_t *ts, session_cleanup_ntf_t ntf) http_conn_timer_stop (hc); /* in case nothing received on cleartext connection */ - if (PREDICT_FALSE (hc->version != HTTP_VERSION_NA)) + if (PREDICT_TRUE (hc->version != HTTP_VERSION_NA)) http_vfts[hc->version].conn_cleanup_callback (hc); if (!(hc->flags & HTTP_CONN_F_IS_SERVER)) diff --git a/src/plugins/http/http2/http2.c b/src/plugins/http/http2/http2.c index f497670ae03..45d35cba09c 100644 --- a/src/plugins/http/http2/http2.c +++ b/src/plugins/http/http2/http2.c @@ -1097,7 +1097,7 @@ http2_sched_dispatch_req_headers (http2_req_t *req, http_conn_t *hc, u8 fh[HTTP2_FRAME_HEADER_SIZE]; hpack_request_control_data_t control_data; u8 flags = 0; - u32 n_written, stream_id, n_deq, max_write, headers_len, headers_left; + u32 n_written, n_deq, max_write, headers_len, headers_left; http2_conn_ctx_t *h2c; http2_worker_ctx_t *wrk = http2_get_worker (hc->c_thread_index); @@ -1197,9 +1197,6 @@ http2_sched_dispatch_req_headers (http2_req_t *req, http_conn_t *hc, max_write -= HTTP2_FRAME_HEADER_SIZE; max_write = clib_min (max_write, h2c->peer_settings.max_frame_size); - stream_id = http2_conn_get_next_stream_id (h2c); - http2_req_set_stream_id (req, h2c, stream_id, 1); - http_io_as_dequeue_notify (&req->base, n_deq); if (headers_len <= max_write) @@ -1240,7 +1237,7 @@ http2_sched_dispatch_req_headers (http2_req_t *req, http_conn_t *hc, *n_emissions += HTTP2_SCHED_WEIGHT_HEADERS_CONTINUATION; } - http2_frame_write_headers_header (headers_len, stream_id, flags, fh); + http2_frame_write_headers_header (headers_len, req->stream_id, flags, fh); svm_fifo_seg_t segs[2] = { { fh, HTTP2_FRAME_HEADER_SIZE }, { request, headers_len } }; n_written = http_io_ts_write_segs (hc, segs, 2, 0); @@ -1905,6 +1902,9 @@ http2_req_state_wait_app_method (http_conn_t *hc, http2_req_t *req, clib_llist_add_tail (wrk->req_pool, sched_list, req, he); http2_conn_schedule (h2c, hc->c_thread_index); + u32 stream_id = http2_conn_get_next_stream_id (h2c); + http2_req_set_stream_id (req, h2c, stream_id, 1); + req->dispatch_headers_cb = http2_sched_dispatch_req_headers; http_req_state_change (&req->base, HTTP_REQ_STATE_APP_IO_MORE_DATA); http_req_deschedule (&req->base, sp); @@ -3196,6 +3196,15 @@ http2_transport_close_callback (http_conn_t *hc) if (clib_llist_elt_is_linked (h2c, sched_list)) clib_llist_remove (wrk->conn_pool, sched_list, h2c); http_disconnect_transport (hc); + /* Notify app that transport for parent req is closing to avoid + * potentially deleting the connection in ready state on transport + * cleanup */ + if (!(hc->flags & HTTP_CONN_F_IS_SERVER) && + h2c->parent_req_index != SESSION_INVALID_INDEX) + { + req = http2_req_get (h2c->parent_req_index, hc->c_thread_index); + session_transport_closing_notify (&req->base.connection); + } } } -- 2.16.6