Patch subject is complete summary.
src/event/quic/ngx_event_quic_ack.c | 69 +++++++++++++++++++++++++++++++++++- 1 files changed, 66 insertions(+), 3 deletions(-)
# HG changeset patch # User Vladimir Khomutov <v...@wbsrv.ru> # Date 1703081117 -10800 # Wed Dec 20 17:05:17 2023 +0300 # Node ID f275f3a9992ca09a34a5281269d05e23136c6f0b # Parent f39271dd260b831fac70c776904d9f5ded053968 QUIC: client loss detection updates. diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -307,6 +307,18 @@ ngx_quic_handle_ack_frame_range(ngx_conn ngx_post_event(&qc->push, &ngx_posted_events); } + if (qc->client && ctx->level == ssl_encryption_initial) { + /* + * RFC 9002 6.2.1. Computing PTO + * + * the PTO backoff is not reset at a client that is not yet certain + * that the server has finished validating the client's address. That + * is, a client does not reset the PTO backoff factor on receiving + * acknowledgments in Initial packets. + */ + return NGX_OK; + } + qc->pto_count = 0; return NGX_OK; @@ -383,8 +395,8 @@ ngx_quic_congestion_reset(ngx_quic_conne ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t)); qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, - ngx_max(2 * qc->tp.max_udp_payload_size, - 14720)); + ngx_max(2 * qc->tp.max_udp_payload_size, + 14720)); qc->congestion.ssthresh = (size_t) -1; qc->congestion.recovery_start = ngx_current_msec; } @@ -804,6 +816,30 @@ ngx_quic_set_lost_timer(ngx_connection_t return; } + /* no lost packets and no in-flight packets */ + if (qc->client && !c->ssl->handshaked + && ngx_quic_keys_available(qc->keys, ssl_encryption_handshake, 1)) + { + /* + * 6.2.2.1 + * + * That is, the client MUST set the PTO timer if the client has not + * received an acknowledgment for any of its Handshake packets and the + * handshake is not confirmed (see Section 4.1.2 of [QUIC-TLS]), even + * if there are no packets in flight. + */ + + ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake); + + pto = (ngx_quic_pto(c, ctx) << qc->pto_count); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic client lost timer pto:%M", pto); + + qc->pto.handler = ngx_quic_pto_handler; ngx_add_timer(&qc->pto, pto); + return; + } + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic lost timer unset"); } @@ -850,7 +886,7 @@ void ngx_quic_lost_handler(ngx_event_t * void ngx_quic_pto_handler(ngx_event_t *ev) { - ngx_uint_t i; + ngx_uint_t i, sent; ngx_msec_t now; ngx_queue_t *q; ngx_msec_int_t w; @@ -864,6 +900,7 @@ ngx_quic_pto_handler(ngx_event_t *ev) c = ev->data; qc = ngx_quic_get_connection(c); now = ngx_current_msec; + sent = 0; for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { @@ -896,6 +933,32 @@ ngx_quic_pto_handler(ngx_event_t *ev) ngx_quic_close_connection(c, NGX_ERROR); return; } + + sent = 1; + } + + + /* + * RFC 9002 6.2.2.1 Before Address Validation + * + * When the PTO fires, the client MUST send a Handshake packet if it has + * Handshake keys, otherwise it MUST send an Initial packet in a UDP + * datagram with a payload of at least 1200 bytes. + */ + + if (qc->client && !c->ssl->handshaked && !sent) { + + if (ngx_quic_keys_available(qc->keys, ssl_encryption_handshake, 1)) { + ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake); + + } else { + ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial); + } + + if (ngx_quic_ping_peer(c, ctx) != NGX_OK) { + ngx_quic_close_connection(c, NGX_ERROR); + return; + } } qc->pto_count++;
_______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel