From f9b03265f08b7ee6a08dca5b6990a7b3c9252fbf Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 9 Jan 2023 10:34:25 +0100 Subject: [PATCH] MEDIUM: h3: send SETTINGS before STREAM frames Complete qcc_send_stream() function to allow to specify if the stream should be handled in priority. Internally this will insert the qcs instance in front of to be able to treat it before other streams. This functionality is useful when some QUIC streams should be sent before others. Most notably, this is used to guarantee that H3 SETTINGS is done first via the control stream. This must be backported up to 2.7. --- include/haproxy/mux_quic.h | 2 +- src/h3.c | 2 +- src/mux_quic.c | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index 1d374b0b0..1d5b962c0 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -21,7 +21,7 @@ void qcs_notify_send(struct qcs *qcs); void qcc_emit_cc_app(struct qcc *qcc, int err, int immediate); void qcc_reset_stream(struct qcs *qcs, int err); -void qcc_send_stream(struct qcs *qcs); +void qcc_send_stream(struct qcs *qcs, int urg); void qcc_abort_stream_read(struct qcs *qcs); int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset, char fin, char *data); diff --git a/src/h3.c b/src/h3.c index e84044857..d51e35ff8 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1034,7 +1034,7 @@ static int h3_control_send(struct qcs *qcs, void *ctx) ret = b_force_xfer(res, &pos, b_data(&pos)); if (ret > 0) { /* Register qcs for sending before other streams. */ - qcc_send_stream(qcs); + qcc_send_stream(qcs, 1); h3c->flags |= H3_CF_SETTINGS_SENT; } diff --git a/src/mux_quic.c b/src/mux_quic.c index 6a324acf5..bb30f588a 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -821,8 +821,11 @@ void qcc_reset_stream(struct qcs *qcs, int err) tasklet_wakeup(qcc->wait_event.tasklet); } -/* Register stream for emission of STREAM, STOP_SENDING or RESET_STREAM. */ -void qcc_send_stream(struct qcs *qcs) +/* Register stream for emission of STREAM, STOP_SENDING or RESET_STREAM. + * Set to 1 if stream content should be treated in priority compared to + * other streams. + */ +void qcc_send_stream(struct qcs *qcs, int urg) { struct qcc *qcc = qcs->qcc; @@ -831,8 +834,14 @@ void qcc_send_stream(struct qcs *qcs) /* Cannot send if already closed. */ BUG_ON(qcs_is_close_local(qcs)); - if (!LIST_INLIST(&qcs->el_send)) - LIST_APPEND(&qcs->qcc->send_list, &qcs->el_send); + if (urg) { + LIST_DEL_INIT(&qcs->el_send); + LIST_INSERT(&qcc->send_list, &qcs->el_send); + } + else { + if (!LIST_INLIST(&qcs->el_send)) + LIST_APPEND(&qcs->qcc->send_list, &qcs->el_send); + } TRACE_LEAVE(QMUX_EV_QCS_SEND, qcc->conn, qcs); } @@ -2327,7 +2336,7 @@ static size_t qc_send_buf(struct stconn *sc, struct buffer *buf, qcs->flags |= QC_SF_FIN_STREAM; if (ret || fin) { - qcc_send_stream(qcs); + qcc_send_stream(qcs, 0); if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND)) tasklet_wakeup(qcs->qcc->wait_event.tasklet); }