]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic/h3: prepare CONNECTION_CLOSE on release
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 15 Jul 2022 08:58:25 +0000 (10:58 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 15 Jul 2022 13:20:33 +0000 (15:20 +0200)
When MUX is released, a CONNECTION_CLOSE frame should be emitted. This
will ensure that the client does not use anymore a half-dead connection.

App protocol layer is responsible to provide the error code via release
callback. For HTTP/3 NO_ERROR is used as specified in RFC 9114. If no
release callback is provided, generic QUIC NO_ERROR code is used. Note
that a graceful shutdown is used : quic_conn must emit CONNECTION_CLOSE
frame when possible. This will be provided in another patch.

This change should limit the risk of browsers stuck on webpage loading
if MUX has been released. On CONNECTION_CLOSE reception, the client will
reopen a new QUIC connection.

src/h3.c
src/mux_quic.c

index 7fb5f9489c11347cbb36e885c784b379b6e3b077..c1a9979388f333eca1cc579e4c35a843a880fa78 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -1121,6 +1121,15 @@ static int h3_init(struct qcc *qcc)
 static void h3_release(void *ctx)
 {
        struct h3c *h3c = ctx;
+
+       /* RFC 9114 5.2. Connection Shutdown
+        *
+        * An endpoint that completes a
+        * graceful shutdown SHOULD use the H3_NO_ERROR error code when closing
+        * the connection.
+        */
+       qcc_emit_cc_app(h3c->qcc, H3_NO_ERROR, 0);
+
        pool_free(pool_head_h3c, h3c);
 }
 
index 658a97437d48eeaddbc84990390dd6d094a86eec..5a0d9879e75987563bdd285d360be86bf68b99cf 100644 (file)
@@ -1024,8 +1024,15 @@ static void qc_release(struct qcc *qcc)
 
        TRACE_ENTER(QMUX_EV_QCC_END);
 
-       if (qcc->app_ops && qcc->app_ops->release)
+       if (qcc->app_ops && qcc->app_ops->release) {
+               /* Application protocol with dedicated connection closing
+                * procedure.
+                */
                qcc->app_ops->release(qcc->ctx);
+       }
+       else {
+               qcc_emit_cc_app(qcc, QC_ERR_NO_ERROR, 0);
+       }
 
        if (qcc->task) {
                task_destroy(qcc->task);