]> git.kaiwu.me - nginx.git/commitdiff
Stream: set SO_REUSEADDR for UDP upstream sockets.
authorRoman Arutyunyan <arut@nginx.com>
Mon, 20 Jun 2016 09:48:47 +0000 (12:48 +0300)
committerRoman Arutyunyan <arut@nginx.com>
Mon, 20 Jun 2016 09:48:47 +0000 (12:48 +0300)
The option is only set if the socket is bound to a specific port to allow
several such sockets coexist at the same time.  This is required, for example,
when nginx acts as a transparent proxy and receives two datagrams from the same
client in a short time.

The feature is only implemented for Linux.

src/event/ngx_event_connect.c

index 9a8f4d93142003f899a35c46b2f8b1878764c01c..30cb59a048b021c9b32476a036fa6fdea058e372 100644 (file)
@@ -21,6 +21,9 @@ ngx_int_t
 ngx_event_connect_peer(ngx_peer_connection_t *pc)
 {
     int                rc, type;
+#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
+    in_port_t          port;
+#endif
     ngx_int_t          event;
     ngx_err_t          err;
     ngx_uint_t         level;
@@ -87,9 +90,13 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
         }
 #endif
 
+#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
+        port = ngx_inet_get_port(pc->sockaddr);
+#endif
+
 #if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT)
 
-        if (pc->sockaddr->sa_family != AF_UNIX) {
+        if (pc->sockaddr->sa_family != AF_UNIX && port == 0) {
             static int  bind_address_no_port = 1;
 
             if (bind_address_no_port) {
@@ -111,6 +118,23 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
             }
         }
 
+#endif
+
+#if (NGX_LINUX)
+
+        if (pc->type == SOCK_DGRAM && port != 0) {
+            int  reuse_addr = 1;
+
+            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                           (const void *) &reuse_addr, sizeof(int))
+                 == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+                              "setsockopt(SO_REUSEADDR) failed");
+                goto failed;
+            }
+        }
+
 #endif
 
         if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {