]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: adjust buffer handling for STREAM transmission
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 23 Feb 2022 09:54:42 +0000 (10:54 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 25 Feb 2022 14:06:17 +0000 (15:06 +0100)
Simplify the data manipulation of STREAM frames on TX. Only stream data
and len field are used to generate a valid STREAM frames from the
buffer. Do not use the offset field, which required that a single buffer
instance should be shared for every frames on a single stream.

include/haproxy/quic_frame-t.h
src/mux_quic.c
src/quic_frame.c
src/xprt_quic.c

index 1d2d354210d806954468d11b0b54513789399947..057ad1563addb750dbc63e0de322ccba16835297 100644 (file)
@@ -148,10 +148,23 @@ struct quic_new_token {
 struct quic_stream {
        uint64_t id;
        struct qcs *qcs;
+
+       /* used only on TX when constructing frames.
+        * Data cleared when processing ACK related to this STREAM frame.
+        *
+        * A same buffer may be shared between several STREAM frames. The
+        * <data> field of each quic_stream serves to differentiate the payload
+        * of each of these.
+        */
        struct buffer *buf;
+
        struct eb64_node offset;
        uint64_t len;
        int fin;
+
+       /* for TX pointer into <buf> field.
+        * for RX pointer into the packet buffer.
+        */
        const unsigned char *data;
 };
 
index e286d6a9aa92545ed3af0d826d01163d9e5a3874..4be7d83d8630174d5871b999ce0248e618936e05 100644 (file)
@@ -271,6 +271,7 @@ static int qcs_push_frame(struct qcs *qcs, struct buffer *payload, int fin, uint
        struct buffer *buf = &qcs->tx.xprt_buf;
        struct quic_enc_level *qel = &qcs->qcc->conn->qc->els[QUIC_TLS_ENC_LEVEL_APP];
        int total = 0, to_xfer;
+       unsigned char *btail;
 
        fprintf(stderr, "%s\n", __func__);
 
@@ -283,6 +284,8 @@ static int qcs_push_frame(struct qcs *qcs, struct buffer *payload, int fin, uint
        if (!frm)
                goto err;
 
+       /* store buffer end before transfering data for frm.stream.data */
+       btail = (unsigned char *)b_tail(buf);
        total = b_force_xfer(buf, payload, to_xfer);
        /* FIN is positioned only when the buffer has been totally emptied. */
        fin = fin && !b_data(payload);
@@ -295,6 +298,7 @@ static int qcs_push_frame(struct qcs *qcs, struct buffer *payload, int fin, uint
        }
        frm->stream.qcs = (struct qcs *)qcs;
        frm->stream.buf = buf;
+       frm->stream.data = btail;
        frm->stream.id = qcs->by_id.key;
        if (total) {
                frm->type |= QUIC_STREAM_FRAME_TYPE_LEN_BIT;
index 0adce4c1f79b86bff9a862038c680d1525a0f39a..c5adddc1bb9d095ce4b86f72dbea5647a991cd92 100644 (file)
@@ -501,8 +501,7 @@ static int quic_build_stream_frame(unsigned char **buf, const unsigned char *end
                                    struct quic_frame *frm, struct quic_conn *conn)
 {
        struct quic_stream *stream = &frm->stream;
-       size_t offset, block1, block2;
-       struct buffer b;
+       const unsigned char *wrap;
 
        if (!quic_enc_int(buf, end, stream->id) ||
            ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(buf, end, stream->offset.key)) ||
@@ -510,19 +509,19 @@ static int quic_build_stream_frame(unsigned char **buf, const unsigned char *end
             (!quic_enc_int(buf, end, stream->len) || end - *buf < stream->len)))
                return 0;
 
-       /* Buffer copy */
-       b = *stream->buf;
-       offset = (frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ?
-               stream->offset.key & (b_size(stream->buf) - 1): 0;
-       block1 = b_wrap(&b) - (b_orig(&b) + offset);
-       if (block1 > stream->len)
-               block1 = stream->len;
-       block2 = stream->len - block1;
-       memcpy(*buf, b_orig(&b) + offset, block1);
-       *buf += block1;
-       if (block2) {
-               memcpy(*buf, b_orig(&b), block2);
-               *buf += block2;
+       wrap = (const unsigned char *)b_wrap(stream->buf);
+       if (stream->data + stream->len > wrap) {
+               size_t to_copy = wrap - stream->data;
+               memcpy(*buf, stream->data, to_copy);
+               *buf += to_copy;
+
+               to_copy = stream->len - to_copy;
+               memcpy(*buf, b_orig(stream->buf), to_copy);
+               *buf += to_copy;
+       }
+       else {
+               memcpy(*buf, stream->data, stream->len);
+               *buf += stream->len;
        }
 
        return 1;
index 52f843dd22d9fa2c0a291621e302a55abc975c89..a6eda370b54a37b1f3e2250780774f11334bcb3c 100644 (file)
@@ -4775,6 +4775,7 @@ static inline int qc_build_frms(struct list *l,
                        }
                        else {
                                struct quic_frame *new_cf;
+                               struct buffer cf_buf;
 
                                new_cf = pool_zalloc(pool_head_quic_frame);
                                if (!new_cf) {
@@ -4796,9 +4797,12 @@ static inline int qc_build_frms(struct list *l,
                                LIST_APPEND(l, &new_cf->list);
                                cf->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;
                                /* Consume <dlen> bytes of the current frame. */
+                               cf_buf = b_make(b_orig(cf->stream.buf),
+                                               b_size(cf->stream.buf),
+                                               (char *)cf->stream.data - b_orig(cf->stream.buf), 0);
                                cf->stream.len -= dlen;
                                cf->stream.offset.key += dlen;
-                               cf->stream.data += dlen;
+                               cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen);
                        }
                        break;