1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11
12
13 #define ngx_http_upstream_tries(p) ((p)->number \
14 + ((p)->next ? (p)->next->number : 0))
15
16
17 static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
18 ngx_http_upstream_rr_peer_data_t *rrp);
19
20 #if (NGX_HTTP_SSL)
21
22 static ngx_int_t ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc,
23 void *data);
24 static void ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc,
25 void *data);
26
27 #endif
28
29
30 ngx_int_t
ngx_http_upstream_init_round_robin(ngx_conf_t * cf,ngx_http_upstream_srv_conf_t * us)31 ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
32 ngx_http_upstream_srv_conf_t *us)
33 {
34 ngx_url_t u;
35 ngx_uint_t i, j, n, w;
36 ngx_http_upstream_server_t *server;
37 ngx_http_upstream_rr_peer_t *peer, **peerp;
38 ngx_http_upstream_rr_peers_t *peers, *backup;
39
40 us->peer.init = ngx_http_upstream_init_round_robin_peer;
41
42 if (us->servers) {
43 server = us->servers->elts;
44
45 n = 0;
46 w = 0;
47
48 for (i = 0; i < us->servers->nelts; i++) {
49 if (server[i].backup) {
50 continue;
51 }
52
53 n += server[i].naddrs;
54 w += server[i].naddrs * server[i].weight;
55 }
56
57 if (n == 0) {
58 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
59 "no servers in upstream \"%V\" in %s:%ui",
60 &us->host, us->file_name, us->line);
61 return NGX_ERROR;
62 }
63
64 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t));
65 if (peers == NULL) {
66 return NGX_ERROR;
67 }
68
69 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n);
70 if (peer == NULL) {
71 return NGX_ERROR;
72 }
73
74 peers->single = (n == 1);
75 peers->number = n;
76 peers->weighted = (w != n);
77 peers->total_weight = w;
78 peers->name = &us->host;
79
80 n = 0;
81 peerp = &peers->peer;
82
83 for (i = 0; i < us->servers->nelts; i++) {
84 if (server[i].backup) {
85 continue;
86 }
87
88 for (j = 0; j < server[i].naddrs; j++) {
89 peer[n].sockaddr = server[i].addrs[j].sockaddr;
90 peer[n].socklen = server[i].addrs[j].socklen;
91 peer[n].name = server[i].addrs[j].name;
92 peer[n].weight = server[i].weight;
93 peer[n].effective_weight = server[i].weight;
94 peer[n].current_weight = 0;
95 peer[n].max_conns = server[i].max_conns;
96 peer[n].max_fails = server[i].max_fails;
97 peer[n].fail_timeout = server[i].fail_timeout;
98 peer[n].down = server[i].down;
99 peer[n].server = server[i].name;
100
101 *peerp = &peer[n];
102 peerp = &peer[n].next;
103 n++;
104 }
105 }
106
107 us->peer.data = peers;
108
109 /* backup servers */
110
111 n = 0;
112 w = 0;
113
114 for (i = 0; i < us->servers->nelts; i++) {
115 if (!server[i].backup) {
116 continue;
117 }
118
119 n += server[i].naddrs;
120 w += server[i].naddrs * server[i].weight;
121 }
122
123 if (n == 0) {
124 return NGX_OK;
125 }
126
127 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t));
128 if (backup == NULL) {
129 return NGX_ERROR;
130 }
131
132 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n);
133 if (peer == NULL) {
134 return NGX_ERROR;
135 }
136
137 peers->single = 0;
138 backup->single = 0;
139 backup->number = n;
140 backup->weighted = (w != n);
141 backup->total_weight = w;
142 backup->name = &us->host;
143
144 n = 0;
145 peerp = &backup->peer;
146
147 for (i = 0; i < us->servers->nelts; i++) {
148 if (!server[i].backup) {
149 continue;
150 }
151
152 for (j = 0; j < server[i].naddrs; j++) {
153 peer[n].sockaddr = server[i].addrs[j].sockaddr;
154 peer[n].socklen = server[i].addrs[j].socklen;
155 peer[n].name = server[i].addrs[j].name;
156 peer[n].weight = server[i].weight;
157 peer[n].effective_weight = server[i].weight;
158 peer[n].current_weight = 0;
159 peer[n].max_conns = server[i].max_conns;
160 peer[n].max_fails = server[i].max_fails;
161 peer[n].fail_timeout = server[i].fail_timeout;
162 peer[n].down = server[i].down;
163 peer[n].server = server[i].name;
164
165 *peerp = &peer[n];
166 peerp = &peer[n].next;
167 n++;
168 }
169 }
170
171 peers->next = backup;
172
173 return NGX_OK;
174 }
175
176
177 /* an upstream implicitly defined by proxy_pass, etc. */
178
179 if (us->port == 0) {
180 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
181 "no port in upstream \"%V\" in %s:%ui",
182 &us->host, us->file_name, us->line);
183 return NGX_ERROR;
184 }
185
186 ngx_memzero(&u, sizeof(ngx_url_t));
187
188 u.host = us->host;
189 u.port = us->port;
190
191 if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
192 if (u.err) {
193 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
194 "%s in upstream \"%V\" in %s:%ui",
195 u.err, &us->host, us->file_name, us->line);
196 }
197
198 return NGX_ERROR;
199 }
200
201 n = u.naddrs;
202
203 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t));
204 if (peers == NULL) {
205 return NGX_ERROR;
206 }
207
208 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n);
209 if (peer == NULL) {
210 return NGX_ERROR;
211 }
212
213 peers->single = (n == 1);
214 peers->number = n;
215 peers->weighted = 0;
216 peers->total_weight = n;
217 peers->name = &us->host;
218
219 peerp = &peers->peer;
220
221 for (i = 0; i < u.naddrs; i++) {
222 peer[i].sockaddr = u.addrs[i].sockaddr;
223 peer[i].socklen = u.addrs[i].socklen;
224 peer[i].name = u.addrs[i].name;
225 peer[i].weight = 1;
226 peer[i].effective_weight = 1;
227 peer[i].current_weight = 0;
228 peer[i].max_conns = 0;
229 peer[i].max_fails = 1;
230 peer[i].fail_timeout = 10;
231 *peerp = &peer[i];
232 peerp = &peer[i].next;
233 }
234
235 us->peer.data = peers;
236
237 /* implicitly defined upstream has no backup servers */
238
239 return NGX_OK;
240 }
241
242
243 ngx_int_t
ngx_http_upstream_init_round_robin_peer(ngx_http_request_t * r,ngx_http_upstream_srv_conf_t * us)244 ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
245 ngx_http_upstream_srv_conf_t *us)
246 {
247 ngx_uint_t n;
248 ngx_http_upstream_rr_peer_data_t *rrp;
249
250 rrp = r->upstream->peer.data;
251
252 if (rrp == NULL) {
253 rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
254 if (rrp == NULL) {
255 return NGX_ERROR;
256 }
257
258 r->upstream->peer.data = rrp;
259 }
260
261 rrp->peers = us->peer.data;
262 rrp->current = NULL;
263 rrp->config = 0;
264
265 n = rrp->peers->number;
266
267 if (rrp->peers->next && rrp->peers->next->number > n) {
268 n = rrp->peers->next->number;
269 }
270
271 if (n <= 8 * sizeof(uintptr_t)) {
272 rrp->tried = &rrp->data;
273 rrp->data = 0;
274
275 } else {
276 n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
277
278 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
279 if (rrp->tried == NULL) {
280 return NGX_ERROR;
281 }
282 }
283
284 r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
285 r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
286 r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers);
287 #if (NGX_HTTP_SSL)
288 r->upstream->peer.set_session =
289 ngx_http_upstream_set_round_robin_peer_session;
290 r->upstream->peer.save_session =
291 ngx_http_upstream_save_round_robin_peer_session;
292 #endif
293
294 return NGX_OK;
295 }
296
297
298 ngx_int_t
ngx_http_upstream_create_round_robin_peer(ngx_http_request_t * r,ngx_http_upstream_resolved_t * ur)299 ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
300 ngx_http_upstream_resolved_t *ur)
301 {
302 u_char *p;
303 size_t len;
304 socklen_t socklen;
305 ngx_uint_t i, n;
306 struct sockaddr *sockaddr;
307 ngx_http_upstream_rr_peer_t *peer, **peerp;
308 ngx_http_upstream_rr_peers_t *peers;
309 ngx_http_upstream_rr_peer_data_t *rrp;
310
311 rrp = r->upstream->peer.data;
312
313 if (rrp == NULL) {
314 rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
315 if (rrp == NULL) {
316 return NGX_ERROR;
317 }
318
319 r->upstream->peer.data = rrp;
320 }
321
322 peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t));
323 if (peers == NULL) {
324 return NGX_ERROR;
325 }
326
327 peer = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peer_t)
328 * ur->naddrs);
329 if (peer == NULL) {
330 return NGX_ERROR;
331 }
332
333 peers->single = (ur->naddrs == 1);
334 peers->number = ur->naddrs;
335 peers->name = &ur->host;
336
337 if (ur->sockaddr) {
338 peer[0].sockaddr = ur->sockaddr;
339 peer[0].socklen = ur->socklen;
340 peer[0].name = ur->name.data ? ur->name : ur->host;
341 peer[0].weight = 1;
342 peer[0].effective_weight = 1;
343 peer[0].current_weight = 0;
344 peer[0].max_conns = 0;
345 peer[0].max_fails = 1;
346 peer[0].fail_timeout = 10;
347 peers->peer = peer;
348
349 } else {
350 peerp = &peers->peer;
351
352 for (i = 0; i < ur->naddrs; i++) {
353
354 socklen = ur->addrs[i].socklen;
355
356 sockaddr = ngx_palloc(r->pool, socklen);
357 if (sockaddr == NULL) {
358 return NGX_ERROR;
359 }
360
361 ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen);
362 ngx_inet_set_port(sockaddr, ur->port);
363
364 p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN);
365 if (p == NULL) {
366 return NGX_ERROR;
367 }
368
369 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
370
371 peer[i].sockaddr = sockaddr;
372 peer[i].socklen = socklen;
373 peer[i].name.len = len;
374 peer[i].name.data = p;
375 peer[i].weight = 1;
376 peer[i].effective_weight = 1;
377 peer[i].current_weight = 0;
378 peer[i].max_conns = 0;
379 peer[i].max_fails = 1;
380 peer[i].fail_timeout = 10;
381 *peerp = &peer[i];
382 peerp = &peer[i].next;
383 }
384 }
385
386 rrp->peers = peers;
387 rrp->current = NULL;
388 rrp->config = 0;
389
390 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {
391 rrp->tried = &rrp->data;
392 rrp->data = 0;
393
394 } else {
395 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
396 / (8 * sizeof(uintptr_t));
397
398 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
399 if (rrp->tried == NULL) {
400 return NGX_ERROR;
401 }
402 }
403
404 r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
405 r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
406 r->upstream->peer.tries = ngx_http_upstream_tries(rrp->peers);
407 #if (NGX_HTTP_SSL)
408 r->upstream->peer.set_session = ngx_http_upstream_empty_set_session;
409 r->upstream->peer.save_session = ngx_http_upstream_empty_save_session;
410 #endif
411
412 return NGX_OK;
413 }
414
415
416 ngx_int_t
ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t * pc,void * data)417 ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
418 {
419 ngx_http_upstream_rr_peer_data_t *rrp = data;
420
421 ngx_int_t rc;
422 ngx_uint_t i, n;
423 ngx_http_upstream_rr_peer_t *peer;
424 ngx_http_upstream_rr_peers_t *peers;
425
426 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
427 "get rr peer, try: %ui", pc->tries);
428
429 pc->cached = 0;
430 pc->connection = NULL;
431
432 peers = rrp->peers;
433 ngx_http_upstream_rr_peers_wlock(peers);
434
435 if (peers->single) {
436 peer = peers->peer;
437
438 if (peer->down) {
439 goto failed;
440 }
441
442 if (peer->max_conns && peer->conns >= peer->max_conns) {
443 goto failed;
444 }
445
446 rrp->current = peer;
447
448 } else {
449
450 /* there are several peers */
451
452 peer = ngx_http_upstream_get_peer(rrp);
453
454 if (peer == NULL) {
455 goto failed;
456 }
457
458 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
459 "get rr peer, current: %p %i",
460 peer, peer->current_weight);
461 }
462
463 pc->sockaddr = peer->sockaddr;
464 pc->socklen = peer->socklen;
465 pc->name = &peer->name;
466
467 peer->conns++;
468
469 ngx_http_upstream_rr_peers_unlock(peers);
470
471 return NGX_OK;
472
473 failed:
474
475 if (peers->next) {
476
477 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");
478
479 rrp->peers = peers->next;
480
481 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
482 / (8 * sizeof(uintptr_t));
483
484 for (i = 0; i < n; i++) {
485 rrp->tried[i] = 0;
486 }
487
488 ngx_http_upstream_rr_peers_unlock(peers);
489
490 rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);
491
492 if (rc != NGX_BUSY) {
493 return rc;
494 }
495
496 ngx_http_upstream_rr_peers_wlock(peers);
497 }
498
499 ngx_http_upstream_rr_peers_unlock(peers);
500
501 pc->name = peers->name;
502
503 return NGX_BUSY;
504 }
505
506
507 static ngx_http_upstream_rr_peer_t *
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t * rrp)508 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
509 {
510 time_t now;
511 uintptr_t m;
512 ngx_int_t total;
513 ngx_uint_t i, n, p;
514 ngx_http_upstream_rr_peer_t *peer, *best;
515
516 now = ngx_time();
517
518 best = NULL;
519 total = 0;
520
521 #if (NGX_SUPPRESS_WARN)
522 p = 0;
523 #endif
524
525 for (peer = rrp->peers->peer, i = 0;
526 peer;
527 peer = peer->next, i++)
528 {
529 n = i / (8 * sizeof(uintptr_t));
530 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
531
532 if (rrp->tried[n] & m) {
533 continue;
534 }
535
536 if (peer->down) {
537 continue;
538 }
539
540 if (peer->max_fails
541 && peer->fails >= peer->max_fails
542 && now - peer->checked <= peer->fail_timeout)
543 {
544 continue;
545 }
546
547 if (peer->max_conns && peer->conns >= peer->max_conns) {
548 continue;
549 }
550
551 peer->current_weight += peer->effective_weight;
552 total += peer->effective_weight;
553
554 if (peer->effective_weight < peer->weight) {
555 peer->effective_weight++;
556 }
557
558 if (best == NULL || peer->current_weight > best->current_weight) {
559 best = peer;
560 p = i;
561 }
562 }
563
564 if (best == NULL) {
565 return NULL;
566 }
567
568 rrp->current = best;
569
570 n = p / (8 * sizeof(uintptr_t));
571 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
572
573 rrp->tried[n] |= m;
574
575 best->current_weight -= total;
576
577 if (now - best->checked > best->fail_timeout) {
578 best->checked = now;
579 }
580
581 return best;
582 }
583
584
585 void
ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t * pc,void * data,ngx_uint_t state)586 ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
587 ngx_uint_t state)
588 {
589 ngx_http_upstream_rr_peer_data_t *rrp = data;
590
591 time_t now;
592 ngx_http_upstream_rr_peer_t *peer;
593
594 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
595 "free rr peer %ui %ui", pc->tries, state);
596
597 /* TODO: NGX_PEER_KEEPALIVE */
598
599 peer = rrp->current;
600
601 ngx_http_upstream_rr_peers_rlock(rrp->peers);
602 ngx_http_upstream_rr_peer_lock(rrp->peers, peer);
603
604 if (rrp->peers->single) {
605
606 peer->conns--;
607
608 ngx_http_upstream_rr_peer_unlock(rrp->peers, peer);
609 ngx_http_upstream_rr_peers_unlock(rrp->peers);
610
611 pc->tries = 0;
612 return;
613 }
614
615 if (state & NGX_PEER_FAILED) {
616 now = ngx_time();
617
618 peer->fails++;
619 peer->accessed = now;
620 peer->checked = now;
621
622 if (peer->max_fails) {
623 peer->effective_weight -= peer->weight / peer->max_fails;
624
625 if (peer->fails >= peer->max_fails) {
626 ngx_log_error(NGX_LOG_WARN, pc->log, 0,
627 "upstream server temporarily disabled");
628 }
629 }
630
631 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
632 "free rr peer failed: %p %i",
633 peer, peer->effective_weight);
634
635 if (peer->effective_weight < 0) {
636 peer->effective_weight = 0;
637 }
638
639 } else {
640
641 /* mark peer live if check passed */
642
643 if (peer->accessed < peer->checked) {
644 peer->fails = 0;
645 }
646 }
647
648 peer->conns--;
649
650 ngx_http_upstream_rr_peer_unlock(rrp->peers, peer);
651 ngx_http_upstream_rr_peers_unlock(rrp->peers);
652
653 if (pc->tries) {
654 pc->tries--;
655 }
656 }
657
658
659 #if (NGX_HTTP_SSL)
660
661 ngx_int_t
ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t * pc,void * data)662 ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
663 void *data)
664 {
665 ngx_http_upstream_rr_peer_data_t *rrp = data;
666
667 ngx_int_t rc;
668 ngx_ssl_session_t *ssl_session;
669 ngx_http_upstream_rr_peer_t *peer;
670 #if (NGX_HTTP_UPSTREAM_ZONE)
671 int len;
672 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
673 const
674 #endif
675 u_char *p;
676 ngx_http_upstream_rr_peers_t *peers;
677 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
678 #endif
679
680 peer = rrp->current;
681
682 #if (NGX_HTTP_UPSTREAM_ZONE)
683 peers = rrp->peers;
684
685 if (peers->shpool) {
686 ngx_http_upstream_rr_peers_rlock(peers);
687 ngx_http_upstream_rr_peer_lock(peers, peer);
688
689 if (peer->ssl_session == NULL) {
690 ngx_http_upstream_rr_peer_unlock(peers, peer);
691 ngx_http_upstream_rr_peers_unlock(peers);
692 return NGX_OK;
693 }
694
695 len = peer->ssl_session_len;
696
697 ngx_memcpy(buf, peer->ssl_session, len);
698
699 ngx_http_upstream_rr_peer_unlock(peers, peer);
700 ngx_http_upstream_rr_peers_unlock(peers);
701
702 p = buf;
703 ssl_session = d2i_SSL_SESSION(NULL, &p, len);
704
705 rc = ngx_ssl_set_session(pc->connection, ssl_session);
706
707 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
708 "set session: %p", ssl_session);
709
710 ngx_ssl_free_session(ssl_session);
711
712 return rc;
713 }
714 #endif
715
716 ssl_session = peer->ssl_session;
717
718 rc = ngx_ssl_set_session(pc->connection, ssl_session);
719
720 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
721 "set session: %p", ssl_session);
722
723 return rc;
724 }
725
726
727 void
ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t * pc,void * data)728 ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
729 void *data)
730 {
731 ngx_http_upstream_rr_peer_data_t *rrp = data;
732
733 ngx_ssl_session_t *old_ssl_session, *ssl_session;
734 ngx_http_upstream_rr_peer_t *peer;
735 #if (NGX_HTTP_UPSTREAM_ZONE)
736 int len;
737 u_char *p;
738 ngx_http_upstream_rr_peers_t *peers;
739 u_char buf[NGX_SSL_MAX_SESSION_SIZE];
740 #endif
741
742 #if (NGX_HTTP_UPSTREAM_ZONE)
743 peers = rrp->peers;
744
745 if (peers->shpool) {
746
747 ssl_session = ngx_ssl_get0_session(pc->connection);
748
749 if (ssl_session == NULL) {
750 return;
751 }
752
753 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
754 "save session: %p", ssl_session);
755
756 len = i2d_SSL_SESSION(ssl_session, NULL);
757
758 /* do not cache too big session */
759
760 if (len > NGX_SSL_MAX_SESSION_SIZE) {
761 return;
762 }
763
764 p = buf;
765 (void) i2d_SSL_SESSION(ssl_session, &p);
766
767 peer = rrp->current;
768
769 ngx_http_upstream_rr_peers_rlock(peers);
770 ngx_http_upstream_rr_peer_lock(peers, peer);
771
772 if (len > peer->ssl_session_len) {
773 ngx_shmtx_lock(&peers->shpool->mutex);
774
775 if (peer->ssl_session) {
776 ngx_slab_free_locked(peers->shpool, peer->ssl_session);
777 }
778
779 peer->ssl_session = ngx_slab_alloc_locked(peers->shpool, len);
780
781 ngx_shmtx_unlock(&peers->shpool->mutex);
782
783 if (peer->ssl_session == NULL) {
784 peer->ssl_session_len = 0;
785
786 ngx_http_upstream_rr_peer_unlock(peers, peer);
787 ngx_http_upstream_rr_peers_unlock(peers);
788 return;
789 }
790
791 peer->ssl_session_len = len;
792 }
793
794 ngx_memcpy(peer->ssl_session, buf, len);
795
796 ngx_http_upstream_rr_peer_unlock(peers, peer);
797 ngx_http_upstream_rr_peers_unlock(peers);
798
799 return;
800 }
801 #endif
802
803 ssl_session = ngx_ssl_get_session(pc->connection);
804
805 if (ssl_session == NULL) {
806 return;
807 }
808
809 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
810 "save session: %p", ssl_session);
811
812 peer = rrp->current;
813
814 old_ssl_session = peer->ssl_session;
815 peer->ssl_session = ssl_session;
816
817 if (old_ssl_session) {
818
819 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
820 "old session: %p", old_ssl_session);
821
822 /* TODO: may block */
823
824 ngx_ssl_free_session(old_ssl_session);
825 }
826 }
827
828
829 static ngx_int_t
ngx_http_upstream_empty_set_session(ngx_peer_connection_t * pc,void * data)830 ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data)
831 {
832 return NGX_OK;
833 }
834
835
836 static void
ngx_http_upstream_empty_save_session(ngx_peer_connection_t * pc,void * data)837 ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data)
838 {
839 return;
840 }
841
842 #endif
843