]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3/mux: detect fin on last h3 frame of the stream
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 24 Aug 2021 14:28:47 +0000 (16:28 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Sep 2021 13:27:25 +0000 (15:27 +0200)
include/haproxy/mux_quic-t.h
src/h3.c
src/mux_quic.c

index 97a6dd765e54b765bba9f670e52f3c2ad28a3cbd..a78a9024bf7c90cb4b3ac1bafe9c4f31be9a9ea6 100644 (file)
@@ -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 */
index 7b1245c8370ac6a9942b310c1fd566071e6ec400..45406803475b35ed20c59631f887fbb53637211b 100644 (file)
--- 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);
 
index 83229c2cb2d665eacbd7a22ce1efed00a507acb9..cb710118c763d7ba81b48ab0e6a096a89df0653a 100644 (file)
@@ -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;
                        }