[nginx] Events: get remote addresses before creating udp connection.

Roman Arutyunyan arut at nginx.com
Mon Jun 4 18:46:27 UTC 2018


details:   http://hg.nginx.org/nginx/rev/52aacc8ddcc5
branches:  
changeset: 7284:52aacc8ddcc5
user:      Roman Arutyunyan <arut at nginx.com>
date:      Fri Jun 01 13:12:57 2018 +0300
description:
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.

diffstat:

 src/event/ngx_event_accept.c |  205 ++++++++++++++++++++++--------------------
 1 files changed, 108 insertions(+), 97 deletions(-)

diffs (266 lines):

diff -r d0b897c0bb5b -r 52aacc8ddcc5 src/event/ngx_event_accept.c
--- a/src/event/ngx_event_accept.c	Fri Jun 01 16:53:02 2018 +0300
+++ b/src/event/ngx_event_accept.c	Fri Jun 01 13:12:57 2018 +0300
@@ -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) {


More information about the nginx-devel mailing list