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