]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: h2: detect the presence of the first settings frame
authorWilly Tarreau <w@1wt.eu>
Tue, 10 Oct 2017 13:16:55 +0000 (15:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 17:16:18 +0000 (18:16 +0100)
Instead of doing a special processing of the first SETTINGS frame, we
simply parse its header, check that it matches the expected frame type
and flags (ie no ACK), and switch to FRAME_P to parse it as any regular
frame. The regular frame parser will take care of decoding it.

src/mux_h2.c

index d2d8574fa3c368ebe161b1d5b1a2ad10d84ceab0..71111eb53d31cd99c5ec7b841ec844772d11cc19 100644 (file)
@@ -771,7 +771,41 @@ static void h2_process_demux(struct h2c *h2c)
                        h2c->max_id = 0;
                        h2c->st0 = H2_CS_SETTINGS1;
                }
-               /* deal with SETTINGS here */
+
+               if (h2c->st0 == H2_CS_SETTINGS1) {
+                       struct h2_fh hdr;
+
+                       /* ensure that what is pending is a valid SETTINGS frame
+                        * without an ACK.
+                        */
+                       if (!h2_get_frame_hdr(h2c->dbuf, &hdr)) {
+                               /* RFC7540#3.5: a GOAWAY frame MAY be omitted */
+                               if (h2c->st0 == H2_CS_ERROR)
+                                       h2c->st0 = H2_CS_ERROR2;
+                               goto fail;
+                       }
+
+                       if (hdr.sid || hdr.ft != H2_FT_SETTINGS || hdr.ff & H2_F_SETTINGS_ACK) {
+                               /* RFC7540#3.5: a GOAWAY frame MAY be omitted */
+                               h2c_error(h2c, H2_ERR_PROTOCOL_ERROR);
+                               h2c->st0 = H2_CS_ERROR2;
+                               goto fail;
+                       }
+
+                       if ((int)hdr.len < 0 || (int)hdr.len > h2c->mfs) {
+                               /* RFC7540#3.5: a GOAWAY frame MAY be omitted */
+                               h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR);
+                               h2c->st0 = H2_CS_ERROR2;
+                               goto fail;
+                       }
+
+                       /* that's OK, switch to FRAME_P to process it */
+                       h2c->dfl = hdr.len;
+                       h2c->dsi = hdr.sid;
+                       h2c->dft = hdr.ft;
+                       h2c->dff = hdr.ff;
+                       h2c->st0 = H2_CS_FRAME_P;
+               }
        }
        return;