*/
enum {
QPACK_ERR_NONE = 0, /* no error */
+ QPACK_ERR_DECOMP, /* corresponds to RFC 9204 decompression error */
QPACK_ERR_RIC, /* cannot decode Required Insert Count prefix field */
QPACK_ERR_DB, /* cannot decode Delta Base prefix field */
QPACK_ERR_TRUNCATED, /* truncated stream */
int qpack_decode_enc(struct buffer *buf, int fin, void *ctx);
int qpack_decode_dec(struct buffer *buf, int fin, void *ctx);
+int qpack_err_decode(const int value);
+
#endif /* _HAPROXY_QPACK_DEC_H */
struct h3c {
struct qcc *qcc;
struct qcs *ctrl_strm; /* Control stream */
- enum h3_err err;
+ int err;
uint32_t flags;
/* Settings */
return 0;
}
+/* Return <value> as is or H3_INTERNAL_ERROR if negative. Useful to prepare a standard error code. */
+static int h3_err(const int value)
+{
+ return value >= 0 ? value : H3_INTERNAL_ERROR;
+}
+
/* Parse from buffer <buf> a H3 HEADERS frame of length <len>. Data are copied
* in a local HTX buffer and transfer to the stream connector layer. <fin> must be
* set if this is the last data to transfer from this stream.
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;
+ h3c->err = h3_err(qpack_err_decode(ret));
len = -1;
goto out;
}
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;
+ h3c->err = h3_err(qpack_err_decode(ret));
len = -1;
goto out;
}
* Count (Section 4.5.1), it MUST treat this as a connection error of
* type QPACK_DECOMPRESSION_FAILED.
*/
- return -QPACK_DECOMPRESSION_FAILED;
+ return -QPACK_ERR_DECOMP;
}
else if (efl_type == QPACK_IFL_WPBI) {
/* Indexed field line with post-base index
* Count (Section 4.5.1), it MUST treat this as a connection error of
* type QPACK_DECOMPRESSION_FAILED.
*/
- return -QPACK_DECOMPRESSION_FAILED;
+ return -QPACK_ERR_DECOMP;
}
else if (efl_type & QPACK_IFL_BIT) {
/* Indexed field line */
*
* TODO adjust this when dynamic table support is implemented.
*/
- return -QPACK_DECOMPRESSION_FAILED;
+ return -QPACK_ERR_DECOMP;
}
qpack_debug_printf(stderr, " t=%d index=%llu", !!static_tbl, (unsigned long long)index);
*
* TODO adjust this when dynamic table support is implemented.
*/
- return -QPACK_DECOMPRESSION_FAILED;
+ return -QPACK_ERR_DECOMP;
}
qpack_debug_printf(stderr, " n=%d t=%d index=%llu", !!n, !!static_tbl, (unsigned long long)index);
trash = chunk_newstr(tmp);
if (!trash) {
qpack_debug_printf(stderr, "##ERR@%d\n", __LINE__);
- ret = -QPACK_DECOMPRESSION_FAILED;
+ ret = -QPACK_ERR_TOO_LARGE;
goto out;
}
nlen = huff_dec(raw, length, trash, tmp->size - tmp->data);
trash = chunk_newstr(tmp);
if (!trash) {
qpack_debug_printf(stderr, "##ERR@%d\n", __LINE__);
- ret = -QPACK_DECOMPRESSION_FAILED;
+ ret = -QPACK_ERR_TOO_LARGE;
goto out;
}
nlen = huff_dec(raw, name_len, trash, tmp->size - tmp->data);
trash = chunk_newstr(tmp);
if (!trash) {
qpack_debug_printf(stderr, "##ERR@%d\n", __LINE__);
- ret = -QPACK_DECOMPRESSION_FAILED;
+ ret = -QPACK_ERR_TOO_LARGE;
goto out;
}
nlen = huff_dec(raw, value_len, trash, tmp->size - tmp->data);
*/
if (!name.len) {
qpack_debug_printf(stderr, "##ERR@%d\n", __LINE__);
- ret = -QPACK_DECOMPRESSION_FAILED;
+ ret = -QPACK_ERR_DECOMP;
goto out;
}
qpack_debug_printf(stderr, "-- done: ret=%d\n", ret);
return ret;
}
+
+/* Convert return value from qpack_decode_fs() to a standard error code usable
+ * in CONNECTION_CLOSE or -1 for an internal error.
+ */
+int qpack_err_decode(const int value)
+{
+ return (value == -QPACK_ERR_DECOMP) ? QPACK_DECOMPRESSION_FAILED : -1;
+}