http: start closing parent connection if no streams 20/43920/5
authorFlorin Coras <[email protected]>
Wed, 22 Oct 2025 05:29:30 +0000 (01:29 -0400)
committerDave Barach <[email protected]>
Wed, 22 Oct 2025 19:14:07 +0000 (19:14 +0000)
If h2 connection is without streams on transport close, start
closing parent req

Type: fix

Change-Id: I3f8c537387d474372d812f0c4989b615f7344125
Signed-off-by: Florin Coras <[email protected]>
Signed-off-by: Matus Fabian <[email protected]>
src/plugins/http/http.c
src/plugins/http/http2/http2.c

index 5e6672c..1ec48ef 100644 (file)
@@ -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))
index f497670..45d35cb 100644 (file)
@@ -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);
+       }
     }
 }