diff options
Diffstat (limited to 'src/event/ngx_event_udp.c')
-rw-r--r-- | src/event/ngx_event_udp.c | 180 |
1 files changed, 114 insertions, 66 deletions
diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c index 1ac82c7f5..1053fa0ac 100644 --- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c @@ -12,35 +12,30 @@ #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, - struct sockaddr *local_sockaddr, socklen_t local_socklen); + ngx_str_t *key, 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 socklen, local_socklen; + socklen_t 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_udp_dgram_t dgram; + struct sockaddr *local_sockaddr; ngx_listening_t *ls; ngx_event_conf_t *ecf; ngx_connection_t *c, *lc; @@ -115,21 +110,21 @@ ngx_event_recvmsg(ngx_event_t *ev) } #endif - sockaddr = msg.msg_name; - socklen = msg.msg_namelen; + dgram.sockaddr = msg.msg_name; + dgram.socklen = msg.msg_namelen; - if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { - socklen = sizeof(ngx_sockaddr_t); + if (dgram.socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + dgram.socklen = sizeof(ngx_sockaddr_t); } - if (socklen == 0) { + if (dgram.socklen == 0) { /* * on Linux recvmsg() returns zero msg_namelen * when receiving packets from unbound AF_UNIX sockets */ - socklen = sizeof(struct sockaddr); + dgram.socklen = sizeof(struct sockaddr); ngx_memzero(&sa, sizeof(struct sockaddr)); sa.sockaddr.sa_family = ls->sockaddr->sa_family; } @@ -157,8 +152,35 @@ ngx_event_recvmsg(ngx_event_t *ev) #endif - c = ngx_lookup_udp_connection(ls, sockaddr, socklen, local_sockaddr, - local_socklen); + 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); if (c) { @@ -180,10 +202,14 @@ 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; - c->udp->buffer = &buf; + dgram.buffer = &buf; + + c->udp->dgram = &dgram; rev->ready = 1; rev->active = 0; @@ -191,7 +217,7 @@ ngx_event_recvmsg(ngx_event_t *ev) rev->handler(rev); if (c->udp) { - c->udp->buffer = NULL; + c->udp->dgram = NULL; } rev->ready = 0; @@ -214,7 +240,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->shared = 1; c->type = SOCK_DGRAM; - c->socklen = socklen; + c->socklen = dgram.socklen; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); @@ -226,13 +252,21 @@ ngx_event_recvmsg(ngx_event_t *ev) return; } - c->sockaddr = ngx_palloc(c->pool, socklen); + len = dgram.socklen; + +#if (NGX_QUIC) + if (ls->quic) { + len = NGX_SOCKADDRLEN; + } +#endif + + c->sockaddr = ngx_palloc(c->pool, len); if (c->sockaddr == NULL) { ngx_close_accepted_udp_connection(c); return; } - ngx_memcpy(c->sockaddr, sockaddr, socklen); + ngx_memcpy(c->sockaddr, dgram.sockaddr, dgram.socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { @@ -335,7 +369,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; } @@ -378,17 +412,17 @@ 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->buffer == NULL) { + if (c->udp == NULL || c->udp->dgram == NULL) { return NGX_AGAIN; } - b = c->udp->buffer; + b = c->udp->dgram->buffer; n = ngx_min(b->last - b->pos, (ssize_t) size); ngx_memcpy(buf, b->pos, n); - c->udp->buffer = NULL; + c->udp->dgram = NULL; c->read->ready = 0; c->read->active = 1; @@ -424,8 +458,8 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, 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 && c->listening->wildcard) { rc = ngx_cmp_sockaddr(c->local_sockaddr, c->local_socklen, @@ -451,12 +485,18 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, 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; } @@ -466,19 +506,6 @@ ngx_insert_udp_connection(ngx_connection_t *c) 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; @@ -487,7 +514,10 @@ 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); + key.data = (u_char *) c->sockaddr; + key.len = c->socklen; + + ngx_insert_udp_connection(c, udp, &key); c->udp = udp; @@ -496,6 +526,30 @@ ngx_insert_udp_connection(ngx_connection_t *c) 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; @@ -511,8 +565,8 @@ 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 *local_sockaddr, socklen_t local_socklen) { uint32_t hash; ngx_int_t rc; @@ -520,27 +574,15 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, ngx_rbtree_node_t *node, *sentinel; ngx_udp_connection_t *udp; -#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; - } + if (key->len == 0) { + return NULL; } -#endif - node = ls->rbtree.root; 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 (ls->wildcard) { ngx_crc32_update(&hash, (u_char *) local_sockaddr, local_socklen); @@ -566,8 +608,7 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, 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 && ls->wildcard) { rc = ngx_cmp_sockaddr(local_sockaddr, local_socklen, @@ -575,6 +616,13 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, } if (rc == 0) { + +#if (NGX_QUIC) + if (ls->quic && c->udp != udp) { + c->udp = udp; + } +#endif + return c; } |