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.

The change also fixes truncated $remote_addr if migration happened while the
stream was active.  The reason is addr_text string was copied to stream by
value.
This commit is contained in:
Roman Arutyunyan 2023-05-11 19:40:11 +04:00
parent a4319bc496
commit 885c488191

View File

@ -637,10 +637,12 @@ ngx_quic_do_init_streams(ngx_connection_t *c)
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,31 @@ ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
*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;
addr_text.data = NULL;
}
reusable = c->reusable;
ngx_reusable_connection(c, 0);
@ -710,10 +737,10 @@ ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
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);