diff --git a/include/haproxy/xprt_qstrm.h b/include/haproxy/xprt_qstrm.h index 5a992f21f..f8af655b8 100644 --- a/include/haproxy/xprt_qstrm.h +++ b/include/haproxy/xprt_qstrm.h @@ -4,7 +4,6 @@ const struct quic_transport_params *xprt_qstrm_lparams(const void *context); const struct quic_transport_params *xprt_qstrm_rparams(const void *context); -struct buffer *xprt_qstrm_rxbuf(const void *context); -size_t xprt_qstrm_rxrlen(const void *context); +size_t xprt_qstrm_xfer_rxbuf(const void *context, struct buffer *out); #endif /* _HAPROXY_XPRT_QSTRM_H */ diff --git a/src/mux_quic.c b/src/mux_quic.c index d2a1e6e3a..127ff048b 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3847,25 +3847,13 @@ static int qmux_init(struct connection *conn, struct proxy *prx, } if (!conn_is_quic(conn)) { - struct buffer *xprt_buf; - qcc->tx.qstrm_buf = BUF_NULL; qcc->rx.qstrm_buf = BUF_NULL; - /* Retrieve data if xprt read too much */ - xprt_buf = xprt_qstrm_rxbuf(conn->xprt_ctx); - if (unlikely(b_data(xprt_buf))) { - b_alloc(&qcc->rx.qstrm_buf, DB_MUX_RX); - if (!b_size(&qcc->rx.qstrm_buf)) { - TRACE_ERROR("rx qstrm buf alloc failure", QMUX_EV_QCC_NEW); - goto err; - } - b_xfer(&qcc->rx.qstrm_buf, xprt_buf, b_data(xprt_buf)); - qcc->rx.rlen = xprt_qstrm_rxrlen(conn->xprt_ctx); - } - else { - qcc->rx.rlen = 0; - } + /* Rx buffer is transfered from xprt layer - necessary if too many data where read */ + qcc->rx.rlen = xprt_qstrm_xfer_rxbuf(conn->xprt_ctx, &qcc->rx.qstrm_buf); + /* Cannot have a non empty record with an empty buffer. */ + BUG_ON(qcc->rx.rlen && !b_data(&qcc->rx.qstrm_buf)); } if (conn_is_back(conn)) { diff --git a/src/xprt_qstrm.c b/src/xprt_qstrm.c index 6dcac7725..a03f455a8 100644 --- a/src/xprt_qstrm.c +++ b/src/xprt_qstrm.c @@ -39,16 +39,16 @@ const struct quic_transport_params *xprt_qstrm_rparams(const void *context) return &ctx->rparams; } -/* Returns RX buffer as mutable to allow zero-copy by the caller. */ -struct buffer *xprt_qstrm_rxbuf(void *context) +/* Transfer Rx buffer into . */ +size_t xprt_qstrm_xfer_rxbuf(void *context, struct buffer *out) { struct xprt_qstrm_ctx *ctx = context; - return &ctx->rxbuf; -} -size_t xprt_qstrm_rxrlen(const void *context) -{ - const struct xprt_qstrm_ctx *ctx = context; + if (b_data(&ctx->rxbuf)) { + *out = ctx->rxbuf; + ctx->rxbuf = BUF_NULL; + } + return ctx->rxrlen; } @@ -221,6 +221,10 @@ struct task *xprt_qstrm_io_cb(struct task *t, void *context, unsigned int state) conn->xprt_ctx = ctx->ctx_lower; conn->xprt = ctx->ops_lower; + /* MUX layer is responsible to retrieve any remaining data in + * the Rx buffer prior to reset it. + */ + BUG_ON(b_data(&ctx->rxbuf)); b_free(&ctx->rxbuf); b_free(&ctx->txbuf);