diff --git a/src/h3.c b/src/h3.c index e802d299c..ea512a404 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1615,7 +1615,23 @@ static size_t h3_snd_buf(struct qcs *qcs, struct htx *htx, size_t count) */ static int h3_close(struct qcs *qcs, enum qcc_app_ops_close_side side) { - /* TODO */ + struct h3s *h3s = qcs->ctx; + struct h3c *h3c = h3s->h3c;; + + /* RFC 9114 6.2.1. Control Streams + * + * The sender + * MUST NOT close the control stream, and the receiver MUST NOT + * request that the sender close the control stream. If either + * control stream is closed at any point, this MUST be treated + * as a connection error of type H3_CLOSED_CRITICAL_STREAM. + */ + if (qcs == h3c->ctrl_strm) { + TRACE_ERROR("closure detected on control stream", H3_EV_H3S_END, qcs->qcc, qcs); + qcc_emit_cc_app(qcs->qcc, H3_CLOSED_CRITICAL_STREAM, 1); + return 1; + } + return 0; } diff --git a/src/mux_quic.c b/src/mux_quic.c index 401ccc0c1..cae22df1f 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -1232,6 +1232,13 @@ int qcc_recv_stop_sending(struct qcc *qcc, uint64_t id, uint64_t err) qcs_idle_open(qcs); + if (qcc->app_ops->close) { + if (qcc->app_ops->close(qcs, QCC_APP_OPS_CLOSE_SIDE_WR)) { + TRACE_ERROR("closure rejected by app layer", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs); + goto out; + } + } + /* RFC 9000 3.5. Solicited State Transitions * * An endpoint that receives a STOP_SENDING frame