]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h1: Xfer as much payload data as possible during output processing
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 14 Oct 2019 12:01:24 +0000 (14:01 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 14 Oct 2019 20:28:44 +0000 (22:28 +0200)
When an outgoing HTX message is formatted to a raw message, DATA blocks may be
splitted to not tranfser more data than expected. But if the buffer is almost
full, the formatting is interrupted, leaving some unused free space in the
buffer, because data are too large to be copied in one time.

Now, we transfer as much data as possible. When the message is chunked, we also
count the size used to encode the data.

src/mux_h1.c

index 3c3beadff82593834e6eb03a3fc53ded47c922e3..935c925dc6d591931f8c473024e03bf1c6312577 100644 (file)
@@ -1571,14 +1571,11 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
                struct ist n, v;
                enum htx_blk_type type = htx_get_blk_type(blk);
                uint32_t sz = htx_get_blksz(blk);
-               uint32_t vlen;
+               uint32_t vlen, chklen;
 
                vlen = sz;
-               if (vlen > count) {
-                       if (type != HTX_BLK_DATA)
-                               goto full;
-                       vlen = count;
-               }
+               if (type != HTX_BLK_DATA && vlen > count)
+                       goto full;
 
                if (type == HTX_BLK_UNUSED)
                        goto nextblk;
@@ -1772,6 +1769,28 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
                                        goto error;
 
                                TRACE_PROTO("sending message data", H1_EV_TX_DATA|H1_EV_TX_BODY, h1c->conn, h1s, chn_htx, (size_t[]){sz});
+
+
+                               if (vlen > count) {
+                                       /* Get the maximum amount of data we can xferred */
+                                       vlen = count;
+                               }
+
+                               chklen = 0;
+                               if (h1m->flags & H1_MF_CHNK) {
+                                       chklen = b_room(&tmp);
+                                       chklen = ((chklen < 16) ? 1 : (chklen < 256) ? 2 :
+                                                 (chklen < 4096) ? 3 : (chklen < 65536) ? 4 :
+                                                 (chklen < 1048576) ? 5 : 8);
+                                       chklen += 4; /* 2 x CRLF */
+                               }
+
+                               if (vlen + chklen > b_room(&tmp)) {
+                                       /* too large for the buffer */
+                                       if (chklen >= b_room(&tmp))
+                                               goto full;
+                                       vlen = b_room(&tmp) - chklen;
+                               }
                                v = htx_get_blk_value(chn_htx, blk);
                                v.len = vlen;
                                if (!htx_data_to_h1(v, &tmp, !!(h1m->flags & H1_MF_CHNK)))