# HG changeset patch # User Sergey Kandaurov # Date 1613561107 -10800 # Node ID d710c457171c5f76aa9980c4238ec80c57a945b2 # Parent d4e02b3b734fe15cdb17dde6874145878fd6f09d QUIC: added ability to reset a stream. diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -2203,6 +2203,40 @@ ngx_quic_close_streams(ngx_connection_t } +ngx_int_t +ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err) +{ + ngx_event_t *wev; + ngx_connection_t *pc; + ngx_quic_frame_t *frame; + ngx_quic_stream_t *qs; + ngx_quic_connection_t *qc; + + qs = c->quic; + pc = qs->parent; + qc = ngx_quic_get_connection(pc); + + frame = ngx_quic_alloc_frame(pc); + if (frame == NULL) { + return NGX_ERROR; + } + + frame->level = ssl_encryption_application; + frame->type = NGX_QUIC_FT_RESET_STREAM; + frame->u.reset_stream.id = qs->id; + frame->u.reset_stream.error_code = err; + frame->u.reset_stream.final_size = c->sent; + + ngx_quic_queue_frame(qc, frame); + + wev = c->write; + wev->error = 1; + wev->ready = 1; + + return NGX_OK; +} + + static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf) { @@ -6408,6 +6442,10 @@ ngx_quic_stream_cleanup_handler(void *da } } + if (c->write->error) { + goto error; + } + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic stream id:0x%xL send fin", qs->id); @@ -6429,6 +6467,8 @@ ngx_quic_stream_cleanup_handler(void *da ngx_quic_queue_frame(qc, frame); +error: + (void) ngx_quic_output(pc); } diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h --- a/src/event/quic/ngx_event_quic.h +++ b/src/event/quic/ngx_event_quic.h @@ -131,6 +131,7 @@ void ngx_quic_run(ngx_connection_t *c, n ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, const char *reason); +ngx_int_t ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err); uint32_t ngx_quic_version(ngx_connection_t *c); ngx_int_t ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t len, ngx_str_t *dcid); diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c --- a/src/event/quic/ngx_event_quic_transport.c +++ b/src/event/quic/ngx_event_quic_transport.c @@ -96,6 +96,8 @@ static ngx_int_t ngx_quic_frame_allowed( static size_t ngx_quic_create_ping(u_char *p); static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges); +static size_t ngx_quic_create_reset_stream(u_char *p, + ngx_quic_reset_stream_frame_t *rs); static size_t ngx_quic_create_stop_sending(u_char *p, ngx_quic_stop_sending_frame_t *ss); static size_t ngx_quic_create_crypto(u_char *p, @@ -1228,6 +1230,9 @@ ngx_quic_create_frame(u_char *p, ngx_qui f->need_ack = 0; return ngx_quic_create_ack(p, &f->u.ack, f->data); + case NGX_QUIC_FT_RESET_STREAM: + return ngx_quic_create_reset_stream(p, &f->u.reset_stream); + case NGX_QUIC_FT_STOP_SENDING: return ngx_quic_create_stop_sending(p, &f->u.stop_sending); @@ -1334,6 +1339,31 @@ ngx_quic_create_ack(u_char *p, ngx_quic_ static size_t +ngx_quic_create_reset_stream(u_char *p, ngx_quic_reset_stream_frame_t *rs) +{ + size_t len; + u_char *start; + + if (p == NULL) { + len = ngx_quic_varint_len(NGX_QUIC_FT_RESET_STREAM); + len += ngx_quic_varint_len(rs->id); + len += ngx_quic_varint_len(rs->error_code); + len += ngx_quic_varint_len(rs->final_size); + return len; + } + + start = p; + + ngx_quic_build_int(&p, NGX_QUIC_FT_RESET_STREAM); + ngx_quic_build_int(&p, rs->id); + ngx_quic_build_int(&p, rs->error_code); + ngx_quic_build_int(&p, rs->final_size); + + return p - start; +} + + +static size_t ngx_quic_create_stop_sending(u_char *p, ngx_quic_stop_sending_frame_t *ss) { size_t len;