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

Reply via email to