]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3/hq-interop: restore function for standalone FIN receive
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 27 Feb 2025 10:33:21 +0000 (11:33 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 7 Mar 2025 11:06:26 +0000 (12:06 +0100)
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.

include/haproxy/qmux_http.h
src/h3.c
src/hq_interop.c
src/qmux_http.c

index 4a7711401e73f32505ba56a9366a67912fbf9b30..218bd012cf31cccac6d512f34acade403eb09412 100644 (file)
@@ -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);
 
index 20023403e9760a7b938837511e60d7e6eef6203e..1f16caf1333836b402b0fd2073b731302fcd75cc 100644 (file)
--- 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;
index 55cccf134616422b8d0e57144ba882a7ee3fdb71..b31f855c21aea2619ec851ee9a5f1ac2d7216e4b 100644 (file)
@@ -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++;
index 092eb15da9aea14a9a478fe1e7a5006397865dae..b4e85ef22b1d8c16ca718d945e825786356cf47a 100644 (file)
@@ -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
  * <buf> to <qcs> stream buffer. Input buffer is expected to be of length
  * <count>. <fin> will be set to signal the last data to send for this stream.