# HG changeset patch # User Roman Arutyunyan # Date 1466416127 -10800 # Node ID e778fe9a4463742fc139c3eb67c8e049a0fab354 # Parent 0c98c40924409fb6c3880b85090b03967dc154c4 Stream: set SO_REUSEADDR for UDP upstream sockets. 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. diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -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_connecti } #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) { @@ -113,6 +120,23 @@ ngx_event_connect_peer(ngx_peer_connecti #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) { ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno, "bind(%V) failed", &pc->local->name);