# HG changeset patch # User Roman Arutyunyan # Date 1650456077 -14400 # Node ID c2f5d79cde64457f1fa7344c56a5248a677a7e46 # Parent 55b38514729b8f848709b31295e72d6886a7a433 QUIC: separate UDP framework for QUIC. Previously, QUIC used the existing UDP framework, which was created for UDP in Stream. However the way QUIC connections are created and looked up is different from the way UDP connections in Stream are created and looked up. Now these two implementations are decoupled. diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -1344,6 +1344,7 @@ if [ $USE_OPENSSL_QUIC = YES ]; then src/event/quic/ngx_event_quic_output.h \ src/event/quic/ngx_event_quic_socket.h" ngx_module_srcs="src/event/quic/ngx_event_quic.c \ + src/event/quic/ngx_event_quic_udp.c \ src/event/quic/ngx_event_quic_transport.c \ src/event/quic/ngx_event_quic_protection.c \ src/event/quic/ngx_event_quic_frames.c \ diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -72,10 +72,6 @@ ngx_create_listening(ngx_conf_t *cf, str ngx_memcpy(ls->addr_text.data, text, len); -#if !(NGX_WIN32) - ngx_rbtree_init(&ls->rbtree, &ls->sentinel, ngx_udp_rbtree_insert_value); -#endif - ls->fd = (ngx_socket_t) -1; ls->type = SOCK_STREAM; diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -886,8 +886,16 @@ ngx_event_process_init(ngx_cycle_t *cycl #else - rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept - : ngx_event_recvmsg; + if (c->type == SOCK_STREAM) { + rev->handler = ngx_event_accept; + +#if (NGX_QUIC) + } else if (ls[i].quic) { + rev->handler = ngx_quic_recvmsg; +#endif + } else { + rev->handler = ngx_event_recvmsg; + } #if (NGX_HAVE_REUSEPORT) diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c --- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c @@ -15,27 +15,25 @@ static void ngx_close_accepted_udp_connection(ngx_connection_t *c); static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size); -static ngx_int_t ngx_create_udp_connection(ngx_connection_t *c); +static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c); static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, - ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen); + struct sockaddr *sockaddr, socklen_t socklen, + struct sockaddr *local_sockaddr, socklen_t local_socklen); void ngx_event_recvmsg(ngx_event_t *ev) { - size_t len; ssize_t n; - ngx_str_t key; ngx_buf_t buf; ngx_log_t *log; ngx_err_t err; - socklen_t local_socklen; + socklen_t socklen, local_socklen; ngx_event_t *rev, *wev; struct iovec iov[1]; struct msghdr msg; ngx_sockaddr_t sa, lsa; - ngx_udp_dgram_t dgram; - struct sockaddr *local_sockaddr; + struct sockaddr *sockaddr, *local_sockaddr; ngx_listening_t *ls; ngx_event_conf_t *ecf; ngx_connection_t *c, *lc; @@ -110,21 +108,21 @@ ngx_event_recvmsg(ngx_event_t *ev) } #endif - dgram.sockaddr = msg.msg_name; - dgram.socklen = msg.msg_namelen; + sockaddr = msg.msg_name; + socklen = msg.msg_namelen; - if (dgram.socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { - dgram.socklen = sizeof(ngx_sockaddr_t); + if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + socklen = sizeof(ngx_sockaddr_t); } - if (dgram.socklen == 0) { + if (socklen == 0) { /* * on Linux recvmsg() returns zero msg_namelen * when receiving packets from unbound AF_UNIX sockets */ - dgram.socklen = sizeof(struct sockaddr); + socklen = sizeof(struct sockaddr); ngx_memzero(&sa, sizeof(struct sockaddr)); sa.sockaddr.sa_family = ls->sockaddr->sa_family; } @@ -152,35 +150,8 @@ ngx_event_recvmsg(ngx_event_t *ev) #endif - key.data = (u_char *) dgram.sockaddr; - key.len = dgram.socklen; - -#if (NGX_HAVE_UNIX_DOMAIN) - - if (dgram.sockaddr->sa_family == AF_UNIX) { - struct sockaddr_un *saun = (struct sockaddr_un *) dgram.sockaddr; - - if (dgram.socklen <= (socklen_t) offsetof(struct sockaddr_un, - sun_path) - || saun->sun_path[0] == '\0') - { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "unbound unix socket"); - key.len = 0; - } - } - -#endif - -#if (NGX_QUIC) - if (ls->quic) { - if (ngx_quic_get_packet_dcid(ev->log, buffer, n, &key) != NGX_OK) { - goto next; - } - } -#endif - - c = ngx_lookup_udp_connection(ls, &key, local_sockaddr, local_socklen); + c = ngx_lookup_udp_connection(ls, sockaddr, socklen, local_sockaddr, + local_socklen); if (c) { @@ -202,14 +173,10 @@ ngx_event_recvmsg(ngx_event_t *ev) buf.pos = buffer; buf.last = buffer + n; - buf.start = buf.pos; - buf.end = buffer + sizeof(buffer); rev = c->read; - dgram.buffer = &buf; - - c->udp->dgram = &dgram; + c->udp->buffer = &buf; rev->ready = 1; rev->active = 0; @@ -217,7 +184,7 @@ ngx_event_recvmsg(ngx_event_t *ev) rev->handler(rev); if (c->udp) { - c->udp->dgram = NULL; + c->udp->buffer = NULL; } rev->ready = 0; @@ -240,7 +207,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->shared = 1; c->type = SOCK_DGRAM; - c->socklen = dgram.socklen; + c->socklen = socklen; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); @@ -252,21 +219,13 @@ ngx_event_recvmsg(ngx_event_t *ev) return; } - len = dgram.socklen; - -#if (NGX_QUIC) - if (ls->quic) { - len = NGX_SOCKADDRLEN; - } -#endif - - c->sockaddr = ngx_palloc(c->pool, len); + c->sockaddr = ngx_palloc(c->pool, socklen); if (c->sockaddr == NULL) { ngx_close_accepted_udp_connection(c); return; } - ngx_memcpy(c->sockaddr, dgram.sockaddr, dgram.socklen); + ngx_memcpy(c->sockaddr, sockaddr, socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { @@ -369,7 +328,7 @@ ngx_event_recvmsg(ngx_event_t *ev) } #endif - if (ngx_create_udp_connection(c) != NGX_OK) { + if (ngx_insert_udp_connection(c) != NGX_OK) { ngx_close_accepted_udp_connection(c); return; } @@ -412,17 +371,17 @@ ngx_udp_shared_recv(ngx_connection_t *c, ssize_t n; ngx_buf_t *b; - if (c->udp == NULL || c->udp->dgram == NULL) { + if (c->udp == NULL || c->udp->buffer == NULL) { return NGX_AGAIN; } - b = c->udp->dgram->buffer; + b = c->udp->buffer; n = ngx_min(b->last - b->pos, (ssize_t) size); ngx_memcpy(buf, b->pos, n); - c->udp->dgram = NULL; + c->udp->buffer = NULL; c->read->ready = 0; c->read->active = 1; @@ -458,8 +417,8 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n udpt = (ngx_udp_connection_t *) temp; ct = udpt->connection; - rc = ngx_memn2cmp(udp->key.data, udpt->key.data, - udp->key.len, udpt->key.len); + rc = ngx_cmp_sockaddr(c->sockaddr, c->socklen, + ct->sockaddr, ct->socklen, 1); if (rc == 0 && c->listening->wildcard) { rc = ngx_cmp_sockaddr(c->local_sockaddr, c->local_socklen, @@ -485,18 +444,12 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n static ngx_int_t -ngx_create_udp_connection(ngx_connection_t *c) +ngx_insert_udp_connection(ngx_connection_t *c) { - ngx_str_t key; + uint32_t hash; ngx_pool_cleanup_t *cln; ngx_udp_connection_t *udp; -#if (NGX_QUIC) - if (c->listening->quic) { - return NGX_OK; - } -#endif - if (c->udp) { return NGX_OK; } @@ -506,6 +459,19 @@ ngx_create_udp_connection(ngx_connection return NGX_ERROR; } + udp->connection = c; + + ngx_crc32_init(hash); + ngx_crc32_update(&hash, (u_char *) c->sockaddr, c->socklen); + + if (c->listening->wildcard) { + ngx_crc32_update(&hash, (u_char *) c->local_sockaddr, c->local_socklen); + } + + ngx_crc32_final(hash); + + udp->node.key = hash; + cln = ngx_pool_cleanup_add(c->pool, 0); if (cln == NULL) { return NGX_ERROR; @@ -514,10 +480,7 @@ ngx_create_udp_connection(ngx_connection cln->data = c; cln->handler = ngx_delete_udp_connection; - key.data = (u_char *) c->sockaddr; - key.len = c->socklen; - - ngx_insert_udp_connection(c, udp, &key); + ngx_rbtree_insert(&c->listening->rbtree, &udp->node); c->udp = udp; @@ -526,30 +489,6 @@ ngx_create_udp_connection(ngx_connection void -ngx_insert_udp_connection(ngx_connection_t *c, ngx_udp_connection_t *udp, - ngx_str_t *key) -{ - uint32_t hash; - - ngx_crc32_init(hash); - - ngx_crc32_update(&hash, key->data, key->len); - - if (c->listening->wildcard) { - ngx_crc32_update(&hash, (u_char *) c->local_sockaddr, c->local_socklen); - } - - ngx_crc32_final(hash); - - udp->connection = c; - udp->key = *key; - udp->node.key = hash; - - ngx_rbtree_insert(&c->listening->rbtree, &udp->node); -} - - -void ngx_delete_udp_connection(void *data) { ngx_connection_t *c = data; @@ -565,8 +504,8 @@ ngx_delete_udp_connection(void *data) static ngx_connection_t * -ngx_lookup_udp_connection(ngx_listening_t *ls, ngx_str_t *key, - struct sockaddr *local_sockaddr, socklen_t local_socklen) +ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, + socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen) { uint32_t hash; ngx_int_t rc; @@ -574,15 +513,27 @@ ngx_lookup_udp_connection(ngx_listening_ ngx_rbtree_node_t *node, *sentinel; ngx_udp_connection_t *udp; - if (key->len == 0) { - return NULL; +#if (NGX_HAVE_UNIX_DOMAIN) + + if (sockaddr->sa_family == AF_UNIX) { + struct sockaddr_un *saun = (struct sockaddr_un *) sockaddr; + + if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path) + || saun->sun_path[0] == '\0') + { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, + "unbound unix socket"); + return NULL; + } } +#endif + node = ls->rbtree.root; sentinel = ls->rbtree.sentinel; ngx_crc32_init(hash); - ngx_crc32_update(&hash, key->data, key->len); + ngx_crc32_update(&hash, (u_char *) sockaddr, socklen); if (ls->wildcard) { ngx_crc32_update(&hash, (u_char *) local_sockaddr, local_socklen); @@ -608,7 +559,8 @@ ngx_lookup_udp_connection(ngx_listening_ c = udp->connection; - rc = ngx_memn2cmp(key->data, udp->key.data, key->len, udp->key.len); + rc = ngx_cmp_sockaddr(sockaddr, socklen, + c->sockaddr, c->socklen, 1); if (rc == 0 && ls->wildcard) { rc = ngx_cmp_sockaddr(local_sockaddr, local_socklen, @@ -616,13 +568,6 @@ ngx_lookup_udp_connection(ngx_listening_ } if (rc == 0) { - -#if (NGX_QUIC) - if (ls->quic && c->udp != udp) { - c->udp = udp; - } -#endif - return c; } diff --git a/src/event/ngx_event_udp.h b/src/event/ngx_event_udp.h --- a/src/event/ngx_event_udp.h +++ b/src/event/ngx_event_udp.h @@ -23,18 +23,10 @@ #endif -typedef struct { - ngx_buf_t *buffer; - struct sockaddr *sockaddr; - socklen_t socklen; -} ngx_udp_dgram_t; - - struct ngx_udp_connection_s { - ngx_rbtree_node_t node; - ngx_connection_t *connection; - ngx_str_t key; - ngx_udp_dgram_t *dgram; + ngx_rbtree_node_t node; + ngx_connection_t *connection; + ngx_buf_t *buffer; }; @@ -65,9 +57,6 @@ void ngx_event_recvmsg(ngx_event_t *ev); ssize_t ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags); void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); -void ngx_insert_udp_connection(ngx_connection_t *c, ngx_udp_connection_t *udp, - ngx_str_t *key); - #endif void ngx_delete_udp_connection(void *data); diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -430,7 +430,7 @@ ngx_quic_input_handler(ngx_event_t *rev) return; } - b = c->udp->dgram->buffer; + b = c->udp->buffer; rc = ngx_quic_handle_datagram(c, b, NULL); @@ -758,6 +758,7 @@ ngx_quic_handle_packet(ngx_connection_t ngx_quic_header_t *pkt) { ngx_int_t rc; + ngx_quic_socket_t *qsock; ngx_quic_connection_t *qc; c->log->action = "parsing quic packet"; @@ -809,8 +810,9 @@ ngx_quic_handle_packet(ngx_connection_t } if (pkt->first) { - if (ngx_cmp_sockaddr(c->udp->dgram->sockaddr, - c->udp->dgram->socklen, + qsock = ngx_quic_get_socket(c); + + if (ngx_cmp_sockaddr(&qsock->sockaddr.sockaddr, qsock->socklen, qc->path->sockaddr, qc->path->socklen, 1) != NGX_OK) { diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h --- a/src/event/quic/ngx_event_quic.h +++ b/src/event/quic/ngx_event_quic.h @@ -102,6 +102,9 @@ struct ngx_quic_stream_s { }; +void ngx_quic_recvmsg(ngx_event_t *ev); +void ngx_quic_rbtree_insert_value(ngx_rbtree_node_t *temp, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); void ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf); ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -107,6 +107,8 @@ struct ngx_quic_socket_s { ngx_quic_connection_t *quic; ngx_queue_t queue; ngx_quic_server_id_t sid; + ngx_sockaddr_t sockaddr; + socklen_t socklen; ngx_uint_t used; /* unsigned used:1; */ }; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -264,7 +264,7 @@ ngx_quic_set_path(ngx_connection_t *c, n len = pkt->raw->last - pkt->raw->start; - if (c->udp->dgram == NULL) { + if (c->udp->buffer == NULL) { /* first ever packet in connection, path already exists */ path = qc->path; goto update; @@ -278,7 +278,7 @@ ngx_quic_set_path(ngx_connection_t *c, n { path = ngx_queue_data(q, ngx_quic_path_t, queue); - if (ngx_cmp_sockaddr(c->udp->dgram->sockaddr, c->udp->dgram->socklen, + if (ngx_cmp_sockaddr(&qsock->sockaddr.sockaddr, qsock->socklen, path->sockaddr, path->socklen, 1) == NGX_OK) { @@ -315,8 +315,7 @@ ngx_quic_set_path(ngx_connection_t *c, n return NGX_DONE; } - path = ngx_quic_new_path(c, c->udp->dgram->sockaddr, - c->udp->dgram->socklen, cid); + path = ngx_quic_new_path(c, &qsock->sockaddr.sockaddr, qsock->socklen, cid); if (path == NULL) { return NGX_ERROR; } diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -177,7 +177,10 @@ ngx_quic_listen(ngx_connection_t *c, ngx id.data = sid->id; id.len = sid->len; - ngx_insert_udp_connection(c, &qsock->udp, &id); + qsock->udp.connection = c; + qsock->udp.node.key = ngx_crc32_long(id.data, id.len); + + ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node); ngx_queue_insert_tail(&qc->sockets, &qsock->queue); diff --git a/src/event/ngx_event_udp.c b/src/event/quic/ngx_event_quic_udp.c copy from src/event/ngx_event_udp.c copy to src/event/quic/ngx_event_quic_udp.c --- a/src/event/ngx_event_udp.c +++ b/src/event/quic/ngx_event_quic_udp.c @@ -8,38 +8,33 @@ #include #include #include +#include -#if !(NGX_WIN32) - -static void ngx_close_accepted_udp_connection(ngx_connection_t *c); -static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, - size_t size); -static ngx_int_t ngx_create_udp_connection(ngx_connection_t *c); -static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, +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); void -ngx_event_recvmsg(ngx_event_t *ev) +ngx_quic_recvmsg(ngx_event_t *ev) { - size_t len; - ssize_t n; - ngx_str_t key; - ngx_buf_t buf; - ngx_log_t *log; - ngx_err_t err; - socklen_t local_socklen; - ngx_event_t *rev, *wev; - struct iovec iov[1]; - struct msghdr msg; - ngx_sockaddr_t sa, lsa; - ngx_udp_dgram_t dgram; - struct sockaddr *local_sockaddr; - ngx_listening_t *ls; - ngx_event_conf_t *ecf; - ngx_connection_t *c, *lc; - static u_char buffer[65535]; + ssize_t n; + ngx_str_t key; + ngx_buf_t buf; + ngx_log_t *log; + ngx_err_t err; + socklen_t socklen, local_socklen; + ngx_event_t *rev, *wev; + struct iovec iov[1]; + struct msghdr msg; + ngx_sockaddr_t sa, lsa; + struct sockaddr *sockaddr, *local_sockaddr; + ngx_listening_t *ls; + ngx_event_conf_t *ecf; + ngx_connection_t *c, *lc; + ngx_quic_socket_t *qsock; + static u_char buffer[65535]; #if (NGX_HAVE_ADDRINFO_CMSG) u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))]; @@ -64,7 +59,8 @@ ngx_event_recvmsg(ngx_event_t *ev) ev->ready = 0; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "recvmsg on %V, ready: %d", &ls->addr_text, ev->available); + "quic recvmsg on %V, ready: %d", + &ls->addr_text, ev->available); do { ngx_memzero(&msg, sizeof(struct msghdr)); @@ -93,11 +89,11 @@ ngx_event_recvmsg(ngx_event_t *ev) if (err == NGX_EAGAIN) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, - "recvmsg() not ready"); + "quic recvmsg() not ready"); return; } - ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); + ngx_log_error(NGX_LOG_ALERT, ev->log, err, "quic recvmsg() failed"); return; } @@ -105,29 +101,33 @@ ngx_event_recvmsg(ngx_event_t *ev) #if (NGX_HAVE_ADDRINFO_CMSG) if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { ngx_log_error(NGX_LOG_ALERT, ev->log, 0, - "recvmsg() truncated data"); + "quic recvmsg() truncated data"); continue; } #endif - dgram.sockaddr = msg.msg_name; - dgram.socklen = msg.msg_namelen; + sockaddr = msg.msg_name; + socklen = msg.msg_namelen; - if (dgram.socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { - dgram.socklen = sizeof(ngx_sockaddr_t); + if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + socklen = sizeof(ngx_sockaddr_t); } - if (dgram.socklen == 0) { +#if (NGX_HAVE_UNIX_DOMAIN) + + if (sockaddr->sa_family == AF_UNIX) { + struct sockaddr_un *saun = (struct sockaddr_un *) sockaddr; - /* - * on Linux recvmsg() returns zero msg_namelen - * when receiving packets from unbound AF_UNIX sockets - */ + if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path) + || saun->sun_path[0] == '\0') + { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, + "unbound unix socket"); + goto next; + } + } - dgram.socklen = sizeof(struct sockaddr); - ngx_memzero(&sa, sizeof(struct sockaddr)); - sa.sockaddr.sa_family = ls->sockaddr->sa_family; - } +#endif local_sockaddr = ls->sockaddr; local_socklen = ls->socklen; @@ -152,35 +152,11 @@ ngx_event_recvmsg(ngx_event_t *ev) #endif - key.data = (u_char *) dgram.sockaddr; - key.len = dgram.socklen; - -#if (NGX_HAVE_UNIX_DOMAIN) - - if (dgram.sockaddr->sa_family == AF_UNIX) { - struct sockaddr_un *saun = (struct sockaddr_un *) dgram.sockaddr; - - if (dgram.socklen <= (socklen_t) offsetof(struct sockaddr_un, - sun_path) - || saun->sun_path[0] == '\0') - { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "unbound unix socket"); - key.len = 0; - } + if (ngx_quic_get_packet_dcid(ev->log, buffer, n, &key) != NGX_OK) { + goto next; } -#endif - -#if (NGX_QUIC) - if (ls->quic) { - if (ngx_quic_get_packet_dcid(ev->log, buffer, n, &key) != NGX_OK) { - goto next; - } - } -#endif - - c = ngx_lookup_udp_connection(ls, &key, local_sockaddr, local_socklen); + c = ngx_quic_lookup_connection(ls, &key, local_sockaddr, local_socklen); if (c) { @@ -192,7 +168,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->log->handler = NULL; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recvmsg: fd:%d n:%z", c->fd, n); + "quic recvmsg: fd:%d n:%z", c->fd, n); c->log->handler = handler; } @@ -205,19 +181,21 @@ ngx_event_recvmsg(ngx_event_t *ev) buf.start = buf.pos; buf.end = buffer + sizeof(buffer); - rev = c->read; + qsock = ngx_quic_get_socket(c); - dgram.buffer = &buf; + ngx_memcpy(&qsock->sockaddr.sockaddr, sockaddr, socklen); + qsock->socklen = socklen; - c->udp->dgram = &dgram; + c->udp->buffer = &buf; + rev = c->read; rev->ready = 1; rev->active = 0; rev->handler(rev); if (c->udp) { - c->udp->dgram = NULL; + c->udp->buffer = NULL; } rev->ready = 0; @@ -240,7 +218,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->shared = 1; c->type = SOCK_DGRAM; - c->socklen = dgram.socklen; + c->socklen = socklen; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); @@ -248,40 +226,26 @@ ngx_event_recvmsg(ngx_event_t *ev) c->pool = ngx_create_pool(ls->pool_size, ev->log); if (c->pool == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } - len = dgram.socklen; - -#if (NGX_QUIC) - if (ls->quic) { - len = NGX_SOCKADDRLEN; - } -#endif - - c->sockaddr = ngx_palloc(c->pool, len); + c->sockaddr = ngx_palloc(c->pool, NGX_SOCKADDRLEN); if (c->sockaddr == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } - ngx_memcpy(c->sockaddr, dgram.sockaddr, dgram.socklen); + ngx_memcpy(c->sockaddr, sockaddr, socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } *log = ls->log; - c->recv = ngx_udp_shared_recv; - c->send = ngx_udp_send; - c->send_chain = ngx_udp_send_chain; - - c->need_flush_buf = 1; - c->log = log; c->pool->log = log; c->listening = ls; @@ -289,7 +253,7 @@ ngx_event_recvmsg(ngx_event_t *ev) if (local_sockaddr == &lsa.sockaddr) { local_sockaddr = ngx_palloc(c->pool, local_socklen); if (local_sockaddr == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } @@ -301,7 +265,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->buffer = ngx_create_temp_buf(c->pool, n); if (c->buffer == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } @@ -336,7 +300,7 @@ ngx_event_recvmsg(ngx_event_t *ev) if (ls->addr_ntop) { c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len); if (c->addr_text.data == NULL) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } @@ -344,7 +308,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->addr_text.data, ls->addr_text_max_len, 0); if (c->addr_text.len == 0) { - ngx_close_accepted_udp_connection(c); + ngx_quic_close_accepted_connection(c); return; } } @@ -362,18 +326,13 @@ ngx_event_recvmsg(ngx_event_t *ev) NGX_SOCKADDR_STRLEN, 1); ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, - "*%uA recvmsg: %V fd:%d n:%z", + "*%uA quic recvmsg: %V fd:%d n:%z", c->number, &addr, c->fd, n); } } #endif - if (ngx_create_udp_connection(c) != NGX_OK) { - ngx_close_accepted_udp_connection(c); - return; - } - log->data = NULL; log->handler = NULL; @@ -390,7 +349,7 @@ ngx_event_recvmsg(ngx_event_t *ev) static void -ngx_close_accepted_udp_connection(ngx_connection_t *c) +ngx_quic_close_accepted_connection(ngx_connection_t *c) { ngx_free_connection(c); @@ -406,39 +365,14 @@ ngx_close_accepted_udp_connection(ngx_co } -static ssize_t -ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size) -{ - ssize_t n; - ngx_buf_t *b; - - if (c->udp == NULL || c->udp->dgram == NULL) { - return NGX_AGAIN; - } - - b = c->udp->dgram->buffer; - - n = ngx_min(b->last - b->pos, (ssize_t) size); - - ngx_memcpy(buf, b->pos, n); - - c->udp->dgram = NULL; - - c->read->ready = 0; - c->read->active = 1; - - return n; -} - - void -ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, +ngx_quic_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { - ngx_int_t rc; - ngx_connection_t *c, *ct; - ngx_rbtree_node_t **p; - ngx_udp_connection_t *udp, *udpt; + ngx_int_t rc; + ngx_connection_t *c, *ct; + ngx_rbtree_node_t **p; + ngx_quic_socket_t *qsock, *qsockt; for ( ;; ) { @@ -452,14 +386,14 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n } else { /* node->key == temp->key */ - udp = (ngx_udp_connection_t *) node; - c = udp->connection; + qsock = (ngx_quic_socket_t *) node; + c = qsock->udp.connection; - udpt = (ngx_udp_connection_t *) temp; - ct = udpt->connection; + qsockt = (ngx_quic_socket_t *) temp; + ct = qsockt->udp.connection; - rc = ngx_memn2cmp(udp->key.data, udpt->key.data, - udp->key.len, udpt->key.len); + rc = ngx_memn2cmp(qsock->sid.id, qsockt->sid.id, + qsock->sid.len, qsockt->sid.len); if (rc == 0 && c->listening->wildcard) { rc = ngx_cmp_sockaddr(c->local_sockaddr, c->local_socklen, @@ -484,95 +418,15 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n } -static ngx_int_t -ngx_create_udp_connection(ngx_connection_t *c) -{ - ngx_str_t key; - ngx_pool_cleanup_t *cln; - ngx_udp_connection_t *udp; - -#if (NGX_QUIC) - if (c->listening->quic) { - return NGX_OK; - } -#endif - - if (c->udp) { - return NGX_OK; - } - - udp = ngx_pcalloc(c->pool, sizeof(ngx_udp_connection_t)); - if (udp == NULL) { - return NGX_ERROR; - } - - cln = ngx_pool_cleanup_add(c->pool, 0); - if (cln == NULL) { - return NGX_ERROR; - } - - cln->data = c; - cln->handler = ngx_delete_udp_connection; - - key.data = (u_char *) c->sockaddr; - key.len = c->socklen; - - ngx_insert_udp_connection(c, udp, &key); - - c->udp = udp; - - return NGX_OK; -} - - -void -ngx_insert_udp_connection(ngx_connection_t *c, ngx_udp_connection_t *udp, - ngx_str_t *key) -{ - uint32_t hash; - - ngx_crc32_init(hash); - - ngx_crc32_update(&hash, key->data, key->len); - - if (c->listening->wildcard) { - ngx_crc32_update(&hash, (u_char *) c->local_sockaddr, c->local_socklen); - } - - ngx_crc32_final(hash); - - udp->connection = c; - udp->key = *key; - udp->node.key = hash; - - ngx_rbtree_insert(&c->listening->rbtree, &udp->node); -} - - -void -ngx_delete_udp_connection(void *data) -{ - ngx_connection_t *c = data; - - if (c->udp == NULL) { - return; - } - - ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node); - - c->udp = NULL; -} - - static ngx_connection_t * -ngx_lookup_udp_connection(ngx_listening_t *ls, ngx_str_t *key, +ngx_quic_lookup_connection(ngx_listening_t *ls, ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen) { - uint32_t hash; - ngx_int_t rc; - ngx_connection_t *c; - ngx_rbtree_node_t *node, *sentinel; - ngx_udp_connection_t *udp; + uint32_t hash; + ngx_int_t rc; + ngx_connection_t *c; + ngx_rbtree_node_t *node, *sentinel; + ngx_quic_socket_t *qsock; if (key->len == 0) { return NULL; @@ -580,15 +434,7 @@ ngx_lookup_udp_connection(ngx_listening_ node = ls->rbtree.root; sentinel = ls->rbtree.sentinel; - - ngx_crc32_init(hash); - ngx_crc32_update(&hash, key->data, key->len); - - if (ls->wildcard) { - ngx_crc32_update(&hash, (u_char *) local_sockaddr, local_socklen); - } - - ngx_crc32_final(hash); + hash = ngx_crc32_long(key->data, key->len); while (node != sentinel) { @@ -604,11 +450,11 @@ ngx_lookup_udp_connection(ngx_listening_ /* hash == node->key */ - udp = (ngx_udp_connection_t *) node; + qsock = (ngx_quic_socket_t *) node; - c = udp->connection; + rc = ngx_memn2cmp(key->data, qsock->sid.id, key->len, qsock->sid.len); - rc = ngx_memn2cmp(key->data, udp->key.data, key->len, udp->key.len); + c = qsock->udp.connection; if (rc == 0 && ls->wildcard) { rc = ngx_cmp_sockaddr(local_sockaddr, local_socklen, @@ -616,13 +462,7 @@ ngx_lookup_udp_connection(ngx_listening_ } if (rc == 0) { - -#if (NGX_QUIC) - if (ls->quic && c->udp != udp) { - c->udp = udp; - } -#endif - + c->udp = &qsock->udp; return c; } @@ -631,13 +471,3 @@ ngx_lookup_udp_connection(ngx_listening_ return NULL; } - -#else - -void -ngx_delete_udp_connection(void *data) -{ - return; -} - -#endif diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1822,7 +1822,14 @@ ngx_http_add_listening(ngx_conf_t *cf, n ls->wildcard = addr->opt.wildcard; #if (NGX_HTTP_V3) + ls->quic = addr->opt.http3; + + if (ls->quic) { + ngx_rbtree_init(&ls->rbtree, &ls->sentinel, + ngx_quic_rbtree_insert_value); + } + #endif return ls; diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -519,8 +519,23 @@ ngx_stream_optimize_servers(ngx_conf_t * #endif #if (NGX_STREAM_QUIC) + ls->quic = addr[i].opt.quic; + + if (ls->quic) { + ngx_rbtree_init(&ls->rbtree, &ls->sentinel, + ngx_quic_rbtree_insert_value); + } + #endif + +#if !(NGX_WIN32) + if (!ls->quic) { + ngx_rbtree_init(&ls->rbtree, &ls->sentinel, + ngx_udp_rbtree_insert_value); + } +#endif + stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t)); if (stport == NULL) { return NGX_CONF_ERROR;