Mercurial > hg > nginx
diff src/event/ngx_event_udp.c @ 8628:45db1b5c1706 quic
QUIC: connection multiplexing per port.
Also, connection migration within a single worker is implemented.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 11 Nov 2020 11:57:50 +0000 |
parents | 6d4bc025c5a7 |
children | d62a16fff3a4 |
line wrap: on
line diff
--- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c @@ -12,19 +12,12 @@ #if !(NGX_WIN32) -struct ngx_udp_connection_s { - ngx_rbtree_node_t node; - ngx_connection_t *connection; - ngx_buf_t *buffer; -}; - - 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_insert_udp_connection(ngx_connection_t *c); +static ngx_int_t ngx_create_udp_connection(ngx_connection_t *c); static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, - struct sockaddr *sockaddr, socklen_t socklen, + ngx_str_t *key, struct sockaddr *sockaddr, socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen); @@ -32,6 +25,7 @@ void ngx_event_recvmsg(ngx_event_t *ev) { ssize_t n; + ngx_str_t key; ngx_buf_t buf; ngx_log_t *log; ngx_err_t err; @@ -229,8 +223,18 @@ ngx_event_recvmsg(ngx_event_t *ev) #endif - c = ngx_lookup_udp_connection(ls, sockaddr, socklen, local_sockaddr, - local_socklen); + ngx_str_null(&key); + +#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, sockaddr, socklen, + local_sockaddr, local_socklen); if (c) { @@ -403,7 +407,7 @@ ngx_event_recvmsg(ngx_event_t *ev) } #endif - if (ngx_insert_udp_connection(c) != NGX_OK) { + if (ngx_create_udp_connection(c) != NGX_OK) { ngx_close_accepted_udp_connection(c); return; } @@ -492,8 +496,13 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n udpt = (ngx_udp_connection_t *) temp; ct = udpt->connection; - rc = ngx_cmp_sockaddr(c->sockaddr, c->socklen, - ct->sockaddr, ct->socklen, 1); + rc = ngx_memn2cmp(udp->key.data, udpt->key.data, + udp->key.len, udpt->key.len); + + if (rc == 0 && udp->key.len == 0) { + 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, @@ -519,12 +528,18 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_n static ngx_int_t -ngx_insert_udp_connection(ngx_connection_t *c) +ngx_create_udp_connection(ngx_connection_t *c) { - uint32_t hash; + 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; } @@ -534,19 +549,6 @@ ngx_insert_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; @@ -555,7 +557,9 @@ ngx_insert_udp_connection(ngx_connection cln->data = c; cln->handler = ngx_delete_udp_connection; - ngx_rbtree_insert(&c->listening->rbtree, &udp->node); + key.len = 0; + + ngx_insert_udp_connection(c, udp, &key); c->udp = udp; @@ -564,6 +568,34 @@ ngx_insert_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 (key->len == 0) { + 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->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; @@ -579,8 +611,9 @@ ngx_delete_udp_connection(void *data) static ngx_connection_t * -ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, - socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen) +ngx_lookup_udp_connection(ngx_listening_t *ls, ngx_str_t *key, + struct sockaddr *sockaddr, socklen_t socklen, + struct sockaddr *local_sockaddr, socklen_t local_socklen) { uint32_t hash; ngx_int_t rc; @@ -608,7 +641,12 @@ ngx_lookup_udp_connection(ngx_listening_ sentinel = ls->rbtree.sentinel; ngx_crc32_init(hash); - ngx_crc32_update(&hash, (u_char *) sockaddr, socklen); + + ngx_crc32_update(&hash, key->data, key->len); + + if (key->len == 0) { + ngx_crc32_update(&hash, (u_char *) sockaddr, socklen); + } if (ls->wildcard) { ngx_crc32_update(&hash, (u_char *) local_sockaddr, local_socklen); @@ -634,8 +672,12 @@ ngx_lookup_udp_connection(ngx_listening_ c = udp->connection; - rc = ngx_cmp_sockaddr(sockaddr, socklen, - c->sockaddr, c->socklen, 1); + rc = ngx_memn2cmp(key->data, udp->key.data, key->len, udp->key.len); + + if (rc == 0 && key->len == 0) { + rc = ngx_cmp_sockaddr(sockaddr, socklen, + c->sockaddr, c->socklen, 1); + } if (rc == 0 && ls->wildcard) { rc = ngx_cmp_sockaddr(local_sockaddr, local_socklen, @@ -643,6 +685,37 @@ ngx_lookup_udp_connection(ngx_listening_ } if (rc == 0) { + if (key->len) { + rc = ngx_cmp_sockaddr(sockaddr, socklen, + c->sockaddr, c->socklen, 1); + + if (rc) { +#if (NGX_DEBUG) + if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { + ngx_str_t addr; + u_char text[NGX_SOCKADDR_STRLEN]; + + addr.data = text; + addr.len = ngx_sock_ntop(sockaddr, socklen, text, + NGX_SOCKADDR_STRLEN, 1); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "client migrated to %V", &addr); + } +#endif + + if (c->socklen < socklen) { + c->sockaddr = ngx_palloc(c->pool, socklen); + if (c->sockaddr == NULL) { + return c; + } + } + + ngx_memcpy(c->sockaddr, sockaddr, socklen); + c->socklen = socklen; + } + } + return c; }