]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h2: handle RST_STREAM frames
authorWilly Tarreau <w@1wt.eu>
Fri, 18 Aug 2017 08:59:39 +0000 (10:59 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 17:16:19 +0000 (18:16 +0100)
These ones are received when the browser aborts a page load, it's the
only moment we can abort the stream.

src/mux_h2.c

index fb0e90ce86b2661b40fe5f80c2ade16c00fa6d25..e1836008ad5a8e5007efb271b4d6594468bc2073 100644 (file)
@@ -1193,6 +1193,57 @@ static int h2c_handle_window_update(struct h2c *h2c, struct h2s *h2s)
        return 0;
 }
 
+/* processes an RST_STREAM frame, and sets the 32-bit error code on the stream.
+ * Returns > 0 on success or zero on missing data. It may return an error in
+ * h2c. Described in RFC7540#6.4.
+ */
+static int h2c_handle_rst_stream(struct h2c *h2c, struct h2s *h2s)
+{
+       int error;
+
+       if (h2c->dsi == 0) {
+               error = H2_ERR_PROTOCOL_ERROR;
+               goto conn_err;
+       }
+
+       if (h2s->st == H2_SS_IDLE) {
+               error = H2_ERR_PROTOCOL_ERROR;
+               goto conn_err;
+       }
+
+       if (h2c->dfl != 4) {
+               error = H2_ERR_FRAME_SIZE_ERROR;
+               goto conn_err;
+       }
+
+       /* process full frame only */
+       if (h2c->dbuf->i < h2c->dfl)
+               return 0;
+
+       /* late RST, already handled */
+       if (h2s->st == H2_SS_CLOSED)
+               return 1;
+
+       h2s->errcode = h2_get_n32(h2c->dbuf, 0);
+       h2s->st = H2_SS_CLOSED;
+
+       if (h2s->cs) {
+               h2s->cs->flags |= CS_FL_EOS;
+               /* recv is used to force to detect CS_FL_EOS that wake()
+                * doesn't handle in the stream-int code.
+                */
+               h2s->cs->data_cb->recv(h2s->cs);
+               h2s->cs->data_cb->wake(h2s->cs);
+       }
+
+       h2s->flags |= H2_SF_RST_RCVD;
+       return 1;
+
+ conn_err:
+       h2c_error(h2c, error);
+       return 0;
+}
+
 /* processes a HEADERS frame. Returns > 0 on success or zero on missing data.
  * It may return an error in h2c or h2s. Described in RFC7540#6.2. Most of the
  * errors here are reported as connection errors since it's impossible to
@@ -1485,6 +1536,12 @@ static void h2_process_demux(struct h2c *h2c)
                        if (h2c->st0 == H2_CS_FRAME_A)
                                ret = h2c_send_strm_wu(h2c);
                        break;
+
+               case H2_FT_RST_STREAM:
+                       if (h2c->st0 == H2_CS_FRAME_P)
+                               ret = h2c_handle_rst_stream(h2c, h2s);
+                       break;
+
                        /* FIXME: implement all supported frame types here */
                default:
                        /* drop frames that we ignore. They may be larger than