diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index b91ccdcbd..425924212 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -25,7 +25,7 @@ void qcs_notify_send(struct qcs *qcs); struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs); struct buffer *qcc_get_stream_txbuf(struct qcs *qcs); void qcc_reset_stream(struct qcs *qcs, int err); -void qcc_send_stream(struct qcs *qcs, int urg); +void qcc_send_stream(struct qcs *qcs, int urg, int count); 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 424ecd833..00eed1259 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1476,7 +1476,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, 1); + qcc_send_stream(qcs, 1, ret); h3c->flags |= H3_CF_SETTINGS_SENT; } @@ -2213,6 +2213,7 @@ static int h3_send_goaway(struct h3c *h3c) struct buffer pos, *res; unsigned char data[3 * QUIC_VARINT_MAX_SIZE]; size_t frm_len = quic_int_getsize(h3c->id_goaway); + size_t xfer; TRACE_ENTER(H3_EV_H3C_END, h3c->qcc->conn); @@ -2234,8 +2235,8 @@ static int h3_send_goaway(struct h3c *h3c) goto err; } - b_force_xfer(res, &pos, b_data(&pos)); - qcc_send_stream(qcs, 1); + xfer = b_force_xfer(res, &pos, b_data(&pos)); + qcc_send_stream(qcs, 1, xfer); h3c->flags |= H3_CF_GOAWAY_SENT; TRACE_LEAVE(H3_EV_H3C_END, h3c->qcc->conn); diff --git a/src/mux_quic.c b/src/mux_quic.c index 55c395a09..b75d4fff7 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -963,15 +963,16 @@ void qcc_reset_stream(struct qcs *qcs, int err) qcs_alert(qcs); } - qcc_send_stream(qcs, 1); + qcc_send_stream(qcs, 1, 0); tasklet_wakeup(qcc->wait_event.tasklet); } /* 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. + * other streams. For STREAM emission, must contains the size of the + * frame payload. */ -void qcc_send_stream(struct qcs *qcs, int urg) +void qcc_send_stream(struct qcs *qcs, int urg, int count) { struct qcc *qcc = qcs->qcc; @@ -1005,7 +1006,7 @@ void qcc_abort_stream_read(struct qcs *qcs) TRACE_STATE("abort stream read", QMUX_EV_QCS_END, qcc->conn, qcs); qcs->flags |= (QC_SF_TO_STOP_SENDING|QC_SF_READ_ABORTED); - qcc_send_stream(qcs, 1); + qcc_send_stream(qcs, 1, 0); tasklet_wakeup(qcc->wait_event.tasklet); end: @@ -2804,6 +2805,7 @@ static size_t qmux_strm_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, int flags) { struct qcs *qcs = __sc_mux_strm(sc); + const size_t old_data = b_data(&qcs->tx.buf); size_t ret = 0; char fin; @@ -2829,7 +2831,7 @@ static size_t qmux_strm_snd_buf(struct stconn *sc, struct buffer *buf, } if (ret || fin) { - qcc_send_stream(qcs, 0); + qcc_send_stream(qcs, 0, b_data(&qcs->tx.buf) - old_data); if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND)) tasklet_wakeup(qcs->qcc->wait_event.tasklet); } @@ -2910,7 +2912,7 @@ static size_t qmux_strm_done_ff(struct stconn *sc) struct qcs *qcs = __sc_mux_strm(sc); struct qcc *qcc = qcs->qcc; struct sedesc *sd = qcs->sd; - size_t total = 0; + size_t total = 0, data = sd->iobuf.data; TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); @@ -2922,9 +2924,10 @@ static size_t qmux_strm_done_ff(struct stconn *sc) if (!(qcs->flags & QC_SF_FIN_STREAM) && !sd->iobuf.data) goto end; + data += sd->iobuf.offset; total = qcs->qcc->app_ops->done_ff(qcs); - qcc_send_stream(qcs, 0); + qcc_send_stream(qcs, 0, data); if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND)) tasklet_wakeup(qcc->wait_event.tasklet); @@ -3012,7 +3015,7 @@ static void qmux_strm_shutw(struct stconn *sc, enum co_shw_mode mode) TRACE_STATE("set FIN STREAM", QMUX_EV_STRM_SHUT, qcc->conn, qcs); qcs->flags |= QC_SF_FIN_STREAM; - qcc_send_stream(qcs, 0); + qcc_send_stream(qcs, 0, 0); } } else {