]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h2: Handle EOM flag when sending a DATA frame with zero-copy
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 27 Apr 2021 20:51:07 +0000 (22:51 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 28 Apr 2021 09:08:35 +0000 (11:08 +0200)
When a DATA frame is sent, we must take care to properly detect the EOM flag
on the HTX message to set ES flag on the frame when necessary, to finish the
stream. But it is only done when data are copied from the HTX message to the
mux buffer and not when the frame are sent via a zero-copy. This patch fixes
this bug.

It is a 2.4-specific bug. No backport is needed.

src/mux_h2.c

index f1749f8d13a68a4993833a856a0dbfbf792473e5..ebae4382c375e60c22c935949f580e1fae09b259 100644 (file)
@@ -5703,6 +5703,13 @@ static size_t h2s_make_data(struct h2s *h2s, struct buffer *buf, size_t count)
                        goto end;
                }
 
+               if (htx->flags & HTX_FL_EOM) {
+                       /* EOM+empty: we may need to add END_STREAM (except for tunneled
+                        * message)
+                        */
+                       if (!(h2s->flags & H2_SF_BODY_TUNNEL))
+                               es_now = 1;
+               }
                /* map an H2 frame to the HTX block so that we can put the
                 * frame header there.
                 */
@@ -5712,6 +5719,8 @@ static size_t h2s_make_data(struct h2s *h2s, struct buffer *buf, size_t count)
                /* prepend an H2 DATA frame header just before the DATA block */
                memcpy(outbuf.area, "\x00\x00\x00\x00\x00", 5);
                write_n32(outbuf.area + 5, h2s->id); // 4 bytes
+               if (es_now)
+                       outbuf.area[4] |= H2_F_DATA_END_STREAM;
                h2_set_frame_size(outbuf.area, fsize);
 
                /* update windows */
@@ -5722,9 +5731,10 @@ static size_t h2s_make_data(struct h2s *h2s, struct buffer *buf, size_t count)
                buf->area = old_area;
                buf->data = buf->head = 0;
                total += fsize;
+               fsize = 0;
 
                TRACE_PROTO("sent H2 DATA frame (zero-copy)", H2_EV_TX_FRAME|H2_EV_TX_DATA, h2c->conn, h2s);
-               goto end;
+               goto out;
        }
 
  copy:
@@ -5847,6 +5857,7 @@ static size_t h2s_make_data(struct h2s *h2s, struct buffer *buf, size_t count)
        /* commit the H2 response */
        b_add(mbuf, fsize + 9);
 
+ out:
        if (es_now) {
                if (h2s->st == H2_SS_OPEN)
                        h2s->st = H2_SS_HLOC;