Back to home page

Nginx displayed by LXR

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