[PATCH 3 of 3] QUIC: keep stream sockaddr and addr_text constant

Roman Arutyunyan arut at nginx.com
Tue May 2 12:34:15 UTC 2023


# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1682679819 -14400
#      Fri Apr 28 15:03:39 2023 +0400
# Branch quic
# Node ID 43f0ceffa227a33e5c5ceb35b77f9a1f86dd2481
# Parent  cdc41ec778ffae822fefce639e67f2f57e3667f0
QUIC: keep stream sockaddr and addr_text constant.

HTTP and Stream variables $remote_addr and $binary_remote_addr rely on
constant client address, particularly because they are cacheable.
However, QUIC client may migrate to a new address.  While there's no perfect
way to handle this, the proposed solution is to copy client address to QUIC
stream at stream creation.  Previously, the address was only referenced, which
could result in changing it while stream was active, which in turn would lead
to broken cached variables values, since address length is cached as well.

diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -637,10 +637,12 @@ ngx_quic_do_init_streams(ngx_connection_
 static ngx_quic_stream_t *
 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
 {
+    ngx_str_t               addr_text;
     ngx_log_t              *log;
     ngx_pool_t             *pool;
     ngx_uint_t              reusable;
     ngx_queue_t            *q;
+    struct sockaddr        *sockaddr;
     ngx_connection_t       *sc;
     ngx_quic_stream_t      *qs;
     ngx_pool_cleanup_t     *cln;
@@ -692,6 +694,30 @@ ngx_quic_create_stream(ngx_connection_t 
     *log = *c->log;
     pool->log = log;
 
+    sockaddr = ngx_palloc(pool, c->socklen);
+    if (sockaddr == NULL) {
+        ngx_destroy_pool(pool);
+        ngx_queue_insert_tail(&qc->streams.free, &qs->queue);
+        return NULL;
+    }
+
+    ngx_memcpy(sockaddr, c->sockaddr, c->socklen);
+
+    if (c->addr_text.data) {
+        addr_text.data = ngx_pnalloc(pool, c->addr_text.len);
+        if (addr_text.data == NULL) {
+            ngx_destroy_pool(pool);
+            ngx_queue_insert_tail(&qc->streams.free, &qs->queue);
+            return NULL;
+        }
+
+        ngx_memcpy(addr_text.data, c->addr_text.data, c->addr_text.len);
+        addr_text.len = c->addr_text.len;
+
+    } else {
+        addr_text.len = 0;
+    }
+
     reusable = c->reusable;
     ngx_reusable_connection(c, 0);
 
@@ -710,10 +736,10 @@ ngx_quic_create_stream(ngx_connection_t 
     sc->type = SOCK_STREAM;
     sc->pool = pool;
     sc->ssl = c->ssl;
-    sc->sockaddr = c->sockaddr;
+    sc->sockaddr = sockaddr;
     sc->socklen = c->socklen;
     sc->listening = c->listening;
-    sc->addr_text = c->addr_text;
+    sc->addr_text = addr_text;
     sc->local_sockaddr = c->local_sockaddr;
     sc->local_socklen = c->local_socklen;
     sc->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);


More information about the nginx-devel mailing list