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_stream.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyev#define ngx_stream_upstream_tries(p) ((p)->number                             \
14e18a033bSKonstantin Ananyev                                      + ((p)->next ? (p)->next->number : 0))
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev
17e18a033bSKonstantin Ananyevstatic ngx_stream_upstream_rr_peer_t *ngx_stream_upstream_get_peer(
18e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peer_data_t *rrp);
19e18a033bSKonstantin Ananyevstatic void ngx_stream_upstream_notify_round_robin_peer(
20e18a033bSKonstantin Ananyev    ngx_peer_connection_t *pc, void *data, ngx_uint_t state);
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyev#if (NGX_STREAM_SSL)
23e18a033bSKonstantin Ananyev
24e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_stream_upstream_set_round_robin_peer_session(
25e18a033bSKonstantin Ananyev    ngx_peer_connection_t *pc, void *data);
26e18a033bSKonstantin Ananyevstatic void ngx_stream_upstream_save_round_robin_peer_session(
27e18a033bSKonstantin Ananyev    ngx_peer_connection_t *pc, void *data);
28e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_stream_upstream_empty_set_session(
29e18a033bSKonstantin Ananyev    ngx_peer_connection_t *pc, void *data);
30e18a033bSKonstantin Ananyevstatic void ngx_stream_upstream_empty_save_session(ngx_peer_connection_t *pc,
31e18a033bSKonstantin Ananyev    void *data);
32e18a033bSKonstantin Ananyev
33e18a033bSKonstantin Ananyev#endif
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev
36e18a033bSKonstantin Ananyevngx_int_t
37e18a033bSKonstantin Ananyevngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
38e18a033bSKonstantin Ananyev    ngx_stream_upstream_srv_conf_t *us)
39e18a033bSKonstantin Ananyev{
40e18a033bSKonstantin Ananyev    ngx_url_t                        u;
41e18a033bSKonstantin Ananyev    ngx_uint_t                       i, j, n, w;
42e18a033bSKonstantin Ananyev    ngx_stream_upstream_server_t    *server;
43e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peer_t   *peer, **peerp;
44e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peers_t  *peers, *backup;
45e18a033bSKonstantin Ananyev
46e18a033bSKonstantin Ananyev    us->peer.init = ngx_stream_upstream_init_round_robin_peer;
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev    if (us->servers) {
49e18a033bSKonstantin Ananyev        server = us->servers->elts;
50e18a033bSKonstantin Ananyev
51e18a033bSKonstantin Ananyev        n = 0;
52e18a033bSKonstantin Ananyev        w = 0;
53e18a033bSKonstantin Ananyev
54e18a033bSKonstantin Ananyev        for (i = 0; i < us->servers->nelts; i++) {
55e18a033bSKonstantin Ananyev            if (server[i].backup) {
56e18a033bSKonstantin Ananyev                continue;
57e18a033bSKonstantin Ananyev            }
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev            n += server[i].naddrs;
60e18a033bSKonstantin Ananyev            w += server[i].naddrs * server[i].weight;
61e18a033bSKonstantin Ananyev        }
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev        if (n == 0) {
64e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
65e18a033bSKonstantin Ananyev                          "no servers in upstream \"%V\" in %s:%ui",
66e18a033bSKonstantin Ananyev                          &us->host, us->file_name, us->line);
67e18a033bSKonstantin Ananyev            return NGX_ERROR;
68e18a033bSKonstantin Ananyev        }
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev        peers = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t));
71e18a033bSKonstantin Ananyev        if (peers == NULL) {
72e18a033bSKonstantin Ananyev            return NGX_ERROR;
73e18a033bSKonstantin Ananyev        }
74e18a033bSKonstantin Ananyev
75e18a033bSKonstantin Ananyev        peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n);
76e18a033bSKonstantin Ananyev        if (peer == NULL) {
77e18a033bSKonstantin Ananyev            return NGX_ERROR;
78e18a033bSKonstantin Ananyev        }
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev        peers->single = (n == 1);
81e18a033bSKonstantin Ananyev        peers->number = n;
82e18a033bSKonstantin Ananyev        peers->weighted = (w != n);
83e18a033bSKonstantin Ananyev        peers->total_weight = w;
84e18a033bSKonstantin Ananyev        peers->name = &us->host;
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev        n = 0;
87e18a033bSKonstantin Ananyev        peerp = &peers->peer;
88e18a033bSKonstantin Ananyev
89e18a033bSKonstantin Ananyev        for (i = 0; i < us->servers->nelts; i++) {
90e18a033bSKonstantin Ananyev            if (server[i].backup) {
91e18a033bSKonstantin Ananyev                continue;
92e18a033bSKonstantin Ananyev            }
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev            for (j = 0; j < server[i].naddrs; j++) {
95e18a033bSKonstantin Ananyev                peer[n].sockaddr = server[i].addrs[j].sockaddr;
96e18a033bSKonstantin Ananyev                peer[n].socklen = server[i].addrs[j].socklen;
97e18a033bSKonstantin Ananyev                peer[n].name = server[i].addrs[j].name;
98e18a033bSKonstantin Ananyev                peer[n].weight = server[i].weight;
99e18a033bSKonstantin Ananyev                peer[n].effective_weight = server[i].weight;
100e18a033bSKonstantin Ananyev                peer[n].current_weight = 0;
101e18a033bSKonstantin Ananyev                peer[n].max_conns = server[i].max_conns;
102e18a033bSKonstantin Ananyev                peer[n].max_fails = server[i].max_fails;
103e18a033bSKonstantin Ananyev                peer[n].fail_timeout = server[i].fail_timeout;
104e18a033bSKonstantin Ananyev                peer[n].down = server[i].down;
105e18a033bSKonstantin Ananyev                peer[n].server = server[i].name;
106e18a033bSKonstantin Ananyev
107e18a033bSKonstantin Ananyev                *peerp = &peer[n];
108e18a033bSKonstantin Ananyev                peerp = &peer[n].next;
109e18a033bSKonstantin Ananyev                n++;
110e18a033bSKonstantin Ananyev            }
111e18a033bSKonstantin Ananyev        }
112e18a033bSKonstantin Ananyev
113e18a033bSKonstantin Ananyev        us->peer.data = peers;
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev        /* backup servers */
116e18a033bSKonstantin Ananyev
117e18a033bSKonstantin Ananyev        n = 0;
118e18a033bSKonstantin Ananyev        w = 0;
119e18a033bSKonstantin Ananyev
120e18a033bSKonstantin Ananyev        for (i = 0; i < us->servers->nelts; i++) {
121e18a033bSKonstantin Ananyev            if (!server[i].backup) {
122e18a033bSKonstantin Ananyev                continue;
123e18a033bSKonstantin Ananyev            }
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev            n += server[i].naddrs;
126e18a033bSKonstantin Ananyev            w += server[i].naddrs * server[i].weight;
127e18a033bSKonstantin Ananyev        }
128e18a033bSKonstantin Ananyev
129e18a033bSKonstantin Ananyev        if (n == 0) {
130e18a033bSKonstantin Ananyev            return NGX_OK;
131e18a033bSKonstantin Ananyev        }
132e18a033bSKonstantin Ananyev
133e18a033bSKonstantin Ananyev        backup = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t));
134e18a033bSKonstantin Ananyev        if (backup == NULL) {
135e18a033bSKonstantin Ananyev            return NGX_ERROR;
136e18a033bSKonstantin Ananyev        }
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev        peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n);
139e18a033bSKonstantin Ananyev        if (peer == NULL) {
140e18a033bSKonstantin Ananyev            return NGX_ERROR;
141e18a033bSKonstantin Ananyev        }
142e18a033bSKonstantin Ananyev
143e18a033bSKonstantin Ananyev        peers->single = 0;
144e18a033bSKonstantin Ananyev        backup->single = 0;
145e18a033bSKonstantin Ananyev        backup->number = n;
146e18a033bSKonstantin Ananyev        backup->weighted = (w != n);
147e18a033bSKonstantin Ananyev        backup->total_weight = w;
148e18a033bSKonstantin Ananyev        backup->name = &us->host;
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyev        n = 0;
151e18a033bSKonstantin Ananyev        peerp = &backup->peer;
152e18a033bSKonstantin Ananyev
153e18a033bSKonstantin Ananyev        for (i = 0; i < us->servers->nelts; i++) {
154e18a033bSKonstantin Ananyev            if (!server[i].backup) {
155e18a033bSKonstantin Ananyev                continue;
156e18a033bSKonstantin Ananyev            }
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev            for (j = 0; j < server[i].naddrs; j++) {
159e18a033bSKonstantin Ananyev                peer[n].sockaddr = server[i].addrs[j].sockaddr;
160e18a033bSKonstantin Ananyev                peer[n].socklen = server[i].addrs[j].socklen;
161e18a033bSKonstantin Ananyev                peer[n].name = server[i].addrs[j].name;
162e18a033bSKonstantin Ananyev                peer[n].weight = server[i].weight;
163e18a033bSKonstantin Ananyev                peer[n].effective_weight = server[i].weight;
164e18a033bSKonstantin Ananyev                peer[n].current_weight = 0;
165e18a033bSKonstantin Ananyev                peer[n].max_conns = server[i].max_conns;
166e18a033bSKonstantin Ananyev                peer[n].max_fails = server[i].max_fails;
167e18a033bSKonstantin Ananyev                peer[n].fail_timeout = server[i].fail_timeout;
168e18a033bSKonstantin Ananyev                peer[n].down = server[i].down;
169e18a033bSKonstantin Ananyev                peer[n].server = server[i].name;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev                *peerp = &peer[n];
172e18a033bSKonstantin Ananyev                peerp = &peer[n].next;
173e18a033bSKonstantin Ananyev                n++;
174e18a033bSKonstantin Ananyev            }
175e18a033bSKonstantin Ananyev        }
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev        peers->next = backup;
178e18a033bSKonstantin Ananyev
179e18a033bSKonstantin Ananyev        return NGX_OK;
180e18a033bSKonstantin Ananyev    }
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev
183e18a033bSKonstantin Ananyev    /* an upstream implicitly defined by proxy_pass, etc. */
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev    if (us->port == 0) {
186e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
187e18a033bSKonstantin Ananyev                      "no port in upstream \"%V\" in %s:%ui",
188e18a033bSKonstantin Ananyev                      &us->host, us->file_name, us->line);
189e18a033bSKonstantin Ananyev        return NGX_ERROR;
190e18a033bSKonstantin Ananyev    }
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev    ngx_memzero(&u, sizeof(ngx_url_t));
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev    u.host = us->host;
195e18a033bSKonstantin Ananyev    u.port = us->port;
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev    if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
198e18a033bSKonstantin Ananyev        if (u.err) {
199e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
200e18a033bSKonstantin Ananyev                          "%s in upstream \"%V\" in %s:%ui",
201e18a033bSKonstantin Ananyev                          u.err, &us->host, us->file_name, us->line);
202e18a033bSKonstantin Ananyev        }
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev        return NGX_ERROR;
205e18a033bSKonstantin Ananyev    }
206e18a033bSKonstantin Ananyev
207e18a033bSKonstantin Ananyev    n = u.naddrs;
208e18a033bSKonstantin Ananyev
209e18a033bSKonstantin Ananyev    peers = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t));
210e18a033bSKonstantin Ananyev    if (peers == NULL) {
211e18a033bSKonstantin Ananyev        return NGX_ERROR;
212e18a033bSKonstantin Ananyev    }
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev    peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n);
215e18a033bSKonstantin Ananyev    if (peer == NULL) {
216e18a033bSKonstantin Ananyev        return NGX_ERROR;
217e18a033bSKonstantin Ananyev    }
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyev    peers->single = (n == 1);
220e18a033bSKonstantin Ananyev    peers->number = n;
221e18a033bSKonstantin Ananyev    peers->weighted = 0;
222e18a033bSKonstantin Ananyev    peers->total_weight = n;
223e18a033bSKonstantin Ananyev    peers->name = &us->host;
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev    peerp = &peers->peer;
226e18a033bSKonstantin Ananyev
227e18a033bSKonstantin Ananyev    for (i = 0; i < u.naddrs; i++) {
228e18a033bSKonstantin Ananyev        peer[i].sockaddr = u.addrs[i].sockaddr;
229e18a033bSKonstantin Ananyev        peer[i].socklen = u.addrs[i].socklen;
230e18a033bSKonstantin Ananyev        peer[i].name = u.addrs[i].name;
231e18a033bSKonstantin Ananyev        peer[i].weight = 1;
232e18a033bSKonstantin Ananyev        peer[i].effective_weight = 1;
233e18a033bSKonstantin Ananyev        peer[i].current_weight = 0;
234e18a033bSKonstantin Ananyev        peer[i].max_conns = 0;
235e18a033bSKonstantin Ananyev        peer[i].max_fails = 1;
236e18a033bSKonstantin Ananyev        peer[i].fail_timeout = 10;
237e18a033bSKonstantin Ananyev        *peerp = &peer[i];
238e18a033bSKonstantin Ananyev        peerp = &peer[i].next;
239e18a033bSKonstantin Ananyev    }
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyev    us->peer.data = peers;
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev    /* implicitly defined upstream has no backup servers */
244e18a033bSKonstantin Ananyev
245e18a033bSKonstantin Ananyev    return NGX_OK;
246e18a033bSKonstantin Ananyev}
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev
249e18a033bSKonstantin Ananyevngx_int_t
250e18a033bSKonstantin Ananyevngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s,
251e18a033bSKonstantin Ananyev    ngx_stream_upstream_srv_conf_t *us)
252e18a033bSKonstantin Ananyev{
253e18a033bSKonstantin Ananyev    ngx_uint_t                           n;
254e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peer_data_t  *rrp;
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev    rrp = s->upstream->peer.data;
257e18a033bSKonstantin Ananyev
258e18a033bSKonstantin Ananyev    if (rrp == NULL) {
259e18a033bSKonstantin Ananyev        rrp = ngx_palloc(s->connection->pool,
260e18a033bSKonstantin Ananyev                         sizeof(ngx_stream_upstream_rr_peer_data_t));
261e18a033bSKonstantin Ananyev        if (rrp == NULL) {
262e18a033bSKonstantin Ananyev            return NGX_ERROR;
263e18a033bSKonstantin Ananyev        }
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev        s->upstream->peer.data = rrp;
266e18a033bSKonstantin Ananyev    }
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev    rrp->peers = us->peer.data;
269e18a033bSKonstantin Ananyev    rrp->current = NULL;
270e18a033bSKonstantin Ananyev    rrp->config = 0;
271e18a033bSKonstantin Ananyev
272e18a033bSKonstantin Ananyev    n = rrp->peers->number;
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev    if (rrp->peers->next && rrp->peers->next->number > n) {
275e18a033bSKonstantin Ananyev        n = rrp->peers->next->number;
276e18a033bSKonstantin Ananyev    }
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev    if (n <= 8 * sizeof(uintptr_t)) {
279e18a033bSKonstantin Ananyev        rrp->tried = &rrp->data;
280e18a033bSKonstantin Ananyev        rrp->data = 0;
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyev    } else {
283e18a033bSKonstantin Ananyev        n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyev        rrp->tried = ngx_pcalloc(s->connection->pool, n * sizeof(uintptr_t));
286e18a033bSKonstantin Ananyev        if (rrp->tried == NULL) {
287e18a033bSKonstantin Ananyev            return NGX_ERROR;
288e18a033bSKonstantin Ananyev        }
289e18a033bSKonstantin Ananyev    }
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev    s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer;
292e18a033bSKonstantin Ananyev    s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer;
293e18a033bSKonstantin Ananyev    s->upstream->peer.notify = ngx_stream_upstream_notify_round_robin_peer;
294e18a033bSKonstantin Ananyev    s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers);
295e18a033bSKonstantin Ananyev#if (NGX_STREAM_SSL)
296e18a033bSKonstantin Ananyev    s->upstream->peer.set_session =
297e18a033bSKonstantin Ananyev                             ngx_stream_upstream_set_round_robin_peer_session;
298e18a033bSKonstantin Ananyev    s->upstream->peer.save_session =
299e18a033bSKonstantin Ananyev                             ngx_stream_upstream_save_round_robin_peer_session;
300e18a033bSKonstantin Ananyev#endif
301e18a033bSKonstantin Ananyev
302e18a033bSKonstantin Ananyev    return NGX_OK;
303e18a033bSKonstantin Ananyev}
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyev
306e18a033bSKonstantin Ananyevngx_int_t
307e18a033bSKonstantin Ananyevngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s,
308e18a033bSKonstantin Ananyev    ngx_stream_upstream_resolved_t *ur)
309e18a033bSKonstantin Ananyev{
310e18a033bSKonstantin Ananyev    u_char                              *p;
311e18a033bSKonstantin Ananyev    size_t                               len;
312e18a033bSKonstantin Ananyev    socklen_t                            socklen;
313e18a033bSKonstantin Ananyev    ngx_uint_t                           i, n;
314e18a033bSKonstantin Ananyev    struct sockaddr                     *sockaddr;
315e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peer_t       *peer, **peerp;
316e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peers_t      *peers;
317e18a033bSKonstantin Ananyev    ngx_stream_upstream_rr_peer_data_t  *rrp;
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev    rrp = s->upstream->peer.data;
320e18a033bSKonstantin Ananyev
321e18a033bSKonstantin Ananyev    if (rrp == NULL) {
322e18a033bSKonstantin Ananyev        rrp = ngx_palloc(s->connection->pool,
323e18a033bSKonstantin Ananyev                         sizeof(ngx_stream_upstream_rr_peer_data_t));
324e18a033bSKonstantin Ananyev        if (rrp == NULL) {
325e18a033bSKonstantin Ananyev            return NGX_ERROR;
326e18a033bSKonstantin Ananyev        }
327e18a033bSKonstantin Ananyev
328e18a033bSKonstantin Ananyev        s->upstream->peer.data = rrp;
329e18a033bSKonstantin Ananyev    }
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev    peers = ngx_pcalloc(s->connection->pool,
332e18a033bSKonstantin Ananyev                        sizeof(ngx_stream_upstream_rr_peers_t));
333e18a033bSKonstantin Ananyev    if (peers == NULL) {
334e18a033bSKonstantin Ananyev        return NGX_ERROR;
335e18a033bSKonstantin Ananyev    }
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev    peer = ngx_pcalloc(s->connection->pool,
338e18a033bSKonstantin Ananyev                       sizeof(ngx_stream_upstream_rr_peer_t) * ur->naddrs);
339e18a033bSKonstantin Ananyev    if (peer == NULL) {
340e18a033bSKonstantin Ananyev        return NGX_ERROR;
341e18a033bSKonstantin Ananyev    }
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev    peers->single = (ur->naddrs == 1);
344e18a033bSKonstantin Ananyev    peers->number = ur->naddrs;
345e18a033bSKonstantin Ananyev    peers->name = &ur->host;
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev    if (ur->sockaddr) {
348e18a033bSKonstantin Ananyev        peer[0].sockaddr = ur->sockaddr;
349e18a033bSKonstantin Ananyev        peer[0].socklen = ur->socklen;
350e18a033bSKonstantin Ananyev        peer[0].name = ur->name;
351e18a033bSKonstantin Ananyev        peer[0].weight = 1;
352e18a033bSKonstantin Ananyev        peer[0].effective_weight = 1;
353e18a033bSKonstantin Ananyev        peer[0].current_weight = 0;
354e18a033bSKonstantin Ananyev        peer[0].max_conns = 0;
355e18a033bSKonstantin Ananyev        peer[0].max_fails = 1;
356e18a033bSKonstantin Ananyev        peer[0].fail_timeout = 10;
357e18a033bSKonstantin Ananyev        peers->peer = peer;
358e18a033bSKonstantin Ananyev
359e18a033bSKonstantin Ananyev    } else {
360e18a033bSKonstantin Ananyev        peerp = &peers->peer;
361e18a033bSKonstantin Ananyev
362e18a033bSKonstantin Ananyev        for (i = 0; i < ur->naddrs; i++) {
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev            socklen = ur->addrs[i].socklen;
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev            sockaddr = ngx_palloc(s->connection->pool, socklen);
367e18a033bSKonstantin Ananyev            if (sockaddr == NULL) {
368e18a033bSKonstantin Ananyev                return NGX_ERROR;
369e18a033bSKonstantin Ananyev            }
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev            ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen);
372e18a033bSKonstantin Ananyev            ngx_inet_set_port(sockaddr, ur->port);
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev            p = ngx_pnalloc(s->connection->pool, NGX_SOCKADDR_STRLEN);
375e18a033bSKonstantin Ananyev            if (p == NULL) {
376e18a033bSKonstantin Ananyev                return NGX_ERROR;
377e18a033bSKonstantin Ananyev            }
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyev            len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
380e18a033bSKonstantin Ananyev
381e18a033bSKonstantin Ananyev            peer[i].sockaddr = sockaddr;
382e18a033bSKonstantin Ananyev            peer[i].socklen = socklen;
383e18a033bSKonstantin Ananyev            peer[i].name.len = len;
384e18a033bSKonstantin Ananyev            peer[i].name.data = p;
385e18a033bSKonstantin Ananyev            peer[i].weight = 1;
386e18a033bSKonstantin Ananyev            peer[i].effective_weight = 1;
387e18a033bSKonstantin Ananyev            peer[i].current_weight = 0;
388e18a033bSKonstantin Ananyev            peer[i].max_conns = 0;
389e18a033bSKonstantin Ananyev            peer[i].max_fails = 1;
390e18a033bSKonstantin Ananyev            peer[i].fail_timeout = 10;
391e18a033bSKonstantin Ananyev            *peerp = &peer[i];
392e18a033bSKonstantin Ananyev            peerp = &peer[i].next;
393e18a033bSKonstantin Ananyev        }
394e18a033bSKonstantin Ananyev    }
395e18a033bSKonstantin Ananyev
396e18a033bSKonstantin Ananyev    rrp->peers = peers;
397e18a033bSKonstantin Ananyev    rrp->current = NULL;
398e18a033bSKonstantin Ananyev    rrp->config = 0;
399e18a033bSKonstantin Ananyev
400e18a033bSKonstantin Ananyev    if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {
401e18a033bSKonstantin Ananyev        rrp->tried = &rrp->data;
402e18a033bSKonstantin Ananyev        rrp->data = 0;
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyev    } else {
405e18a033bSKonstantin Ananyev        n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
406e18a033bSKonstantin Ananyev                / (8 * sizeof(uintptr_t));
407e18a033bSKonstantin Ananyev
408e18a033bSKonstantin Ananyev        rrp->tried = ngx_pcalloc(s->connection->pool, n * sizeof(uintptr_t));
409e18a033bSKonstantin Ananyev        if (rrp->tried == NULL) {
410e18a033bSKonstantin Ananyev            return NGX_ERROR;
411e18a033bSKonstantin Ananyev        }
412e18a033bSKonstantin Ananyev    }
413e18a033bSKonstantin Ananyev
414