diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index c24db7962..6b7f1218a 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -209,7 +209,7 @@ struct qcc_app_ops { ssize_t (*rcv_buf)(struct qcs *qcs, struct buffer *b, int fin); /* Convert HTX to HTTP payload for sending. */ - size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count); + size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count, char *fin); /* Negotiate and commit fast-forward data from opposite MUX. */ size_t (*nego_ff)(struct qcs *qcs, size_t count); diff --git a/src/h3.c b/src/h3.c index ac39feef4..2adda3d21 100644 --- a/src/h3.c +++ b/src/h3.c @@ -2635,11 +2635,14 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx, * stream instance. Successfully transcoded HTX blocks are removed from input * buffer. * + * is used as an output boolean. It will be set if the last blocks of the + * HTX message were encoded, which should trigger a FIN STREAM emission. + * * Returns the amount of consumed bytes from . In case of error, * connection is flagged and transcoding is interrupted. The returned value is * unchanged though. */ -static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count) +static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, char *fin) { size_t total = 0; enum htx_blk_type btype; @@ -2647,11 +2650,15 @@ static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count) struct htx_blk *blk; uint32_t bsize; int32_t idx; + char eom; int ret = 0; TRACE_ENTER(H3_EV_STRM_SEND, qcs->qcc->conn, qcs); + *fin = 0; htx = htx_from_buf(buf); + /* EOM is saved here, useful if 0-copy is performed with HTX buf. */ + eom = htx->flags & HTX_FL_EOM; while (count && !htx_is_empty(htx) && qcc_stream_can_send(qcs) && ret >= 0) { idx = htx_get_head(htx); @@ -2752,6 +2759,10 @@ static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count) #endif out: + if (eom && htx_is_empty(htx)) { + TRACE_USER("transcoding last HTX message", H3_EV_STRM_SEND, qcs->qcc->conn, qcs); + *fin = 1; + } htx_to_buf(htx, buf); TRACE_LEAVE(H3_EV_STRM_SEND, qcs->qcc->conn, qcs); diff --git a/src/hq_interop.c b/src/hq_interop.c index 6f9f47a95..4dbd9adf4 100644 --- a/src/hq_interop.c +++ b/src/hq_interop.c @@ -161,7 +161,7 @@ static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin) /* Returns the amount of consumed bytes from . */ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf, - size_t count) + size_t count, char *fin) { enum htx_blk_type btype; struct htx *htx = NULL; @@ -173,6 +173,7 @@ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf, size_t total = 0; int err; + *fin = 0; htx = htx_from_buf(buf); while (count && !htx_is_empty(htx) && qcc_stream_can_send(qcs)) { @@ -266,6 +267,8 @@ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf, } end: + if (htx->flags & HTX_FL_EOM && htx_is_empty(htx)) + *fin = 1; htx_to_buf(htx, buf); return total; diff --git a/src/qmux_http.c b/src/qmux_http.c index b4e85ef22..57b1eef35 100644 --- a/src/qmux_http.c +++ b/src/qmux_http.c @@ -94,7 +94,6 @@ size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, { struct htx *htx; size_t ret; - int eom = 0; TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); @@ -108,9 +107,7 @@ size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, if (htx->extra && htx->extra == HTX_UNKOWN_PAYLOAD_LENGTH) qcs->flags |= QC_SF_UNKNOWN_PL_LENGTH; - eom = (htx->flags & HTX_FL_EOM); - ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count); - *fin = (eom && !b_data(buf)); + ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count, fin); TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);