diff --git a/include/haproxy/qmux_trace.h b/include/haproxy/qmux_trace.h index c612c9611..0bc89a318 100644 --- a/include/haproxy/qmux_trace.h +++ b/include/haproxy/qmux_trace.h @@ -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" }, { } }; diff --git a/src/mux_quic.c b/src/mux_quic.c index 8e48493d0..a5e443f7d 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -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 , if 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",