]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-quic: prevent CC status to be erased by shutdown
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 20 Mar 2023 16:34:22 +0000 (17:34 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Mar 2023 13:38:06 +0000 (14:38 +0100)
HTTP/3 graceful shutdown operation is used to emit a GOAWAY followed by
a CONNECTION_CLOSE with H3_NO_ERROR status. It is used for every
connection on release which means that if a CONNECTION_CLOSE was already
registered for a previous error, its status code is overwritten.

To fix this, skip shutdown operation if a CONNECTION_CLOSE is already
registered at the MUX level. This ensures that the correct error status
is reported to the peer.

This should be backported up to 2.6. Note that qc_shutdown() does not
exists on 2.6 so modification will have to be made directly in
qc_release() as followed :

diff --git a/src/mux_quic.c b/src/mux_quic.c
index 49df0dc418..3463222956 100644
--- a/src/mux_quic.c
+++ b/src/mux_quic.c
@@ -1766,19 +1766,21 @@ static void qc_release(struct qcc *qcc)

        TRACE_ENTER(QMUX_EV_QCC_END, conn);

-       if (qcc->app_ops && qcc->app_ops->shutdown) {
-               /* Application protocol with dedicated connection closing
-                * procedure.
-                */
-               qcc->app_ops->shutdown(qcc->ctx);
+       if (!(qcc->flags & QC_CF_CC_EMIT)) {
+               if (qcc->app_ops && qcc->app_ops->shutdown) {
+                       /* Application protocol with dedicated connection closing
+                        * procedure.
+                        */
+                       qcc->app_ops->shutdown(qcc->ctx);

-               /* useful if application protocol should emit some closing
-                * frames. For example HTTP/3 GOAWAY frame.
-                */
-               qc_send(qcc);
-       }
-       else {
-               qcc_emit_cc_app(qcc, QC_ERR_NO_ERROR, 0);
+                       /* useful if application protocol should emit some closing
+                        * frames. For example HTTP/3 GOAWAY frame.
+                        */
+                       qc_send(qcc);
+               }
+               else {
+                       qcc_emit_cc_app(qcc, QC_ERR_NO_ERROR, 0);
+               }
        }

        if (qcc->task) {

src/mux_quic.c

index 0d28c44f6d4ff2dfc521714066a33bc0ddd47b72..835011a23fcfa62990a591b3053f9b065c526184 100644 (file)
@@ -2004,8 +2004,10 @@ static void qc_shutdown(struct qcc *qcc)
 {
        TRACE_ENTER(QMUX_EV_QCC_END, qcc->conn);
 
-       if (qcc->flags & QC_CF_APP_SHUT)
+       if (qcc->flags & (QC_CF_APP_SHUT|QC_CF_CC_EMIT)) {
+               TRACE_DATA("connection closed", QMUX_EV_QCC_END, qcc->conn);
                goto out;
+       }
 
        if (qcc->app_ops && qcc->app_ops->shutdown) {
                qcc->app_ops->shutdown(qcc->ctx);