/* Retrieve data if xprt read too much */
xprt_buf = xprt_qstrm_rxbuf(conn->xprt_ctx);
- if (unlikely(b_data(xprt_buf)))
+ if (unlikely(b_data(xprt_buf))) {
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;
+ }
}
if (conn_is_back(conn)) {
#include <haproxy/fd.h>
#include <haproxy/global.h>
#include <haproxy/mux_quic.h>
+#include <haproxy/mux_quic_qstrm.h>
#include <haproxy/pool.h>
#include <haproxy/quic_frame.h>
#include <haproxy/quic_tp-t.h>
struct buffer txbuf;
struct buffer rxbuf;
+ size_t rxrlen;
};
DECLARE_STATIC_TYPED_POOL(xprt_qstrm_ctx_pool, "xprt_qstrm_ctx", struct xprt_qstrm_ctx);
return &ctx->rxbuf;
}
+size_t xprt_qstrm_rxrlen(const void *context)
+{
+ const struct xprt_qstrm_ctx *ctx = context;
+ return ctx->rxrlen;
+}
+
int conn_recv_qstrm(struct connection *conn, struct xprt_qstrm_ctx *ctx, int flag)
{
struct quic_frame frm;
struct buffer *buf = &ctx->rxbuf;
- const unsigned char *pos, *end;
+ const unsigned char *pos, *old, *end;
size_t ret;
if (!conn_ctrl_ready(conn))
if (!b_data(buf))
goto not_ready;
- pos = (unsigned char *)b_orig(buf);
- end = (unsigned char *)(b_orig(buf) + b_data(buf));
- if (!qc_parse_frm_type(&frm, &pos, end, NULL))
+ /* Read record length. */
+ if (!b_quic_dec_int(&ctx->rxrlen, buf, NULL))
goto not_ready;
+ /* Reject too small or too big records. */
+ if (!ctx->rxrlen || ctx->rxrlen > b_size(buf))
+ goto fail;
+ if (ctx->rxrlen > b_data(buf))
+ goto not_ready;
+
+ old = pos = (unsigned char *)b_head(buf);
+ end = pos + ctx->rxrlen;
+ if (!qc_parse_frm_type(&frm, &pos, end, NULL))
+ goto fail;
+
/* TODO close connection with TRANSPORT_PARAMETER_ERROR if frame not present. */
BUG_ON(frm.type != QUIC_FT_QX_TRANSPORT_PARAMETERS);
if (!qc_parse_frm_payload(&frm, &pos, end, NULL))
- goto not_ready;
+ goto fail;
ctx->rparams = frm.qmux_transport_params.params;
+ b_del(buf, pos - old);
+ /* <end> delimiter should guarantee than frame length does not go beyong the record end */
+ BUG_ON(ctx->rxrlen < pos - old);
+ ctx->rxrlen -= (pos - old);
conn->flags &= ~flag;
return 1;
ctx->ops_lower = NULL;
ctx->rxbuf = BUF_NULL;
+ ctx->rxrlen = 0;
ctx->txbuf = BUF_NULL;
memset(&ctx->rparams, 0, sizeof(struct quic_transport_params));