diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h index fca28f7fa..40f784c31 100644 --- a/include/haproxy/mux_quic-t.h +++ b/include/haproxy/mux_quic-t.h @@ -100,6 +100,7 @@ struct qcc { #define QC_SF_DETACH 0x00000008 /* cs is detached but there is remaining data to send */ #define QC_SF_BLK_SFCTL 0x00000010 /* stream blocked due to stream flow control limit */ #define QC_SF_DEM_FULL 0x00000020 /* demux blocked on request channel buffer full */ +#define QC_SF_READ_ABORTED 0x00000040 /* stream rejected by app layer */ struct qcs { struct qcc *qcc; diff --git a/src/h3.c b/src/h3.c index a792851ab..3fb6942b8 100644 --- a/src/h3.c +++ b/src/h3.c @@ -144,8 +144,13 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs, break; default: - h3s->flags |= H3_SF_UNI_NO_H3; - break; + /* draft-ietf-quic-http34 9. Extensions to HTTP/3 + * + * Implementations MUST [...] abort reading on unidirectional + * streams that have unknown or unsupported types. + */ + qcs->flags |= QC_SF_READ_ABORTED; + return 1; }; h3s->flags |= H3_SF_UNI_INIT; @@ -175,10 +180,10 @@ static int h3_parse_uni_stream_no_h3(struct qcs *qcs, struct ncbuf *rxbuf) if (!qpack_decode_enc(qcs, NULL)) return 1; break; + case H3S_T_UNKNOWN: default: - /* unknown uni stream : just consume it. */ - qcs_consume(qcs, ncb_data(rxbuf, 0)); - break; + /* Unknown stream should be flagged with QC_SF_READ_ABORTED. */ + ABORT_NOW(); } return 0; diff --git a/src/mux_quic.c b/src/mux_quic.c index c47e83a2c..b7d1e17f4 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -584,6 +584,11 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset, if (ncb_data(&qcs->rx.ncbuf, 0) && !(qcs->flags & QC_SF_DEM_FULL)) qcc_decode_qcs(qcc, qcs); + if (qcs->flags & QC_SF_READ_ABORTED) { + /* TODO should send a STOP_SENDING */ + qcs_free(qcs); + } + TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn); return 0; } @@ -1192,6 +1197,11 @@ static int qc_recv(struct qcc *qcc) qcc_decode_qcs(qcc, qcs); node = eb64_next(node); + + if (qcs->flags & QC_SF_READ_ABORTED) { + /* TODO should send a STOP_SENDING */ + qcs_free(qcs); + } } TRACE_LEAVE(QMUX_EV_QCC_RECV);