diff src/http/ngx_http_upstream.c @ 126:df17fbafec8f NGINX_0_3_10

nginx 0.3.10 *) Change: the "valid_referers" directive and the "$invalid_referer" variable were moved to the new ngx_http_referer_module from the ngx_http_rewrite_module. *) Change: the "$apache_bytes_sent" variable name was changed to "$body_bytes_sent". *) Feature: the "$sent_http_..." variables. *) Feature: the "if" directive supports the "=" and "!=" operations. *) Feature: the "proxy_pass" directive supports the HTTPS protocol. *) Feature: the "proxy_set_body" directive. *) Feature: the "post_action" directive. *) Feature: the ngx_http_empty_gif_module. *) Feature: the "worker_cpu_affinity" directive for Linux. *) Bugfix: the "rewrite" directive did not unescape URI part in redirect, now it is unescaped except the %00-%25 and %7F-%FF characters. *) Bugfix: nginx could not be built by the icc 9.0 compiler. *) Bugfix: if the SSI was enabled for zero size static file, then the chunked response was encoded incorrectly.
author Igor Sysoev <http://sysoev.ru>
date Tue, 15 Nov 2005 00:00:00 +0300
parents d25a1d6034f1
children 82d695e3d662
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -84,6 +84,12 @@ static ngx_int_t ngx_http_upstream_respo
 static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
 
+#if (NGX_HTTP_SSL)
+static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
+static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c,
+    ngx_peer_t *peer);
+#endif
+
 
 ngx_http_upstream_header_t  ngx_http_upstream_headers_in[] = {
 
@@ -147,6 +153,12 @@ ngx_http_upstream_header_t  ngx_http_ups
                  ngx_http_upstream_copy_header_line,
                  offsetof(ngx_http_headers_out_t, expires), 1 },
 
+    { ngx_string("Accept-Ranges"),
+                 ngx_http_upstream_process_header_line,
+                 offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
+                 ngx_http_upstream_copy_header_line,
+                 offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
+
     { ngx_string("Connection"),
                  ngx_http_upstream_ignore_header_line, 0,
                  ngx_http_upstream_ignore_header_line, 0, 0 },
@@ -199,7 +211,7 @@ ngx_http_module_t  ngx_http_upstream_mod
     NULL,                                  /* create location configuration */
     NULL                                   /* merge location configuration */
 };
