/* first unhandled streams ID, set by MUX after release */
uint64_t stream_max_uni;
uint64_t stream_max_bidi;
+ /* first stream IDs, which cannot be opened by the peer due to flow-control, set by MUX after release */
+ uint64_t stream_lim_uni;
+ uint64_t stream_lim_bidi;
/* Number of received packets which failed authentication. */
uint64_t auth_fails;
if (!conn_is_back(conn)) {
qc->rx.stream_max_uni = qcc->largest_uni_r;
qc->rx.stream_max_bidi = qcc->largest_bidi_r;
+ qc->rx.stream_lim_uni = qcc->lfctl.ms_uni * 4;
+ qc->rx.stream_lim_bidi = qcc->lfctl.ms_bidi * 4;
}
}
memset(&qc->rx.params, 0, sizeof(qc->rx.params));
qc->rx.buf = b_make(qc->rx.buf.area, QUIC_CONN_RX_BUFSZ, 0, 0);
qc->rx.stream_max_uni = qc->rx.stream_max_bidi = 0;
+ qc->rx.stream_lim_uni = qc->rx.stream_lim_bidi = UINT64_MAX;
qc->rx.auth_fails = 0;
qc->max_udp_payload = l ?
{
struct qf_stream *strm_frm = &frm->stream;
const char fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
- uint64_t max;
+ uint64_t max, lim;
/* The upper layer may not be allocated. */
if (!qc_is_conn_ready(qc)) {
break;
}
- max = quic_stream_is_uni(strm_frm->id) ?
- qc->rx.stream_max_uni : qc->rx.stream_max_bidi;
+ if (quic_stream_is_uni(strm_frm->id)) {
+ lim = qc->rx.stream_lim_uni;
+ max = qc->rx.stream_max_uni;
+ }
+ else {
+ lim = qc->rx.stream_lim_bidi;
+ max = qc->rx.stream_max_bidi;
+ }
+
if (strm_frm->id < max) {
TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
}
else {
+ if (strm_frm->id & QCS_ID_SRV_INTIATOR_BIT) {
+ TRACE_ERROR("Unknown local stream ID after MUX closure", QUIC_EV_CONN_PRSHPKT, qc);
+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_STREAM_STATE_ERROR));
+ goto err;
+ }
+ else if (strm_frm->id >= lim) {
+ TRACE_ERROR("Stream ID limit violation after MUX closure", QUIC_EV_CONN_PRSHPKT, qc);
+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_STREAM_LIMIT_ERROR));
+ goto err;
+ }
+
TRACE_DEVEL("No mux for new stream", QUIC_EV_CONN_PRSHPKT, qc);
if (qc->strm_reject) {
if (!qc->strm_reject(&qc->ael->pktns->tx.frms, strm_frm->id)) {