mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-21 21:12:47 +00:00
MINOR: mux-quic: handle RESET_STREAM reception
Implement RESET_STREAM reception by mux-quic. On reception, qcs instance will be mark as remotely closed and its Rx buffer released. The stream layer will be flagged on error if still attached. This commit is part of implementing H3 errors at the stream level. Indeed, on H3 stream errors, STOP_SENDING + RESET_STREAM should be emitted. The STOP_SENDING will in turn generate a RESET_STREAM by the remote peer which will be handled thanks to this patch. This should be backported up to 2.7.
This commit is contained in:
parent
bb6296ce06
commit
5854fc08cc
@ -25,6 +25,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_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t final_size);
|
||||
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);
|
||||
|
||||
|
@ -888,6 +888,11 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (qcs_is_close_remote(qcs)) {
|
||||
TRACE_DATA("skipping STREAM for remotely closed", QMUX_EV_QCC_RECV, qcc->conn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (offset + len <= qcs->rx.offset) {
|
||||
/* TODO offset may have been received without FIN first and now
|
||||
* with it. In this case, it must be notified to be able to
|
||||
@ -1055,6 +1060,60 @@ int qcc_recv_max_stream_data(struct qcc *qcc, uint64_t id, uint64_t max)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle a new RESET_STREAM frame from stream ID <id> with error code <err>
|
||||
* and final stream size <final_size>.
|
||||
*
|
||||
* Returns 0 on success else non-zero. On error, the received frame should not
|
||||
* be acknowledged.
|
||||
*/
|
||||
int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t final_size)
|
||||
{
|
||||
struct qcs *qcs;
|
||||
|
||||
TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
|
||||
|
||||
/* RFC 9000 19.4. RESET_STREAM Frames
|
||||
*
|
||||
* An endpoint that receives a RESET_STREAM frame for a send-only stream
|
||||
* MUST terminate the connection with error STREAM_STATE_ERROR.
|
||||
*/
|
||||
if (qcc_get_qcs(qcc, id, 1, 0, &qcs)) {
|
||||
TRACE_ERROR("RESET_STREAM for send-only stream received", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
|
||||
qcc_emit_cc(qcc, QC_ERR_STREAM_STATE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!qcs || qcs_is_close_remote(qcs))
|
||||
goto out;
|
||||
|
||||
TRACE_PROTO("receiving RESET_STREAM", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
|
||||
qcs_idle_open(qcs);
|
||||
|
||||
if (qcs->rx.offset_max > final_size ||
|
||||
((qcs->flags & QC_SF_SIZE_KNOWN) && qcs->rx.offset_max != final_size)) {
|
||||
TRACE_ERROR("final size error on RESET_STREAM", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
|
||||
qcc_emit_cc(qcc, QC_ERR_FINAL_SIZE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
qcs->flags |= QC_SF_SIZE_KNOWN;
|
||||
qcs_close_remote(qcs);
|
||||
qc_free_ncbuf(qcs, &qcs->rx.ncbuf);
|
||||
|
||||
if (qcs_sc(qcs)) {
|
||||
se_fl_set_error(qcs->sd);
|
||||
qcs_alert(qcs);
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle a new STOP_SENDING frame for stream ID <id>. The error code should be
|
||||
* specified in <err>.
|
||||
*
|
||||
|
@ -2802,8 +2802,11 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
break;
|
||||
}
|
||||
case QUIC_FT_RESET_STREAM:
|
||||
/* TODO: handle this frame at STREAM level */
|
||||
break;
|
||||
if (qc->mux_state == QC_MUX_READY) {
|
||||
struct quic_reset_stream *rs = &frm.reset_stream;
|
||||
qcc_recv_reset_stream(qc->qcc, rs->id, rs->app_error_code, rs->final_size);
|
||||
}
|
||||
break;
|
||||
case QUIC_FT_STOP_SENDING:
|
||||
{
|
||||
struct quic_stop_sending *stop_sending = &frm.stop_sending;
|
||||
|
Loading…
Reference in New Issue
Block a user