From bb9e9d78705f9b2276da8fd52fc54cff8ba21c35 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 23 Sep 2025 18:34:06 +0400 Subject: [PATCH] Reference connection tree from UDP and QUIC connection. The tree is located in listening objects. Referencing it from UDP and QUIC connections allows to transfer the connection to a new listening and keep receiving UDP packets. --- src/event/ngx_event_udp.c | 5 +++-- src/event/ngx_event_udp.h | 1 + src/event/quic/ngx_event_quic_connid.c | 2 +- src/event/quic/ngx_event_quic_socket.c | 15 +++++--------- src/event/quic/ngx_event_quic_udp.c | 27 ++++++++++++++++++++++++++ src/stream/ngx_stream_pass_module.c | 4 ---- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c index 43fa621b0..f65e8854d 100644 --- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c @@ -459,6 +459,7 @@ ngx_insert_udp_connection(ngx_connection_t *c) return NGX_ERROR; } + udp->rbtree = &c->listening->rbtree; udp->connection = c; ngx_crc32_init(hash); @@ -482,7 +483,7 @@ ngx_insert_udp_connection(ngx_connection_t *c) cln->data = c; cln->handler = ngx_delete_udp_connection; - ngx_rbtree_insert(&c->listening->rbtree, &udp->node); + ngx_rbtree_insert(udp->rbtree, &udp->node); c->udp = udp; @@ -499,7 +500,7 @@ ngx_delete_udp_connection(void *data) return; } - ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node); + ngx_rbtree_delete(c->udp->rbtree, &c->udp->node); c->udp = NULL; } diff --git a/src/event/ngx_event_udp.h b/src/event/ngx_event_udp.h index e5ddf1b31..db2096b9a 100644 --- a/src/event/ngx_event_udp.h +++ b/src/event/ngx_event_udp.h @@ -25,6 +25,7 @@ struct ngx_udp_connection_s { ngx_rbtree_node_t node; + ngx_rbtree_t *rbtree; ngx_connection_t *connection; ngx_buf_t *buffer; ngx_str_t key; diff --git a/src/event/quic/ngx_event_quic_connid.c b/src/event/quic/ngx_event_quic_connid.c index 4e7b8dc22..91d3d1cd9 100644 --- a/src/event/quic/ngx_event_quic_connid.c +++ b/src/event/quic/ngx_event_quic_connid.c @@ -51,7 +51,7 @@ ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id) uint64_t cookie; socklen_t optlen; - fd = c->listening->fd; + fd = c->fd; optlen = sizeof(cookie); diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index c2bc822a5..f42b51145 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -62,6 +62,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_memcpy(qc->tp.initial_scid.data, qsock->sid.id, qsock->sid.len); /* for all packets except first, this is set at udp layer */ + tmp = (ngx_quic_socket_t *) c->udp; c->udp = &qsock->udp; /* ngx_quic_get_connection(c) macro is now usable */ @@ -86,13 +87,6 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_quic_path_dbg(c, "set active", qc->path); - tmp = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); - if (tmp == NULL) { - goto failed; - } - - tmp->sid.seqnum = NGX_QUIC_UNSET_PN; /* temporary socket */ - ngx_memcpy(tmp->sid.id, pkt->dcid.data, pkt->dcid.len); tmp->sid.len = pkt->dcid.len; @@ -104,7 +98,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, failed: - ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); + ngx_rbtree_delete(qsock->udp.rbtree, &qsock->udp.node); c->udp = NULL; return NGX_ERROR; @@ -155,7 +149,7 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) ngx_queue_remove(&qsock->queue); ngx_queue_insert_head(&qc->free_sockets, &qsock->queue); - ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); + ngx_rbtree_delete(qsock->udp.rbtree, &qsock->udp.node); qc->nsockets--; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, @@ -176,11 +170,12 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, id.data = sid->id; id.len = sid->len; + qsock->udp.rbtree = c->udp->rbtree; qsock->udp.connection = c; qsock->udp.node.key = ngx_crc32_long(id.data, id.len); qsock->udp.key = id; - ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node); + ngx_rbtree_insert(qsock->udp.rbtree, &qsock->udp.node); ngx_queue_insert_tail(&qc->sockets, &qsock->queue); diff --git a/src/event/quic/ngx_event_quic_udp.c b/src/event/quic/ngx_event_quic_udp.c index 15b54bc82..8a5fa6fca 100644 --- a/src/event/quic/ngx_event_quic_udp.c +++ b/src/event/quic/ngx_event_quic_udp.c @@ -14,6 +14,7 @@ static void ngx_quic_close_accepted_connection(ngx_connection_t *c); static ngx_connection_t *ngx_quic_lookup_connection(ngx_listening_t *ls, ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen); +static ngx_int_t ngx_quic_insert_connection(ngx_connection_t *c); void @@ -333,6 +334,11 @@ ngx_quic_recvmsg(ngx_event_t *ev) } #endif + if (ngx_quic_insert_connection(c) != NGX_OK) { + ngx_quic_close_accepted_connection(c); + return; + } + log->data = NULL; log->handler = NULL; @@ -418,3 +424,24 @@ ngx_quic_lookup_connection(ngx_listening_t *ls, ngx_str_t *key, return NULL; } + + +static ngx_int_t +ngx_quic_insert_connection(ngx_connection_t *c) +{ + ngx_quic_socket_t *qsock; + + qsock = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); + if (qsock == NULL) { + return NGX_ERROR; + } + + qsock->sid.seqnum = NGX_QUIC_UNSET_PN; + + qsock->udp.rbtree = &c->listening->rbtree; + qsock->udp.connection = c; + + c->udp = &qsock->udp; + + return NGX_OK; +} diff --git a/src/stream/ngx_stream_pass_module.c b/src/stream/ngx_stream_pass_module.c index 1d671087c..333dce42f 100644 --- a/src/stream/ngx_stream_pass_module.c +++ b/src/stream/ngx_stream_pass_module.c @@ -222,10 +222,6 @@ ngx_stream_pass_cleanup(void *data) static ngx_int_t ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr) { - if (ls->type == SOCK_DGRAM) { - return NGX_DECLINED; - } - if (!ls->wildcard) { return ngx_cmp_sockaddr(ls->sockaddr, ls->socklen, addr->sockaddr, addr->socklen, 1);