# HG changeset patch # User Roman Arutyunyan # Date 1527847977 -10800 # Node ID 52aacc8ddcc54879442c707dab0625cfc4b3a44f # Parent d0b897c0bb5b894616b193c05f6eaf5069545f65 Events: get remote addresses before creating udp connection. Previously, ngx_event_recvmsg() got remote socket addresses after creating the connection object. In preparation to handling multiple UDP packets in a single session, this code was moved up. diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -328,10 +328,12 @@ ngx_event_recvmsg(ngx_event_t *ev) ssize_t n; 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; + ngx_sockaddr_t sa, lsa; + struct sockaddr *sockaddr, *local_sockaddr; ngx_listening_t *ls; ngx_event_conf_t *ecf; ngx_connection_t *c, *lc; @@ -420,10 +422,6 @@ ngx_event_recvmsg(ngx_event_t *ev) return; } -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); -#endif - #if (NGX_HAVE_MSGHDR_MSG_CONTROL) if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { ngx_log_error(NGX_LOG_ALERT, ev->log, 0, @@ -432,6 +430,102 @@ ngx_event_recvmsg(ngx_event_t *ev) } #endif + sockaddr = msg.msg_name; + socklen = msg.msg_namelen; + + if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + socklen = sizeof(ngx_sockaddr_t); + } + + if (socklen == 0) { + + /* + * on Linux recvmsg() returns zero msg_namelen + * when receiving packets from unbound AF_UNIX sockets + */ + + socklen = sizeof(struct sockaddr); + ngx_memzero(&sa, sizeof(struct sockaddr)); + sa.sockaddr.sa_family = ls->sockaddr->sa_family; + } + + local_sockaddr = ls->sockaddr; + local_socklen = ls->socklen; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + if (ls->wildcard) { + struct cmsghdr *cmsg; + + ngx_memcpy(&lsa, local_sockaddr, local_socklen); + local_sockaddr = &lsa.sockaddr; + + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + +#if (NGX_HAVE_IP_RECVDSTADDR) + + if (cmsg->cmsg_level == IPPROTO_IP + && cmsg->cmsg_type == IP_RECVDSTADDR + && local_sockaddr->sa_family == AF_INET) + { + struct in_addr *addr; + struct sockaddr_in *sin; + + addr = (struct in_addr *) CMSG_DATA(cmsg); + sin = (struct sockaddr_in *) local_sockaddr; + sin->sin_addr = *addr; + + break; + } + +#elif (NGX_HAVE_IP_PKTINFO) + + if (cmsg->cmsg_level == IPPROTO_IP + && cmsg->cmsg_type == IP_PKTINFO + && local_sockaddr->sa_family == AF_INET) + { + struct in_pktinfo *pkt; + struct sockaddr_in *sin; + + pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); + sin = (struct sockaddr_in *) local_sockaddr; + sin->sin_addr = pkt->ipi_addr; + + break; + } + +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + + if (cmsg->cmsg_level == IPPROTO_IPV6 + && cmsg->cmsg_type == IPV6_PKTINFO + && local_sockaddr->sa_family == AF_INET6) + { + struct in6_pktinfo *pkt6; + struct sockaddr_in6 *sin6; + + pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); + sin6 = (struct sockaddr_in6 *) local_sockaddr; + sin6->sin6_addr = pkt6->ipi6_addr; + + break; + } + +#endif + + } + } + +#endif + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); +#endif + ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n; @@ -442,23 +536,7 @@ ngx_event_recvmsg(ngx_event_t *ev) c->shared = 1; c->type = SOCK_DGRAM; - c->socklen = msg.msg_namelen; - - if (c->socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { - c->socklen = sizeof(ngx_sockaddr_t); - } - - if (c->socklen == 0) { - - /* - * on Linux recvmsg() returns zero msg_namelen - * when receiving packets from unbound AF_UNIX sockets - */ - - c->socklen = sizeof(struct sockaddr); - ngx_memzero(&sa, sizeof(struct sockaddr)); - sa.sockaddr.sa_family = ls->sockaddr->sa_family; - } + c->socklen = socklen; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); @@ -470,13 +548,13 @@ ngx_event_recvmsg(ngx_event_t *ev) return; } - c->sockaddr = ngx_palloc(c->pool, c->socklen); + c->sockaddr = ngx_palloc(c->pool, socklen); if (c->sockaddr == NULL) { ngx_close_accepted_connection(c); return; } - ngx_memcpy(c->sockaddr, msg.msg_name, c->socklen); + ngx_memcpy(c->sockaddr, sockaddr, socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { @@ -491,87 +569,20 @@ ngx_event_recvmsg(ngx_event_t *ev) c->log = log; c->pool->log = log; - c->listening = ls; - c->local_sockaddr = ls->sockaddr; - c->local_socklen = ls->socklen; - -#if (NGX_HAVE_MSGHDR_MSG_CONTROL) - if (ls->wildcard) { - struct cmsghdr *cmsg; - struct sockaddr *sockaddr; - - sockaddr = ngx_palloc(c->pool, c->local_socklen); - if (sockaddr == NULL) { + if (local_sockaddr == &lsa.sockaddr) { + local_sockaddr = ngx_palloc(c->pool, local_socklen); + if (local_sockaddr == NULL) { ngx_close_accepted_connection(c); return; } - ngx_memcpy(sockaddr, c->local_sockaddr, c->local_socklen); - c->local_sockaddr = sockaddr; - - for (cmsg = CMSG_FIRSTHDR(&msg); - cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) - { - -#if (NGX_HAVE_IP_RECVDSTADDR) - - if (cmsg->cmsg_level == IPPROTO_IP - && cmsg->cmsg_type == IP_RECVDSTADDR - && sockaddr->sa_family == AF_INET) - { - struct in_addr *addr; - struct sockaddr_in *sin; - - addr = (struct in_addr *) CMSG_DATA(cmsg); - sin = (struct sockaddr_in *) sockaddr; - sin->sin_addr = *addr; - - break; - } - -#elif (NGX_HAVE_IP_PKTINFO) - - if (cmsg->cmsg_level == IPPROTO_IP - && cmsg->cmsg_type == IP_PKTINFO - && sockaddr->sa_family == AF_INET) - { - struct in_pktinfo *pkt; - struct sockaddr_in *sin; - - pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); - sin = (struct sockaddr_in *) sockaddr; - sin->sin_addr = pkt->ipi_addr; - - break; - } - -#endif - -#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) - - if (cmsg->cmsg_level == IPPROTO_IPV6 - && cmsg->cmsg_type == IPV6_PKTINFO - && sockaddr->sa_family == AF_INET6) - { - struct in6_pktinfo *pkt6; - struct sockaddr_in6 *sin6; - - pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); - sin6 = (struct sockaddr_in6 *) sockaddr; - sin6->sin6_addr = pkt6->ipi6_addr; - - break; - } - -#endif - - } + ngx_memcpy(local_sockaddr, &lsa, local_socklen); } -#endif + c->local_sockaddr = local_sockaddr; + c->local_socklen = local_socklen; c->buffer = ngx_create_temp_buf(c->pool, n); if (c->buffer == NULL) {