MINOR: h3: handle errors on HEADERS parsing/QPACK decoding
Emit a CONNECTION_CLOSE if HEADERS parsing function returns an error.
This is useful to remove previous ABORT_NOW guards.
For the moment, the whole connection is closed. In the future, it may be
justified to only reset the faulting stream in some cases. This requires
the implementation of RESET_STREAM emission.
diff --git a/src/h3.c b/src/h3.c
index c15adf0..60c003b 100644
--- a/src/h3.c
+++ b/src/h3.c
@@ -326,6 +326,8 @@
static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
uint64_t len, char fin)
{
+ struct h3s *h3s = qcs->ctx;
+ struct h3c *h3c = h3s->h3c;
struct buffer htx_buf = BUF_NULL;
struct buffer *tmp = get_trash_chunk();
struct htx *htx = NULL;
@@ -335,14 +337,17 @@
struct ist meth = IST_NULL, path = IST_NULL;
//struct ist scheme = IST_NULL, authority = IST_NULL;
struct ist authority = IST_NULL;
- int hdr_idx;
+ int hdr_idx, ret;
TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
/* TODO support buffer wrapping */
BUG_ON(b_head(buf) + len >= b_wrap(buf));
- if (qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
- list, sizeof(list) / sizeof(list[0])) < 0) {
+ ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
+ list, sizeof(list) / sizeof(list[0]));
+ if (ret < 0) {
+ TRACE_ERROR("QPACK decoding error", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+ h3c->err = -ret;
return -1;
}
@@ -375,8 +380,10 @@
flags |= HTX_SL_F_XFER_LEN;
sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, path, ist("HTTP/3.0"));
- if (!sl)
+ if (!sl) {
+ h3c->err = H3_INTERNAL_ERROR;
return -1;
+ }
if (fin)
sl->flags |= HTX_SL_F_BODYLESS;
@@ -404,8 +411,10 @@
if (fin)
htx->flags |= HTX_FL_EOM;
- if (!qc_attach_sc(qcs, &htx_buf))
+ if (!qc_attach_sc(qcs, &htx_buf)) {
+ h3c->err = H3_INTERNAL_ERROR;
return -1;
+ }
/* buffer is transferred to the stream connector and set to NULL
* except on stream creation error.
@@ -651,8 +660,14 @@
break;
case H3_FT_HEADERS:
ret = h3_headers_to_htx(qcs, b, flen, last_stream_frame);
- /* TODO handle error reporting. Stream closure required. */
- if (ret < 0) { ABORT_NOW(); }
+ if (ret < 0) {
+ /* TODO for some error, it may be preferable to
+ * only close the stream once RESET_STREAM is
+ * supported.
+ */
+ qcc_emit_cc_app(qcs->qcc, h3c->err);
+ return -1;
+ }
break;
case H3_FT_CANCEL_PUSH:
case H3_FT_PUSH_PROMISE: