}
/* register streams IDs so that quic-conn layer can ignore already closed streams. */
- qc->rx.stream_max_uni = qcc->largest_uni_r;
- qc->rx.stream_max_bidi = qcc->largest_bidi_r;
+ if (!conn_is_back(conn)) {
+ qc->rx.stream_max_uni = qcc->largest_uni_r;
+ qc->rx.stream_max_bidi = qcc->largest_bidi_r;
+ }
}
tasklet_free(qcc->wait_event.tasklet);
if (qcc->app_ops) {
if (qcc->app_ops->release)
qcc->app_ops->release(qcc->ctx);
- if (conn && conn_is_quic(conn) && conn->handle.qc)
+ if (conn && !conn_is_back(conn) && conn_is_quic(conn) && conn->handle.qc)
conn->handle.qc->strm_reject = qcc->app_ops->strm_reject;
}
TRACE_PROTO("application layer released", QMUX_EV_QCC_END, conn);
{
struct qf_stream *strm_frm = &frm->stream;
const char fin = frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
- const uint64_t max = quic_stream_is_uni(strm_frm->id) ?
- qc->rx.stream_max_uni : qc->rx.stream_max_bidi;
+ uint64_t max;
/* The upper layer may not be allocated. */
if (!qc_is_conn_ready(qc)) {
+ if (qc_is_back(qc)) {
+ /* Drain STREAM frames on the backend side. MUX should
+ * have emitted STOP_SENDING on shut for incomplete streams,
+ * so the peer should soon stop emission.
+ */
+ TRACE_DATA("Ignore stream on backend", QUIC_EV_CONN_PRSHPKT, qc);
+ break;
+ }
+
+ max = quic_stream_is_uni(strm_frm->id) ?
+ qc->rx.stream_max_uni : qc->rx.stream_max_bidi;
if (strm_frm->id < max) {
TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
}