Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static void ngx_http_wait_request_handler(ngx_event_t *ev);
0014 static ngx_http_request_t *ngx_http_alloc_request(ngx_connection_t *c);
0015 static void ngx_http_process_request_line(ngx_event_t *rev);
0016 static void ngx_http_process_request_headers(ngx_event_t *rev);
0017 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
0018 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
0019     ngx_uint_t request_line);
0020 
0021 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
0022     ngx_table_elt_t *h, ngx_uint_t offset);
0023 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
0024     ngx_table_elt_t *h, ngx_uint_t offset);
0025 static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
0026     ngx_table_elt_t *h, ngx_uint_t offset);
0027 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
0028     ngx_table_elt_t *h, ngx_uint_t offset);
0029 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
0030     ngx_table_elt_t *h, ngx_uint_t offset);
0031 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
0032     ngx_table_elt_t *h, ngx_uint_t offset);
0033 
0034 static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
0035     ngx_uint_t alloc);
0036 static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
0037     ngx_str_t *host);
0038 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
0039     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
0040     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
0041 
0042 static void ngx_http_request_handler(ngx_event_t *ev);
0043 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
0044 static void ngx_http_terminate_handler(ngx_http_request_t *r);
0045 static void ngx_http_finalize_connection(ngx_http_request_t *r);
0046 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
0047 static void ngx_http_writer(ngx_http_request_t *r);
0048 static void ngx_http_request_finalizer(ngx_http_request_t *r);
0049 
0050 static void ngx_http_set_keepalive(ngx_http_request_t *r);
0051 static void ngx_http_keepalive_handler(ngx_event_t *ev);
0052 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
0053 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
0054 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
0055 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
0056 static void ngx_http_log_request(ngx_http_request_t *r);
0057 
0058 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
0059 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
0060     ngx_http_request_t *sr, u_char *buf, size_t len);
0061 
0062 #if (NGX_HTTP_SSL)
0063 static void ngx_http_ssl_handshake(ngx_event_t *rev);
0064 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
0065 #endif
0066 
0067 
0068 static char *ngx_http_client_errors[] = {
0069 
0070     /* NGX_HTTP_PARSE_INVALID_METHOD */
0071     "client sent invalid method",
0072 
0073     /* NGX_HTTP_PARSE_INVALID_REQUEST */
0074     "client sent invalid request",
0075 
0076     /* NGX_HTTP_PARSE_INVALID_VERSION */
0077     "client sent invalid version",
0078 
0079     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
0080     "client sent invalid method in HTTP/0.9 request"
0081 };
0082 
0083 
0084 ngx_http_header_t  ngx_http_headers_in[] = {
0085     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
0086                  ngx_http_process_host },
0087 
0088     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
0089                  ngx_http_process_connection },
0090 
0091     { ngx_string("If-Modified-Since"),
0092                  offsetof(ngx_http_headers_in_t, if_modified_since),
0093                  ngx_http_process_unique_header_line },
0094 
0095     { ngx_string("If-Unmodified-Since"),
0096                  offsetof(ngx_http_headers_in_t, if_unmodified_since),
0097                  ngx_http_process_unique_header_line },
0098 
0099     { ngx_string("If-Match"),
0100                  offsetof(ngx_http_headers_in_t, if_match),
0101                  ngx_http_process_unique_header_line },
0102 
0103     { ngx_string("If-None-Match"),
0104                  offsetof(ngx_http_headers_in_t, if_none_match),
0105                  ngx_http_process_unique_header_line },
0106 
0107     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
0108                  ngx_http_process_user_agent },
0109 
0110     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
0111                  ngx_http_process_header_line },
0112 
0113     { ngx_string("Content-Length"),
0114                  offsetof(ngx_http_headers_in_t, content_length),
0115                  ngx_http_process_unique_header_line },
0116 
0117     { ngx_string("Content-Range"),
0118                  offsetof(ngx_http_headers_in_t, content_range),
0119                  ngx_http_process_unique_header_line },
0120 
0121     { ngx_string("Content-Type"),
0122                  offsetof(ngx_http_headers_in_t, content_type),
0123                  ngx_http_process_header_line },
0124 
0125     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
0126                  ngx_http_process_header_line },
0127 
0128     { ngx_string("If-Range"),
0129                  offsetof(ngx_http_headers_in_t, if_range),
0130                  ngx_http_process_unique_header_line },
0131 
0132     { ngx_string("Transfer-Encoding"),
0133                  offsetof(ngx_http_headers_in_t, transfer_encoding),
0134                  ngx_http_process_header_line },
0135 
0136     { ngx_string("TE"),
0137                  offsetof(ngx_http_headers_in_t, te),
0138                  ngx_http_process_header_line },
0139 
0140     { ngx_string("Expect"),
0141                  offsetof(ngx_http_headers_in_t, expect),
0142                  ngx_http_process_unique_header_line },
0143 
0144     { ngx_string("Upgrade"),
0145                  offsetof(ngx_http_headers_in_t, upgrade),
0146                  ngx_http_process_header_line },
0147 
0148 #if (NGX_HTTP_GZIP || NGX_HTTP_HEADERS)
0149     { ngx_string("Accept-Encoding"),
0150                  offsetof(ngx_http_headers_in_t, accept_encoding),
0151                  ngx_http_process_header_line },
0152 
0153     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
0154                  ngx_http_process_header_line },
0155 #endif
0156 
0157     { ngx_string("Authorization"),
0158                  offsetof(ngx_http_headers_in_t, authorization),
0159                  ngx_http_process_unique_header_line },
0160 
0161     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
0162                  ngx_http_process_header_line },
0163 
0164 #if (NGX_HTTP_X_FORWARDED_FOR)
0165     { ngx_string("X-Forwarded-For"),
0166                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
0167                  ngx_http_process_multi_header_lines },
0168 #endif
0169 
0170 #if (NGX_HTTP_REALIP)
0171     { ngx_string("X-Real-IP"),
0172                  offsetof(ngx_http_headers_in_t, x_real_ip),
0173                  ngx_http_process_header_line },
0174 #endif
0175 
0176 #if (NGX_HTTP_HEADERS)
0177     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
0178                  ngx_http_process_header_line },
0179 
0180     { ngx_string("Accept-Language"),
0181                  offsetof(ngx_http_headers_in_t, accept_language),
0182                  ngx_http_process_header_line },
0183 #endif
0184 
0185 #if (NGX_HTTP_DAV)
0186     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
0187                  ngx_http_process_header_line },
0188 
0189     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
0190                  ngx_http_process_header_line },
0191 
0192     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
0193                  ngx_http_process_header_line },
0194 
0195     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
0196                  ngx_http_process_header_line },
0197 #endif
0198 
0199     { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
0200                  ngx_http_process_multi_header_lines },
0201 
0202     { ngx_null_string, 0, NULL }
0203 };
0204 
0205 
0206 void
0207 ngx_http_init_connection(ngx_connection_t *c)
0208 {
0209     ngx_uint_t              i;
0210     ngx_event_t            *rev;
0211     struct sockaddr_in     *sin;
0212     ngx_http_port_t        *port;
0213     ngx_http_in_addr_t     *addr;
0214     ngx_http_log_ctx_t     *ctx;
0215     ngx_http_connection_t  *hc;
0216 #if (NGX_HAVE_INET6)
0217     struct sockaddr_in6    *sin6;
0218     ngx_http_in6_addr_t    *addr6;
0219 #endif
0220 
0221     hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
0222     if (hc == NULL) {
0223         ngx_http_close_connection(c);
0224         return;
0225     }
0226 
0227     c->data = hc;
0228 
0229     /* find the server configuration for the address:port */
0230 
0231     port = c->listening->servers;
0232 
0233     if (port->naddrs > 1) {
0234 
0235         /*
0236          * there are several addresses on this port and one of them
0237          * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
0238          * is required to determine a server address
0239          */
0240 
0241         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
0242             ngx_http_close_connection(c);
0243             return;
0244         }
0245 
0246         switch (c->local_sockaddr->sa_family) {
0247 
0248 #if (NGX_HAVE_INET6)
0249         case AF_INET6:
0250             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
0251 
0252             addr6 = port->addrs;
0253 
0254             /* the last address is "*" */
0255 
0256             for (i = 0; i < port->naddrs - 1; i++) {
0257                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
0258                     break;
0259                 }
0260             }
0261 
0262             hc->addr_conf = &addr6[i].conf;
0263 
0264             break;
0265 #endif
0266 
0267         default: /* AF_INET */
0268             sin = (struct sockaddr_in *) c->local_sockaddr;
0269 
0270             addr = port->addrs;
0271 
0272             /* the last address is "*" */
0273 
0274             for (i = 0; i < port->naddrs - 1; i++) {
0275                 if (addr[i].addr == sin->sin_addr.s_addr) {
0276                     break;
0277                 }
0278             }
0279 
0280             hc->addr_conf = &addr[i].conf;
0281 
0282             break;
0283         }
0284 
0285     } else {
0286 
0287         switch (c->local_sockaddr->sa_family) {
0288 
0289 #if (NGX_HAVE_INET6)
0290         case AF_INET6:
0291             addr6 = port->addrs;
0292             hc->addr_conf = &addr6[0].conf;
0293             break;
0294 #endif
0295 
0296         default: /* AF_INET */
0297             addr = port->addrs;
0298             hc->addr_conf = &addr[0].conf;
0299             break;
0300         }
0301     }
0302 
0303     /* the default server configuration for the address:port */
0304     hc->conf_ctx = hc->addr_conf->default_server->ctx;
0305 
0306     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
0307     if (ctx == NULL) {
0308         ngx_http_close_connection(c);
0309         return;
0310     }
0311 
0312     ctx->connection = c;
0313     ctx->request = NULL;
0314     ctx->current_request = NULL;
0315 
0316     c->log->connection = c->number;
0317     c->log->handler = ngx_http_log_error;
0318     c->log->data = ctx;
0319     c->log->action = "waiting for request";
0320 
0321     c->log_error = NGX_ERROR_INFO;
0322 
0323     rev = c->read;
0324     rev->handler = ngx_http_wait_request_handler;
0325     c->write->handler = ngx_http_empty_handler;
0326 
0327 #if (NGX_HTTP_V2)
0328     if (hc->addr_conf->http2) {
0329         rev->handler = ngx_http_v2_init;
0330     }
0331 #endif
0332 
0333 #if (NGX_HTTP_SSL)
0334     {
0335     ngx_http_ssl_srv_conf_t  *sscf;
0336 
0337     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
0338 
0339     if (sscf->enable || hc->addr_conf->ssl) {
0340         hc->ssl = 1;
0341         c->log->action = "SSL handshaking";
0342         rev->handler = ngx_http_ssl_handshake;
0343     }
0344     }
0345 #endif
0346 
0347     if (hc->addr_conf->proxy_protocol) {
0348         hc->proxy_protocol = 1;
0349         c->log->action = "reading PROXY protocol";
0350     }
0351 
0352     if (rev->ready) {
0353         /* the deferred accept(), iocp */
0354 
0355         if (ngx_use_accept_mutex) {
0356             ngx_post_event(rev, &ngx_posted_events);
0357             return;
0358         }
0359 
0360         rev->handler(rev);
0361         return;
0362     }
0363 
0364     ngx_add_timer(rev, c->listening->post_accept_timeout);
0365     ngx_reusable_connection(c, 1);
0366 
0367     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0368         ngx_http_close_connection(c);
0369         return;
0370     }
0371 }
0372 
0373 
0374 static void
0375 ngx_http_wait_request_handler(ngx_event_t *rev)
0376 {
0377     u_char                    *p;
0378     size_t                     size;
0379     ssize_t                    n;
0380     ngx_buf_t                 *b;
0381     ngx_connection_t          *c;
0382     ngx_http_connection_t     *hc;
0383     ngx_http_core_srv_conf_t  *cscf;
0384 
0385     c = rev->data;
0386 
0387     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
0388 
0389     if (rev->timedout) {
0390         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0391         ngx_http_close_connection(c);
0392         return;
0393     }
0394 
0395     if (c->close) {
0396         ngx_http_close_connection(c);
0397         return;
0398     }
0399 
0400     hc = c->data;
0401     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
0402 
0403     size = cscf->client_header_buffer_size;
0404 
0405     b = c->buffer;
0406 
0407     if (b == NULL) {
0408         b = ngx_create_temp_buf(c->pool, size);
0409         if (b == NULL) {
0410             ngx_http_close_connection(c);
0411             return;
0412         }
0413 
0414         c->buffer = b;
0415 
0416     } else if (b->start == NULL) {
0417 
0418         b->start = ngx_palloc(c->pool, size);
0419         if (b->start == NULL) {
0420             ngx_http_close_connection(c);
0421             return;
0422         }
0423 
0424         b->pos = b->start;
0425         b->last = b->start;
0426         b->end = b->last + size;
0427     }
0428 
0429     n = c->recv(c, b->last, size);
0430 
0431     if (n == NGX_AGAIN) {
0432 
0433         if (!rev->timer_set) {
0434             ngx_add_timer(rev, c->listening->post_accept_timeout);
0435             ngx_reusable_connection(c, 1);
0436         }
0437 
0438         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0439             ngx_http_close_connection(c);
0440             return;
0441         }
0442 
0443         /*
0444          * We are trying to not hold c->buffer's memory for an idle connection.
0445          */
0446 
0447         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
0448             b->start = NULL;
0449         }
0450 
0451         return;
0452     }
0453 
0454     if (n == NGX_ERROR) {
0455         ngx_http_close_connection(c);
0456         return;
0457     }
0458 
0459     if (n == 0) {
0460         ngx_log_error(NGX_LOG_INFO, c->log, 0,
0461                       "client closed connection");
0462         ngx_http_close_connection(c);
0463         return;
0464     }
0465 
0466     b->last += n;
0467 
0468     if (hc->proxy_protocol) {
0469         hc->proxy_protocol = 0;
0470 
0471         p = ngx_proxy_protocol_read(c, b->pos, b->last);
0472 
0473         if (p == NULL) {
0474             ngx_http_close_connection(c);
0475             return;
0476         }
0477 
0478         b->pos = p;
0479 
0480         if (b->pos == b->last) {
0481             c->log->action = "waiting for request";
0482             b->pos = b->start;
0483             b->last = b->start;
0484             ngx_post_event(rev, &ngx_posted_events);
0485             return;
0486         }
0487     }
0488 
0489     c->log->action = "reading client request line";
0490 
0491     ngx_reusable_connection(c, 0);
0492 
0493     c->data = ngx_http_create_request(c);
0494     if (c->data == NULL) {
0495         ngx_http_close_connection(c);
0496         return;
0497     }
0498 
0499     rev->handler = ngx_http_process_request_line;
0500     ngx_http_process_request_line(rev);
0501 }
0502 
0503 
0504 ngx_http_request_t *
0505 ngx_http_create_request(ngx_connection_t *c)
0506 {
0507     ngx_http_request_t        *r;
0508     ngx_http_log_ctx_t        *ctx;
0509     ngx_http_core_loc_conf_t  *clcf;
0510 
0511     r = ngx_http_alloc_request(c);
0512     if (r == NULL) {
0513         return NULL;
0514     }
0515 
0516     c->requests++;
0517 
0518     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0519 
0520     ngx_set_connection_log(c, clcf->error_log);
0521 
0522     ctx = c->log->data;
0523     ctx->request = r;
0524     ctx->current_request = r;
0525 
0526 #if (NGX_STAT_STUB)
0527     (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
0528     r->stat_reading = 1;
0529     (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
0530 #endif
0531 
0532     return r;
0533 }
0534 
0535 
0536 static ngx_http_request_t *
0537 ngx_http_alloc_request(ngx_connection_t *c)
0538 {
0539     ngx_pool_t                 *pool;
0540     ngx_time_t                 *tp;
0541     ngx_http_request_t         *r;
0542     ngx_http_connection_t      *hc;
0543     ngx_http_core_srv_conf_t   *cscf;
0544     ngx_http_core_main_conf_t  *cmcf;
0545 
0546     hc = c->data;
0547 
0548     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
0549 
0550     pool = ngx_create_pool(cscf->request_pool_size, c->log);
0551     if (pool == NULL) {
0552         return NULL;
0553     }
0554 
0555     r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
0556     if (r == NULL) {
0557         ngx_destroy_pool(pool);
0558         return NULL;
0559     }
0560 
0561     r->pool = pool;
0562 
0563     r->http_connection = hc;
0564     r->signature = NGX_HTTP_MODULE;
0565     r->connection = c;
0566 
0567     r->main_conf = hc->conf_ctx->main_conf;
0568     r->srv_conf = hc->conf_ctx->srv_conf;
0569     r->loc_conf = hc->conf_ctx->loc_conf;
0570 
0571     r->read_event_handler = ngx_http_block_reading;
0572 
0573     r->header_in = hc->busy ? hc->busy->buf : c->buffer;
0574 
0575     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
0576                       sizeof(ngx_table_elt_t))
0577         != NGX_OK)
0578     {
0579         ngx_destroy_pool(r->pool);
0580         return NULL;
0581     }
0582 
0583     if (ngx_list_init(&r->headers_out.trailers, r->pool, 4,
0584                       sizeof(ngx_table_elt_t))
0585         != NGX_OK)
0586     {
0587         ngx_destroy_pool(r->pool);
0588         return NULL;
0589     }
0590 
0591     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
0592     if (r->ctx == NULL) {
0593         ngx_destroy_pool(r->pool);
0594         return NULL;
0595     }
0596 
0597     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
0598 
0599     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
0600                                         * sizeof(ngx_http_variable_value_t));
0601     if (r->variables == NULL) {
0602         ngx_destroy_pool(r->pool);
0603         return NULL;
0604     }
0605 
0606 #if (NGX_HTTP_SSL)
0607     if (c->ssl) {
0608         r->main_filter_need_in_memory = 1;
0609     }
0610 #endif
0611 
0612     r->main = r;
0613     r->count = 1;
0614 
0615     tp = ngx_timeofday();
0616     r->start_sec = tp->sec;
0617     r->start_msec = tp->msec;
0618 
0619     r->method = NGX_HTTP_UNKNOWN;
0620     r->http_version = NGX_HTTP_VERSION_10;
0621 
0622     r->headers_in.content_length_n = -1;
0623     r->headers_in.keep_alive_n = -1;
0624     r->headers_out.content_length_n = -1;
0625     r->headers_out.last_modified_time = -1;
0626 
0627     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
0628     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
0629 
0630     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
0631 
0632     r->log_handler = ngx_http_log_error_handler;
0633 
0634     return r;
0635 }
0636 
0637 
0638 #if (NGX_HTTP_SSL)
0639 
0640 static void
0641 ngx_http_ssl_handshake(ngx_event_t *rev)
0642 {
0643     u_char                    *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
0644     size_t                     size;
0645     ssize_t                    n;
0646     ngx_err_t                  err;
0647     ngx_int_t                  rc;
0648     ngx_connection_t          *c;
0649     ngx_http_connection_t     *hc;
0650     ngx_http_ssl_srv_conf_t   *sscf;
0651     ngx_http_core_loc_conf_t  *clcf;
0652 
0653     c = rev->data;
0654     hc = c->data;
0655 
0656     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
0657                    "http check ssl handshake");
0658 
0659     if (rev->timedout) {
0660         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0661         ngx_http_close_connection(c);
0662         return;
0663     }
0664 
0665     if (c->close) {
0666         ngx_http_close_connection(c);
0667         return;
0668     }
0669 
0670     size = hc->proxy_protocol ? sizeof(buf) : 1;
0671 
0672     n = recv(c->fd, (char *) buf, size, MSG_PEEK);
0673 
0674     err = ngx_socket_errno;
0675 
0676     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %z", n);
0677 
0678     if (n == -1) {
0679         if (err == NGX_EAGAIN) {
0680             rev->ready = 0;
0681 
0682             if (!rev->timer_set) {
0683                 ngx_add_timer(rev, c->listening->post_accept_timeout);
0684                 ngx_reusable_connection(c, 1);
0685             }
0686 
0687             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0688                 ngx_http_close_connection(c);
0689             }
0690 
0691             return;
0692         }
0693 
0694         ngx_connection_error(c, err, "recv() failed");
0695         ngx_http_close_connection(c);
0696 
0697         return;
0698     }
0699 
0700     if (hc->proxy_protocol) {
0701         hc->proxy_protocol = 0;
0702 
0703         p = ngx_proxy_protocol_read(c, buf, buf + n);
0704 
0705         if (p == NULL) {
0706             ngx_http_close_connection(c);
0707             return;
0708         }
0709 
0710         size = p - buf;
0711 
0712         if (c->recv(c, buf, size) != (ssize_t) size) {
0713             ngx_http_close_connection(c);
0714             return;
0715         }
0716 
0717         c->log->action = "SSL handshaking";
0718 
0719         if (n == (ssize_t) size) {
0720             ngx_post_event(rev, &ngx_posted_events);
0721             return;
0722         }
0723 
0724         n = 1;
0725         buf[0] = *p;
0726     }
0727 
0728     if (n == 1) {
0729         if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
0730             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
0731                            "https ssl handshake: 0x%02Xd", buf[0]);
0732 
0733             clcf = ngx_http_get_module_loc_conf(hc->conf_ctx,
0734                                                 ngx_http_core_module);
0735 
0736             if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
0737                 ngx_http_close_connection(c);
0738                 return;
0739             }
0740 
0741             sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
0742                                                 ngx_http_ssl_module);
0743 
0744             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
0745                 != NGX_OK)
0746             {
0747                 ngx_http_close_connection(c);
0748                 return;
0749             }
0750 
0751             rc = ngx_ssl_handshake(c);
0752 
0753             if (rc == NGX_AGAIN) {
0754 
0755                 if (!rev->timer_set) {
0756                     ngx_add_timer(rev, c->listening->post_accept_timeout);
0757                 }
0758 
0759                 ngx_reusable_connection(c, 0);
0760 
0761                 c->ssl->handler = ngx_http_ssl_handshake_handler;
0762                 return;
0763             }
0764 
0765             ngx_http_ssl_handshake_handler(c);
0766 
0767             return;
0768         }
0769 
0770         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
0771 
0772         c->log->action = "waiting for request";
0773 
0774         rev->handler = ngx_http_wait_request_handler;
0775         ngx_http_wait_request_handler(rev);
0776 
0777         return;
0778     }
0779 
0780     ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
0781     ngx_http_close_connection(c);
0782 }
0783 
0784 
0785 static void
0786 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
0787 {
0788     if (c->ssl->handshaked) {
0789 
0790         /*
0791          * The majority of browsers do not send the "close notify" alert.
0792          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
0793          * and Links.  And what is more, MSIE ignores the server's alert.
0794          *
0795          * Opera and recent Mozilla send the alert.
0796          */
0797 
0798         c->ssl->no_wait_shutdown = 1;
0799 
0800 #if (NGX_HTTP_V2                                                              \
0801      && (defined TLSEXT_TYPE_application_layer_protocol_negotiation           \
0802          || defined TLSEXT_TYPE_next_proto_neg))
0803         {
0804         unsigned int            len;
0805         const unsigned char    *data;
0806         ngx_http_connection_t  *hc;
0807 
0808         hc = c->data;
0809 
0810         if (hc->addr_conf->http2) {
0811 
0812 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
0813             SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
0814 
0815 #ifdef TLSEXT_TYPE_next_proto_neg
0816             if (len == 0) {
0817                 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
0818             }
0819 #endif
0820 
0821 #else /* TLSEXT_TYPE_next_proto_neg */
0822             SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
0823 #endif
0824 
0825             if (len == 2 && data[0] == 'h' && data[1] == '2') {
0826                 ngx_http_v2_init(c->read);
0827                 return;
0828             }
0829         }
0830         }
0831 #endif
0832 
0833         c->log->action = "waiting for request";
0834 
0835         c->read->handler = ngx_http_wait_request_handler;
0836         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
0837 
0838         ngx_reusable_connection(c, 1);
0839 
0840         ngx_http_wait_request_handler(c->read);
0841 
0842         return;
0843     }
0844 
0845     if (c->read->timedout) {
0846         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0847     }
0848 
0849     ngx_http_close_connection(c);
0850 }
0851 
0852 
0853 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0854 
0855 int
0856 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
0857 {
0858     ngx_int_t                  rc;
0859     ngx_str_t                  host;
0860     const char                *servername;
0861     ngx_connection_t          *c;
0862     ngx_http_connection_t     *hc;
0863     ngx_http_ssl_srv_conf_t   *sscf;
0864     ngx_http_core_loc_conf_t  *clcf;
0865     ngx_http_core_srv_conf_t  *cscf;
0866 
0867     c = ngx_ssl_get_connection(ssl_conn);
0868 
0869     if (c->ssl->handshaked) {
0870         *ad = SSL_AD_NO_RENEGOTIATION;
0871         return SSL_TLSEXT_ERR_ALERT_FATAL;
0872     }
0873 
0874     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
0875 
0876     if (servername == NULL) {
0877         return SSL_TLSEXT_ERR_OK;
0878     }
0879 
0880     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0881                    "SSL server name: \"%s\"", servername);
0882 
0883     host.len = ngx_strlen(servername);
0884 
0885     if (host.len == 0) {
0886         return SSL_TLSEXT_ERR_OK;
0887     }
0888 
0889     host.data = (u_char *) servername;
0890 
0891     rc = ngx_http_validate_host(&host, c->pool, 1);
0892 
0893     if (rc == NGX_ERROR) {
0894         *ad = SSL_AD_INTERNAL_ERROR;
0895         return SSL_TLSEXT_ERR_ALERT_FATAL;
0896     }
0897 
0898     if (rc == NGX_DECLINED) {
0899         return SSL_TLSEXT_ERR_OK;
0900     }
0901 
0902     hc = c->data;
0903 
0904     rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
0905                                       NULL, &cscf);
0906 
0907     if (rc == NGX_ERROR) {
0908         *ad = SSL_AD_INTERNAL_ERROR;
0909         return SSL_TLSEXT_ERR_ALERT_FATAL;
0910     }
0911 
0912     if (rc == NGX_DECLINED) {
0913         return SSL_TLSEXT_ERR_OK;
0914     }
0915 
0916     hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
0917     if (hc->ssl_servername == NULL) {
0918         *ad = SSL_AD_INTERNAL_ERROR;
0919         return SSL_TLSEXT_ERR_ALERT_FATAL;
0920     }
0921 
0922     *hc->ssl_servername = host;
0923 
0924     hc->conf_ctx = cscf->ctx;
0925 
0926     clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
0927 
0928     ngx_set_connection_log(c, clcf->error_log);
0929 
0930     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
0931 
0932     c->ssl->buffer_size = sscf->buffer_size;
0933 
0934     if (sscf->ssl.ctx) {
0935         SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
0936 
0937         /*
0938          * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
0939          * adjust other things we care about
0940          */
0941 
0942         SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
0943                        SSL_CTX_get_verify_callback(sscf->ssl.ctx));
0944 
0945         SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
0946 
0947 #if OPENSSL_VERSION_NUMBER >= 0x009080dfL
0948         /* only in 0.9.8m+ */
0949         SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
0950                                     ~SSL_CTX_get_options(sscf->ssl.ctx));
0951 #endif
0952 
0953         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
0954 
0955 #ifdef SSL_OP_NO_RENEGOTIATION
0956         SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION);
0957 #endif
0958     }
0959 
0960     return SSL_TLSEXT_ERR_OK;
0961 }
0962 
0963 #endif
0964 
0965 
0966 #ifdef SSL_R_CERT_CB_ERROR
0967 
0968 int
0969 ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
0970 {
0971     ngx_str_t                  cert, key;
0972     ngx_uint_t                 i, nelts;
0973     ngx_connection_t          *c;
0974     ngx_http_request_t        *r;
0975     ngx_http_ssl_srv_conf_t   *sscf;
0976     ngx_http_complex_value_t  *certs, *keys;
0977 
0978     c = ngx_ssl_get_connection(ssl_conn);
0979 
0980     if (c->ssl->handshaked) {
0981         return 0;
0982     }
0983 
0984     r = ngx_http_alloc_request(c);
0985     if (r == NULL) {
0986         return 0;
0987     }
0988 
0989     r->logged = 1;
0990 
0991     sscf = arg;
0992 
0993     nelts = sscf->certificate_values->nelts;
0994     certs = sscf->certificate_values->elts;
0995     keys = sscf->certificate_key_values->elts;
0996 
0997     for (i = 0; i < nelts; i++) {
0998 
0999         if (ngx_http_complex_value(r, &certs[i], &cert) != NGX_OK) {
1000             goto failed;
1001         }
1002 
1003         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1004                        "ssl cert: \"%s\"", cert.data);
1005 
1006         if (ngx_http_complex_value(r, &keys[i], &key) != NGX_OK) {
1007             goto failed;
1008         }
1009 
1010         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1011                        "ssl key: \"%s\"", key.data);
1012 
1013         if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key,
1014                                            sscf->passwords)
1015             != NGX_OK)
1016         {
1017             goto failed;
1018         }
1019     }
1020 
1021     ngx_http_free_request(r, 0);
1022     c->destroyed = 0;
1023     return 1;
1024 
1025 failed:
1026 
1027     ngx_http_free_request(r, 0);
1028     c->destroyed = 0;
1029     return 0;
1030 }
1031 
1032 #endif
1033 
1034 #endif
1035 
1036 
1037 static void
1038 ngx_http_process_request_line(ngx_event_t *rev)
1039 {
1040     ssize_t              n;
1041     ngx_int_t            rc, rv;
1042     ngx_str_t            host;
1043     ngx_connection_t    *c;
1044     ngx_http_request_t  *r;
1045 
1046     c = rev->data;
1047     r = c->data;
1048 
1049     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1050                    "http process request line");
1051 
1052     if (rev->timedout) {
1053         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1054         c->timedout = 1;
1055         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1056         return;
1057     }
1058 
1059     rc = NGX_AGAIN;
1060 
1061     for ( ;; ) {
1062 
1063         if (rc == NGX_AGAIN) {
1064             n = ngx_http_read_request_header(r);
1065 
1066             if (n == NGX_AGAIN || n == NGX_ERROR) {
1067                 break;
1068             }
1069         }
1070 
1071         rc = ngx_http_parse_request_line(r, r->header_in);
1072 
1073         if (rc == NGX_OK) {
1074 
1075             /* the request line has been parsed successfully */
1076 
1077             r->request_line.len = r->request_end - r->request_start;
1078             r->request_line.data = r->request_start;
1079             r->request_length = r->header_in->pos - r->request_start;
1080 
1081             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1082                            "http request line: \"%V\"", &r->request_line);
1083 
1084             r->method_name.len = r->method_end - r->request_start + 1;
1085             r->method_name.data = r->request_line.data;
1086 
1087             if (r->http_protocol.data) {
1088                 r->http_protocol.len = r->request_end - r->http_protocol.data;
1089             }
1090 
1091             if (ngx_http_process_request_uri(r) != NGX_OK) {
1092                 break;
1093             }
1094 
1095             if (r->schema_end) {
1096                 r->schema.len = r->schema_end - r->schema_start;
1097                 r->schema.data = r->schema_start;
1098             }
1099 
1100             if (r->host_end) {
1101 
1102                 host.len = r->host_end - r->host_start;
1103                 host.data = r->host_start;
1104 
1105                 rc = ngx_http_validate_host(&host, r->pool, 0);
1106 
1107                 if (rc == NGX_DECLINED) {
1108                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1109                                   "client sent invalid host in request line");
1110                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1111                     break;
1112                 }
1113 
1114                 if (rc == NGX_ERROR) {
1115                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1116                     break;
1117                 }
1118 
1119                 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1120                     break;
1121                 }
1122 
1123                 r->headers_in.server = host;
1124             }
1125 
1126             if (r->http_version < NGX_HTTP_VERSION_10) {
1127 
1128                 if (r->headers_in.server.len == 0
1129                     && ngx_http_set_virtual_server(r, &r->headers_in.server)
1130                        == NGX_ERROR)
1131                 {
1132                     break;
1133                 }
1134 
1135                 ngx_http_process_request(r);
1136                 break;
1137             }
1138 
1139 
1140             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
1141                               sizeof(ngx_table_elt_t))
1142                 != NGX_OK)
1143             {
1144                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1145                 break;
1146             }
1147 
1148             c->log->action = "reading client request headers";
1149 
1150             rev->handler = ngx_http_process_request_headers;
1151             ngx_http_process_request_headers(rev);
1152 
1153             break;
1154         }
1155 
1156         if (rc != NGX_AGAIN) {
1157 
1158             /* there was error while a request line parsing */
1159 
1160             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1161                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
1162 
1163             if (rc == NGX_HTTP_PARSE_INVALID_VERSION) {
1164                 ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED);
1165 
1166             } else {
1167                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1168             }
1169 
1170             break;
1171         }
1172 
1173         /* NGX_AGAIN: a request line parsing is still incomplete */
1174 
1175         if (r->header_in->pos == r->header_in->end) {
1176 
1177             rv = ngx_http_alloc_large_header_buffer(r, 1);
1178 
1179             if (rv == NGX_ERROR) {
1180                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1181                 break;
1182             }
1183 
1184             if (rv == NGX_DECLINED) {
1185                 r->request_line.len = r->header_in->end - r->request_start;
1186                 r->request_line.data = r->request_start;
1187 
1188                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1189                               "client sent too long URI");
1190                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
1191                 break;
1192             }
1193         }
1194     }
1195 
1196     ngx_http_run_posted_requests(c);
1197 }
1198 
1199 
1200 ngx_int_t
1201 ngx_http_process_request_uri(ngx_http_request_t *r)
1202 {
1203     ngx_http_core_srv_conf_t  *cscf;
1204 
1205     if (r->args_start) {
1206         r->uri.len = r->args_start - 1 - r->uri_start;
1207     } else {
1208         r->uri.len = r->uri_end - r->uri_start;
1209     }
1210 
1211     if (r->complex_uri || r->quoted_uri) {
1212 
1213         r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
1214         if (r->uri.data == NULL) {
1215             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1216             return NGX_ERROR;
1217         }
1218 
1219         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1220 
1221         if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1222             r->uri.len = 0;
1223 
1224             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1225                           "client sent invalid request");
1226             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1227             return NGX_ERROR;
1228         }
1229 
1230     } else {
1231         r->uri.data = r->uri_start;
1232     }
1233 
1234     r->unparsed_uri.len = r->uri_end - r->uri_start;
1235     r->unparsed_uri.data = r->uri_start;
1236 
1237     r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
1238 
1239     if (r->uri_ext) {
1240         if (r->args_start) {
1241             r->exten.len = r->args_start - 1 - r->uri_ext;
1242         } else {
1243             r->exten.len = r->uri_end - r->uri_ext;
1244         }
1245 
1246         r->exten.data = r->uri_ext;
1247     }
1248 
1249     if (r->args_start && r->uri_end > r->args_start) {
1250         r->args.len = r->uri_end - r->args_start;
1251         r->args.data = r->args_start;
1252     }
1253 
1254 #if (NGX_WIN32)
1255     {
1256     u_char  *p, *last;
1257 
1258     p = r->uri.data;
1259     last = r->uri.data + r->uri.len;
1260 
1261     while (p < last) {
1262 
1263         if (*p++ == ':') {
1264 
1265             /*
1266              * this check covers "::$data", "::$index_allocation" and
1267              * ":$i30:$index_allocation"
1268              */
1269 
1270             if (p < last && *p == '$') {
1271                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1272                               "client sent unsafe win32 URI");
1273                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1274                 return NGX_ERROR;
1275             }
1276         }
1277     }
1278 
1279     p = r->uri.data + r->uri.len - 1;
1280 
1281     while (p > r->uri.data) {
1282 
1283         if (*p == ' ') {
1284             p--;
1285             continue;
1286         }
1287 
1288         if (*p == '.') {
1289             p--;
1290             continue;
1291         }
1292 
1293         break;
1294     }
1295 
1296     if (p != r->uri.data + r->uri.len - 1) {
1297         r->uri.len = p + 1 - r->uri.data;
1298         ngx_http_set_exten(r);
1299     }
1300 
1301     }
1302 #endif
1303 
1304     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1305                    "http uri: \"%V\"", &r->uri);
1306 
1307     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1308                    "http args: \"%V\"", &r->args);
1309 
1310     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1311                    "http exten: \"%V\"", &r->exten);
1312 
1313     return NGX_OK;
1314 }
1315 
1316 
1317 static void
1318 ngx_http_process_request_headers(ngx_event_t *rev)
1319 {
1320     u_char                     *p;
1321     size_t                      len;
1322     ssize_t                     n;
1323     ngx_int_t                   rc, rv;
1324     ngx_table_elt_t            *h;
1325     ngx_connection_t           *c;
1326     ngx_http_header_t          *hh;
1327     ngx_http_request_t         *r;
1328     ngx_http_core_srv_conf_t   *cscf;
1329     ngx_http_core_main_conf_t  *cmcf;
1330 
1331     c = rev->data;
1332     r = c->data;
1333 
1334     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1335                    "http process request header line");
1336 
1337     if (rev->timedout) {
1338         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1339         c->timedout = 1;
1340         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1341         return;
1342     }
1343 
1344     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1345 
1346     rc = NGX_AGAIN;
1347 
1348     for ( ;; ) {
1349 
1350         if (rc == NGX_AGAIN) {
1351 
1352             if (r->header_in->pos == r->header_in->end) {
1353 
1354                 rv = ngx_http_alloc_large_header_buffer(r, 0);
1355 
1356                 if (rv == NGX_ERROR) {
1357                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1358                     break;
1359                 }
1360 
1361                 if (rv == NGX_DECLINED) {
1362                     p = r->header_name_start;
1363 
1364                     r->lingering_close = 1;
1365 
1366                     if (p == NULL) {
1367                         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1368                                       "client sent too large request");
1369                         ngx_http_finalize_request(r,
1370                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1371                         break;
1372                     }
1373 
1374                     len = r->header_in->end - p;
1375 
1376                     if (len > NGX_MAX_ERROR_STR - 300) {
1377                         len = NGX_MAX_ERROR_STR - 300;
1378                     }
1379 
1380                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1381                                 "client sent too long header line: \"%*s...\"",
1382                                 len, r->header_name_start);
1383 
1384                     ngx_http_finalize_request(r,
1385                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1386                     break;
1387                 }
1388             }
1389 
1390             n = ngx_http_read_request_header(r);
1391 
1392             if (n == NGX_AGAIN || n == NGX_ERROR) {
1393                 break;
1394             }
1395         }
1396 
1397         /* the host header could change the server configuration context */
1398         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1399 
1400         rc = ngx_http_parse_header_line(r, r->header_in,
1401                                         cscf->underscores_in_headers);
1402 
1403         if (rc == NGX_OK) {
1404 
1405             r->request_length += r->header_in->pos - r->header_name_start;
1406 
1407             if (r->invalid_header && cscf->ignore_invalid_headers) {
1408 
1409                 /* there was error while a header line parsing */
1410 
1411                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1412                               "client sent invalid header line: \"%*s\"",
1413                               r->header_end - r->header_name_start,
1414                               r->header_name_start);
1415                 continue;
1416             }
1417 
1418             /* a header line has been parsed successfully */
1419 
1420             h = ngx_list_push(&r->headers_in.headers);
1421             if (h == NULL) {
1422                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1423                 break;
1424             }
1425 
1426             h->hash = r->header_hash;
1427 
1428             h->key.len = r->header_name_end - r->header_name_start;
1429             h->key.data = r->header_name_start;
1430             h->key.data[h->key.len] = '\0';
1431 
1432             h->value.len = r->header_end - r->header_start;
1433             h->value.data = r->header_start;
1434             h->value.data[h->value.len] = '\0';
1435 
1436             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1437             if (h->lowcase_key == NULL) {
1438                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1439                 break;
1440             }
1441 
1442             if (h->key.len == r->lowcase_index) {
1443                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1444 
1445             } else {
1446                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1447             }
1448 
1449             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1450                                h->lowcase_key, h->key.len);
1451 
1452             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1453                 break;
1454             }
1455 
1456             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1457                            "http header: \"%V: %V\"",
1458                            &h->key, &h->value);
1459 
1460             continue;
1461         }
1462 
1463         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1464 
1465             /* a whole header has been parsed successfully */
1466 
1467             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1468                            "http header done");
1469 
1470             r->request_length += r->header_in->pos - r->header_name_start;
1471 
1472             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1473 
1474             rc = ngx_http_process_request_header(r);
1475 
1476             if (rc != NGX_OK) {
1477                 break;
1478             }
1479 
1480             ngx_http_process_request(r);
1481 
1482             break;
1483         }
1484 
1485         if (rc == NGX_AGAIN) {
1486 
1487             /* a header line parsing is still not complete */
1488 
1489             continue;
1490         }
1491 
1492         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
1493 
1494         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1495                       "client sent invalid header line");
1496 
1497         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1498         break;
1499     }
1500 
1501     ngx_http_run_posted_requests(c);
1502 }
1503 
1504 
1505 static ssize_t
1506 ngx_http_read_request_header(ngx_http_request_t *r)
1507 {
1508     ssize_t                    n;
1509     ngx_event_t               *rev;
1510     ngx_connection_t          *c;
1511     ngx_http_core_srv_conf_t  *cscf;
1512 
1513     c = r->connection;
1514     rev = c->read;
1515 
1516     n = r->header_in->last - r->header_in->pos;
1517 
1518     if (n > 0) {
1519         return n;
1520     }
1521 
1522     if (rev->ready) {
1523         n = c->recv(c, r->header_in->last,
1524                     r->header_in->end - r->header_in->last);
1525     } else {
1526         n = NGX_AGAIN;
1527     }
1528 
1529     if (n == NGX_AGAIN) {
1530         if (!rev->timer_set) {
1531             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1532             ngx_add_timer(rev, cscf->client_header_timeout);
1533         }
1534 
1535         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1536             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1537             return NGX_ERROR;
1538         }
1539 
1540         return NGX_AGAIN;
1541     }
1542 
1543     if (n == 0) {
1544         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1545                       "client prematurely closed connection");
1546     }
1547 
1548     if (n == 0 || n == NGX_ERROR) {
1549         c->error = 1;
1550         c->log->action = "reading client request headers";
1551 
1552         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1553         return NGX_ERROR;
1554     }
1555 
1556     r->header_in->last += n;
1557 
1558     return n;
1559 }
1560 
1561 
1562 static ngx_int_t
1563 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1564     ngx_uint_t request_line)
1565 {
1566     u_char                    *old, *new;
1567     ngx_buf_t                 *b;
1568     ngx_chain_t               *cl;
1569     ngx_http_connection_t     *hc;
1570     ngx_http_core_srv_conf_t  *cscf;
1571 
1572     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1573                    "http alloc large header buffer");
1574 
1575     if (request_line && r->state == 0) {
1576 
1577         /* the client fills up the buffer with "\r\n" */
1578 
1579         r->header_in->pos = r->header_in->start;
1580         r->header_in->last = r->header_in->start;
1581 
1582         return NGX_OK;
1583     }
1584 
1585     old = request_line ? r->request_start : r->header_name_start;
1586 
1587     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1588 
1589     if (r->state != 0
1590         && (size_t) (r->header_in->pos - old)
1591                                      >= cscf->large_client_header_buffers.size)
1592     {
1593         return NGX_DECLINED;
1594     }
1595 
1596     hc = r->http_connection;
1597 
1598     if (hc->free) {
1599         cl = hc->free;
1600         hc->free = cl->next;
1601 
1602         b = cl->buf;
1603 
1604         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1605                        "http large header free: %p %uz",
1606                        b->pos, b->end - b->last);
1607 
1608     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1609 
1610         b = ngx_create_temp_buf(r->connection->pool,
1611                                 cscf->large_client_header_buffers.size);
1612         if (b == NULL) {
1613             return NGX_ERROR;
1614         }
1615 
1616         cl = ngx_alloc_chain_link(r->connection->pool);
1617         if (cl == NULL) {
1618             return NGX_ERROR;
1619         }
1620 
1621         cl->buf = b;
1622 
1623         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1624                        "http large header alloc: %p %uz",
1625                        b->pos, b->end - b->last);
1626 
1627     } else {
1628         return NGX_DECLINED;
1629     }
1630 
1631     cl->next = hc->busy;
1632     hc->busy = cl;
1633     hc->nbusy++;
1634 
1635     if (r->state == 0) {
1636         /*
1637          * r->state == 0 means that a header line was parsed successfully
1638          * and we do not need to copy incomplete header line and
1639          * to relocate the parser header pointers
1640          */
1641 
1642         r->header_in = b;
1643 
1644         return NGX_OK;
1645     }
1646 
1647     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1648                    "http large header copy: %uz", r->header_in->pos - old);
1649 
1650     new = b->start;
1651 
1652     ngx_memcpy(new, old, r->header_in->pos - old);
1653 
1654     b->pos = new + (r->header_in->pos - old);
1655     b->last = new + (r->header_in->pos - old);
1656 
1657     if (request_line) {
1658         r->request_start = new;
1659 
1660         if (r->request_end) {
1661             r->request_end = new + (r->request_end - old);
1662         }
1663 
1664         r->method_end = new + (r->method_end - old);
1665 
1666         r->uri_start = new + (r->uri_start - old);
1667         r->uri_end = new + (r->uri_end - old);
1668 
1669         if (r->schema_start) {
1670             r->schema_start = new + (r->schema_start - old);
1671             r->schema_end = new + (r->schema_end - old);
1672         }
1673 
1674         if (r->host_start) {
1675             r->host_start = new + (r->host_start - old);
1676             if (r->host_end) {
1677                 r->host_end = new + (r->host_end - old);
1678             }
1679         }
1680 
1681         if (r->port_start) {
1682             r->port_start = new + (r->port_start - old);
1683             r->port_end = new + (r->port_end - old);
1684         }
1685 
1686         if (r->uri_ext) {
1687             r->uri_ext = new + (r->uri_ext - old);
1688         }
1689 
1690         if (r->args_start) {
1691             r->args_start = new + (r->args_start - old);
1692         }
1693 
1694         if (r->http_protocol.data) {
1695             r->http_protocol.data = new + (r->http_protocol.data - old);
1696         }
1697 
1698     } else {
1699         r->header_name_start = new;
1700         r->header_name_end = new + (r->header_name_end - old);
1701         r->header_start = new + (r->header_start - old);
1702         r->header_end = new + (r->header_end - old);
1703     }
1704 
1705     r->header_in = b;
1706 
1707     return NGX_OK;
1708 }
1709 
1710 
1711 static ngx_int_t
1712 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1713     ngx_uint_t offset)
1714 {
1715     ngx_table_elt_t  **ph;
1716 
1717     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1718 
1719     if (*ph == NULL) {
1720         *ph = h;
1721     }
1722 
1723     return NGX_OK;
1724 }
1725 
1726 
1727 static ngx_int_t
1728 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1729     ngx_uint_t offset)
1730 {
1731     ngx_table_elt_t  **ph;
1732 
1733     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1734 
1735     if (*ph == NULL) {
1736         *ph = h;
1737         return NGX_OK;
1738     }
1739 
1740     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1741                   "client sent duplicate header line: \"%V: %V\", "
1742                   "previous value: \"%V: %V\"",
1743                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1744 
1745     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1746 
1747     return NGX_ERROR;
1748 }
1749 
1750 
1751 static ngx_int_t
1752 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1753     ngx_uint_t offset)
1754 {
1755     ngx_int_t  rc;
1756     ngx_str_t  host;
1757 
1758     if (r->headers_in.host == NULL) {
1759         r->headers_in.host = h;
1760     }
1761 
1762     host = h->value;
1763 
1764     rc = ngx_http_validate_host(&host, r->pool, 0);
1765 
1766     if (rc == NGX_DECLINED) {
1767         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1768                       "client sent invalid host header");
1769         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1770         return NGX_ERROR;
1771     }
1772 
1773     if (rc == NGX_ERROR) {
1774         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1775         return NGX_ERROR;
1776     }
1777 
1778     if (r->headers_in.server.len) {
1779         return NGX_OK;
1780     }
1781 
1782     if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1783         return NGX_ERROR;
1784     }
1785 
1786     r->headers_in.server = host;
1787 
1788     return NGX_OK;
1789 }
1790 
1791 
1792 static ngx_int_t
1793 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1794     ngx_uint_t offset)
1795 {
1796     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1797         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1798 
1799     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1800         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1801     }
1802 
1803     return NGX_OK;
1804 }
1805 
1806 
1807 static ngx_int_t
1808 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1809     ngx_uint_t offset)
1810 {
1811     u_char  *user_agent, *msie;
1812 
1813     if (r->headers_in.user_agent) {
1814         return NGX_OK;
1815     }
1816 
1817     r->headers_in.user_agent = h;
1818 
1819     /* check some widespread browsers while the header is in CPU cache */
1820 
1821     user_agent = h->value.data;
1822 
1823     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1824 
1825     if (msie && msie + 7 < user_agent + h->value.len) {
1826 
1827         r->headers_in.msie = 1;
1828 
1829         if (msie[6] == '.') {
1830 
1831             switch (msie[5]) {
1832             case '4':
1833             case '5':
1834                 r->headers_in.msie6 = 1;
1835                 break;
1836             case '6':
1837                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1838                     r->headers_in.msie6 = 1;
1839                 }
1840                 break;
1841             }
1842         }
1843 
1844 #if 0
1845         /* MSIE ignores the SSL "close notify" alert */
1846         if (c->ssl) {
1847             c->ssl->no_send_shutdown = 1;
1848         }
1849 #endif
1850     }
1851 
1852     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1853         r->headers_in.opera = 1;
1854         r->headers_in.msie = 0;
1855         r->headers_in.msie6 = 0;
1856     }
1857 
1858     if (!r->headers_in.msie && !r->headers_in.opera) {
1859 
1860         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1861             r->headers_in.gecko = 1;
1862 
1863         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1864             r->headers_in.chrome = 1;
1865 
1866         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1867                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1868         {
1869             r->headers_in.safari = 1;
1870 
1871         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1872             r->headers_in.konqueror = 1;
1873         }
1874     }
1875 
1876     return NGX_OK;
1877 }
1878 
1879 
1880 static ngx_int_t
1881 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1882     ngx_uint_t offset)
1883 {
1884     ngx_array_t       *headers;
1885     ngx_table_elt_t  **ph;
1886 
1887     headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1888 
1889     if (headers->elts == NULL) {
1890         if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1891             != NGX_OK)
1892         {
1893             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1894             return NGX_ERROR;
1895         }
1896     }
1897 
1898     ph = ngx_array_push(headers);
1899     if (ph == NULL) {
1900         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1901         return NGX_ERROR;
1902     }
1903 
1904     *ph = h;
1905     return NGX_OK;
1906 }
1907 
1908 
1909 ngx_int_t
1910 ngx_http_process_request_header(ngx_http_request_t *r)
1911 {
1912     if (r->headers_in.server.len == 0
1913         && ngx_http_set_virtual_server(r, &r->headers_in.server)
1914            == NGX_ERROR)
1915     {
1916         return NGX_ERROR;
1917     }
1918 
1919     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1920         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1921                    "client sent HTTP/1.1 request without \"Host\" header");
1922         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1923         return NGX_ERROR;
1924     }
1925 
1926     if (r->headers_in.content_length) {
1927         r->headers_in.content_length_n =
1928                             ngx_atoof(r->headers_in.content_length->value.data,
1929                                       r->headers_in.content_length->value.len);
1930 
1931         if (r->headers_in.content_length_n == NGX_ERROR) {
1932             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1933                           "client sent invalid \"Content-Length\" header");
1934             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1935             return NGX_ERROR;
1936         }
1937     }
1938 
1939     if (r->method == NGX_HTTP_TRACE) {
1940         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1941                       "client sent TRACE method");
1942         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1943         return NGX_ERROR;
1944     }
1945 
1946     if (r->headers_in.transfer_encoding) {
1947         if (r->headers_in.transfer_encoding->value.len == 7
1948             && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1949                                (u_char *) "chunked", 7) == 0)
1950         {
1951             r->headers_in.content_length = NULL;
1952             r->headers_in.content_length_n = -1;
1953             r->headers_in.chunked = 1;
1954 
1955         } else if (r->headers_in.transfer_encoding->value.len != 8
1956             || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1957                                (u_char *) "identity", 8) != 0)
1958         {
1959             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1960                           "client sent unknown \"Transfer-Encoding\": \"%V\"",
1961                           &r->headers_in.transfer_encoding->value);
1962             ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
1963             return NGX_ERROR;
1964         }
1965     }
1966 
1967     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1968         if (r->headers_in.keep_alive) {
1969             r->headers_in.keep_alive_n =
1970                             ngx_atotm(r->headers_in.keep_alive->value.data,
1971                                       r->headers_in.keep_alive->value.len);
1972         }
1973     }
1974 
1975     return NGX_OK;
1976 }
1977 
1978 
1979 void
1980 ngx_http_process_request(ngx_http_request_t *r)
1981 {
1982     ngx_connection_t  *c;
1983 
1984     c = r->connection;
1985 
1986 #if (NGX_HTTP_SSL)
1987 
1988     if (r->http_connection->ssl) {
1989         long                      rc;
1990         X509                     *cert;
1991         ngx_http_ssl_srv_conf_t  *sscf;
1992 
1993         if (c->ssl == NULL) {
1994             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1995                           "client sent plain HTTP request to HTTPS port");
1996             ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1997             return;
1998         }
1999 
2000         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
2001 
2002         if (sscf->verify) {
2003             rc = SSL_get_verify_result(c->ssl->connection);
2004 
2005             if (rc != X509_V_OK
2006                 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
2007             {
2008                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2009                               "client SSL certificate verify error: (%l:%s)",
2010                               rc, X509_verify_cert_error_string(rc));
2011 
2012                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2013                                        (SSL_get0_session(c->ssl->connection)));
2014 
2015                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
2016                 return;
2017             }
2018 
2019             if (sscf->verify == 1) {
2020                 cert = SSL_get_peer_certificate(c->ssl->connection);
2021 
2022                 if (cert == NULL) {
2023                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
2024                                   "client sent no required SSL certificate");
2025 
2026                     ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2027                                        (SSL_get0_session(c->ssl->connection)));
2028 
2029                     ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
2030                     return;
2031                 }
2032 
2033                 X509_free(cert);
2034             }
2035         }
2036     }
2037 
2038 #endif
2039 
2040     if (c->read->timer_set) {
2041         ngx_del_timer(c->read);
2042     }
2043 
2044 #if (NGX_STAT_STUB)
2045     (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
2046     r->stat_reading = 0;
2047     (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
2048     r->stat_writing = 1;
2049 #endif
2050 
2051     c->read->handler = ngx_http_request_handler;
2052     c->write->handler = ngx_http_request_handler;
2053     r->read_event_handler = ngx_http_block_reading;
2054 
2055     ngx_http_handler(r);
2056 }
2057 
2058 
2059 static ngx_int_t
2060 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
2061 {
2062     u_char  *h, ch;
2063     size_t   i, dot_pos, host_len;
2064 
2065     enum {
2066         sw_usual = 0,
2067         sw_literal,
2068         sw_rest
2069     } state;
2070 
2071     dot_pos = host->len;
2072     host_len = host->len;
2073 
2074     h = host->data;
2075 
2076     state = sw_usual;
2077 
2078     for (i = 0; i < host->len; i++) {
2079         ch = h[i];
2080 
2081         switch (ch) {
2082 
2083         case '.':
2084             if (dot_pos == i - 1) {
2085                 return NGX_DECLINED;
2086             }
2087             dot_pos = i;
2088             break;
2089 
2090         case ':':
2091             if (state == sw_usual) {
2092                 host_len = i;
2093                 state = sw_rest;
2094             }
2095             break;
2096 
2097         case '[':
2098             if (i == 0) {
2099                 state = sw_literal;
2100             }
2101             break;
2102 
2103         case ']':
2104             if (state == sw_literal) {
2105                 host_len = i + 1;
2106                 state = sw_rest;
2107             }
2108             break;
2109 
2110         case '\0':
2111             return NGX_DECLINED;
2112 
2113         default:
2114 
2115             if (ngx_path_separator(ch)) {
2116                 return NGX_DECLINED;
2117             }
2118 
2119             if (ch >= 'A' && ch <= 'Z') {
2120                 alloc = 1;
2121             }
2122 
2123             break;
2124         }
2125     }
2126 
2127     if (dot_pos == host_len - 1) {
2128         host_len--;
2129     }
2130 
2131     if (host_len == 0) {
2132         return NGX_DECLINED;
2133     }
2134 
2135     if (alloc) {
2136         host->data = ngx_pnalloc(pool, host_len);
2137         if (host->data == NULL) {
2138             return NGX_ERROR;
2139         }
2140 
2141         ngx_strlow(host->data, h, host_len);
2142     }
2143 
2144     host->len = host_len;
2145 
2146     return NGX_OK;
2147 }
2148 
2149 
2150 static ngx_int_t
2151 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
2152 {
2153     ngx_int_t                  rc;
2154     ngx_http_connection_t     *hc;
2155     ngx_http_core_loc_conf_t  *clcf;
2156     ngx_http_core_srv_conf_t  *cscf;
2157 
2158 #if (NGX_SUPPRESS_WARN)
2159     cscf = NULL;
2160 #endif
2161 
2162     hc = r->http_connection;
2163 
2164 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2165 
2166     if (hc->ssl_servername) {
2167         if (hc->ssl_servername->len == host->len
2168             && ngx_strncmp(hc->ssl_servername->data,
2169                            host->data, host->len) == 0)
2170         {
2171 #if (NGX_PCRE)
2172             if (hc->ssl_servername_regex
2173                 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
2174                                           hc->ssl_servername) != NGX_OK)
2175             {
2176                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2177                 return NGX_ERROR;
2178             }
2179 #endif
2180             return NGX_OK;
2181         }
2182     }
2183 
2184 #endif
2185 
2186     rc = ngx_http_find_virtual_server(r->connection,
2187                                       hc->addr_conf->virtual_names,
2188                                       host, r, &cscf);
2189 
2190     if (rc == NGX_ERROR) {
2191         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2192         return NGX_ERROR;
2193     }
2194 
2195 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2196 
2197     if (hc->ssl_servername) {
2198         ngx_http_ssl_srv_conf_t  *sscf;
2199 
2200         if (rc == NGX_DECLINED) {
2201             cscf = hc->addr_conf->default_server;
2202             rc = NGX_OK;
2203         }
2204 
2205         sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2206 
2207         if (sscf->verify) {
2208             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2209                           "client attempted to request the server name "
2210                           "different from the one that was negotiated");
2211             ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
2212             return NGX_ERROR;
2213         }
2214     }
2215 
2216 #endif
2217 
2218     if (rc == NGX_DECLINED) {
2219         return NGX_OK;
2220     }
2221 
2222     r->srv_conf = cscf->ctx->srv_conf;
2223     r->loc_conf = cscf->ctx->loc_conf;
2224 
2225     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2226 
2227     ngx_set_connection_log(r->connection, clcf->error_log);
2228 
2229     return NGX_OK;
2230 }
2231 
2232 
2233 static ngx_int_t
2234 ngx_http_find_virtual_server(ngx_connection_t *c,
2235     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2236     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2237 {
2238     ngx_http_core_srv_conf_t  *cscf;
2239 
2240     if (virtual_names == NULL) {
2241         return NGX_DECLINED;
2242     }
2243 
2244     cscf = ngx_hash_find_combined(&virtual_names->names,
2245                                   ngx_hash_key(host->data, host->len),
2246                                   host->data, host->len);
2247 
2248     if (cscf) {
2249         *cscfp = cscf;
2250         return NGX_OK;
2251     }
2252 
2253 #if (NGX_PCRE)
2254 
2255     if (host->len && virtual_names->nregex) {
2256         ngx_int_t                n;
2257         ngx_uint_t               i;
2258         ngx_http_server_name_t  *sn;
2259 
2260         sn = virtual_names->regex;
2261 
2262 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2263 
2264         if (r == NULL) {
2265             ngx_http_connection_t  *hc;
2266 
2267             for (i = 0; i < virtual_names->nregex; i++) {
2268 
2269                 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2270 
2271                 if (n == NGX_REGEX_NO_MATCHED) {
2272                     continue;
2273                 }
2274 
2275                 if (n >= 0) {
2276                     hc = c->data;
2277                     hc->ssl_servername_regex = sn[i].regex;
2278 
2279                     *cscfp = sn[i].server;
2280                     return NGX_OK;
2281                 }
2282 
2283                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2284                               ngx_regex_exec_n " failed: %i "
2285                               "on \"%V\" using \"%V\"",
2286                               n, host, &sn[i].regex->name);
2287 
2288                 return NGX_ERROR;
2289             }
2290 
2291             return NGX_DECLINED;
2292         }
2293 
2294 #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */
2295 
2296         for (i = 0; i < virtual_names->nregex; i++) {
2297 
2298             n = ngx_http_regex_exec(r, sn[i].regex, host);
2299 
2300             if (n == NGX_DECLINED) {
2301                 continue;
2302             }
2303 
2304             if (n == NGX_OK) {
2305                 *cscfp = sn[i].server;
2306                 return NGX_OK;
2307             }
2308 
2309             return NGX_ERROR;
2310         }
2311     }
2312 
2313 #endif /* NGX_PCRE */
2314 
2315     return NGX_DECLINED;
2316 }
2317 
2318 
2319 static void
2320 ngx_http_request_handler(ngx_event_t *ev)
2321 {
2322     ngx_connection_t    *c;
2323     ngx_http_request_t  *r;
2324 
2325     c = ev->data;
2326     r = c->data;
2327 
2328     ngx_http_set_log_request(c->log, r);
2329 
2330     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2331                    "http run request: \"%V?%V\"", &r->uri, &r->args);
2332 
2333     if (c->close) {
2334         r->main->count++;
2335         ngx_http_terminate_request(r, 0);
2336         ngx_http_run_posted_requests(c);
2337         return;
2338     }
2339 
2340     if (ev->delayed && ev->timedout) {
2341         ev->delayed = 0;
2342         ev->timedout = 0;
2343     }
2344 
2345     if (ev->write) {
2346         r->write_event_handler(r);
2347 
2348     } else {
2349         r->read_event_handler(r);
2350     }
2351 
2352     ngx_http_run_posted_requests(c);
2353 }
2354 
2355 
2356 void
2357 ngx_http_run_posted_requests(ngx_connection_t *c)
2358 {
2359     ngx_http_request_t         *r;
2360     ngx_http_posted_request_t  *pr;
2361 
2362     for ( ;; ) {
2363 
2364         if (c->destroyed) {
2365             return;
2366         }
2367 
2368         r = c->data;
2369         pr = r->main->posted_requests;
2370 
2371         if (pr == NULL) {
2372             return;
2373         }
2374 
2375         r->main->posted_requests = pr->next;
2376 
2377         r = pr->request;
2378 
2379         ngx_http_set_log_request(c->log, r);
2380 
2381         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2382                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
2383 
2384         r->write_event_handler(r);
2385     }
2386 }
2387 
2388 
2389 ngx_int_t
2390 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2391 {
2392     ngx_http_posted_request_t  **p;
2393 
2394     if (pr == NULL) {
2395         pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2396         if (pr == NULL) {
2397             return NGX_ERROR;
2398         }
2399     }
2400 
2401     pr->request = r;
2402     pr->next = NULL;
2403 
2404     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2405 
2406     *p = pr;
2407 
2408     return NGX_OK;
2409 }
2410 
2411 
2412 void
2413 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2414 {
2415     ngx_connection_t          *c;
2416     ngx_http_request_t        *pr;
2417     ngx_http_core_loc_conf_t  *clcf;
2418 
2419     c = r->connection;
2420 
2421     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2422                    "http finalize request: %i, \"%V?%V\" a:%d, c:%d",
2423                    rc, &r->uri, &r->args, r == c->data, r->main->count);
2424 
2425     if (rc == NGX_DONE) {
2426         ngx_http_finalize_connection(r);
2427         return;
2428     }
2429 
2430     if (rc == NGX_OK && r->filter_finalize) {
2431         c->error = 1;
2432     }
2433 
2434     if (rc == NGX_DECLINED) {
2435         r->content_handler = NULL;
2436         r->write_event_handler = ngx_http_core_run_phases;
2437         ngx_http_core_run_phases(r);
2438         return;
2439     }
2440 
2441     if (r != r->main && r->post_subrequest) {
2442         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2443     }
2444 
2445     if (rc == NGX_ERROR
2446         || rc == NGX_HTTP_REQUEST_TIME_OUT
2447         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2448         || c->error)
2449     {
2450         if (ngx_http_post_action(r) == NGX_OK) {
2451             return;
2452         }
2453 
2454         ngx_http_terminate_request(r, rc);
2455         return;
2456     }
2457 
2458     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2459         || rc == NGX_HTTP_CREATED
2460         || rc == NGX_HTTP_NO_CONTENT)
2461     {
2462         if (rc == NGX_HTTP_CLOSE) {
2463             c->timedout = 1;
2464             ngx_http_terminate_request(r, rc);
2465             return;
2466         }
2467 
2468         if (r == r->main) {
2469             if (c->read->timer_set) {
2470                 ngx_del_timer(c->read);
2471             }
2472 
2473             if (c->write->timer_set) {
2474                 ngx_del_timer(c->write);
2475             }
2476         }
2477 
2478         c->read->handler = ngx_http_request_handler;
2479         c->write->handler = ngx_http_request_handler;
2480 
2481         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2482         return;
2483     }
2484 
2485     if (r != r->main) {
2486         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2487 
2488         if (r->background) {
2489             if (!r->logged) {
2490                 if (clcf->log_subrequest) {
2491                     ngx_http_log_request(r);
2492                 }
2493 
2494                 r->logged = 1;
2495 
2496             } else {
2497                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2498                               "subrequest: \"%V?%V\" logged again",
2499                               &r->uri, &r->args);
2500             }
2501 
2502             r->done = 1;
2503             ngx_http_finalize_connection(r);
2504             return;
2505         }
2506 
2507         if (r->buffered || r->postponed) {
2508 
2509             if (ngx_http_set_write_handler(r) != NGX_OK) {
2510                 ngx_http_terminate_request(r, 0);
2511             }
2512 
2513             return;
2514         }
2515 
2516         pr = r->parent;
2517 
2518         if (r == c->data) {
2519 
2520             r->main->count--;
2521 
2522             if (!r->logged) {
2523                 if (clcf->log_subrequest) {
2524                     ngx_http_log_request(r);
2525                 }
2526 
2527                 r->logged = 1;
2528 
2529             } else {
2530                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2531                               "subrequest: \"%V?%V\" logged again",
2532                               &r->uri, &r->args);
2533             }
2534 
2535             r->done = 1;
2536 
2537             if (pr->postponed && pr->postponed->request == r) {
2538                 pr->postponed = pr->postponed->next;
2539             }
2540 
2541             c->data = pr;
2542 
2543         } else {
2544 
2545             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2546                            "http finalize non-active request: \"%V?%V\"",
2547                            &r->uri, &r->args);
2548 
2549             r->write_event_handler = ngx_http_request_finalizer;
2550 
2551             if (r->waited) {
2552                 r->done = 1;
2553             }
2554         }
2555 
2556         if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2557             r->main->count++;
2558             ngx_http_terminate_request(r, 0);
2559             return;
2560         }
2561 
2562         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2563                        "http wake parent request: \"%V?%V\"",
2564                        &pr->uri, &pr->args);
2565 
2566         return;
2567     }
2568 
2569     if (r->buffered || c->buffered || r->postponed) {
2570 
2571         if (ngx_http_set_write_handler(r) != NGX_OK) {
2572             ngx_http_terminate_request(r, 0);
2573         }
2574 
2575         return;
2576     }
2577 
2578     if (r != c->data) {
2579         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2580                       "http finalize non-active request: \"%V?%V\"",
2581                       &r->uri, &r->args);
2582         return;
2583     }
2584 
2585     r->done = 1;
2586 
2587     r->read_event_handler = ngx_http_block_reading;
2588     r->write_event_handler = ngx_http_request_empty_handler;
2589 
2590     if (!r->post_action) {
2591         r->request_complete = 1;
2592     }
2593 
2594     if (ngx_http_post_action(r) == NGX_OK) {
2595         return;
2596     }
2597 
2598     if (c->read->timer_set) {
2599         ngx_del_timer(c->read);
2600     }
2601 
2602     if (c->write->timer_set) {
2603         c->write->delayed = 0;
2604         ngx_del_timer(c->write);
2605     }
2606 
2607     if (c->read->eof) {
2608         ngx_http_close_request(r, 0);
2609         return;
2610     }
2611 
2612     ngx_http_finalize_connection(r);
2613 }
2614 
2615 
2616 static void
2617 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2618 {
2619     ngx_http_cleanup_t    *cln;
2620     ngx_http_request_t    *mr;
2621     ngx_http_ephemeral_t  *e;
2622 
2623     mr = r->main;
2624 
2625     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2626                    "http terminate request count:%d", mr->count);
2627 
2628     if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2629         mr->headers_out.status = rc;
2630     }
2631 
2632     cln = mr->cleanup;
2633     mr->cleanup = NULL;
2634 
2635     while (cln) {
2636         if (cln->handler) {
2637             cln->handler(cln->data);
2638         }
2639 
2640         cln = cln->next;
2641     }
2642 
2643     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2644                    "http terminate cleanup count:%d blk:%d",
2645                    mr->count, mr->blocked);
2646 
2647     if (mr->write_event_handler) {
2648 
2649         if (mr->blocked) {
2650             r->connection->error = 1;
2651             r->write_event_handler = ngx_http_request_finalizer;
2652             return;
2653         }
2654 
2655         e = ngx_http_ephemeral(mr);
2656         mr->posted_requests = NULL;
2657         mr->write_event_handler = ngx_http_terminate_handler;
2658         (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2659         return;
2660     }
2661 
2662     ngx_http_close_request(mr, rc);
2663 }
2664 
2665 
2666 static void
2667 ngx_http_terminate_handler(ngx_http_request_t *r)
2668 {
2669     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2670                    "http terminate handler count:%d", r->count);
2671 
2672     r->count = 1;
2673 
2674     ngx_http_close_request(r, 0);
2675 }
2676 
2677 
2678 static void
2679 ngx_http_finalize_connection(ngx_http_request_t *r)
2680 {
2681     ngx_http_core_loc_conf_t  *clcf;
2682 
2683 #if (NGX_HTTP_V2)
2684     if (r->stream) {
2685         ngx_http_close_request(r, 0);
2686         return;
2687     }
2688 #endif
2689 
2690     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2691 
2692     if (r->main->count != 1) {
2693 
2694         if (r->discard_body) {
2695             r->read_event_handler = ngx_http_discarded_request_body_handler;
2696             ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2697 
2698             if (r->lingering_time == 0) {
2699                 r->lingering_time = ngx_time()
2700                                       + (time_t) (clcf->lingering_time / 1000);
2701             }
2702         }
2703 
2704         ngx_http_close_request(r, 0);
2705         return;
2706     }
2707 
2708     r = r->main;
2709 
2710     if (r->reading_body) {
2711         r->keepalive = 0;
2712         r->lingering_close = 1;
2713     }
2714 
2715     if (!ngx_terminate
2716          && !ngx_exiting
2717          && r->keepalive
2718          && clcf->keepalive_timeout > 0)
2719     {
2720         ngx_http_set_keepalive(r);
2721         return;
2722     }
2723 
2724     if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2725         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2726             && (r->lingering_close
2727                 || r->header_in->pos < r->header_in->last
2728                 || r->connection->read->ready)))
2729     {
2730         ngx_http_set_lingering_close(r);
2731         return;
2732     }
2733 
2734     ngx_http_close_request(r, 0);
2735 }
2736 
2737 
2738 static ngx_int_t
2739 ngx_http_set_write_handler(ngx_http_request_t *r)
2740 {
2741     ngx_event_t               *wev;
2742     ngx_http_core_loc_conf_t  *clcf;
2743 
2744     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2745 
2746     r->read_event_handler = r->discard_body ?
2747                                 ngx_http_discarded_request_body_handler:
2748                                 ngx_http_test_reading;
2749     r->write_event_handler = ngx_http_writer;
2750 
2751     wev = r->connection->write;
2752 
2753     if (wev->ready && wev->delayed) {
2754         return NGX_OK;
2755     }
2756 
2757     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2758     if (!wev->delayed) {
2759         ngx_add_timer(wev, clcf->send_timeout);
2760     }
2761 
2762     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2763         ngx_http_close_request(r, 0);
2764         return NGX_ERROR;
2765     }
2766 
2767     return NGX_OK;
2768 }
2769 
2770 
2771 static void
2772 ngx_http_writer(ngx_http_request_t *r)
2773 {
2774     ngx_int_t                  rc;
2775     ngx_event_t               *wev;
2776     ngx_connection_t          *c;
2777     ngx_http_core_loc_conf_t  *clcf;
2778 
2779     c = r->connection;
2780     wev = c->write;
2781 
2782     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2783                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2784 
2785     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2786 
2787     if (wev->timedout) {
2788         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2789                       "client timed out");
2790         c->timedout = 1;
2791 
2792         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2793         return;
2794     }
2795 
2796     if (wev->delayed || r->aio) {
2797         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2798                        "http writer delayed");
2799 
2800         if (!wev->delayed) {
2801             ngx_add_timer(wev, clcf->send_timeout);
2802         }
2803 
2804         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2805             ngx_http_close_request(r, 0);
2806         }
2807 
2808         return;
2809     }
2810 
2811     rc = ngx_http_output_filter(r, NULL);
2812 
2813     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2814                    "http writer output filter: %i, \"%V?%V\"",
2815                    rc, &r->uri, &r->args);
2816 
2817     if (rc == NGX_ERROR) {
2818         ngx_http_finalize_request(r, rc);
2819         return;
2820     }
2821 
2822     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2823 
2824         if (!wev->delayed) {
2825             ngx_add_timer(wev, clcf->send_timeout);
2826         }
2827 
2828         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2829             ngx_http_close_request(r, 0);
2830         }
2831 
2832         return;
2833     }
2834 
2835     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2836                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
2837 
2838     r->write_event_handler = ngx_http_request_empty_handler;
2839 
2840     ngx_http_finalize_request(r, rc);
2841 }
2842 
2843 
2844 static void
2845 ngx_http_request_finalizer(ngx_http_request_t *r)
2846 {
2847     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2848                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2849 
2850     ngx_http_finalize_request(r, 0);
2851 }
2852 
2853 
2854 void
2855 ngx_http_block_reading(ngx_http_request_t *r)
2856 {
2857     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2858                    "http reading blocked");
2859 
2860     /* aio does not call this handler */
2861 
2862     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2863         && r->connection->read->active)
2864     {
2865         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2866             ngx_http_close_request(r, 0);
2867         }
2868     }
2869 }
2870 
2871 
2872 void
2873 ngx_http_test_reading(ngx_http_request_t *r)
2874 {
2875     int                n;
2876     char               buf[1];
2877     ngx_err_t          err;
2878     ngx_event_t       *rev;
2879     ngx_connection_t  *c;
2880 
2881     c = r->connection;
2882     rev = c->read;
2883 
2884     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2885 
2886 #if (NGX_HTTP_V2)
2887 
2888     if (r->stream) {
2889         if (c->error) {
2890             err = 0;
2891             goto closed;
2892         }
2893 
2894         return;
2895     }
2896 
2897 #endif
2898 
2899 #if (NGX_HAVE_KQUEUE)
2900 
2901     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2902 
2903         if (!rev->pending_eof) {
2904             return;
2905         }
2906 
2907         rev->eof = 1;
2908         c->error = 1;
2909         err = rev->kq_errno;
2910 
2911         goto closed;
2912     }
2913 
2914 #endif
2915 
2916 #if (NGX_HAVE_EPOLLRDHUP)
2917 
2918     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
2919         socklen_t  len;
2920 
2921         if (!rev->pending_eof) {
2922             return;
2923         }
2924 
2925         rev->eof = 1;
2926         c->error = 1;
2927 
2928         err = 0;
2929         len = sizeof(ngx_err_t);
2930 
2931         /*
2932          * BSDs and Linux return 0 and set a pending error in err
2933          * Solaris returns -1 and sets errno
2934          */
2935 
2936         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
2937             == -1)
2938         {
2939             err = ngx_socket_errno;
2940         }
2941 
2942         goto closed;
2943     }
2944 
2945 #endif
2946 
2947     n = recv(c->fd, buf, 1, MSG_PEEK);
2948 
2949     if (n == 0) {
2950         rev->eof = 1;
2951         c->error = 1;
2952         err = 0;
2953 
2954         goto closed;
2955 
2956     } else if (n == -1) {
2957         err = ngx_socket_errno;
2958 
2959         if (err != NGX_EAGAIN) {
2960             rev->eof = 1;
2961             c->error = 1;
2962 
2963             goto closed;
2964         }
2965     }
2966 
2967     /* aio does not call this handler */
2968 
2969     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2970 
2971         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2972             ngx_http_close_request(r, 0);
2973         }
2974     }
2975 
2976     return;
2977 
2978 closed:
2979 
2980     if (err) {
2981         rev->error = 1;
2982     }
2983 
2984     ngx_log_error(NGX_LOG_INFO, c->log, err,
2985                   "client prematurely closed connection");
2986 
2987     ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
2988 }
2989 
2990 
2991 static void
2992 ngx_http_set_keepalive(ngx_http_request_t *r)
2993 {
2994     int                        tcp_nodelay;
2995     ngx_buf_t                 *b, *f;
2996     ngx_chain_t               *cl, *ln;
2997     ngx_event_t               *rev, *wev;
2998     ngx_connection_t          *c;
2999     ngx_http_connection_t     *hc;
3000     ngx_http_core_loc_conf_t  *clcf;
3001 
3002     c = r->connection;
3003     rev = c->read;
3004 
3005     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3006 
3007     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
3008 
3009     if (r->discard_body) {
3010         r->write_event_handler = ngx_http_request_empty_handler;
3011         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3012         ngx_add_timer(rev, clcf->lingering_timeout);
3013         return;
3014     }
3015 
3016     c->log->action = "closing request";
3017 
3018     hc = r->http_connection;
3019     b = r->header_in;
3020 
3021     if (b->pos < b->last) {
3022 
3023         /* the pipelined request */
3024 
3025         if (b != c->buffer) {
3026 
3027             /*
3028              * If the large header buffers were allocated while the previous
3029              * request processing then we do not use c->buffer for
3030              * the pipelined request (see ngx_http_create_request()).
3031              *
3032              * Now we would move the large header buffers to the free list.
3033              */
3034 
3035             for (cl = hc->busy; cl; /* void */) {
3036                 ln = cl;
3037                 cl = cl->next;
3038 
3039                 if (ln->buf == b) {
3040                     ngx_free_chain(c->pool, ln);
3041                     continue;
3042                 }
3043 
3044                 f = ln->buf;
3045                 f->pos = f->start;
3046                 f->last = f->start;
3047 
3048                 ln->next = hc->free;
3049                 hc->free = ln;
3050             }
3051 
3052             cl = ngx_alloc_chain_link(c->pool);
3053             if (cl == NULL) {
3054                 ngx_http_close_request(r, 0);
3055                 return;
3056             }
3057 
3058             cl->buf = b;
3059             cl->next = NULL;
3060 
3061             hc->busy = cl;
3062             hc->nbusy = 1;
3063         }
3064     }
3065 
3066     /* guard against recursive call from ngx_http_finalize_connection() */
3067     r->keepalive = 0;
3068 
3069     ngx_http_free_request(r, 0);
3070 
3071     c->data = hc;
3072 
3073     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3074         ngx_http_close_connection(c);
3075         return;
3076     }
3077 
3078     wev = c->write;
3079     wev->handler = ngx_http_empty_handler;
3080 
3081     if (b->pos < b->last) {
3082 
3083         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
3084 
3085         c->log->action = "reading client pipelined request line";
3086 
3087         r = ngx_http_create_request(c);
3088         if (r == NULL) {
3089             ngx_http_close_connection(c);
3090             return;
3091         }
3092 
3093         r->pipeline = 1;
3094 
3095         c->data = r;
3096 
3097         c->sent = 0;
3098         c->destroyed = 0;
3099 
3100         if (rev->timer_set) {
3101             ngx_del_timer(rev);
3102         }
3103 
3104         rev->handler = ngx_http_process_request_line;
3105         ngx_post_event(rev, &ngx_posted_events);
3106         return;
3107     }
3108 
3109     /*
3110      * To keep a memory footprint as small as possible for an idle keepalive
3111      * connection we try to free c->buffer's memory if it was allocated outside
3112      * the c->pool.  The large header buffers are always allocated outside the
3113      * c->pool and are freed too.
3114      */
3115 
3116     b = c->buffer;
3117 
3118     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3119 
3120         /*
3121          * the special note for ngx_http_keepalive_handler() that
3122          * c->buffer's memory was freed
3123          */
3124 
3125         b->pos = NULL;
3126 
3127     } else {
3128         b->pos = b->start;
3129         b->last = b->start;
3130     }
3131 
3132     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
3133                    hc->free);
3134 
3135     if (hc->free) {
3136         for (cl = hc->free; cl; /* void */) {
3137             ln = cl;
3138             cl = cl->next;
3139             ngx_pfree(c->pool, ln->buf->start);
3140             ngx_free_chain(c->pool, ln);
3141         }
3142 
3143         hc->free = NULL;
3144     }
3145 
3146     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
3147                    hc->busy, hc->nbusy);
3148 
3149     if (hc->busy) {
3150         for (cl = hc->busy; cl; /* void */) {
3151             ln = cl;
3152             cl = cl->next;
3153             ngx_pfree(c->pool, ln->buf->start);
3154             ngx_free_chain(c->pool, ln);
3155         }
3156 
3157         hc->busy = NULL;
3158         hc->nbusy = 0;
3159     }
3160 
3161 #if (NGX_HTTP_SSL)
3162     if (c->ssl) {
3163         ngx_ssl_free_buffer(c);
3164     }
3165 #endif
3166 
3167     rev->handler = ngx_http_keepalive_handler;
3168 
3169     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3170         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3171             ngx_http_close_connection(c);
3172             return;
3173         }
3174     }
3175 
3176     c->log->action = "keepalive";
3177 
3178     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
3179         if (ngx_tcp_push(c->fd) == -1) {
3180             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
3181             ngx_http_close_connection(c);
3182             return;
3183         }
3184 
3185         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
3186         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
3187 
3188     } else {
3189         tcp_nodelay = 1;
3190     }
3191 
3192     if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
3193         ngx_http_close_connection(c);
3194         return;
3195     }
3196 
3197 #if 0
3198     /* if ngx_http_request_t was freed then we need some other place */
3199     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
3200 #endif
3201 
3202     c->idle = 1;
3203     ngx_reusable_connection(c, 1);
3204 
3205     ngx_add_timer(rev, clcf->keepalive_timeout);
3206 
3207     if (rev->ready) {
3208         ngx_post_event(rev, &ngx_posted_events);
3209     }
3210 }
3211 
3212 
3213 static void
3214 ngx_http_keepalive_handler(ngx_event_t *rev)
3215 {
3216     size_t             size;
3217     ssize_t            n;
3218     ngx_buf_t         *b;
3219     ngx_connection_t  *c;
3220 
3221     c = rev->data;
3222 
3223     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
3224 
3225     if (rev->timedout || c->close) {
3226         ngx_http_close_connection(c);
3227         return;
3228     }
3229 
3230 #if (NGX_HAVE_KQUEUE)
3231 
3232     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
3233         if (rev->pending_eof) {
3234             c->log->handler = NULL;
3235             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
3236                           "kevent() reported that client %V closed "
3237                           "keepalive connection", &c->addr_text);
3238 #if (NGX_HTTP_SSL)
3239             if (c->ssl) {
3240                 c->ssl->no_send_shutdown = 1;
3241             }
3242 #endif
3243             ngx_http_close_connection(c);
3244             return;
3245         }
3246     }
3247 
3248 #endif
3249 
3250     b = c->buffer;
3251     size = b->end - b->start;
3252 
3253     if (b->pos == NULL) {
3254 
3255         /*
3256          * The c->buffer's memory was freed by ngx_http_set_keepalive().
3257          * However, the c->buffer->start and c->buffer->end were not changed
3258          * to keep the buffer size.
3259          */
3260 
3261         b->pos = ngx_palloc(c->pool, size);
3262         if (b->pos == NULL) {
3263             ngx_http_close_connection(c);
3264             return;
3265         }
3266 
3267         b->start = b->pos;
3268         b->last = b->pos;
3269         b->end = b->pos + size;
3270     }
3271 
3272     /*
3273      * MSIE closes a keepalive connection with RST flag
3274      * so we ignore ECONNRESET here.
3275      */
3276 
3277     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3278     ngx_set_socket_errno(0);
3279 
3280     n = c->recv(c, b->last, size);
3281     c->log_error = NGX_ERROR_INFO;
3282 
3283     if (n == NGX_AGAIN) {
3284         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3285             ngx_http_close_connection(c);
3286             return;
3287         }
3288 
3289         /*
3290          * Like ngx_http_set_keepalive() we are trying to not hold
3291          * c->buffer's memory for a keepalive connection.
3292          */
3293 
3294         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3295 
3296             /*
3297              * the special note that c->buffer's memory was freed
3298              */
3299 
3300             b->pos = NULL;
3301         }
3302 
3303         return;
3304     }
3305 
3306     if (n == NGX_ERROR) {
3307         ngx_http_close_connection(c);
3308         return;
3309     }
3310 
3311     c->log->handler = NULL;
3312 
3313     if (n == 0) {
3314         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3315                       "client %V closed keepalive connection", &c->addr_text);
3316         ngx_http_close_connection(c);
3317         return;
3318     }
3319 
3320     b->last += n;
3321 
3322     c->log->handler = ngx_http_log_error;
3323     c->log->action = "reading client request line";
3324 
3325     c->idle = 0;
3326     ngx_reusable_connection(c, 0);
3327 
3328     c->data = ngx_http_create_request(c);
3329     if (c->data == NULL) {
3330         ngx_http_close_connection(c);
3331         return;
3332     }
3333 
3334     c->sent = 0;
3335     c->destroyed = 0;
3336 
3337     ngx_del_timer(rev);
3338 
3339     rev->handler = ngx_http_process_request_line;
3340     ngx_http_process_request_line(rev);
3341 }
3342 
3343 
3344 static void
3345 ngx_http_set_lingering_close(ngx_http_request_t *r)
3346 {
3347     ngx_event_t               *rev, *wev;
3348     ngx_connection_t          *c;
3349     ngx_http_core_loc_conf_t  *clcf;
3350 
3351     c = r->connection;
3352 
3353     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3354 
3355     rev = c->read;
3356     rev->handler = ngx_http_lingering_close_handler;
3357 
3358     r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3359     ngx_add_timer(rev, clcf->lingering_timeout);
3360 
3361     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3362         ngx_http_close_request(r, 0);
3363         return;
3364     }
3365 
3366     wev = c->write;
3367     wev->handler = ngx_http_empty_handler;
3368 
3369     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3370         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3371             ngx_http_close_request(r, 0);
3372             return;
3373         }
3374     }
3375 
3376     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3377         ngx_connection_error(c, ngx_socket_errno,
3378                              ngx_shutdown_socket_n " failed");
3379         ngx_http_close_request(r, 0);
3380         return;
3381     }
3382 
3383     if (rev->ready) {
3384         ngx_http_lingering_close_handler(rev);
3385     }
3386 }
3387 
3388 
3389 static void
3390 ngx_http_lingering_close_handler(ngx_event_t *rev)
3391 {
3392     ssize_t                    n;
3393     ngx_msec_t                 timer;
3394     ngx_connection_t          *c;
3395     ngx_http_request_t        *r;
3396     ngx_http_core_loc_conf_t  *clcf;
3397     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3398 
3399     c = rev->data;
3400     r = c->data;
3401 
3402     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3403                    "http lingering close handler");
3404 
3405     if (rev->timedout) {
3406         ngx_http_close_request(r, 0);
3407         return;
3408     }
3409 
3410     timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
3411     if ((ngx_msec_int_t) timer <= 0) {
3412         ngx_http_close_request(r, 0);
3413         return;
3414     }
3415 
3416     do {
3417         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3418 
3419         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
3420 
3421         if (n == NGX_AGAIN) {
3422             break;
3423         }
3424 
3425         if (n == NGX_ERROR || n == 0) {
3426             ngx_http_close_request(r, 0);
3427             return;
3428         }
3429 
3430     } while (rev->ready);
3431 
3432     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3433         ngx_http_close_request(r, 0);
3434         return;
3435     }
3436 
3437     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3438 
3439     timer *= 1000;
3440 
3441     if (timer > clcf->lingering_timeout) {
3442         timer = clcf->lingering_timeout;
3443     }
3444 
3445     ngx_add_timer(rev, timer);
3446 }
3447 
3448 
3449 void
3450 ngx_http_empty_handler(ngx_event_t *wev)
3451 {
3452     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3453 
3454     return;
3455 }
3456 
3457 
3458 void
3459 ngx_http_request_empty_handler(ngx_http_request_t *r)
3460 {
3461     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3462                    "http request empty handler");
3463 
3464     return;
3465 }
3466 
3467 
3468 ngx_int_t
3469 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3470 {
3471     ngx_buf_t    *b;
3472     ngx_chain_t   out;
3473 
3474     b = ngx_calloc_buf(r->pool);
3475     if (b == NULL) {
3476         return NGX_ERROR;
3477     }
3478 
3479     if (flags & NGX_HTTP_LAST) {
3480 
3481         if (r == r->main && !r->post_action) {
3482             b->last_buf = 1;
3483 
3484         } else {
3485             b->sync = 1;
3486             b->last_in_chain = 1;
3487         }
3488     }
3489 
3490     if (flags & NGX_HTTP_FLUSH) {
3491         b->flush = 1;
3492     }
3493 
3494     out.buf = b;
3495     out.next = NULL;
3496 
3497     return ngx_http_output_filter(r, &out);
3498 }
3499 
3500 
3501 static ngx_int_t
3502 ngx_http_post_action(ngx_http_request_t *r)
3503 {
3504     ngx_http_core_loc_conf_t  *clcf;
3505 
3506     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3507 
3508     if (clcf->post_action.data == NULL) {
3509         return NGX_DECLINED;
3510     }
3511 
3512     if (r->post_action && r->uri_changes == 0) {
3513         return NGX_DECLINED;
3514     }
3515 
3516     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3517                    "post action: \"%V\"", &clcf->post_action);
3518 
3519     r->main->count--;
3520 
3521     r->http_version = NGX_HTTP_VERSION_9;
3522     r->header_only = 1;
3523     r->post_action = 1;
3524 
3525     r->read_event_handler = ngx_http_block_reading;
3526 
3527     if (clcf->post_action.data[0] == '/') {
3528         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3529 
3530     } else {
3531         ngx_http_named_location(r, &clcf->post_action);
3532     }
3533 
3534     return NGX_OK;
3535 }
3536 
3537 
3538 static void
3539 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3540 {
3541     ngx_connection_t  *c;
3542 
3543     r = r->main;
3544     c = r->connection;
3545 
3546     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3547                    "http request count:%d blk:%d", r->count, r->blocked);
3548 
3549     if (r->count == 0) {
3550         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3551     }
3552 
3553     r->count--;
3554 
3555     if (r->count || r->blocked) {
3556         return;
3557     }
3558 
3559 #if (NGX_HTTP_V2)
3560     if (r->stream) {
3561         ngx_http_v2_close_stream(r->stream, rc);
3562         return;
3563     }
3564 #endif
3565 
3566     ngx_http_free_request(r, rc);
3567     ngx_http_close_connection(c);
3568 }
3569 
3570 
3571 void
3572 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3573 {
3574     ngx_log_t                 *log;
3575     ngx_pool_t                *pool;
3576     struct linger              linger;
3577     ngx_http_cleanup_t        *cln;
3578     ngx_http_log_ctx_t        *ctx;
3579     ngx_http_core_loc_conf_t  *clcf;
3580 
3581     log = r->connection->log;
3582 
3583     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3584 
3585     if (r->pool == NULL) {
3586         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3587         return;
3588     }
3589 
3590     cln = r->cleanup;
3591     r->cleanup = NULL;
3592 
3593     while (cln) {
3594         if (cln->handler) {
3595             cln->handler(cln->data);
3596         }
3597 
3598         cln = cln->next;
3599     }
3600 
3601 #if (NGX_STAT_STUB)
3602 
3603     if (r->stat_reading) {
3604         (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3605     }
3606 
3607     if (r->stat_writing) {
3608         (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3609     }
3610 
3611 #endif
3612 
3613     if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3614         r->headers_out.status = rc;
3615     }
3616 
3617     if (!r->logged) {
3618         log->action = "logging request";
3619 
3620         ngx_http_log_request(r);
3621     }
3622 
3623     log->action = "closing request";
3624 
3625     if (r->connection->timedout) {
3626         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3627 
3628         if (clcf->reset_timedout_connection) {
3629             linger.l_onoff = 1;
3630             linger.l_linger = 0;
3631 
3632             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3633                            (const void *) &linger, sizeof(struct linger)) == -1)
3634             {
3635                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3636                               "setsockopt(SO_LINGER) failed");
3637             }
3638         }
3639     }
3640 
3641     /* the various request strings were allocated from r->pool */
3642     ctx = log->data;
3643     ctx->request = NULL;
3644 
3645     r->request_line.len = 0;
3646 
3647     r->connection->destroyed = 1;
3648 
3649     /*
3650      * Setting r->pool to NULL will increase probability to catch double close
3651      * of request since the request object is allocated from its own pool.
3652      */
3653 
3654     pool = r->pool;
3655     r->pool = NULL;
3656 
3657     ngx_destroy_pool(pool);
3658 }
3659 
3660 
3661 static void
3662 ngx_http_log_request(ngx_http_request_t *r)
3663 {
3664     ngx_uint_t                  i, n;
3665     ngx_http_handler_pt        *log_handler;
3666     ngx_http_core_main_conf_t  *cmcf;
3667 
3668     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3669 
3670     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3671     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3672 
3673     for (i = 0; i < n; i++) {
3674         log_handler[i](r);
3675     }
3676 }
3677 
3678 
3679 void
3680 ngx_http_close_connection(ngx_connection_t *c)
3681 {
3682     ngx_pool_t  *pool;
3683 
3684     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3685                    "close http connection: %d", c->fd);
3686 
3687 #if (NGX_HTTP_SSL)
3688 
3689     if (c->ssl) {
3690         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3691             c->ssl->handler = ngx_http_close_connection;
3692             return;
3693         }
3694     }
3695 
3696 #endif
3697 
3698 #if (NGX_STAT_STUB)
3699     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3700 #endif
3701 
3702     c->destroyed = 1;
3703 
3704     pool = c->pool;
3705 
3706     ngx_close_connection(c);
3707 
3708     ngx_destroy_pool(pool);
3709 }
3710 
3711 
3712 static u_char *
3713 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3714 {
3715     u_char              *p;
3716     ngx_http_request_t  *r;
3717     ngx_http_log_ctx_t  *ctx;
3718 
3719     if (log->action) {
3720         p = ngx_snprintf(buf, len, " while %s", log->action);
3721         len -= p - buf;
3722         buf = p;
3723     }
3724 
3725     ctx = log->data;
3726 
3727     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3728     len -= p - buf;
3729 
3730     r = ctx->request;
3731 
3732     if (r) {
3733         return r->log_handler(r, ctx->current_request, p, len);
3734 
3735     } else {
3736         p = ngx_snprintf(p, len, ", server: %V",
3737                          &ctx->connection->listening->addr_text);
3738     }
3739 
3740     return p;
3741 }
3742 
3743 
3744 static u_char *
3745 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3746     u_char *buf, size_t len)
3747 {
3748     char                      *uri_separator;
3749     u_char                    *p;
3750     ngx_http_upstream_t       *u;
3751     ngx_http_core_srv_conf_t  *cscf;
3752 
3753     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3754 
3755     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3756     len -= p - buf;
3757     buf = p;
3758 
3759     if (r->request_line.data == NULL && r->request_start) {
3760         for (p = r->request_start; p < r->header_in->last; p++) {
3761             if (*p == CR || *p == LF) {
3762                 break;
3763             }
3764         }
3765 
3766         r->request_line.len = p - r->request_start;
3767         r->request_line.data = r->request_start;
3768     }
3769 
3770     if (r->request_line.len) {
3771         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3772         len -= p - buf;
3773         buf = p;
3774     }
3775 
3776     if (r != sr) {
3777         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3778         len -= p - buf;
3779         buf = p;
3780     }
3781 
3782     u = sr->upstream;
3783 
3784     if (u && u->peer.name) {
3785 
3786         uri_separator = "";
3787 
3788 #if (NGX_HAVE_UNIX_DOMAIN)
3789         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3790             uri_separator = ":";
3791         }
3792 #endif
3793 
3794         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3795                          &u->schema, u->peer.name,
3796                          uri_separator, &u->uri);
3797         len -= p - buf;
3798         buf = p;
3799     }
3800 
3801     if (r->headers_in.host) {
3802         p = ngx_snprintf(buf, len, ", host: \"%V\"",
3803                          &r->headers_in.host->value);
3804         len -= p - buf;
3805         buf = p;
3806     }
3807 
3808     if (r->headers_in.referer) {
3809         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3810                          &r->headers_in.referer->value);
3811         buf = p;
3812     }
3813 
3814     return buf;
3815 }