MEDIUM: mux-quic: implement STOP_SENDING handling

Implement support for STOP_SENDING frame parsing. The stream is resetted
as specified by RFC 9000. This will automatically interrupt all future
send operation in qc_send(). A RESET_STREAM will be sent with the code
extracted from the original STOP_SENDING frame.
This commit is contained in:
Amaury Denoyelle 2022-07-04 11:44:53 +02:00
parent 843a1196b3
commit a5b5075211
3 changed files with 60 additions and 1 deletions

View file

@ -27,6 +27,7 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
char fin, char *data);
int qcc_recv_max_data(struct qcc *qcc, uint64_t max);
int qcc_recv_max_stream_data(struct qcc *qcc, uint64_t id, uint64_t max);
int qcc_recv_stop_sending(struct qcc *qcc, uint64_t id, uint64_t err);
void qcc_streams_sent_done(struct qcs *qcs, uint64_t data, uint64_t offset);
/* Bit shift to get the stream sub ID for internal use which is obtained

View file

@ -888,6 +888,56 @@ int qcc_recv_max_stream_data(struct qcc *qcc, uint64_t id, uint64_t max)
return 0;
}
/* Handle a new STOP_SENDING frame for stream ID <id>. The error code should be
* specified in <err>.
*
* Returns 0 on success else non-zero. On error, the received frame should not
* be acknowledged.
*/
int qcc_recv_stop_sending(struct qcc *qcc, uint64_t id, uint64_t err)
{
struct qcs *qcs;
TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
/* RFC 9000 19.5. STOP_SENDING Frames
*
* Receiving a STOP_SENDING frame for a
* locally initiated stream that has not yet been created MUST be
* treated as a connection error of type STREAM_STATE_ERROR. An
* endpoint that receives a STOP_SENDING frame for a receive-only stream
* MUST terminate the connection with error STREAM_STATE_ERROR.
*/
if (qcc_get_qcs(qcc, id, 0, 1, &qcs)) {
TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
return 1;
}
if (!qcs)
goto out;
/* RFC 9000 3.5. Solicited State Transitions
*
* An endpoint that receives a STOP_SENDING frame
* MUST send a RESET_STREAM frame if the stream is in the "Ready" or
* "Send" state. If the stream is in the "Data Sent" state, the
* endpoint MAY defer sending the RESET_STREAM frame until the packets
* containing outstanding data are acknowledged or declared lost. If
* any outstanding data is declared lost, the endpoint SHOULD send a
* RESET_STREAM frame instead of retransmitting the data.
*
* An endpoint SHOULD copy the error code from the STOP_SENDING frame to
* the RESET_STREAM frame it sends, but it can use any application error
* code.
*/
TRACE_DEVEL("receiving STOP_SENDING on stream", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
qcc_reset_stream(qcs, err);
out:
TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
return 0;
}
/* Signal the closing of remote stream with id <id>. Flow-control for new
* streams may be allocated for the peer if needed.
*/

View file

@ -2412,8 +2412,16 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
/* TODO: handle this frame at STREAM level */
break;
case QUIC_FT_STOP_SENDING:
/* TODO: handle this frame at STREAM level */
{
struct quic_stop_sending *stop_sending = &frm.stop_sending;
if (qc->mux_state == QC_MUX_READY) {
if (qcc_recv_stop_sending(qc->qcc, stop_sending->id,
stop_sending->app_error_code)) {
goto err;
}
}
break;
}
case QUIC_FT_CRYPTO:
{
struct quic_rx_crypto_frm *cf;