-    
+
 
 ngx_module_t  ngx_http_upstream_module = {
     NGX_MODULE_V1,
@@ -266,7 +278,7 @@ ngx_http_upstream_init(ngx_http_request_
 
     r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
     r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
-    
+
     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         if (!c->write->active) {
@@ -359,7 +371,7 @@ ngx_http_upstream_check_broken_connectio
 {
     int                  n;
     char                 buf[1];
-    ngx_err_t            err; 
+    ngx_err_t            err;
     ngx_connection_t     *c;
     ngx_http_upstream_t  *u;
 
@@ -482,6 +494,7 @@ static void
 ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
 {
     ngx_int_t            rc;
+    ngx_peer_t          *peer;
     ngx_connection_t    *c;
 
     r->connection->log->action = "connecting to upstream";
@@ -499,7 +512,8 @@ ngx_http_upstream_connect(ngx_http_reque
         return;
     }
 
-    u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name;
+    peer = &u->peer.peers->peer[u->peer.cur_peer];
+    u->state->peer = &peer->name;
 
     if (rc == NGX_BUSY) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
@@ -510,6 +524,8 @@ ngx_http_upstream_connect(ngx_http_reque
         return;
     }
 
+    /* rc == NGX_OK || rc == NGX_AGAIN */
+
     c = u->peer.connection;
 
     c->data = r;
@@ -568,10 +584,75 @@ ngx_http_upstream_connect(ngx_http_reque
 
     /* rc == NGX_OK */
 
+#if (NGX_HTTP_SSL)
+
+    if (u->conf->ssl) {
+        if (c->ssl == NULL) {
+
+            if (ngx_ssl_create_connection(u->conf->ssl, c,
+                                          NGX_SSL_BUFFER|NGX_SSL_CLIENT)
+                == NGX_ERROR)
+            {
+                ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+                return;
+            }
+
+            c->sendfile = 0;
+        }
+
+        if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
+            ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        rc = ngx_ssl_handshake(c);
+
+        if (rc == NGX_AGAIN) {
+            c->ssl->handler = ngx_http_upstream_ssl_handshake;
+            return;
+        }
+
+        ngx_http_upstream_ssl_handshake(c);
+
+        return;
+    }
+
+#endif
+
     ngx_http_upstream_send_request(r, u);
 }
 
 
+#if (NGX_HTTP_SSL)
+
+static void
+ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
+{
+    ngx_http_request_t   *r;
+    ngx_http_upstream_t  *u;
+
+    r = c->data;
+    u = r->upstream;
+
+    if (c->ssl->handshaked) {
+
+        c->write->handler = ngx_http_upstream_send_request_handler;
+        c->read->handler = ngx_http_upstream_process_header;
+
+        ngx_http_upstream_send_request(r, u);
+
+        return;
+    }
+
+    ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+
+}
+
+#endif
+
+
 static ngx_int_t
 ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
 {
@@ -591,7 +672,7 @@ ngx_http_upstream_reinit(ngx_http_reques
     }
 
     /* reinit the request chain */
-    
+
     for (cl = u->request_bufs; cl; cl = cl->next) {
         cl->buf->pos = cl->buf->start;
         cl->buf->file_pos = 0;
@@ -617,9 +698,9 @@ ngx_http_upstream_reinit(ngx_http_reques
     u->output.buf = NULL;
     u->output.in = NULL;
     u->output.busy = NULL;
-    
+
     /* reinit u->header_in buffer */
-    
+
 #if 0
     if (u->cache) {
         u->header_in.pos = u->header_in.start + u->cache->ctx.header_size;
@@ -654,7 +735,7 @@ ngx_http_upstream_send_request(ngx_http_
 {
     int                rc;
     ngx_connection_t  *c;
-    
+
     c = u->peer.connection;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
@@ -710,17 +791,17 @@ ngx_http_upstream_send_request(ngx_http_
                           ngx_tcp_push_n " failed");
             ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
-            return; 
+            return;
         }
 
         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
     }
-    
+
     ngx_add_timer(c->read, u->conf->read_timeout);
 
 #if 1
     if (c->read->ready) {
-    
+
         /* post aio operation */
 
         /*
@@ -799,7 +880,7 @@ ngx_http_upstream_process_header(ngx_eve
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
         return;
     }
-    
+
     if (u->header_in.start == NULL) {
         u->header_in.start = ngx_palloc(r->pool, u->conf->header_buffer_size);
         if (u->header_in.start == NULL) {
@@ -831,8 +912,8 @@ ngx_http_upstream_process_header(ngx_eve
 #endif
     }
 
-    n = ngx_recv(u->peer.connection, u->header_in.last,
-                 u->header_in.end - u->header_in.last);
+    n = u->peer.connection->recv(u->peer.connection, u->header_in.last,
+                                 u->header_in.end - u->header_in.last);
 
     if (n == NGX_AGAIN) {
 #if 0
@@ -958,7 +1039,7 @@ ngx_http_upstream_process_header(ngx_eve
                             return;
                         }
 
-                        *r->headers_out.www_authenticate = 
+                        *r->headers_out.www_authenticate =
                                                *u->headers_in.www_authenticate;
                     }
 
@@ -985,7 +1066,7 @@ ngx_http_upstream_process_header(ngx_eve
                 if (part->next == NULL) {
                     break;
                 }
-    
+
                 part = part->next;
                 h = part->elts;
                 i = 0;
@@ -1054,7 +1135,7 @@ ngx_http_upstream_send_response(ngx_http
             if (part->next == NULL) {
                 break;
             }
-    
+
             part = part->next;
             h = part->elts;
             i = 0;
@@ -1140,13 +1221,13 @@ ngx_http_upstream_send_response(ngx_http
     p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter;
     p->output_ctx = r;
     p->tag = u->output.tag;
-    p->bufs = u->conf->bufs;     
+    p->bufs = u->conf->bufs;
     p->busy_size = u->conf->busy_buffers_size;
     p->upstream = u->peer.connection;
     p->downstream = r->connection;
     p->pool = r->pool;
     p->log = r->connection->log;
-    
+
     p->cachable = u->cachable;
 
     p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
@@ -1159,7 +1240,7 @@ ngx_http_upstream_send_response(ngx_http
     p->temp_file->file.log = r->connection->log;
     p->temp_file->path = u->conf->temp_path;
     p->temp_file->pool = r->pool;
-    
+
     if (u->cachable) {
         p->temp_file->persistent = 1;
     } else {
@@ -1257,13 +1338,13 @@ ngx_http_upstream_process_body(ngx_event
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http upstream process downstream");
         c->log->action = "sending to client";
-    
+
     } else {
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http upstream process upstream");
         c->log->action = "reading upstream";
     }
-    
+
     p = &u->pipe;
 
     if (ev->timedout) {
@@ -1292,12 +1373,13 @@ ngx_http_upstream_process_body(ngx_event
 
             } else {
                 p->downstream_error = 1;
+                c->timedout = 1;
                 ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
                               "client timed out");
             }
 
         } else {
-            p->upstream_error = 1; 
+            p->upstream_error = 1;
             ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
                           "upstream timed out");
         }
@@ -1319,7 +1401,7 @@ ngx_http_upstream_process_body(ngx_event
             return;
         }
     }
-    
+
     if (u->peer.connection) {
 
 #if (NGX_HTTP_FILE_CACHE)
@@ -1399,7 +1481,7 @@ ngx_http_upstream_next(ngx_http_request_
         ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,
                       "upstream timed out");
     }
-    
+
     if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
         status = 0;
 
@@ -1458,7 +1540,12 @@ ngx_http_upstream_next(ngx_http_request_
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "close http upstream connection: %d",
                        u->peer.connection->fd);
-
+#if (NGX_HTTP_SSL)
+        if (u->peer.connection->ssl) {
+            ngx_http_upstream_ssl_shutdown(u->peer.connection,
+                                       &u->peer.peers->peer[u->peer.cur_peer]);
+        }
+#endif
         ngx_close_connection(u->peer.connection);
     }
 
@@ -1508,7 +1595,15 @@ ngx_http_upstream_finalize_request(ngx_h
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "close http upstream connection: %d",
                        u->peer.connection->fd);
-
+#if (NGX_HTTP_SSL)
+
+        /* TODO: do not shutdown persistent connection */
+
+        if (u->peer.connection->ssl) {
+            ngx_http_upstream_ssl_shutdown(u->peer.connection,
+                                       &u->peer.peers->peer[u->peer.cur_peer]);
+        }
+#endif
         ngx_close_connection(u->peer.connection);
     }
 
@@ -1549,12 +1644,41 @@ ngx_http_upstream_finalize_request(ngx_h
 }
 
 
+#if (NGX_HTTP_SSL)
+
+static void
+ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, ngx_peer_t *peer)
+{
+    /* lock peer mutex */
+
+    if (peer->ssl_session) {
+        ngx_ssl_free_session(peer->ssl_session);
+    }
+
+    peer->ssl_session = ngx_ssl_get_session(c);
+
+    /* unlock peer mutex */
+
+    /*
+     * We send the "close notify" shutdown alert to the upstream only
+     * and do not wait its "close notify" shutdown alert.
+     * It is acceptable according to the TLS standard.
+     */
+
+    c->ssl->no_wait_shutdown = 1;
+
+    (void) ngx_ssl_shutdown(c);
+}
+
+#endif
+
+
 static ngx_int_t
 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
-{   
+{
     ngx_table_elt_t  **ph;
-    
+
     ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
 
     if (*ph == NULL) {
@@ -1603,7 +1727,7 @@ ngx_http_upstream_ignore_header_line(ngx
 static ngx_int_t
 ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
-{   
+{
     ngx_int_t  n;
 
     r->upstream->headers_in.x_accel_limit_rate = h;
@@ -2119,7 +2243,7 @@ ngx_http_core_init_main_conf(ngx_conf_t 
 {
     ngx_http_upstream_main_conf_t  *umcf = conf;
 
-    umcf->headers_in_hash.max_size = 100; 
+    umcf->headers_in_hash.max_size = 100;
     umcf->headers_in_hash.bucket_limit = 1;
     umcf->headers_in_hash.bucket_size = sizeof(ngx_http_upstream_header_t);
     umcf->headers_in_hash.name = "upstream_headers_in";