]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: mux-h1: Use RAW_DATA blocks to store tunneled data
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 15 Sep 2026 12:00:08 +0000 (14:00 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 18 Sep 2026 15:05:19 +0000 (17:05 +0200)
When a H1 stream is switched in tunnel mode, the transfer length is unknown
and the data are read till the shutdown. This is exactly the same code path
than a message without any transfer length information. So the block type to
use is chosen depending on the parser state: in H1_MSG_TUNNEL state, the
data are tunneled data and a RAW_DATA block is used. Otherwise it is still an
HTTP payload and a DATA block is used.

h1_copy_msg_data() takes the block type as extra argument for that purpose.

Thanks to this change, HTTP data and tunneled data are no longer mixed on
the H1 side. It also means the end of the message, reported just after the
headers for a tunneled stream, is now preserved when tunneled data are
received.

src/h1_htx.c

index 8b25d33cfa23e558ca71f2125f62444c15577b20..24daf0a3cebb013230679d47c1161cd7ad0d545d 100644 (file)
@@ -476,7 +476,8 @@ int h1_parse_msg_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx *dsthtx,
  * zero-copy is performed. It returns the number of bytes copied.
  */
 static size_t h1_copy_msg_data(struct htx **dsthtx, struct buffer *srcbuf, size_t ofs,
-                              size_t count, size_t max, struct buffer *htxbuf)
+                              size_t count, size_t max, struct buffer *htxbuf,
+                              enum htx_blk_type type)
 {
        struct htx *tmp_htx = *dsthtx;
        size_t block1, block2, ret = 0;
@@ -512,7 +513,7 @@ static size_t h1_copy_msg_data(struct htx **dsthtx, struct buffer *srcbuf, size_
                htx_reset(tmp_htx);
                b_set_data(htxbuf, b_size(htxbuf));
 
-               blk = htx_add_blk(tmp_htx, HTX_BLK_DATA, count);
+               blk = htx_add_blk(tmp_htx, type, count);
                blk->info += count;
 
                *dsthtx = tmp_htx;
@@ -541,9 +542,9 @@ static size_t h1_copy_msg_data(struct htx **dsthtx, struct buffer *srcbuf, size_
                        block2 = max;
        }
 
-       ret = htx_add_data(tmp_htx, ist2(b_peek(srcbuf, ofs), block1));
+       ret = htx_add_data_type(tmp_htx, ist2(b_peek(srcbuf, ofs), block1), type);
        if (ret == block1 && block2)
-               ret += htx_add_data(tmp_htx, ist2(b_orig(srcbuf), block2));
+               ret += htx_add_data_type(tmp_htx, ist2(b_orig(srcbuf), block2), type);
   end:
        return ret;
 }
@@ -583,7 +584,7 @@ static size_t h1_parse_chunk(struct h1m *h1m, struct htx **dsthtx,
                sz =  b_data(srcbuf) - ofs;
                if (unlikely(sz > h1m->curr_len))
                        sz = h1m->curr_len;
-               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, lmax, htxbuf);
+               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, lmax, htxbuf, HTX_BLK_DATA);
                lmax -= htx_used_space(*dsthtx) - used;
                ofs += sz;
                total += sz;
@@ -933,7 +934,7 @@ size_t h1_parse_msg_data(struct h1m *h1m, struct htx **dsthtx,
                sz = b_data(srcbuf) - ofs;
                if (unlikely(sz > h1m->curr_len))
                        sz = h1m->curr_len;
-               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, max, htxbuf);
+               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, max, htxbuf, HTX_BLK_DATA);
                h1m->curr_len -= sz;
                total += sz;
                if (!h1m->curr_len) {
@@ -953,9 +954,13 @@ size_t h1_parse_msg_data(struct h1m *h1m, struct htx **dsthtx,
                htx_set_eom(*dsthtx);
        }
        else {
-               /* no content length, read till SHUTW */
+               /* no content length, read till SHUTW. In TUNNEL state, these
+                * data are tunneled data. They must not be mixed with HTTP
+                * data, so a dedicated block type is used for them.
+                */
                sz = b_data(srcbuf) - ofs;
-               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, max, htxbuf);
+               sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, max, htxbuf,
+                                     (h1m->state == H1_MSG_TUNNEL ? HTX_BLK_RAW_DATA : HTX_BLK_DATA));
                total += sz;
                h1m->body_len += sz;
        }