From 84ea8dcbc45cb0ae9f966bbf1882f48fe4a7037f Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Fri, 3 Dec 2021 14:40:01 +0100 Subject: [PATCH] MEDIUM: mux-quic: handle when sending buffer is full Handle the case when the app layer sending buffer is full. A new flag QC_SF_BLK_MROOM is set in this case and the transfer is interrupted. It is expected that then the conn-stream layer will subscribe to SEND. The MROOM flag is reset each time the muxer transfer data from the app layer to its own buffer. If the app layer has been subscribed on SEND it is woken up. --- include/haproxy/mux_quic-t.h | 1 + src/h3.c | 13 ++++++++----- src/hq_interop.c | 2 +- src/mux_quic.c | 3 +++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index 3bded6753..1515a5bc5 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -55,6 +55,7 @@ struct qcc { #define QC_SF_NONE 0x00000000 #define QC_SF_FIN_STREAM 0x00000001 // FIN bit must be set for last frame of the stream +#define QC_SF_BLK_MROOM 0x00000002 // app layer is blocked waiting for room in the qcs.tx.buf struct qcs { struct qcc *qcc; diff --git a/src/h3.c b/src/h3.c index 359b27676..0ed180027 100644 --- a/src/h3.c +++ b/src/h3.c @@ -534,11 +534,14 @@ static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count) b_slow_realign(res, trash.area, b_data(res)); } - /* not enough room for headers and at least one data byte, block the - * stream + /* Not enough room for headers and at least one data byte, block the + * stream. It is expected that the conn-stream layer will subscribe on + * SEND. */ - if (b_size(&outbuf) <= hsize) - ABORT_NOW(); + if (b_size(&outbuf) <= hsize) { + qcs->flags |= QC_SF_BLK_MROOM; + goto end; + } if (b_size(&outbuf) < hsize + fsize) fsize = b_size(&outbuf) - hsize; @@ -579,7 +582,7 @@ size_t h3_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int htx = htx_from_buf(buf); - while (count && !htx_is_empty(htx)) { + while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) { idx = htx_get_head(htx); blk = htx_get_blk(htx, idx); btype = htx_get_blk_type(blk); diff --git a/src/hq_interop.c b/src/hq_interop.c index 3d530f4bf..075e785b0 100644 --- a/src/hq_interop.c +++ b/src/hq_interop.c @@ -81,7 +81,7 @@ static size_t hq_interop_snd_buf(struct conn_stream *cs, struct buffer *buf, res = mux_get_buf(qcs); outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0); - while (count && !htx_is_empty(htx)) { + while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) { /* Not implemented : QUIC on backend side */ idx = htx_get_head(htx); blk = htx_get_blk(htx, idx); diff --git a/src/mux_quic.c b/src/mux_quic.c index c11e1cedd..2a28a5155 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -193,6 +193,9 @@ static int qc_send(struct qcc *qcc) if (ret > 0) { qcs_notify_send(qcs); + if (qcs->flags & QC_SF_BLK_MROOM) + qcs->flags &= ~QC_SF_BLK_MROOM; + xprt_wake = 1; }