]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux-quic: implement shutw
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 21 Dec 2022 09:21:58 +0000 (10:21 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 22 Dec 2022 15:22:39 +0000 (16:22 +0100)
Implement mux_ops shutw operation for QUIC mux. A RESET_STREAM is
emitted unless the stream is already closed due to all data or
RESET_STREAM already transmitted.

This operation is notably useful when upper stream layer wants to close
the connection early due to an error.

This was tested by using a HTTP server which listens with PROXY protocol
support. The corresponding server line on haproxy configuration
deliberately not specify send-proxy. This causes the server to close
abruptly the connection. Without this patch, nothing was done on the QUIC
stream which was kept open until the whole connection is closed. Now, a
proper RESET_STREAM is emitted to report the error.

This should be backported up to 2.7.

include/haproxy/qmux_trace.h
src/mux_quic.c

index c612c961153784c6c3f59f343699ad4f0319d3a2..0bc89a31852989cd0a167e568afd19135b26892b 100644 (file)
@@ -34,17 +34,19 @@ static const struct trace_event qmux_trace_events[] = {
        { .mask = QMUX_EV_STRM_RECV,    .name = "strm_recv",    .desc = "receiving data for stream" },
 #define           QMUX_EV_STRM_SEND     (1ULL << 11)
        { .mask = QMUX_EV_STRM_SEND,    .name = "strm_send",    .desc = "sending data for stream" },
-#define           QMUX_EV_STRM_END      (1ULL << 12)
+#define           QMUX_EV_STRM_SHUT     (1ULL << 12)
+       { .mask = QMUX_EV_STRM_SHUT,    .name = "strm_shut",    .desc = "stream shutdown" },
+#define           QMUX_EV_STRM_END      (1ULL << 13)
        { .mask = QMUX_EV_STRM_END,     .name = "strm_end",     .desc = "detaching app-layer stream" },
-#define           QMUX_EV_SEND_FRM      (1ULL << 13)
+#define           QMUX_EV_SEND_FRM      (1ULL << 14)
        { .mask = QMUX_EV_SEND_FRM,     .name = "send_frm",     .desc = "sending QUIC frame" },
 /* special event dedicated to qcs_xfer_data */
-#define           QMUX_EV_QCS_XFER_DATA  (1ULL << 14)
+#define           QMUX_EV_QCS_XFER_DATA  (1ULL << 15)
        { .mask = QMUX_EV_QCS_XFER_DATA,  .name = "qcs_xfer_data", .desc = "qcs_xfer_data" },
 /* special event dedicated to qcs_build_stream_frm */
-#define           QMUX_EV_QCS_BUILD_STRM (1ULL << 15)
+#define           QMUX_EV_QCS_BUILD_STRM (1ULL << 16)
        { .mask = QMUX_EV_QCS_BUILD_STRM, .name = "qcs_build_stream_frm", .desc = "qcs_build_stream_frm" },
-#define           QMUX_EV_PROTO_ERR     (1ULL << 16)
+#define           QMUX_EV_PROTO_ERR     (1ULL << 17)
        { .mask = QMUX_EV_PROTO_ERR,    .name = "proto_err",    .desc = "protocol error" },
        { }
 };
index 8e48493d04cd4f934ea8b126ca7cda5b5786c80b..a5e443f7d3e7485b024f513b9663e4362b9bf51c 100644 (file)
@@ -2269,6 +2269,25 @@ static int qc_wake(struct connection *conn)
        return 1;
 }
 
+static void qc_shutw(struct stconn *sc, enum co_shw_mode mode)
+{
+       struct qcs *qcs = __sc_mux_strm(sc);
+
+       TRACE_ENTER(QMUX_EV_STRM_SHUT, qcs->qcc->conn, qcs);
+
+       /* If QC_SF_FIN_STREAM is not set and stream is not closed locally, it
+        * means that upper layer reported an early closure. A RESET_STREAM is
+        * necessary if not already scheduled.
+        */
+
+       if (!qcs_is_close_local(qcs) &&
+           !(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_RESET))) {
+               qcc_reset_stream(qcs, 0);
+               se_fl_set_error(qcs->sd);
+       }
+
+       TRACE_LEAVE(QMUX_EV_STRM_SHUT, qcs->qcc->conn, qcs);
+}
 
 /* for debugging with CLI's "show sess" command. May emit multiple lines, each
  * new one being prefixed with <pfx>, if <pfx> is not NULL, otherwise a single
@@ -2306,6 +2325,7 @@ static const struct mux_ops qc_ops = {
        .subscribe = qc_subscribe,
        .unsubscribe = qc_unsubscribe,
        .wake = qc_wake,
+       .shutw = qc_shutw,
        .show_sd = qc_show_sd,
        .flags = MX_FL_HTX|MX_FL_NO_UPG|MX_FL_FRAMED,
        .name = "QUIC",