diff src/http/ngx_http_upstream_round_robin.c @ 6103:79ddb0bdb273

Upstream: the "zone" directive. Upstreams with the "zone" directive are kept in shared memory, with a consistent view of all worker processes.
author Ruslan Ermilov <ru@nginx.com>
date Tue, 14 Apr 2015 19:01:25 +0300
parents 3264b7828f72
children 4a640716f4e2
line wrap: on
line diff
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -657,12 +657,55 @@ ngx_http_upstream_set_round_robin_peer_s
 {
     ngx_http_upstream_rr_peer_data_t  *rrp = data;
 
-    ngx_int_t                     rc;
-    ngx_ssl_session_t            *ssl_session;
-    ngx_http_upstream_rr_peer_t  *peer;
+    ngx_int_t                      rc;
+    ngx_ssl_session_t             *ssl_session;
+    ngx_http_upstream_rr_peer_t   *peer;
+#if (NGX_HTTP_UPSTREAM_ZONE)
+    int                            len;
+#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
+    const
+#endif
+    u_char                        *p;
+    ngx_http_upstream_rr_peers_t  *peers;
+    u_char                         buf[NGX_SSL_MAX_SESSION_SIZE];
+#endif
 
     peer = rrp->current;
 
+#if (NGX_HTTP_UPSTREAM_ZONE)
+    peers = rrp->peers;
+
+    if (peers->shpool) {
+        ngx_http_upstream_rr_peers_rlock(peers);
+        ngx_http_upstream_rr_peer_lock(peers, peer);
+
+        if (peer->ssl_session == NULL) {
+            ngx_http_upstream_rr_peer_unlock(peers, peer);
+            ngx_http_upstream_rr_peers_unlock(peers);
+            return NGX_OK;
+        }
+
+        len = peer->ssl_session_len;
+
+        ngx_memcpy(buf, peer->ssl_session, len);
+
+        ngx_http_upstream_rr_peer_unlock(peers, peer);
+        ngx_http_upstream_rr_peers_unlock(peers);
+
+        p = buf;
+        ssl_session = d2i_SSL_SESSION(NULL, &p, len);
+
+        rc = ngx_ssl_set_session(pc->connection, ssl_session);
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+                       "set session: %p", ssl_session);
+
+        ngx_ssl_free_session(ssl_session);
+
+        return rc;
+    }
+#endif
+
     ssl_session = peer->ssl_session;
 
     rc = ngx_ssl_set_session(pc->connection, ssl_session);
@@ -680,8 +723,75 @@ ngx_http_upstream_save_round_robin_peer_
 {
     ngx_http_upstream_rr_peer_data_t  *rrp = data;
 
-    ngx_ssl_session_t            *old_ssl_session, *ssl_session;
-    ngx_http_upstream_rr_peer_t  *peer;
+    ngx_ssl_session_t             *old_ssl_session, *ssl_session;
+    ngx_http_upstream_rr_peer_t   *peer;
+#if (NGX_HTTP_UPSTREAM_ZONE)
+    int                            len;
+    u_char                        *p;
+    ngx_http_upstream_rr_peers_t  *peers;
+    u_char                         buf[NGX_SSL_MAX_SESSION_SIZE];
+#endif
+
+#if (NGX_HTTP_UPSTREAM_ZONE)
+    peers = rrp->peers;
+
+    if (peers->shpool) {
+
+        ssl_session = SSL_get0_session(pc->connection->ssl->connection);
+
+        if (ssl_session == NULL) {
+            return;
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+                       "save session: %p", ssl_session);
+
+        len = i2d_SSL_SESSION(ssl_session, NULL);
+
+        /* do not cache too big session */
+
+        if (len > NGX_SSL_MAX_SESSION_SIZE) {
+            return;
+        }
+
+        p = buf;
+        (void) i2d_SSL_SESSION(ssl_session, &p);
+
+        peer = rrp->current;
+
+        ngx_http_upstream_rr_peers_rlock(peers);
+        ngx_http_upstream_rr_peer_lock(peers, peer);
+
+        if (len > peer->ssl_session_len) {
+            ngx_shmtx_lock(&peers->shpool->mutex);
+
+            if (peer->ssl_session) {
+                ngx_slab_free_locked(peers->shpool, peer->ssl_session);
+            }
+
+            peer->ssl_session = ngx_slab_alloc_locked(peers->shpool, len);
+
+            ngx_shmtx_unlock(&peers->shpool->mutex);
+
+            if (peer->ssl_session == NULL) {
+                peer->ssl_session_len = 0;
+
+                ngx_http_upstream_rr_peer_unlock(peers, peer);
+                ngx_http_upstream_rr_peers_unlock(peers);
+                return;
+            }
+
+            peer->ssl_session_len = len;
+        }
+
+        ngx_memcpy(peer->ssl_session, buf, len);
+
+        ngx_http_upstream_rr_peer_unlock(peers, peer);
+        ngx_http_upstream_rr_peers_unlock(peers);
+
+        return;
+    }
+#endif
 
     ssl_session = ngx_ssl_get_session(pc->connection);