MINOR: h3: abort read on unknown uni stream

As specified by HTTP/3 draft, an unknown unidirectional stream can be
aborted. To do this, use a new flag QC_SF_READ_ABORTED. When the MUX
detects this flag, QCS instance is automatically freed.

Previously, such streams were instead automatically drained. By aborting
them, we economize some useless memcpy instruction. On future data
reception, QCS instance is not found in the tree and considered as
already closed. The frame payload is thus deleted without copying it.
This commit is contained in:
Amaury Denoyelle 2022-05-24 17:22:07 +02:00
parent 9cc475182c
commit 849b24f15b
3 changed files with 21 additions and 5 deletions

View File

@ -100,6 +100,7 @@ struct qcc {
#define QC_SF_DETACH 0x00000008 /* cs is detached but there is remaining data to send */ #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_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_DEM_FULL 0x00000020 /* demux blocked on request channel buffer full */
#define QC_SF_READ_ABORTED 0x00000040 /* stream rejected by app layer */
struct qcs { struct qcs {
struct qcc *qcc; struct qcc *qcc;

View File

@ -144,8 +144,13 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
break; break;
default: default:
h3s->flags |= H3_SF_UNI_NO_H3; /* draft-ietf-quic-http34 9. Extensions to HTTP/3
break; *
* 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; 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)) if (!qpack_decode_enc(qcs, NULL))
return 1; return 1;
break; break;
case H3S_T_UNKNOWN:
default: default:
/* unknown uni stream : just consume it. */ /* Unknown stream should be flagged with QC_SF_READ_ABORTED. */
qcs_consume(qcs, ncb_data(rxbuf, 0)); ABORT_NOW();
break;
} }
return 0; return 0;

View File

@ -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)) if (ncb_data(&qcs->rx.ncbuf, 0) && !(qcs->flags & QC_SF_DEM_FULL))
qcc_decode_qcs(qcc, qcs); 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); TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
return 0; return 0;
} }
@ -1192,6 +1197,11 @@ static int qc_recv(struct qcc *qcc)
qcc_decode_qcs(qcc, qcs); qcc_decode_qcs(qcc, qcs);
node = eb64_next(node); 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); TRACE_LEAVE(QMUX_EV_QCC_RECV);