1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevngx_os_io_t  ngx_io;
14e18a033bSKonstantin Ananyev
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyevstatic void ngx_drain_connections(ngx_cycle_t *cycle);
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyevngx_listening_t *
20e18a033bSKonstantin Ananyevngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
21e18a033bSKonstantin Ananyev    socklen_t socklen)
22e18a033bSKonstantin Ananyev{
23e18a033bSKonstantin Ananyev    size_t            len;
24e18a033bSKonstantin Ananyev    ngx_listening_t  *ls;
25e18a033bSKonstantin Ananyev    struct sockaddr  *sa;
26e18a033bSKonstantin Ananyev    u_char            text[NGX_SOCKADDR_STRLEN];
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev    ls = ngx_array_push(&cf->cycle->listening);
29e18a033bSKonstantin Ananyev    if (ls == NULL) {
30e18a033bSKonstantin Ananyev        return NULL;
31e18a033bSKonstantin Ananyev    }
32e18a033bSKonstantin Ananyev
33e18a033bSKonstantin Ananyev    ngx_memzero(ls, sizeof(ngx_listening_t));
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev    sa = ngx_palloc(cf->pool, socklen);
36e18a033bSKonstantin Ananyev    if (sa == NULL) {
37e18a033bSKonstantin Ananyev        return NULL;
38e18a033bSKonstantin Ananyev    }
39e18a033bSKonstantin Ananyev
40e18a033bSKonstantin Ananyev    ngx_memcpy(sa, sockaddr, socklen);
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyev    ls->sockaddr = sa;
43e18a033bSKonstantin Ananyev    ls->socklen = socklen;
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyev    len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
46e18a033bSKonstantin Ananyev    ls->addr_text.len = len;
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev    switch (ls->sockaddr->sa_family) {
49e18a033bSKonstantin Ananyev#if (NGX_HAVE_INET6)
50e18a033bSKonstantin Ananyev    case AF_INET6:
51e18a033bSKonstantin Ananyev        ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
52e18a033bSKonstantin Ananyev        break;
53e18a033bSKonstantin Ananyev#endif
54e18a033bSKonstantin Ananyev#if (NGX_HAVE_UNIX_DOMAIN)
55e18a033bSKonstantin Ananyev    case AF_UNIX:
56e18a033bSKonstantin Ananyev        ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
57e18a033bSKonstantin Ananyev        len++;
58e18a033bSKonstantin Ananyev        break;
59e18a033bSKonstantin Ananyev#endif
60e18a033bSKonstantin Ananyev    case AF_INET:
61e18a033bSKonstantin Ananyev        ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
62e18a033bSKonstantin Ananyev        break;
63e18a033bSKonstantin Ananyev    default:
64e18a033bSKonstantin Ananyev        ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
65e18a033bSKonstantin Ananyev        break;
66e18a033bSKonstantin Ananyev    }
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    ls->addr_text.data = ngx_pnalloc(cf->pool, len);
69e18a033bSKonstantin Ananyev    if (ls->addr_text.data == NULL) {
70e18a033bSKonstantin Ananyev        return NULL;
71e18a033bSKonstantin Ananyev    }
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev    ngx_memcpy(ls->addr_text.data, text, len);
74e18a033bSKonstantin Ananyev
75e18a033bSKonstantin Ananyev    ls->fd = (ngx_socket_t) -1;
76e18a033bSKonstantin Ananyev    ls->type = SOCK_STREAM;
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev    ls->backlog = NGX_LISTEN_BACKLOG;
79e18a033bSKonstantin Ananyev    ls->rcvbuf = -1;
80e18a033bSKonstantin Ananyev    ls->sndbuf = -1;
81e18a033bSKonstantin Ananyev
82e18a033bSKonstantin Ananyev#if (NGX_HAVE_SETFIB)
83e18a033bSKonstantin Ananyev    ls->setfib = -1;
84e18a033bSKonstantin Ananyev#endif
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev#if (NGX_HAVE_TCP_FASTOPEN)
87e18a033bSKonstantin Ananyev    ls->fastopen = -1;
88e18a033bSKonstantin Ananyev#endif
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev    return ls;
91e18a033bSKonstantin Ananyev}
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyevngx_int_t
95e18a033bSKonstantin Ananyevngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls)
96e18a033bSKonstantin Ananyev{
97e18a033bSKonstantin Ananyev#if (NGX_HAVE_REUSEPORT)
98e18a033bSKonstantin Ananyev
99e18a033bSKonstantin Ananyev    ngx_int_t         n;
100e18a033bSKonstantin Ananyev    ngx_core_conf_t  *ccf;
101e18a033bSKonstantin Ananyev    ngx_listening_t   ols;
102e18a033bSKonstantin Ananyev
103e18a033bSKonstantin Ananyev    if (!ls->reuseport) {
104e18a033bSKonstantin Ananyev        return NGX_OK;
105e18a033bSKonstantin Ananyev    }
106e18a033bSKonstantin Ananyev
107e18a033bSKonstantin Ananyev    ols = *ls;
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyev    ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
110e18a033bSKonstantin Ananyev                                           ngx_core_module);
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev    for (n = 1; n < ccf->worker_processes; n++) {
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev        /* create a socket for each worker process */
115e18a033bSKonstantin Ananyev
116e18a033bSKonstantin Ananyev        ls = ngx_array_push(&cf->cycle->listening);
117e18a033bSKonstantin Ananyev        if (ls == NULL) {
118e18a033bSKonstantin Ananyev            return NGX_ERROR;
119e18a033bSKonstantin Ananyev        }
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev        *ls = ols;
122e18a033bSKonstantin Ananyev        ls->worker = n;
123e18a033bSKonstantin Ananyev    }
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev#endif
126e18a033bSKonstantin Ananyev
127e18a033bSKonstantin Ananyev    return NGX_OK;
128e18a033bSKonstantin Ananyev}
129e18a033bSKonstantin Ananyev
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyevngx_int_t
132e18a033bSKonstantin Ananyevngx_set_inherited_sockets(ngx_cycle_t *cycle)
133e18a033bSKonstantin Ananyev{
134e18a033bSKonstantin Ananyev    size_t                     len;
135e18a033bSKonstantin Ananyev    ngx_uint_t                 i;
136e18a033bSKonstantin Ananyev    ngx_listening_t           *ls;
137e18a033bSKonstantin Ananyev    socklen_t                  olen;
138e18a033bSKonstantin Ananyev#if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
139e18a033bSKonstantin Ananyev    ngx_err_t                  err;
140e18a033bSKonstantin Ananyev#endif
141e18a033bSKonstantin Ananyev#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
142e18a033bSKonstantin Ananyev    struct accept_filter_arg   af;
143e18a033bSKonstantin Ananyev#endif
144e18a033bSKonstantin Ananyev#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
145e18a033bSKonstantin Ananyev    int                        timeout;
146e18a033bSKonstantin Ananyev#endif
147e18a033bSKonstantin Ananyev#if (NGX_HAVE_REUSEPORT)
148e18a033bSKonstantin Ananyev    int                        reuseport;
149e18a033bSKonstantin Ananyev#endif
150e18a033bSKonstantin Ananyev
151e18a033bSKonstantin Ananyev    ls = cycle->listening.elts;
152e18a033bSKonstantin Ananyev    for (i = 0; i < cycle->listening.nelts; i++) {
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev        ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
155e18a033bSKonstantin Ananyev        if (ls[i].sockaddr == NULL) {
156e18a033bSKonstantin Ananyev            return NGX_ERROR;
157e18a033bSKonstantin Ananyev        }
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev        ls[i].socklen = sizeof(ngx_sockaddr_t);
160e18a033bSKonstantin Ananyev        if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
161e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
162e18a033bSKonstantin Ananyev                          "getsockname() of the inherited "
163e18a033bSKonstantin Ananyev                          "socket #%d failed", ls[i].fd);
164e18a033bSKonstantin Ananyev            ls[i].ignore = 1;
165e18a033bSKonstantin Ananyev            continue;
166e18a033bSKonstantin Ananyev        }
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev        switch (ls[i].sockaddr->sa_family) {
169e18a033bSKonstantin Ananyev
170e18a033bSKonstantin Ananyev#if (NGX_HAVE_INET6)
171e18a033bSKonstantin Ananyev        case AF_INET6:
172e18a033bSKonstantin Ananyev            ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
173e18a033bSKonstantin Ananyev            len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
174e18a033bSKonstantin Ananyev            break;
175e18a033bSKonstantin Ananyev#endif
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev#if (NGX_HAVE_UNIX_DOMAIN)
178e18a033bSKonstantin Ananyev        case AF_UNIX:
179e18a033bSKonstantin Ananyev            ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
180e18a033bSKonstantin Ananyev            len = NGX_UNIX_ADDRSTRLEN;
181e18a033bSKonstantin Ananyev            break;
182e18a033bSKonstantin Ananyev#endif
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyev        case AF_INET:
185e18a033bSKonstantin Ananyev            ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
186e18a033bSKonstantin Ananyev            len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
187e18a033bSKonstantin Ananyev            break;
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev        default:
190e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
191e18a033bSKonstantin Ananyev                          "the inherited socket #%d has "
192e18a033bSKonstantin Ananyev                          "an unsupported protocol family", ls[i].fd);
193e18a033bSKonstantin Ananyev            ls[i].ignore = 1;
194e18a033bSKonstantin Ananyev            continue;
195e18a033bSKonstantin Ananyev        }
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev        ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
198e18a033bSKonstantin Ananyev        if (ls[i].addr_text.data == NULL) {
199e18a033bSKonstantin Ananyev            return NGX_ERROR;
200e18a033bSKonstantin Ananyev        }
201e18a033bSKonstantin Ananyev
202e18a033bSKonstantin Ananyev        len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
203e18a033bSKonstantin Ananyev                            ls[i].addr_text.data, len, 1);
204e18a033bSKonstantin Ananyev        if (len == 0) {
205e18a033bSKonstantin Ananyev            return NGX_ERROR;
206e18a033bSKonstantin Ananyev        }
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev        ls[i].addr_text.len = len;
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyev        ls[i].backlog = NGX_LISTEN_BACKLOG;
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev        olen = sizeof(int);
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type,
215e18a033bSKonstantin Ananyev                       &olen)
216e18a033bSKonstantin Ananyev            == -1)
217e18a033bSKonstantin Ananyev        {
218e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
219e18a033bSKonstantin Ananyev                          "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text);
220e18a033bSKonstantin Ananyev            ls[i].ignore = 1;
221e18a033bSKonstantin Ananyev            continue;
222e18a033bSKonstantin Ananyev        }
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyev        olen = sizeof(int);
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
227e18a033bSKonstantin Ananyev                       &olen)
228e18a033bSKonstantin Ananyev            == -1)
229e18a033bSKonstantin Ananyev        {
230e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
231e18a033bSKonstantin Ananyev                          "getsockopt(SO_RCVBUF) %V failed, ignored",
232e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev            ls[i].rcvbuf = -1;
235e18a033bSKonstantin Ananyev        }
236e18a033bSKonstantin Ananyev
237e18a033bSKonstantin Ananyev        olen = sizeof(int);
238e18a033bSKonstantin Ananyev
239e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
240e18a033bSKonstantin Ananyev                       &olen)
241e18a033bSKonstantin Ananyev            == -1)
242e18a033bSKonstantin Ananyev        {
243e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
244e18a033bSKonstantin Ananyev                          "getsockopt(SO_SNDBUF) %V failed, ignored",
245e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
246e18a033bSKonstantin Ananyev
247e18a033bSKonstantin Ananyev            ls[i].sndbuf = -1;
248e18a033bSKonstantin Ananyev        }
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev#if 0
251e18a033bSKonstantin Ananyev        /* SO_SETFIB is currently a set only option */
252e18a033bSKonstantin Ananyev
253e18a033bSKonstantin Ananyev#if (NGX_HAVE_SETFIB)
254e18a033bSKonstantin Ananyev
255e18a033bSKonstantin Ananyev        olen = sizeof(int);
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
258e18a033bSKonstantin Ananyev                       (void *) &ls[i].setfib, &olen)
259e18a033bSKonstantin Ananyev            == -1)
260e18a033bSKonstantin Ananyev        {
261e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
262e18a033bSKonstantin Ananyev                          "getsockopt(SO_SETFIB) %V failed, ignored",
263e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev            ls[i].setfib = -1;
266e18a033bSKonstantin Ananyev        }
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev#endif
269e18a033bSKonstantin Ananyev#endif
270e18a033bSKonstantin Ananyev
271e18a033bSKonstantin Ananyev#if (NGX_HAVE_REUSEPORT)
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev        reuseport = 0;
274e18a033bSKonstantin Ananyev        olen = sizeof(int);
275e18a033bSKonstantin Ananyev
276e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
277e18a033bSKonstantin Ananyev                       (void *) &reuseport, &olen)
278e18a033bSKonstantin Ananyev            == -1)
279e18a033bSKonstantin Ananyev        {
280e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
281e18a033bSKonstantin Ananyev                          "getsockopt(SO_REUSEPORT) %V failed, ignored",
282e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev        } else {
285e18a033bSKonstantin Ananyev            ls[i].reuseport = reuseport ? 1 : 0;
286e18a033bSKonstantin Ananyev        }
287e18a033bSKonstantin Ananyev
288e18a033bSKonstantin Ananyev#endif
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyev        if (ls[i].type != SOCK_STREAM) {
291e18a033bSKonstantin Ananyev            continue;
292e18a033bSKonstantin Ananyev        }
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev#if (NGX_HAVE_TCP_FASTOPEN)
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev        olen = sizeof(int);
297e18a033bSKonstantin Ananyev
298e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
299e18a033bSKonstantin Ananyev                       (void *) &ls[i].fastopen, &olen)
300e18a033bSKonstantin Ananyev            == -1)
301e18a033bSKonstantin Ananyev        {
302e18a033bSKonstantin Ananyev            err = ngx_socket_errno;
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev            if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) {
305e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
306e18a033bSKonstantin Ananyev                              "getsockopt(TCP_FASTOPEN) %V failed, ignored",
307e18a033bSKonstantin Ananyev                              &ls[i].addr_text);
308e18a033bSKonstantin Ananyev            }
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev            ls[i].fastopen = -1;
311e18a033bSKonstantin Ananyev        }
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyev#endif
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev        ngx_memzero(&af, sizeof(struct accept_filter_arg));
318e18a033bSKonstantin Ananyev        olen = sizeof(struct accept_filter_arg);
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
321e18a033bSKonstantin Ananyev            == -1)
322e18a033bSKonstantin Ananyev        {
323e18a033bSKonstantin Ananyev            err = ngx_socket_errno;
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev            if (err == NGX_EINVAL) {
326e18a033bSKonstantin Ananyev                continue;
327e18a033bSKonstantin Ananyev            }
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
330e18a033bSKonstantin Ananyev                          "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
331e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
332e18a033bSKonstantin Ananyev            continue;
333e18a033bSKonstantin Ananyev        }
334e18a033bSKonstantin Ananyev
335e18a033bSKonstantin Ananyev        if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
336e18a033bSKonstantin Ananyev            continue;
337e18a033bSKonstantin Ananyev        }
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev        ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
340e18a033bSKonstantin Ananyev        if (ls[i].accept_filter == NULL) {
341e18a033bSKonstantin Ananyev            return NGX_ERROR;
342e18a033bSKonstantin Ananyev        }
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev        (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
345e18a033bSKonstantin Ananyev                           (u_char *) af.af_name, 16);
346e18a033bSKonstantin Ananyev#endif
347e18a033bSKonstantin Ananyev
348e18a033bSKonstantin Ananyev#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev        timeout = 0;
351e18a033bSKonstantin Ananyev        olen = sizeof(int);
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
354e18a033bSKonstantin Ananyev            == -1)
355e18a033bSKonstantin Ananyev        {
356e18a033bSKonstantin Ananyev            err = ngx_socket_errno;
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev            if (err == NGX_EOPNOTSUPP) {
359e18a033bSKonstantin Ananyev                continue;
360e18a033bSKonstantin Ananyev            }
361e18a033bSKonstantin Ananyev
362e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
363e18a033bSKonstantin Ananyev                          "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
364e18a033bSKonstantin Ananyev                          &ls[i].addr_text);
365e18a033bSKonstantin Ananyev            continue;
366e18a033bSKonstantin Ananyev        }
367e18a033bSKonstantin Ananyev
368e18a033bSKonstantin Ananyev        if (olen < sizeof(int) || timeout == 0) {
369e18a033bSKonstantin Ananyev            continue;
370e18a033bSKonstantin Ananyev        }
371e18a033bSKonstantin Ananyev
372e18a033bSKonstantin Ananyev        ls[i].deferred_accept = 1;
373e18a033bSKonstantin Ananyev#endif
374e18a033bSKonstantin Ananyev    }
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev    return NGX_OK;
377e18a033bSKonstantin Ananyev}
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyevngx_int_t
381e18a033bSKonstantin Ananyevngx_open_listening_sockets(ngx_cycle_t *cycle)
382e18a033bSKonstantin Ananyev{
383e18a033bSKonstantin Ananyev    int               reuseaddr;
384e18a033bSKonstantin Ananyev    ngx_uint_t        i, tries, failed;
385e18a033bSKonstantin Ananyev    ngx_err_t         err;
386e18a033bSKonstantin Ananyev    ngx_log_t        *log;
387e18a033bSKonstantin Ananyev    ngx_socket_t      s;
388e18a033bSKonstantin Ananyev    ngx_listening_t  *ls;
389e18a033bSKonstantin Ananyev
390e18a033bSKonstantin Ananyev    reuseaddr = 1;
391e18a033bSKonstantin Ananyev#if (NGX_SUPPRESS_WARN)
392e18a033bSKonstantin Ananyev    failed = 0;
393e18a033bSKonstantin Ananyev#endif
394e18a033bSKonstantin Ananyev
395e18a033bSKonstantin Ananyev    log = cycle->log;
396e18a033bSKonstantin Ananyev
397e18a033bSKonstantin Ananyev    /* TODO: configurable try number */
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev    for (tries = 5; tries; tries--) {
400e18a033bSKonstantin Ananyev        failed = 0;
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyev        /* for each listening socket */
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyev        ls = cycle->listening.elts;
405e18a033bSKonstantin Ananyev        for (i = 0; i < cycle->listening.nelts; i++) {
406e18a033bSKonstantin Ananyev
407e18a033bSKonstantin Ananyev            if (ls[i].ignore) {
408e18a033bSKonstantin Ananyev                continue;
409e18a033bSKonstantin Ananyev            }
410e18a033bSKonstantin Ananyev
411e18a033bSKonstantin Ananyev#if (NGX_HAVE_REUSEPORT)
412e18a033bSKonstantin Ananyev
413e18a033bSKonstantin Ananyev            if (ls[i].add_reuseport) {
414e18a033bSKonstantin Ananyev
415e18a033bSKonstantin Ananyev                /*
416e18a033bSKonstantin Ananyev                 * to allow transition from a socket without SO_REUSEPORT
417e18a033bSKonstantin Ananyev                 * to multiple sockets with SO_REUSEPORT, we have to set
418e18a033bSKonstantin Ananyev                 * SO_REUSEPORT on the old socket before opening new ones
419e18a033bSKonstantin Ananyev                 */
420