]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: h2: silently ignore frames higher than last_id after GOAWAY
authorWilly Tarreau <w@1wt.eu>
Mon, 30 Oct 2017 17:38:00 +0000 (18:38 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 17:16:19 +0000 (18:16 +0100)
For a graceful shutdown, the specs requries to discard frames with a
stream ID higher than the advertised last_id. (RFC7540#6.8). Well,
finally for now the code is disabled (see last page of #6.8). Some
frames need to be processed anyway to maintain the compression state
and the flow control window state, but we don't have any trivial way
to do this and ignore them at the same time. For the headers it's
the worst case where we can't parse headers frames without coming
from the streams, and we don't want to create such streams as we'd
have to abort them, and aborting would cause errors to flow back.

Possibly that a longterm solution might involve using some dummy
streams and dummy buffers for this and calling the parsers directly.

src/mux_h2.c

index 2f7d4d72d3f6334ff1e7bae3bcf477f339165c06..22340d43fdbfe613fad3c14ce5c6baf032223645 100644 (file)
@@ -1622,6 +1622,28 @@ static void h2_process_demux(struct h2c *h2c)
                        goto strm_err;
                }
 
+#if 0
+               // problem below: it is not possible to completely ignore such
+               // streams as we need to maintain the compression state as well
+               // and for this we need to completely process these frames (eg:
+               // HEADERS frames) as well as counting DATA frames to emit
+               // proper WINDOW UPDATES and ensure the connection doesn't stall.
+               // This is a typical case of layer violation where the
+               // transported contents are critical to the connection's
+               // validity and must be ignored at the same time :-(
+
+               /* graceful shutdown, ignore streams whose ID is higher than
+                * the one advertised in GOAWAY. RFC7540#6.8.
+                */
+               if (unlikely(h2c->last_sid >= 0) && h2c->dsi > h2c->last_sid) {
+                       ret = MIN(h2c->dbuf->i, h2c->dfl);
+                       bi_del(h2c->dbuf, ret);
+                       h2c->dfl -= ret;
+                       ret = h2c->dfl == 0;
+                       goto strm_err;
+               }
+#endif
+
                switch (h2c->dft) {
                case H2_FT_SETTINGS:
                        if (h2c->st0 == H2_CS_FRAME_P)