diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index e2437c351..da686c1bb 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -25,6 +25,7 @@ int qcc_notify_buf(struct qcc *qcc); struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs); struct buffer *qcc_get_stream_txbuf(struct qcs *qcs, int *err); +int qcc_realign_stream_txbuf(const struct qcs *qcs, struct buffer *out); int qcc_release_stream_txbuf(struct qcs *qcs); int qcc_stream_can_send(const struct qcs *qcs); void qcc_reset_stream(struct qcs *qcs, int err); diff --git a/src/h3.c b/src/h3.c index 69bbd8e27..01ef2502e 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1900,8 +1900,14 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx, if (fsize > count) fsize = count; - /* TODO buffer can be realign only if no data waiting for ACK. */ - outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0); + while (1) { + b_reset(&outbuf); + outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0); + if (b_size(&outbuf) > hsize || !b_space_wraps(res)) + break; + if (qcc_realign_stream_txbuf(qcs, res)) + break; + } /* Not enough room for headers and at least one data byte, try to * release the current buffer and allocate a new one. If not possible, @@ -2082,7 +2088,12 @@ static size_t h3_nego_ff(struct qcs *qcs, size_t count) /* h3 DATA headers : 1-byte frame type + varint frame length */ hsize = 1 + QUIC_VARINT_MAX_SIZE; - /* TODO buffer can be realign only if no data waiting for ACK. */ + while (1) { + if (b_contig_space(res) >= hsize || !b_space_wraps(res)) + break; + if (qcc_realign_stream_txbuf(qcs, res)) + break; + } /* Not enough room for headers and at least one data byte, block the * stream. It is expected that the stream connector layer will subscribe diff --git a/src/mux_quic.c b/src/mux_quic.c index 9df45b491..939d5c0da 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -1019,6 +1019,21 @@ static uint64_t qcs_prep_bytes(const struct qcs *qcs) return b_data(out) - diff; } +/* Try to realign buffer for stream. This is done only if there is + * no data waiting for ACK. + * + * Returns 0 if realign was performed else non-zero. + */ +int qcc_realign_stream_txbuf(const struct qcs *qcs, struct buffer *out) +{ + if (qcs_prep_bytes(qcs) == b_data(out)) { + b_slow_realign(out, trash.area, b_data(out)); + return 0; + } + + return 1; +} + /* Release the current Tx buffer. This is useful if space left is not * enough anymore. A new instance can then be allocated to continue sending. *