From: Amaury Denoyelle Date: Thu, 27 Feb 2025 10:33:21 +0000 (+0100) Subject: MINOR: h3/hq-interop: restore function for standalone FIN receive X-Git-Tag: v3.2-dev7~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=861b11334cd4013e89506601482962a726a07e28;p=thirdparty%2Fhaproxy.git MINOR: h3/hq-interop: restore function for standalone FIN receive Previously, a function qcs_http_handle_standalone_fin() was implemented to handle a received standalone FIN, bypassing app_ops layer decoding. However, this was removed as app_ops layer interaction is necessary. For example, HTTP/3 checks that FIN is never sent on the control uni stream. This patch reintroduces qcs_http_handle_standalone_fin(), albeit in a slightly diminished version. Most importantly, it is now the responsibility of the app_ops layer itself to use it, to avoid the shortcoming described above. The main objective of this patch is to be able to support standalone FIN in HTTP/0.9 layer. This is easily done via the reintroduction of qcs_http_handle_standalone_fin() usage. This will be useful to perform testing, as standalone FIN is a corner case which can easily be broken. --- diff --git a/include/haproxy/qmux_http.h b/include/haproxy/qmux_http.h index 4a7711401..218bd012c 100644 --- a/include/haproxy/qmux_http.h +++ b/include/haproxy/qmux_http.h @@ -8,6 +8,9 @@ size_t qcs_http_rcv_buf(struct qcs *qcs, struct buffer *buf, size_t count, char *fin); + +int qcs_http_handle_standalone_fin(struct qcs *qcs); + size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, char *fin); diff --git a/src/h3.c b/src/h3.c index 20023403e..1f16caf13 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1322,21 +1322,8 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin) } if (!b_data(b) && fin && quic_stream_is_bidi(qcs->id)) { - struct buffer *appbuf; - struct htx *htx; - int eom; - TRACE_PROTO("received FIN without data", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); - if (!(appbuf = qcc_get_stream_rxbuf(qcs))) { - TRACE_ERROR("data buffer alloc failure", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); - qcc_set_error(qcs->qcc, H3_ERR_INTERNAL_ERROR, 1); - goto err; - } - - htx = htx_from_buf(appbuf); - eom = htx_set_eom(htx); - htx_to_buf(htx, appbuf); - if (!eom) { + if (qcs_http_handle_standalone_fin(qcs)) { TRACE_ERROR("cannot set EOM", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); qcc_set_error(qcs->qcc, H3_ERR_INTERNAL_ERROR, 1); goto err; diff --git a/src/hq_interop.c b/src/hq_interop.c index 55cccf134..b31f855c2 100644 --- a/src/hq_interop.c +++ b/src/hq_interop.c @@ -23,6 +23,12 @@ static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin) /* hq-interop parser does not support buffer wrapping. */ BUG_ON(b_data(b) != b_contig_data(b, 0)); + if (!b_data(b) && fin && quic_stream_is_bidi(qcs->id)) { + if (qcs_http_handle_standalone_fin(qcs)) + return -1; + return 0; + } + /* skip method */ while (data && HTTP_IS_TOKEN(*ptr)) { ptr++; diff --git a/src/qmux_http.c b/src/qmux_http.c index 092eb15da..b4e85ef22 100644 --- a/src/qmux_http.c +++ b/src/qmux_http.c @@ -62,6 +62,27 @@ size_t qcs_http_rcv_buf(struct qcs *qcs, struct buffer *buf, size_t count, return ret; } +int qcs_http_handle_standalone_fin(struct qcs *qcs) +{ + struct buffer *appbuf; + struct htx *htx; + int eom; + + if (!(appbuf = qcc_get_stream_rxbuf(qcs))) + goto err; + + htx = htx_from_buf(appbuf); + eom = htx_set_eom(htx); + htx_to_buf(htx, appbuf); + if (!eom) + goto err; + + return 0; + + err: + return -1; +} + /* QUIC MUX snd_buf operation using HTX data. HTX data will be transferred from * to stream buffer. Input buffer is expected to be of length * . will be set to signal the last data to send for this stream.