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.
This commit is contained in:
Roman Arutyunyan 2025-09-23 18:34:06 +04:00
parent b505232348
commit bb9e9d7870
6 changed files with 37 additions and 17 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);