From: Amaury Denoyelle Date: Tue, 24 Aug 2021 14:28:47 +0000 (+0200) Subject: MINOR: h3/mux: detect fin on last h3 frame of the stream X-Git-Tag: v2.5-dev8~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42bb8aac659cd4bb3ced811e3e6d0137d5f13d56;p=thirdparty%2Fhaproxy.git MINOR: h3/mux: detect fin on last h3 frame of the stream --- diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index 97a6dd765e..a78a9024bf 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -202,6 +202,7 @@ struct qcs { uint64_t bytes; /* number of bytes sent */ struct buffer buf; /* transmit buffer, always valid (buf_empty or real buffer) */ struct buffer mbuf[QCC_MBUF_CNT]; + uint64_t left; /* data currently stored in mbuf waiting for send */ } tx; struct wait_event *subs; /* recv wait_event the conn_stream associated is waiting on (via qc_subscribe) */ struct list list; /* To be used when adding in qcc->send_list or qcc->fctl_lsit */ diff --git a/src/h3.c b/src/h3.c index 7b1245c837..4540680347 100644 --- a/src/h3.c +++ b/src/h3.c @@ -517,6 +517,7 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx) if (!b_quic_enc_int(res, b_data(&headers_buf))) ABORT_NOW(); b_add(res, b_data(&headers_buf)); + qcs->tx.left += 1 + frame_length_size + b_data(&headers_buf); ret = 0; blk = htx_get_head_blk(htx); @@ -528,6 +529,9 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx) break; } + if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx) && status >= 200) + qcs->flags |= QC_SF_FIN_STREAM; + return ret; err: @@ -585,6 +589,7 @@ static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count) htx_cut_data_blk(htx, blk, fsize); b_add(res, b_data(&outbuf)); + qcs->tx.left += b_data(&outbuf); goto new_frame; end: @@ -648,6 +653,8 @@ size_t h3_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t count, int } } + if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx)) + qcs->flags |= QC_SF_FIN_STREAM; // TODO should I call the mux directly here ? qc_snd_buf(cs, buf, total, flags); diff --git a/src/mux_quic.c b/src/mux_quic.c index 83229c2cb2..cb710118c7 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -984,6 +984,7 @@ struct qcs *bidi_qcs_new(struct qcc *qcc, uint64_t id) qcs->tx.max_data = qcc->strms[qcs_type].tx.max_data; qcs->tx.buf = BUF_NULL; br_init(qcs->tx.mbuf, sizeof(qcs->tx.mbuf) / sizeof(qcs->tx.mbuf[0])); + qcs->tx.left = 0; eb64_insert(&qcc->streams_by_id, &qcs->by_id); qcc->strms[qcs_type].nb_streams++; @@ -1048,6 +1049,7 @@ struct qcs *luqs_new(struct qcc *qcc) qcs->tx.offset = qcs->tx.bytes = 0; qcs->tx.buf = BUF_NULL; br_init(qcs->tx.mbuf, sizeof(qcs->tx.mbuf) / sizeof(qcs->tx.mbuf[0])); + qcs->tx.left = 0; qcs->subs = NULL; LIST_INIT(&qcs->list); @@ -1089,6 +1091,7 @@ struct qcs *ruqs_new(struct qcc *qcc, uint64_t id) qcs->rx.offset = qcs->rx.bytes = 0; qcs->rx.buf = BUF_NULL; br_init(qcs->tx.mbuf, sizeof(qcs->tx.mbuf) / sizeof(qcs->tx.mbuf[0])); + qcs->tx.left = 0; qcs->subs = NULL; LIST_INIT(&qcs->list); @@ -1448,10 +1451,21 @@ static int qc_process(struct qcc *qcc) for (buf = br_head(qcs->tx.mbuf); b_data(buf); buf = br_del_head(qcs->tx.mbuf)) { if (b_data(buf)) { int ret; - ret = qcs_push_frame(qcs, buf, 0, qcs->tx.offset); + char fin = 0; + + /* if FIN is activated, ensure the buffer to + * send is the last + */ + if (qcs->flags & QC_SF_FIN_STREAM) { + BUG_ON(qcs->tx.left < b_data(buf)); + fin = !(qcs->tx.left - b_data(buf)); + } + + ret = qcs_push_frame(qcs, buf, fin, qcs->tx.offset); if (ret <= 0) ABORT_NOW(); + qcs->tx.left -= ret; qcs->tx.offset += ret; qcs->qcc->wait_event.events &= ~SUB_RETRY_SEND; }