xref: /nginx/src/http/ngx_http_request.c (revision 7941:65946a191197)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 static void ngx_http_wait_request_handler(ngx_event_t *ev);
14 static ngx_http_request_t *ngx_http_alloc_request(ngx_connection_t *c);
15 static void ngx_http_process_request_line(ngx_event_t *rev);
16 static void ngx_http_process_request_headers(ngx_event_t *rev);
17 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
18 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
19     ngx_uint_t request_line);
20 
21 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
22     ngx_table_elt_t *h, ngx_uint_t offset);
23 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
24     ngx_table_elt_t *h, ngx_uint_t offset);
25 static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
26     ngx_table_elt_t *h, ngx_uint_t offset);
27 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
28     ngx_table_elt_t *h, ngx_uint_t offset);
29 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
30     ngx_table_elt_t *h, ngx_uint_t offset);
31 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
32     ngx_table_elt_t *h, ngx_uint_t offset);
33 
34 static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
35     ngx_uint_t alloc);
36 static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
37     ngx_str_t *host);
38 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
39     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
40     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
41 
42 static void ngx_http_request_handler(ngx_event_t *ev);
43 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
44 static void ngx_http_terminate_handler(ngx_http_request_t *r);
45 static void ngx_http_finalize_connection(ngx_http_request_t *r);
46 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
47 static void ngx_http_writer(ngx_http_request_t *r);
48 static void ngx_http_request_finalizer(ngx_http_request_t *r);
49 
50 static void ngx_http_set_keepalive(ngx_http_request_t *r);
51 static void ngx_http_keepalive_handler(ngx_event_t *ev);
52 static void ngx_http_set_lingering_close(ngx_connection_t *c);
53 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
54 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
55 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
56 static void ngx_http_log_request(ngx_http_request_t *r);
57 
58 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
59 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
60     ngx_http_request_t *sr, u_char *buf, size_t len);
61 
62 #if (NGX_HTTP_SSL)
63 static void ngx_http_ssl_handshake(ngx_event_t *rev);
64 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
65 #endif
66 
67 
68 static char *ngx_http_client_errors[] = {
69 
70     /* NGX_HTTP_PARSE_INVALID_METHOD */
71     "client sent invalid method",
72 
73     /* NGX_HTTP_PARSE_INVALID_REQUEST */
74     "client sent invalid request",
75 
76     /* NGX_HTTP_PARSE_INVALID_VERSION */
77     "client sent invalid version",
78 
79     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
80     "client sent invalid method in HTTP/0.9 request"
81 };
82 
83 
84 ngx_http_header_t  ngx_http_headers_in[] = {
85     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
86                  ngx_http_process_host },
87 
88     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
89                  ngx_http_process_connection },
90 
91     { ngx_string("If-Modified-Since"),
92                  offsetof(ngx_http_headers_in_t, if_modified_since),
93                  ngx_http_process_unique_header_line },
94 
95     { ngx_string("If-Unmodified-Since"),
96                  offsetof(ngx_http_headers_in_t, if_unmodified_since),
97                  ngx_http_process_unique_header_line },
98 
99     { ngx_string("If-Match"),
100                  offsetof(ngx_http_headers_in_t, if_match),
101                  ngx_http_process_unique_header_line },
102 
103     { ngx_string("If-None-Match"),
104                  offsetof(ngx_http_headers_in_t, if_none_match),
105                  ngx_http_process_unique_header_line },
106 
107     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
108                  ngx_http_process_user_agent },
109 
110     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
111                  ngx_http_process_header_line },
112 
113     { ngx_string("Content-Length"),
114                  offsetof(ngx_http_headers_in_t, content_length),
115                  ngx_http_process_unique_header_line },
116 
117     { ngx_string("Content-Range"),
118                  offsetof(ngx_http_headers_in_t, content_range),
119                  ngx_http_process_unique_header_line },
120 
121     { ngx_string("Content-Type"),
122                  offsetof(ngx_http_headers_in_t, content_type),
123                  ngx_http_process_header_line },
124 
125     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
126                  ngx_http_process_header_line },
127 
128     { ngx_string("If-Range"),
129                  offsetof(ngx_http_headers_in_t, if_range),
130                  ngx_http_process_unique_header_line },
131 
132     { ngx_string("Transfer-Encoding"),
133                  offsetof(ngx_http_headers_in_t, transfer_encoding),
134                  ngx_http_process_unique_header_line },
135 
136     { ngx_string("TE"),
137                  offsetof(ngx_http_headers_in_t, te),
138                  ngx_http_process_header_line },
139 
140     { ngx_string("Expect"),
141                  offsetof(ngx_http_headers_in_t, expect),
142                  ngx_http_process_unique_header_line },
143 
144     { ngx_string("Upgrade"),
145                  offsetof(ngx_http_headers_in_t, upgrade),
146                  ngx_http_process_header_line },
147 
148 #if (NGX_HTTP_GZIP || NGX_HTTP_HEADERS)
149     { ngx_string("Accept-Encoding"),
150                  offsetof(ngx_http_headers_in_t, accept_encoding),
151                  ngx_http_process_header_line },
152 
153     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
154                  ngx_http_process_header_line },
155 #endif
156 
157     { ngx_string("Authorization"),
158                  offsetof(ngx_http_headers_in_t, authorization),
159                  ngx_http_process_unique_header_line },
160 
161     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
162                  ngx_http_process_header_line },
163 
164 #if (NGX_HTTP_X_FORWARDED_FOR)
165     { ngx_string("X-Forwarded-For"),
166                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
167                  ngx_http_process_multi_header_lines },
168 #endif
169 
170 #if (NGX_HTTP_REALIP)
171     { ngx_string("X-Real-IP"),
172                  offsetof(ngx_http_headers_in_t, x_real_ip),
173                  ngx_http_process_header_line },
174 #endif
175 
176 #if (NGX_HTTP_HEADERS)
177     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
178                  ngx_http_process_header_line },
179 
180     { ngx_string("Accept-Language"),
181                  offsetof(ngx_http_headers_in_t, accept_language),
182                  ngx_http_process_header_line },
183 #endif
184 
185 #if (NGX_HTTP_DAV)
186     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
187                  ngx_http_process_header_line },
188 
189     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
190                  ngx_http_process_header_line },
191 
192     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
193                  ngx_http_process_header_line },
194 
195     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
196                  ngx_http_process_header_line },
197 #endif
198 
199     { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
200                  ngx_http_process_multi_header_lines },
201 
202     { ngx_null_string, 0, NULL }
203 };
204 
205 
206 void
207 ngx_http_init_connection(ngx_connection_t *c)
208 {
209     ngx_uint_t                 i;
210     ngx_event_t               *rev;
211     struct sockaddr_in        *sin;
212     ngx_http_port_t           *port;
213     ngx_http_in_addr_t        *addr;
214     ngx_http_log_ctx_t        *ctx;
215     ngx_http_connection_t     *hc;
216     ngx_http_core_srv_conf_t  *cscf;
217 #if (NGX_HAVE_INET6)
218     struct sockaddr_in6       *sin6;
219     ngx_http_in6_addr_t       *addr6;
220 #endif
221 
222     hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
223     if (hc == NULL) {
224         ngx_http_close_connection(c);
225         return;
226     }
227 
228     c->data = hc;
229 
230     /* find the server configuration for the address:port */
231 
232     port = c->listening->servers;
233 
234     if (port->naddrs > 1) {
235 
236         /*
237          * there are several addresses on this port and one of them
238          * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
239          * is required to determine a server address
240          */
241 
242         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
243             ngx_http_close_connection(c);
244             return;
245         }
246 
247         switch (c->local_sockaddr->sa_family) {
248 
249 #if (NGX_HAVE_INET6)
250         case AF_INET6:
251             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
252 
253             addr6 = port->addrs;
254 
255             /* the last address is "*" */
256 
257             for (i = 0; i < port->naddrs - 1; i++) {
258                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
259                     break;
260                 }
261             }
262 
263             hc->addr_conf = &addr6[i].conf;
264 
265             break;
266 #endif
267 
268         default: /* AF_INET */
269             sin = (struct sockaddr_in *) c->local_sockaddr;
270 
271             addr = port->addrs;
272 
273             /* the last address is "*" */
274 
275             for (i = 0; i < port->naddrs - 1; i++) {
276                 if (addr[i].addr == sin->sin_addr.s_addr) {
277                     break;
278                 }
279             }
280 
281             hc->addr_conf = &addr[i].conf;
282 
283             break;
284         }
285 
286     } else {
287 
288         switch (c->local_sockaddr->sa_family) {
289 
290 #if (NGX_HAVE_INET6)
291         case AF_INET6:
292             addr6 = port->addrs;
293             hc->addr_conf = &addr6[0].conf;
294             break;
295 #endif
296 
297         default: /* AF_INET */
298             addr = port->addrs;
299             hc->addr_conf = &addr[0].conf;
300             break;
301         }
302     }
303 
304     /* the default server configuration for the address:port */
305     hc->conf_ctx = hc->addr_conf->default_server->ctx;
306 
307     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
308     if (ctx == NULL) {
309         ngx_http_close_connection(c);
310         return;
311     }
312 
313     ctx->connection = c;
314     ctx->request = NULL;
315     ctx->current_request = NULL;
316 
317     c->log->connection = c->number;
318     c->log->handler = ngx_http_log_error;
319     c->log->data = ctx;
320     c->log->action = "waiting for request";
321 
322     c->log_error = NGX_ERROR_INFO;
323 
324     rev = c->read;
325     rev->handler = ngx_http_wait_request_handler;
326     c->write->handler = ngx_http_empty_handler;
327 
328 #if (NGX_HTTP_V2)
329     if (hc->addr_conf->http2) {
330         rev->handler = ngx_http_v2_init;
331     }
332 #endif
333 
334 #if (NGX_HTTP_SSL)
335     {
336     ngx_http_ssl_srv_conf_t  *sscf;
337 
338     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
339 
340     if (sscf->enable || hc->addr_conf->ssl) {
341         hc->ssl = 1;
342         c->log->action = "SSL handshaking";
343         rev->handler = ngx_http_ssl_handshake;
344     }
345     }
346 #endif
347 
348     if (hc->addr_conf->proxy_protocol) {
349         hc->proxy_protocol = 1;
350         c->log->action = "reading PROXY protocol";
351     }
352 
353     if (rev->ready) {
354         /* the deferred accept(), iocp */
355 
356         if (ngx_use_accept_mutex) {
357             ngx_post_event(rev, &ngx_posted_events);
358             return;
359         }
360 
361         rev->handler(rev);
362         return;
363     }
364 
365     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
366 
367     ngx_add_timer(rev, cscf->client_header_timeout);
368     ngx_reusable_connection(c, 1);
369 
370     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
371         ngx_http_close_connection(c);
372         return;
373     }
374 }
375 
376 
377 static void
378 ngx_http_wait_request_handler(ngx_event_t *rev)
379 {
380     u_char                    *p;
381     size_t                     size;
382     ssize_t                    n;
383     ngx_buf_t                 *b;
384     ngx_connection_t          *c;
385     ngx_http_connection_t     *hc;
386     ngx_http_core_srv_conf_t  *cscf;
387 
388     c = rev->data;
389 
390     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
391 
392     if (rev->timedout) {
393         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
394         ngx_http_close_connection(c);
395         return;
396     }
397 
398     if (c->close) {
399         ngx_http_close_connection(c);
400         return;
401     }
402 
403     hc = c->data;
404     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
405 
406     size = cscf->client_header_buffer_size;
407 
408     b = c->buffer;
409 
410     if (b == NULL) {
411         b = ngx_create_temp_buf(c->pool, size);
412         if (b == NULL) {
413             ngx_http_close_connection(c);
414             return;
415         }
416 
417         c->buffer = b;
418 
419     } else if (b->start == NULL) {
420 
421         b->start = ngx_palloc(c->pool, size);
422         if (b->start == NULL) {
423             ngx_http_close_connection(c);
424             return;
425         }
426 
427         b->pos = b->start;
428         b->last = b->start;
429         b->end = b->last + size;
430     }
431 
432     n = c->recv(c, b->last, size);
433 
434     if (n == NGX_AGAIN) {
435 
436         if (!rev->timer_set) {
437             ngx_add_timer(rev, cscf->client_header_timeout);
438             ngx_reusable_connection(c, 1);
439         }
440 
441         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
442             ngx_http_close_connection(c);
443             return;
444         }
445 
446         /*
447          * We are trying to not hold c->buffer's memory for an idle connection.
448          */
449 
450         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
451             b->start = NULL;
452         }
453 
454         return;
455     }
456 
457     if (n == NGX_ERROR) {
458         ngx_http_close_connection(c);
459         return;
460     }
461 
462     if (n == 0) {
463         ngx_log_error(NGX_LOG_INFO, c->log, 0,
464                       "client closed connection");
465         ngx_http_close_connection(c);
466         return;
467     }
468 
469     b->last += n;
470 
471     if (hc->proxy_protocol) {
472         hc->proxy_protocol = 0;
473 
474         p = ngx_proxy_protocol_read(c, b->pos, b->last);
475 
476         if (p == NULL) {
477             ngx_http_close_connection(c);
478             return;
479         }
480 
481         b->pos = p;
482 
483         if (b->pos == b->last) {
484             c->log->action = "waiting for request";
485             b->pos = b->start;
486             b->last = b->start;
487             ngx_post_event(rev, &ngx_posted_events);
488             return;
489         }
490     }
491 
492     c->log->action = "reading client request line";
493 
494     ngx_reusable_connection(c, 0);
495 
496     c->data = ngx_http_create_request(c);
497     if (c->data == NULL) {
498         ngx_http_close_connection(c);
499         return;
500     }
501 
502     rev->handler = ngx_http_process_request_line;
503     ngx_http_process_request_line(rev);
504 }
505 
506 
507 ngx_http_request_t *
508 ngx_http_create_request(ngx_connection_t *c)
509 {
510     ngx_http_request_t        *r;
511     ngx_http_log_ctx_t        *ctx;
512     ngx_http_core_loc_conf_t  *clcf;
513 
514     r = ngx_http_alloc_request(c);
515     if (r == NULL) {
516         return NULL;
517     }
518 
519     c->requests++;
520 
521     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
522 
523     ngx_set_connection_log(c, clcf->error_log);
524 
525     ctx = c->log->data;
526     ctx->request = r;
527     ctx->current_request = r;
528 
529 #if (NGX_STAT_STUB)
530     (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
531     r->stat_reading = 1;
532     (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
533 #endif
534 
535     return r;
536 }
537 
538 
539 static ngx_http_request_t *
540 ngx_http_alloc_request(ngx_connection_t *c)
541 {
542     ngx_pool_t                 *pool;
543     ngx_time_t                 *tp;
544     ngx_http_request_t         *r;
545     ngx_http_connection_t      *hc;
546     ngx_http_core_srv_conf_t   *cscf;
547     ngx_http_core_main_conf_t  *cmcf;
548 
549     hc = c->data;
550 
551     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
552 
553     pool = ngx_create_pool(cscf->request_pool_size, c->log);
554     if (pool == NULL) {
555         return NULL;
556     }
557 
558     r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
559     if (r == NULL) {
560         ngx_destroy_pool(pool);
561         return NULL;
562     }
563 
564     r->pool = pool;
565 
566     r->http_connection = hc;
567     r->signature = NGX_HTTP_MODULE;
568     r->connection = c;
569 
570     r->main_conf = hc->conf_ctx->main_conf;
571     r->srv_conf = hc->conf_ctx->srv_conf;
572     r->loc_conf = hc->conf_ctx->loc_conf;
573 
574     r->read_event_handler = ngx_http_block_reading;
575 
576     r->header_in = hc->busy ? hc->busy->buf : c->buffer;
577 
578     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
579                       sizeof(ngx_table_elt_t))
580         != NGX_OK)
581     {
582         ngx_destroy_pool(r->pool);
583         return NULL;
584     }
585 
586     if (ngx_list_init(&r->headers_out.trailers, r->pool, 4,
587                       sizeof(ngx_table_elt_t))
588         != NGX_OK)
589     {
590         ngx_destroy_pool(r->pool);
591         return NULL;
592     }
593 
594     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
595     if (r->ctx == NULL) {
596         ngx_destroy_pool(r->pool);
597         return NULL;
598     }
599 
600     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
601 
602     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
603                                         * sizeof(ngx_http_variable_value_t));
604     if (r->variables == NULL) {
605         ngx_destroy_pool(r->pool);
606         return NULL;
607     }
608 
609 #if (NGX_HTTP_SSL)
610     if (c->ssl && !c->ssl->sendfile) {
611         r->main_filter_need_in_memory = 1;
612     }
613 #endif
614 
615     r->main = r;
616     r->count = 1;
617 
618     tp = ngx_timeofday();
619     r->start_sec = tp->sec;
620     r->start_msec = tp->msec;
621 
622     r->method = NGX_HTTP_UNKNOWN;
623     r->http_version = NGX_HTTP_VERSION_10;
624 
625     r->headers_in.content_length_n = -1;
626     r->headers_in.keep_alive_n = -1;
627     r->headers_out.content_length_n = -1;
628     r->headers_out.last_modified_time = -1;
629 
630     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
631     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
632 
633     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
634 
635     r->log_handler = ngx_http_log_error_handler;
636 
637     return r;
638 }
639 
640 
641 #if (NGX_HTTP_SSL)
642 
643 static void
644 ngx_http_ssl_handshake(ngx_event_t *rev)
645 {
646     u_char                    *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
647     size_t                     size;
648     ssize_t                    n;
649     ngx_err_t                  err;
650     ngx_int_t                  rc;
651     ngx_connection_t          *c;
652     ngx_http_connection_t     *hc;
653     ngx_http_ssl_srv_conf_t   *sscf;
654     ngx_http_core_loc_conf_t  *clcf;
655     ngx_http_core_srv_conf_t  *cscf;
656 
657     c = rev->data;
658     hc = c->data;
659 
660     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
661                    "http check ssl handshake");
662 
663     if (rev->timedout) {
664         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
665         ngx_http_close_connection(c);
666         return;
667     }
668 
669     if (c->close) {
670         ngx_http_close_connection(c);
671         return;
672     }
673 
674     size = hc->proxy_protocol ? sizeof(buf) : 1;
675 
676     n = recv(c->fd, (char *) buf, size, MSG_PEEK);
677 
678     err = ngx_socket_errno;
679 
680     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %z", n);
681 
682     if (n == -1) {
683         if (err == NGX_EAGAIN) {
684             rev->ready = 0;
685 
686             if (!rev->timer_set) {
687                 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
688                                                     ngx_http_core_module);
689                 ngx_add_timer(rev, cscf->client_header_timeout);
690                 ngx_reusable_connection(c, 1);
691             }
692 
693             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
694                 ngx_http_close_connection(c);
695             }
696 
697             return;
698         }
699 
700         ngx_connection_error(c, err, "recv() failed");
701         ngx_http_close_connection(c);
702 
703         return;
704     }
705 
706     if (hc->proxy_protocol) {
707         hc->proxy_protocol = 0;
708 
709         p = ngx_proxy_protocol_read(c, buf, buf + n);
710 
711         if (p == NULL) {
712             ngx_http_close_connection(c);
713             return;
714         }
715 
716         size = p - buf;
717 
718         if (c->recv(c, buf, size) != (ssize_t) size) {
719             ngx_http_close_connection(c);
720             return;
721         }
722 
723         c->log->action = "SSL handshaking";
724 
725         if (n == (ssize_t) size) {
726             ngx_post_event(rev, &ngx_posted_events);
727             return;
728         }
729 
730         n = 1;
731         buf[0] = *p;
732     }
733 
734     if (n == 1) {
735         if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
736             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
737                            "https ssl handshake: 0x%02Xd", buf[0]);
738 
739             clcf = ngx_http_get_module_loc_conf(hc->conf_ctx,
740                                                 ngx_http_core_module);
741 
742             if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
743                 ngx_http_close_connection(c);
744                 return;
745             }
746 
747             sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
748                                                 ngx_http_ssl_module);
749 
750             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
751                 != NGX_OK)
752             {
753                 ngx_http_close_connection(c);
754                 return;
755             }
756 
757             ngx_reusable_connection(c, 0);
758 
759             rc = ngx_ssl_handshake(c);
760 
761             if (rc == NGX_AGAIN) {
762 
763                 if (!rev->timer_set) {
764                     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
765                                                         ngx_http_core_module);
766                     ngx_add_timer(rev, cscf->client_header_timeout);
767                 }
768 
769                 c->ssl->handler = ngx_http_ssl_handshake_handler;
770                 return;
771             }
772 
773             ngx_http_ssl_handshake_handler(c);
774 
775             return;
776         }
777 
778         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
779 
780         c->log->action = "waiting for request";
781 
782         rev->handler = ngx_http_wait_request_handler;
783         ngx_http_wait_request_handler(rev);
784 
785         return;
786     }
787 
788     ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
789     ngx_http_close_connection(c);
790 }
791 
792 
793 static void
794 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
795 {
796     if (c->ssl->handshaked) {
797 
798         /*
799          * The majority of browsers do not send the "close notify" alert.
800          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
801          * and Links.  And what is more, MSIE ignores the server's alert.
802          *
803          * Opera and recent Mozilla send the alert.
804          */
805 
806         c->ssl->no_wait_shutdown = 1;
807 
808 #if (NGX_HTTP_V2                                                              \
809      && defined TLSEXT_TYPE_application_layer_protocol_negotiation)
810         {
811         unsigned int            len;
812         const unsigned char    *data;
813         ngx_http_connection_t  *hc;
814 
815         hc = c->data;
816 
817         if (hc->addr_conf->http2) {
818 
819             SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
820 
821             if (len == 2 && data[0] == 'h' && data[1] == '2') {
822                 ngx_http_v2_init(c->read);
823                 return;
824             }
825         }
826         }
827 #endif
828 
829         c->log->action = "waiting for request";
830 
831         c->read->handler = ngx_http_wait_request_handler;
832         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
833 
834         ngx_reusable_connection(c, 1);
835 
836         ngx_http_wait_request_handler(c->read);
837 
838         return;
839     }
840 
841     if (c->read->timedout) {
842         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
843     }
844 
845     ngx_http_close_connection(c);
846 }
847 
848 
849 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
850 
851 int
852 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
853 {
854     ngx_int_t                  rc;
855     ngx_str_t                  host;
856     const char                *servername;
857     ngx_connection_t          *c;
858     ngx_http_connection_t     *hc;
859     ngx_http_ssl_srv_conf_t   *sscf;
860     ngx_http_core_loc_conf_t  *clcf;
861     ngx_http_core_srv_conf_t  *cscf;
862 
863     c = ngx_ssl_get_connection(ssl_conn);
864 
865     if (c->ssl->handshaked) {
866         *ad = SSL_AD_NO_RENEGOTIATION;
867         return SSL_TLSEXT_ERR_ALERT_FATAL;
868     }
869 
870     hc = c->data;
871 
872     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
873 
874     if (servername == NULL) {
875         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
876                        "SSL server name: null");
877         goto done;
878     }
879 
880     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
881                    "SSL server name: \"%s\"", servername);
882 
883     host.len = ngx_strlen(servername);
884 
885     if (host.len == 0) {
886         goto done;
887     }
888 
889     host.data = (u_char *) servername;
890 
891     rc = ngx_http_validate_host(&host, c->pool, 1);
892 
893     if (rc == NGX_ERROR) {
894         goto error;
895     }
896 
897     if (rc == NGX_DECLINED) {
898         goto done;
899     }
900 
901     rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
902                                       NULL, &cscf);
903 
904     if (rc == NGX_ERROR) {
905         goto error;
906     }
907 
908     if (rc == NGX_DECLINED) {
909         goto done;
910     }
911 
912     hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
913     if (hc->ssl_servername == NULL) {
914         goto error;
915     }
916 
917     *hc->ssl_servername = host;
918 
919     hc->conf_ctx = cscf->ctx;
920 
921     clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
922 
923     ngx_set_connection_log(c, clcf->error_log);
924 
925     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
926 
927     c->ssl->buffer_size = sscf->buffer_size;
928 
929     if (sscf->ssl.ctx) {
930         if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
931             goto error;
932         }
933 
934         /*
935          * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
936          * adjust other things we care about
937          */
938 
939         SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
940                        SSL_CTX_get_verify_callback(sscf->ssl.ctx));
941 
942         SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
943 
944 #if OPENSSL_VERSION_NUMBER >= 0x009080dfL
945         /* only in 0.9.8m+ */
946         SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
947                                     ~SSL_CTX_get_options(sscf->ssl.ctx));
948 #endif
949 
950         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
951 
952 #ifdef SSL_OP_NO_RENEGOTIATION
953         SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION);
954 #endif
955     }
956 
957 done:
958 
959     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
960 
961     if (sscf->reject_handshake) {
962         c->ssl->handshake_rejected = 1;
963         *ad = SSL_AD_UNRECOGNIZED_NAME;
964         return SSL_TLSEXT_ERR_ALERT_FATAL;
965     }
966 
967     return SSL_TLSEXT_ERR_OK;
968 
969 error:
970 
971     *ad = SSL_AD_INTERNAL_ERROR;
972     return SSL_TLSEXT_ERR_ALERT_FATAL;
973 }
974 
975 #endif
976 
977 
978 #ifdef SSL_R_CERT_CB_ERROR
979 
980 int
981 ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
982 {
983     ngx_str_t                  cert, key;
984     ngx_uint_t                 i, nelts;
985     ngx_connection_t          *c;
986     ngx_http_request_t        *r;
987     ngx_http_ssl_srv_conf_t   *sscf;
988     ngx_http_complex_value_t  *certs, *keys;
989 
990     c = ngx_ssl_get_connection(ssl_conn);
991 
992     if (c->ssl->handshaked) {
993         return 0;
994     }
995 
996     r = ngx_http_alloc_request(c);
997     if (r == NULL) {
998         return 0;
999     }
1000 
1001     r->logged = 1;
1002 
1003     sscf = arg;
1004 
1005     nelts = sscf->certificate_values->nelts;
1006     certs = sscf->certificate_values->elts;
1007     keys = sscf->certificate_key_values->elts;
1008 
1009     for (i = 0; i < nelts; i++) {
1010 
1011         if (ngx_http_complex_value(r, &certs[i], &cert) != NGX_OK) {
1012             goto failed;
1013         }
1014 
1015         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1016                        "ssl cert: \"%s\"", cert.data);
1017 
1018         if (ngx_http_complex_value(r, &keys[i], &key) != NGX_OK) {
1019             goto failed;
1020         }
1021 
1022         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1023                        "ssl key: \"%s\"", key.data);
1024 
1025         if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key,
1026                                            sscf->passwords)
1027             != NGX_OK)
1028         {
1029             goto failed;
1030         }
1031     }
1032 
1033     ngx_http_free_request(r, 0);
1034     c->log->action = "SSL handshaking";
1035     c->destroyed = 0;
1036     return 1;
1037 
1038 failed:
1039 
1040     ngx_http_free_request(r, 0);
1041     c->log->action = "SSL handshaking";
1042     c->destroyed = 0;
1043     return 0;
1044 }
1045 
1046 #endif
1047 
1048 #endif
1049 
1050 
1051 static void
1052 ngx_http_process_request_line(ngx_event_t *rev)
1053 {
1054     ssize_t              n;
1055     ngx_int_t            rc, rv;
1056     ngx_str_t            host;
1057     ngx_connection_t    *c;
1058     ngx_http_request_t  *r;
1059 
1060     c = rev->data;
1061     r = c->data;
1062 
1063     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1064                    "http process request line");
1065 
1066     if (rev->timedout) {
1067         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1068         c->timedout = 1;
1069         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1070         return;
1071     }
1072 
1073     rc = NGX_AGAIN;
1074 
1075     for ( ;; ) {
1076 
1077         if (rc == NGX_AGAIN) {
1078             n = ngx_http_read_request_header(r);
1079 
1080             if (n == NGX_AGAIN || n == NGX_ERROR) {
1081                 break;
1082             }
1083         }
1084 
1085         rc = ngx_http_parse_request_line(r, r->header_in);
1086 
1087         if (rc == NGX_OK) {
1088 
1089             /* the request line has been parsed successfully */
1090 
1091             r->request_line.len = r->request_end - r->request_start;
1092             r->request_line.data = r->request_start;
1093             r->request_length = r->header_in->pos - r->request_start;
1094 
1095             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1096                            "http request line: \"%V\"", &r->request_line);
1097 
1098             r->method_name.len = r->method_end - r->request_start + 1;
1099             r->method_name.data = r->request_line.data;
1100 
1101             if (r->http_protocol.data) {
1102                 r->http_protocol.len = r->request_end - r->http_protocol.data;
1103             }
1104 
1105             if (ngx_http_process_request_uri(r) != NGX_OK) {
1106                 break;
1107             }
1108 
1109             if (r->schema_end) {
1110                 r->schema.len = r->schema_end - r->schema_start;
1111                 r->schema.data = r->schema_start;
1112             }
1113 
1114             if (r->host_end) {
1115 
1116                 host.len = r->host_end - r->host_start;
1117                 host.data = r->host_start;
1118 
1119                 rc = ngx_http_validate_host(&host, r->pool, 0);
1120 
1121                 if (rc == NGX_DECLINED) {
1122                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1123                                   "client sent invalid host in request line");
1124                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1125                     break;
1126                 }
1127 
1128                 if (rc == NGX_ERROR) {
1129                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1130                     break;
1131                 }
1132 
1133                 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1134                     break;
1135                 }
1136 
1137                 r->headers_in.server = host;
1138             }
1139 
1140             if (r->http_version < NGX_HTTP_VERSION_10) {
1141 
1142                 if (r->headers_in.server.len == 0
1143                     && ngx_http_set_virtual_server(r, &r->headers_in.server)
1144                        == NGX_ERROR)
1145                 {
1146                     break;
1147                 }
1148 
1149                 ngx_http_process_request(r);
1150                 break;
1151             }
1152 
1153 
1154             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
1155                               sizeof(ngx_table_elt_t))
1156                 != NGX_OK)
1157             {
1158                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1159                 break;
1160             }
1161 
1162             c->log->action = "reading client request headers";
1163 
1164             rev->handler = ngx_http_process_request_headers;
1165             ngx_http_process_request_headers(rev);
1166 
1167             break;
1168         }
1169 
1170         if (rc != NGX_AGAIN) {
1171 
1172             /* there was error while a request line parsing */
1173 
1174             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1175                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
1176 
1177             if (rc == NGX_HTTP_PARSE_INVALID_VERSION) {
1178                 ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED);
1179 
1180             } else {
1181                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1182             }
1183 
1184             break;
1185         }
1186 
1187         /* NGX_AGAIN: a request line parsing is still incomplete */
1188 
1189         if (r->header_in->pos == r->header_in->end) {
1190 
1191             rv = ngx_http_alloc_large_header_buffer(r, 1);
1192 
1193             if (rv == NGX_ERROR) {
1194                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1195                 break;
1196             }
1197 
1198             if (rv == NGX_DECLINED) {
1199                 r->request_line.len = r->header_in->end - r->request_start;
1200                 r->request_line.data = r->request_start;
1201 
1202                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1203                               "client sent too long URI");
1204                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
1205                 break;
1206             }
1207         }
1208     }
1209 
1210     ngx_http_run_posted_requests(c);
1211 }
1212 
1213 
1214 ngx_int_t
1215 ngx_http_process_request_uri(ngx_http_request_t *r)
1216 {
1217     ngx_http_core_srv_conf_t  *cscf;
1218 
1219     if (r->args_start) {
1220         r->uri.len = r->args_start - 1 - r->uri_start;
1221     } else {
1222         r->uri.len = r->uri_end - r->uri_start;
1223     }
1224 
1225     if (r->complex_uri || r->quoted_uri || r->empty_path_in_uri) {
1226 
1227         if (r->empty_path_in_uri) {
1228             r->uri.len++;
1229         }
1230 
1231         r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1232         if (r->uri.data == NULL) {
1233             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1234             return NGX_ERROR;
1235         }
1236 
1237         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1238 
1239         if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1240             r->uri.len = 0;
1241 
1242             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1243                           "client sent invalid request");
1244             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1245             return NGX_ERROR;
1246         }
1247 
1248     } else {
1249         r->uri.data = r->uri_start;
1250     }
1251 
1252     r->unparsed_uri.len = r->uri_end - r->uri_start;
1253     r->unparsed_uri.data = r->uri_start;
1254 
1255     r->valid_unparsed_uri = r->empty_path_in_uri ? 0 : 1;
1256 
1257     if (r->uri_ext) {
1258         if (r->args_start) {
1259             r->exten.len = r->args_start - 1 - r->uri_ext;
1260         } else {
1261             r->exten.len = r->uri_end - r->uri_ext;
1262         }
1263 
1264         r->exten.data = r->uri_ext;
1265     }
1266 
1267     if (r->args_start && r->uri_end > r->args_start) {
1268         r->args.len = r->uri_end - r->args_start;
1269         r->args.data = r->args_start;
1270     }
1271 
1272 #if (NGX_WIN32)
1273     {
1274     u_char  *p, *last;
1275 
1276     p = r->uri.data;
1277     last = r->uri.data + r->uri.len;
1278 
1279     while (p < last) {
1280 
1281         if (*p++ == ':') {
1282 
1283             /*
1284              * this check covers "::$data", "::$index_allocation" and
1285              * ":$i30:$index_allocation"
1286              */
1287 
1288             if (p < last && *p == '$') {
1289                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1290                               "client sent unsafe win32 URI");
1291                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1292                 return NGX_ERROR;
1293             }
1294         }
1295     }
1296 
1297     p = r->uri.data + r->uri.len - 1;
1298 
1299     while (p > r->uri.data) {
1300 
1301         if (*p == ' ') {
1302             p--;
1303             continue;
1304         }
1305 
1306         if (*p == '.') {
1307             p--;
1308             continue;
1309         }
1310 
1311         break;
1312     }
1313 
1314     if (p != r->uri.data + r->uri.len - 1) {
1315         r->uri.len = p + 1 - r->uri.data;
1316         ngx_http_set_exten(r);
1317     }
1318 
1319     }
1320 #endif
1321 
1322     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1323                    "http uri: \"%V\"", &r->uri);
1324 
1325     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1326                    "http args: \"%V\"", &r->args);
1327 
1328     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1329                    "http exten: \"%V\"", &r->exten);
1330 
1331     return NGX_OK;
1332 }
1333 
1334 
1335 static void
1336 ngx_http_process_request_headers(ngx_event_t *rev)
1337 {
1338     u_char                     *p;
1339     size_t                      len;
1340     ssize_t                     n;
1341     ngx_int_t                   rc, rv;
1342     ngx_table_elt_t            *h;
1343     ngx_connection_t           *c;
1344     ngx_http_header_t          *hh;
1345     ngx_http_request_t         *r;
1346     ngx_http_core_srv_conf_t   *cscf;
1347     ngx_http_core_main_conf_t  *cmcf;
1348 
1349     c = rev->data;
1350     r = c->data;
1351 
1352     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1353                    "http process request header line");
1354 
1355     if (rev->timedout) {
1356         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1357         c->timedout = 1;
1358         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1359         return;
1360     }
1361 
1362     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1363 
1364     rc = NGX_AGAIN;
1365 
1366     for ( ;; ) {
1367 
1368         if (rc == NGX_AGAIN) {
1369 
1370             if (r->header_in->pos == r->header_in->end) {
1371 
1372                 rv = ngx_http_alloc_large_header_buffer(r, 0);
1373 
1374                 if (rv == NGX_ERROR) {
1375                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1376                     break;
1377                 }
1378 
1379                 if (rv == NGX_DECLINED) {
1380                     p = r->header_name_start;
1381 
1382                     r->lingering_close = 1;
1383 
1384                     if (p == NULL) {
1385                         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1386                                       "client sent too large request");
1387                         ngx_http_finalize_request(r,
1388                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1389                         break;
1390                     }
1391 
1392                     len = r->header_in->end - p;
1393 
1394                     if (len > NGX_MAX_ERROR_STR - 300) {
1395                         len = NGX_MAX_ERROR_STR - 300;
1396                     }
1397 
1398                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1399                                 "client sent too long header line: \"%*s...\"",
1400                                 len, r->header_name_start);
1401 
1402                     ngx_http_finalize_request(r,
1403                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1404                     break;
1405                 }
1406             }
1407 
1408             n = ngx_http_read_request_header(r);
1409 
1410             if (n == NGX_AGAIN || n == NGX_ERROR) {
1411                 break;
1412             }
1413         }
1414 
1415         /* the host header could change the server configuration context */
1416         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1417 
1418         rc = ngx_http_parse_header_line(r, r->header_in,
1419                                         cscf->underscores_in_headers);
1420 
1421         if (rc == NGX_OK) {
1422 
1423             r->request_length += r->header_in->pos - r->header_name_start;
1424 
1425             if (r->invalid_header && cscf->ignore_invalid_headers) {
1426 
1427                 /* there was error while a header line parsing */
1428 
1429                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1430                               "client sent invalid header line: \"%*s\"",
1431                               r->header_end - r->header_name_start,
1432                               r->header_name_start);
1433                 continue;
1434             }
1435 
1436             /* a header line has been parsed successfully */
1437 
1438             h = ngx_list_push(&r->headers_in.headers);
1439             if (h == NULL) {
1440                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1441                 break;
1442             }
1443 
1444             h->hash = r->header_hash;
1445 
1446             h->key.len = r->header_name_end - r->header_name_start;
1447             h->key.data = r->header_name_start;
1448             h->key.data[h->key.len] = '\0';
1449 
1450             h->value.len = r->header_end - r->header_start;
1451             h->value.data = r->header_start;
1452             h->value.data[h->value.len] = '\0';
1453 
1454             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1455             if (h->lowcase_key == NULL) {
1456                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1457                 break;
1458             }
1459 
1460             if (h->key.len == r->lowcase_index) {
1461                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1462 
1463             } else {
1464                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1465             }
1466 
1467             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1468                                h->lowcase_key, h->key.len);
1469 
1470             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1471                 break;
1472             }
1473 
1474             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1475                            "http header: \"%V: %V\"",
1476                            &h->key, &h->value);
1477 
1478             continue;
1479         }
1480 
1481         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1482 
1483             /* a whole header has been parsed successfully */
1484 
1485             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1486                            "http header done");
1487 
1488             r->request_length += r->header_in->pos - r->header_name_start;
1489 
1490             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1491 
1492             rc = ngx_http_process_request_header(r);
1493 
1494             if (rc != NGX_OK) {
1495                 break;
1496             }
1497 
1498             ngx_http_process_request(r);
1499 
1500             break;
1501         }
1502 
1503         if (rc == NGX_AGAIN) {
1504 
1505             /* a header line parsing is still not complete */
1506 
1507             continue;
1508         }
1509 
1510         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
1511 
1512         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1513                       "client sent invalid header line: \"%*s\\x%02xd...\"",
1514                       r->header_end - r->header_name_start,
1515                       r->header_name_start, *r->header_end);
1516 
1517         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1518         break;
1519     }
1520 
1521     ngx_http_run_posted_requests(c);
1522 }
1523 
1524 
1525 static ssize_t
1526 ngx_http_read_request_header(ngx_http_request_t *r)
1527 {
1528     ssize_t                    n;
1529     ngx_event_t               *rev;
1530     ngx_connection_t          *c;
1531     ngx_http_core_srv_conf_t  *cscf;
1532 
1533     c = r->connection;
1534     rev = c->read;
1535 
1536     n = r->header_in->last - r->header_in->pos;
1537 
1538     if (n > 0) {
1539         return n;
1540     }
1541 
1542     if (rev->ready) {
1543         n = c->recv(c, r->header_in->last,
1544                     r->header_in->end - r->header_in->last);
1545     } else {
1546         n = NGX_AGAIN;
1547     }
1548 
1549     if (n == NGX_AGAIN) {
1550         if (!rev->timer_set) {
1551             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1552             ngx_add_timer(rev, cscf->client_header_timeout);
1553         }
1554 
1555         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1556             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1557             return NGX_ERROR;
1558         }
1559 
1560         return NGX_AGAIN;
1561     }
1562 
1563     if (n == 0) {
1564         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1565                       "client prematurely closed connection");
1566     }
1567 
1568     if (n == 0 || n == NGX_ERROR) {
1569         c->error = 1;
1570         c->log->action = "reading client request headers";
1571 
1572         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1573         return NGX_ERROR;
1574     }
1575 
1576     r->header_in->last += n;
1577 
1578     return n;
1579 }
1580 
1581 
1582 static ngx_int_t
1583 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1584     ngx_uint_t request_line)
1585 {
1586     u_char                    *old, *new;
1587     ngx_buf_t                 *b;
1588     ngx_chain_t               *cl;
1589     ngx_http_connection_t     *hc;
1590     ngx_http_core_srv_conf_t  *cscf;
1591 
1592     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1593                    "http alloc large header buffer");
1594 
1595     if (request_line && r->state == 0) {
1596 
1597         /* the client fills up the buffer with "\r\n" */
1598 
1599         r->header_in->pos = r->header_in->start;
1600         r->header_in->last = r->header_in->start;
1601 
1602         return NGX_OK;
1603     }
1604 
1605     old = request_line ? r->request_start : r->header_name_start;
1606 
1607     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1608 
1609     if (r->state != 0
1610         && (size_t) (r->header_in->pos - old)
1611                                      >= cscf->large_client_header_buffers.size)
1612     {
1613         return NGX_DECLINED;
1614     }
1615 
1616     hc = r->http_connection;
1617 
1618     if (hc->free) {
1619         cl = hc->free;
1620         hc->free = cl->next;
1621 
1622         b = cl->buf;
1623 
1624         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1625                        "http large header free: %p %uz",
1626                        b->pos, b->end - b->last);
1627 
1628     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1629 
1630         b = ngx_create_temp_buf(r->connection->pool,
1631                                 cscf->large_client_header_buffers.size);
1632         if (b == NULL) {
1633             return NGX_ERROR;
1634         }
1635 
1636         cl = ngx_alloc_chain_link(r->connection->pool);
1637         if (cl == NULL) {
1638             return NGX_ERROR;
1639         }
1640 
1641         cl->buf = b;
1642 
1643         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1644                        "http large header alloc: %p %uz",
1645                        b->pos, b->end - b->last);
1646 
1647     } else {
1648         return NGX_DECLINED;
1649     }
1650 
1651     cl->next = hc->busy;
1652     hc->busy = cl;
1653     hc->nbusy++;
1654 
1655     if (r->state == 0) {
1656         /*
1657          * r->state == 0 means that a header line was parsed successfully
1658          * and we do not need to copy incomplete header line and
1659          * to relocate the parser header pointers
1660          */
1661 
1662         r->header_in = b;
1663 
1664         return NGX_OK;
1665     }
1666 
1667     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1668                    "http large header copy: %uz", r->header_in->pos - old);
1669 
1670     if (r->header_in->pos - old > b->end - b->start) {
1671         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1672                       "too large header to copy");
1673         return NGX_ERROR;
1674     }
1675 
1676     new = b->start;
1677 
1678     ngx_memcpy(new, old, r->header_in->pos - old);
1679 
1680     b->pos = new + (r->header_in->pos - old);
1681     b->last = new + (r->header_in->pos - old);
1682 
1683     if (request_line) {
1684         r->request_start = new;
1685 
1686         if (r->request_end) {
1687             r->request_end = new + (r->request_end - old);
1688         }
1689 
1690         r->method_end = new + (r->method_end - old);
1691 
1692         r->uri_start = new + (r->uri_start - old);
1693         r->uri_end = new + (r->uri_end - old);
1694 
1695         if (r->schema_start) {
1696             r->schema_start = new + (r->schema_start - old);
1697             r->schema_end = new + (r->schema_end - old);
1698         }
1699 
1700         if (r->host_start) {
1701             r->host_start = new + (r->host_start - old);
1702             if (r->host_end) {
1703                 r->host_end = new + (r->host_end - old);
1704             }
1705         }
1706 
1707         if (r->port_start) {
1708             r->port_start = new + (r->port_start - old);
1709             r->port_end = new + (r->port_end - old);
1710         }
1711 
1712         if (r->uri_ext) {
1713             r->uri_ext = new + (r->uri_ext - old);
1714         }
1715 
1716         if (r->args_start) {
1717             r->args_start = new + (r->args_start - old);
1718         }
1719 
1720         if (r->http_protocol.data) {
1721             r->http_protocol.data = new + (r->http_protocol.data - old);
1722         }
1723 
1724     } else {
1725         r->header_name_start = new;
1726         r->header_name_end = new + (r->header_name_end - old);
1727         r->header_start = new + (r->header_start - old);
1728         r->header_end = new + (r->header_end - old);
1729     }
1730 
1731     r->header_in = b;
1732 
1733     return NGX_OK;
1734 }
1735 
1736 
1737 static ngx_int_t
1738 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1739     ngx_uint_t offset)
1740 {
1741     ngx_table_elt_t  **ph;
1742 
1743     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1744 
1745     if (*ph == NULL) {
1746         *ph = h;
1747     }
1748 
1749     return NGX_OK;
1750 }
1751 
1752 
1753 static ngx_int_t
1754 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1755     ngx_uint_t offset)
1756 {
1757     ngx_table_elt_t  **ph;
1758 
1759     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1760 
1761     if (*ph == NULL) {
1762         *ph = h;
1763         return NGX_OK;
1764     }
1765 
1766     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1767                   "client sent duplicate header line: \"%V: %V\", "
1768                   "previous value: \"%V: %V\"",
1769                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1770 
1771     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1772 
1773     return NGX_ERROR;
1774 }
1775 
1776 
1777 static ngx_int_t
1778 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1779     ngx_uint_t offset)
1780 {
1781     ngx_int_t  rc;
1782     ngx_str_t  host;
1783 
1784     if (r->headers_in.host) {
1785         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1786                       "client sent duplicate host header: \"%V: %V\", "
1787                       "previous value: \"%V: %V\"",
1788                       &h->key, &h->value, &r->headers_in.host->key,
1789                       &r->headers_in.host->value);
1790         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1791         return NGX_ERROR;
1792     }
1793 
1794     r->headers_in.host = h;
1795 
1796     host = h->value;
1797 
1798     rc = ngx_http_validate_host(&host, r->pool, 0);
1799 
1800     if (rc == NGX_DECLINED) {
1801         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1802                       "client sent invalid host header");
1803         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1804         return NGX_ERROR;
1805     }
1806 
1807     if (rc == NGX_ERROR) {
1808         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1809         return NGX_ERROR;
1810     }
1811 
1812     if (r->headers_in.server.len) {
1813         return NGX_OK;
1814     }
1815 
1816     if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1817         return NGX_ERROR;
1818     }
1819 
1820     r->headers_in.server = host;
1821 
1822     return NGX_OK;
1823 }
1824 
1825 
1826 static ngx_int_t
1827 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1828     ngx_uint_t offset)
1829 {
1830     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1831         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1832 
1833     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1834         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1835     }
1836 
1837     return NGX_OK;
1838 }
1839 
1840 
1841 static ngx_int_t
1842 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1843     ngx_uint_t offset)
1844 {
1845     u_char  *user_agent, *msie;
1846 
1847     if (r->headers_in.user_agent) {
1848         return NGX_OK;
1849     }
1850 
1851     r->headers_in.user_agent = h;
1852 
1853     /* check some widespread browsers while the header is in CPU cache */
1854 
1855     user_agent = h->value.data;
1856 
1857     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1858 
1859     if (msie && msie + 7 < user_agent + h->value.len) {
1860 
1861         r->headers_in.msie = 1;
1862 
1863         if (msie[6] == '.') {
1864 
1865             switch (msie[5]) {
1866             case '4':
1867             case '5':
1868                 r->headers_in.msie6 = 1;
1869                 break;
1870             case '6':
1871                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1872                     r->headers_in.msie6 = 1;
1873                 }
1874                 break;
1875             }
1876         }
1877 
1878 #if 0
1879         /* MSIE ignores the SSL "close notify" alert */
1880         if (c->ssl) {
1881             c->ssl->no_send_shutdown = 1;
1882         }
1883 #endif
1884     }
1885 
1886     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1887         r->headers_in.opera = 1;
1888         r->headers_in.msie = 0;
1889         r->headers_in.msie6 = 0;
1890     }
1891 
1892     if (!r->headers_in.msie && !r->headers_in.opera) {
1893 
1894         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1895             r->headers_in.gecko = 1;
1896 
1897         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1898             r->headers_in.chrome = 1;
1899 
1900         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1901                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1902         {
1903             r->headers_in.safari = 1;
1904 
1905         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1906             r->headers_in.konqueror = 1;
1907         }
1908     }
1909 
1910     return NGX_OK;
1911 }
1912 
1913 
1914 static ngx_int_t
1915 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1916     ngx_uint_t offset)
1917 {
1918     ngx_array_t       *headers;
1919     ngx_table_elt_t  **ph;
1920 
1921     headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1922 
1923     if (headers->elts == NULL) {
1924         if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1925             != NGX_OK)
1926         {
1927             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1928             return NGX_ERROR;
1929         }
1930     }
1931 
1932     ph = ngx_array_push(headers);
1933     if (ph == NULL) {
1934         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1935         return NGX_ERROR;
1936     }
1937 
1938     *ph = h;
1939     return NGX_OK;
1940 }
1941 
1942 
1943 ngx_int_t
1944 ngx_http_process_request_header(ngx_http_request_t *r)
1945 {
1946     if (r->headers_in.server.len == 0
1947         && ngx_http_set_virtual_server(r, &r->headers_in.server)
1948            == NGX_ERROR)
1949     {
1950         return NGX_ERROR;
1951     }
1952 
1953     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1954         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1955                    "client sent HTTP/1.1 request without \"Host\" header");
1956         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1957         return NGX_ERROR;
1958     }
1959 
1960     if (r->headers_in.content_length) {
1961         r->headers_in.content_length_n =
1962                             ngx_atoof(r->headers_in.content_length->value.data,
1963                                       r->headers_in.content_length->value.len);
1964 
1965         if (r->headers_in.content_length_n == NGX_ERROR) {
1966             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1967                           "client sent invalid \"Content-Length\" header");
1968             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1969             return NGX_ERROR;
1970         }
1971     }
1972 
1973     if (r->headers_in.transfer_encoding) {
1974         if (r->http_version < NGX_HTTP_VERSION_11) {
1975             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1976                           "client sent HTTP/1.0 request with "
1977                           "\"Transfer-Encoding\" header");
1978             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1979             return NGX_ERROR;
1980         }
1981 
1982         if (r->headers_in.transfer_encoding->value.len == 7
1983             && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1984                                (u_char *) "chunked", 7) == 0)
1985         {
1986             if (r->headers_in.content_length) {
1987                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1988                               "client sent \"Content-Length\" and "
1989                               "\"Transfer-Encoding\" headers "
1990                               "at the same time");
1991                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1992                 return NGX_ERROR;
1993             }
1994 
1995             r->headers_in.chunked = 1;
1996 
1997         } else {
1998             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1999                           "client sent unknown \"Transfer-Encoding\": \"%V\"",
2000                           &r->headers_in.transfer_encoding->value);
2001             ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
2002             return NGX_ERROR;
2003         }
2004     }
2005 
2006     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
2007         if (r->headers_in.keep_alive) {
2008             r->headers_in.keep_alive_n =
2009                             ngx_atotm(r->headers_in.keep_alive->value.data,
2010                                       r->headers_in.keep_alive->value.len);
2011         }
2012     }
2013 
2014     if (r->method == NGX_HTTP_CONNECT) {
2015         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2016                       "client sent CONNECT method");
2017         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
2018         return NGX_ERROR;
2019     }
2020 
2021     if (r->method == NGX_HTTP_TRACE) {
2022         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2023                       "client sent TRACE method");
2024         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
2025         return NGX_ERROR;
2026     }
2027 
2028     return NGX_OK;
2029 }
2030 
2031 
2032 void
2033 ngx_http_process_request(ngx_http_request_t *r)
2034 {
2035     ngx_connection_t  *c;
2036 
2037     c = r->connection;
2038 
2039 #if (NGX_HTTP_SSL)
2040 
2041     if (r->http_connection->ssl) {
2042         long                      rc;
2043         X509                     *cert;
2044         const char               *s;
2045         ngx_http_ssl_srv_conf_t  *sscf;
2046 
2047         if (c->ssl == NULL) {
2048             ngx_log_error(NGX_LOG_INFO, c->log, 0,
2049                           "client sent plain HTTP request to HTTPS port");
2050             ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
2051             return;
2052         }
2053 
2054         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
2055 
2056         if (sscf->verify) {
2057             rc = SSL_get_verify_result(c->ssl->connection);
2058 
2059             if (rc != X509_V_OK
2060                 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
2061             {
2062                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2063                               "client SSL certificate verify error: (%l:%s)",
2064                               rc, X509_verify_cert_error_string(rc));
2065 
2066                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2067                                        (SSL_get0_session(c->ssl->connection)));
2068 
2069                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
2070                 return;
2071             }
2072 
2073             if (sscf->verify == 1) {
2074                 cert = SSL_get_peer_certificate(c->ssl->connection);
2075 
2076                 if (cert == NULL) {
2077                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
2078                                   "client sent no required SSL certificate");
2079 
2080                     ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2081                                        (SSL_get0_session(c->ssl->connection)));
2082 
2083                     ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
2084                     return;
2085                 }
2086 
2087                 X509_free(cert);
2088             }
2089 
2090             if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
2091                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2092                               "client SSL certificate verify error: %s", s);
2093 
2094                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2095                                        (SSL_get0_session(c->ssl->connection)));
2096 
2097                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
2098                 return;
2099             }
2100         }
2101     }
2102 
2103 #endif
2104 
2105     if (c->read->timer_set) {
2106         ngx_del_timer(c->read);
2107     }
2108 
2109 #if (NGX_STAT_STUB)
2110     (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
2111     r->stat_reading = 0;
2112     (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
2113     r->stat_writing = 1;
2114 #endif
2115 
2116     c->read->handler = ngx_http_request_handler;
2117     c->write->handler = ngx_http_request_handler;
2118     r->read_event_handler = ngx_http_block_reading;
2119 
2120     ngx_http_handler(r);
2121 }
2122 
2123 
2124 static ngx_int_t
2125 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
2126 {
2127     u_char  *h, ch;
2128     size_t   i, dot_pos, host_len;
2129 
2130     enum {
2131         sw_usual = 0,
2132         sw_literal,
2133         sw_rest
2134     } state;
2135 
2136     dot_pos = host->len;
2137     host_len = host->len;
2138 
2139     h = host->data;
2140 
2141     state = sw_usual;
2142 
2143     for (i = 0; i < host->len; i++) {
2144         ch = h[i];
2145 
2146         switch (ch) {
2147 
2148         case '.':
2149             if (dot_pos == i - 1) {
2150                 return NGX_DECLINED;
2151             }
2152             dot_pos = i;
2153             break;
2154 
2155         case ':':
2156             if (state == sw_usual) {
2157                 host_len = i;
2158                 state = sw_rest;
2159             }
2160             break;
2161 
2162         case '[':
2163             if (i == 0) {
2164                 state = sw_literal;
2165             }
2166             break;
2167 
2168         case ']':
2169             if (state == sw_literal) {
2170                 host_len = i + 1;
2171                 state = sw_rest;
2172             }
2173             break;
2174 
2175         default:
2176 
2177             if (ngx_path_separator(ch)) {
2178                 return NGX_DECLINED;
2179             }
2180 
2181             if (ch <= 0x20 || ch == 0x7f) {
2182                 return NGX_DECLINED;
2183             }
2184 
2185             if (ch >= 'A' && ch <= 'Z') {
2186                 alloc = 1;
2187             }
2188 
2189             break;
2190         }
2191     }
2192 
2193     if (dot_pos == host_len - 1) {
2194         host_len--;
2195     }
2196 
2197     if (host_len == 0) {
2198         return NGX_DECLINED;
2199     }
2200 
2201     if (alloc) {
2202         host->data = ngx_pnalloc(pool, host_len);
2203         if (host->data == NULL) {
2204             return NGX_ERROR;
2205         }
2206 
2207         ngx_strlow(host->data, h, host_len);
2208     }
2209 
2210     host->len = host_len;
2211 
2212     return NGX_OK;
2213 }
2214 
2215 
2216 static ngx_int_t
2217 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
2218 {
2219     ngx_int_t                  rc;
2220     ngx_http_connection_t     *hc;
2221     ngx_http_core_loc_conf_t  *clcf;
2222     ngx_http_core_srv_conf_t  *cscf;
2223 
2224 #if (NGX_SUPPRESS_WARN)
2225     cscf = NULL;
2226 #endif
2227 
2228     hc = r->http_connection;
2229 
2230 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2231 
2232     if (hc->ssl_servername) {
2233         if (hc->ssl_servername->len == host->len
2234             && ngx_strncmp(hc->ssl_servername->data,
2235                            host->data, host->len) == 0)
2236         {
2237 #if (NGX_PCRE)
2238             if (hc->ssl_servername_regex
2239                 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
2240                                           hc->ssl_servername) != NGX_OK)
2241             {
2242                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2243                 return NGX_ERROR;
2244             }
2245 #endif
2246             return NGX_OK;
2247         }
2248     }
2249 
2250 #endif
2251 
2252     rc = ngx_http_find_virtual_server(r->connection,
2253                                       hc->addr_conf->virtual_names,
2254                                       host, r, &cscf);
2255 
2256     if (rc == NGX_ERROR) {
2257         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2258         return NGX_ERROR;
2259     }
2260 
2261 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2262 
2263     if (hc->ssl_servername) {
2264         ngx_http_ssl_srv_conf_t  *sscf;
2265 
2266         if (rc == NGX_DECLINED) {
2267             cscf = hc->addr_conf->default_server;
2268             rc = NGX_OK;
2269         }
2270 
2271         sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2272 
2273         if (sscf->verify) {
2274             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2275                           "client attempted to request the server name "
2276                           "different from the one that was negotiated");
2277             ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
2278             return NGX_ERROR;
2279         }
2280     }
2281 
2282 #endif
2283 
2284     if (rc == NGX_DECLINED) {
2285         return NGX_OK;
2286     }
2287 
2288     r->srv_conf = cscf->ctx->srv_conf;
2289     r->loc_conf = cscf->ctx->loc_conf;
2290 
2291     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2292 
2293     ngx_set_connection_log(r->connection, clcf->error_log);
2294 
2295     return NGX_OK;
2296 }
2297 
2298 
2299 static ngx_int_t
2300 ngx_http_find_virtual_server(ngx_connection_t *c,
2301     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2302     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2303 {
2304     ngx_http_core_srv_conf_t  *cscf;
2305 
2306     if (virtual_names == NULL) {
2307         return NGX_DECLINED;
2308     }
2309 
2310     cscf = ngx_hash_find_combined(&virtual_names->names,
2311                                   ngx_hash_key(host->data, host->len),
2312                                   host->data, host->len);
2313 
2314     if (cscf) {
2315         *cscfp = cscf;
2316         return NGX_OK;
2317     }
2318 
2319 #if (NGX_PCRE)
2320 
2321     if (host->len && virtual_names->nregex) {
2322         ngx_int_t                n;
2323         ngx_uint_t               i;
2324         ngx_http_server_name_t  *sn;
2325 
2326         sn = virtual_names->regex;
2327 
2328 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2329 
2330         if (r == NULL) {
2331             ngx_http_connection_t  *hc;
2332 
2333             for (i = 0; i < virtual_names->nregex; i++) {
2334 
2335                 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2336 
2337                 if (n == NGX_REGEX_NO_MATCHED) {
2338                     continue;
2339                 }
2340 
2341                 if (n >= 0) {
2342                     hc = c->data;
2343                     hc->ssl_servername_regex = sn[i].regex;
2344 
2345                     *cscfp = sn[i].server;
2346                     return NGX_OK;
2347                 }
2348 
2349                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2350                               ngx_regex_exec_n " failed: %i "
2351                               "on \"%V\" using \"%V\"",
2352                               n, host, &sn[i].regex->name);
2353 
2354                 return NGX_ERROR;
2355             }
2356 
2357             return NGX_DECLINED;
2358         }
2359 
2360 #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */
2361 
2362         for (i = 0; i < virtual_names->nregex; i++) {
2363 
2364             n = ngx_http_regex_exec(r, sn[i].regex, host);
2365 
2366             if (n == NGX_DECLINED) {
2367                 continue;
2368             }
2369 
2370             if (n == NGX_OK) {
2371                 *cscfp = sn[i].server;
2372                 return NGX_OK;
2373             }
2374 
2375             return NGX_ERROR;
2376         }
2377     }
2378 
2379 #endif /* NGX_PCRE */
2380 
2381     return NGX_DECLINED;
2382 }
2383 
2384 
2385 static void
2386 ngx_http_request_handler(ngx_event_t *ev)
2387 {
2388     ngx_connection_t    *c;
2389     ngx_http_request_t  *r;
2390 
2391     c = ev->data;
2392     r = c->data;
2393 
2394     ngx_http_set_log_request(c->log, r);
2395 
2396     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2397                    "http run request: \"%V?%V\"", &r->uri, &r->args);
2398 
2399     if (c->close) {
2400         r->main->count++;
2401         ngx_http_terminate_request(r, 0);
2402         ngx_http_run_posted_requests(c);
2403         return;
2404     }
2405 
2406     if (ev->delayed && ev->timedout) {
2407         ev->delayed = 0;
2408         ev->timedout = 0;
2409     }
2410 
2411     if (ev->write) {
2412         r->write_event_handler(r);
2413 
2414     } else {
2415         r->read_event_handler(r);
2416     }
2417 
2418     ngx_http_run_posted_requests(c);
2419 }
2420 
2421 
2422 void
2423 ngx_http_run_posted_requests(ngx_connection_t *c)
2424 {
2425     ngx_http_request_t         *r;
2426     ngx_http_posted_request_t  *pr;
2427 
2428     for ( ;; ) {
2429 
2430         if (c->destroyed) {
2431             return;
2432         }
2433 
2434         r = c->data;
2435         pr = r->main->posted_requests;
2436 
2437         if (pr == NULL) {
2438             return;
2439         }
2440 
2441         r->main->posted_requests = pr->next;
2442 
2443         r = pr->request;
2444 
2445         ngx_http_set_log_request(c->log, r);
2446 
2447         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2448                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
2449 
2450         r->write_event_handler(r);
2451     }
2452 }
2453 
2454 
2455 ngx_int_t
2456 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2457 {
2458     ngx_http_posted_request_t  **p;
2459 
2460     if (pr == NULL) {
2461         pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2462         if (pr == NULL) {
2463             return NGX_ERROR;
2464         }
2465     }
2466 
2467     pr->request = r;
2468     pr->next = NULL;
2469 
2470     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2471 
2472     *p = pr;
2473 
2474     return NGX_OK;
2475 }
2476 
2477 
2478 void
2479 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2480 {
2481     ngx_connection_t          *c;
2482     ngx_http_request_t        *pr;
2483     ngx_http_core_loc_conf_t  *clcf;
2484 
2485     c = r->connection;
2486 
2487     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2488                    "http finalize request: %i, \"%V?%V\" a:%d, c:%d",
2489                    rc, &r->uri, &r->args, r == c->data, r->main->count);
2490 
2491     if (rc == NGX_DONE) {
2492         ngx_http_finalize_connection(r);
2493         return;
2494     }
2495 
2496     if (rc == NGX_OK && r->filter_finalize) {
2497         c->error = 1;
2498     }
2499 
2500     if (rc == NGX_DECLINED) {
2501         r->content_handler = NULL;
2502         r->write_event_handler = ngx_http_core_run_phases;
2503         ngx_http_core_run_phases(r);
2504         return;
2505     }
2506 
2507     if (r != r->main && r->post_subrequest) {
2508         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2509     }
2510 
2511     if (rc == NGX_ERROR
2512         || rc == NGX_HTTP_REQUEST_TIME_OUT
2513         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2514         || c->error)
2515     {
2516         if (ngx_http_post_action(r) == NGX_OK) {
2517             return;
2518         }
2519 
2520         ngx_http_terminate_request(r, rc);
2521         return;
2522     }
2523 
2524     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2525         || rc == NGX_HTTP_CREATED
2526         || rc == NGX_HTTP_NO_CONTENT)
2527     {
2528         if (rc == NGX_HTTP_CLOSE) {
2529             c->timedout = 1;
2530             ngx_http_terminate_request(r, rc);
2531             return;
2532         }
2533 
2534         if (r == r->main) {
2535             if (c->read->timer_set) {
2536                 ngx_del_timer(c->read);
2537             }
2538 
2539             if (c->write->timer_set) {
2540                 ngx_del_timer(c->write);
2541             }
2542         }
2543 
2544         c->read->handler = ngx_http_request_handler;
2545         c->write->handler = ngx_http_request_handler;
2546 
2547         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2548         return;
2549     }
2550 
2551     if (r != r->main) {
2552 
2553         if (r->buffered || r->postponed) {
2554 
2555             if (ngx_http_set_write_handler(r) != NGX_OK) {
2556                 ngx_http_terminate_request(r, 0);
2557             }
2558 
2559             return;
2560         }
2561 
2562         pr = r->parent;
2563 
2564         if (r == c->data || r->background) {
2565 
2566             if (!r->logged) {
2567 
2568                 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2569 
2570                 if (clcf->log_subrequest) {
2571                     ngx_http_log_request(r);
2572                 }
2573 
2574                 r->logged = 1;
2575 
2576             } else {
2577                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2578                               "subrequest: \"%V?%V\" logged again",
2579                               &r->uri, &r->args);
2580             }
2581 
2582             r->done = 1;
2583 
2584             if (r->background) {
2585                 ngx_http_finalize_connection(r);
2586                 return;
2587             }
2588 
2589             r->main->count--;
2590 
2591             if (pr->postponed && pr->postponed->request == r) {
2592                 pr->postponed = pr->postponed->next;
2593             }
2594 
2595             c->data = pr;
2596 
2597         } else {
2598 
2599             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2600                            "http finalize non-active request: \"%V?%V\"",
2601                            &r->uri, &r->args);
2602 
2603             r->write_event_handler = ngx_http_request_finalizer;
2604 
2605             if (r->waited) {
2606                 r->done = 1;
2607             }
2608         }
2609 
2610         if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2611             r->main->count++;
2612             ngx_http_terminate_request(r, 0);
2613             return;
2614         }
2615 
2616         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2617                        "http wake parent request: \"%V?%V\"",
2618                        &pr->uri, &pr->args);
2619 
2620         return;
2621     }
2622 
2623     if (r->buffered || c->buffered || r->postponed) {
2624 
2625         if (ngx_http_set_write_handler(r) != NGX_OK) {
2626             ngx_http_terminate_request(r, 0);
2627         }
2628 
2629         return;
2630     }
2631 
2632     if (r != c->data) {
2633         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2634                       "http finalize non-active request: \"%V?%V\"",
2635                       &r->uri, &r->args);
2636         return;
2637     }
2638 
2639     r->done = 1;
2640 
2641     r->read_event_handler = ngx_http_block_reading;
2642     r->write_event_handler = ngx_http_request_empty_handler;
2643 
2644     if (!r->post_action) {
2645         r->request_complete = 1;
2646     }
2647 
2648     if (ngx_http_post_action(r) == NGX_OK) {
2649         return;
2650     }
2651 
2652     if (c->read->timer_set) {
2653         ngx_del_timer(c->read);
2654     }
2655 
2656     if (c->write->timer_set) {
2657         c->write->delayed = 0;
2658         ngx_del_timer(c->write);
2659     }
2660 
2661     ngx_http_finalize_connection(r);
2662 }
2663 
2664 
2665 static void
2666 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2667 {
2668     ngx_http_cleanup_t    *cln;
2669     ngx_http_request_t    *mr;
2670     ngx_http_ephemeral_t  *e;
2671 
2672     mr = r->main;
2673 
2674     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2675                    "http terminate request count:%d", mr->count);
2676 
2677     if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2678         mr->headers_out.status = rc;
2679     }
2680 
2681     cln = mr->cleanup;
2682     mr->cleanup = NULL;
2683 
2684     while (cln) {
2685         if (cln->handler) {
2686             cln->handler(cln->data);
2687         }
2688 
2689         cln = cln->next;
2690     }
2691 
2692     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2693                    "http terminate cleanup count:%d blk:%d",
2694                    mr->count, mr->blocked);
2695 
2696     if (mr->write_event_handler) {
2697 
2698         if (mr->blocked) {
2699             r->connection->error = 1;
2700             r->write_event_handler = ngx_http_request_finalizer;
2701             return;
2702         }
2703 
2704         e = ngx_http_ephemeral(mr);
2705         mr->posted_requests = NULL;
2706         mr->write_event_handler = ngx_http_terminate_handler;
2707         (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2708         return;
2709     }
2710 
2711     ngx_http_close_request(mr, rc);
2712 }
2713 
2714 
2715 static void
2716 ngx_http_terminate_handler(ngx_http_request_t *r)
2717 {
2718     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2719                    "http terminate handler count:%d", r->count);
2720 
2721     r->count = 1;
2722 
2723     ngx_http_close_request(r, 0);
2724 }
2725 
2726 
2727 static void
2728 ngx_http_finalize_connection(ngx_http_request_t *r)
2729 {
2730     ngx_http_core_loc_conf_t  *clcf;
2731 
2732 #if (NGX_HTTP_V2)
2733     if (r->stream) {
2734         ngx_http_close_request(r, 0);
2735         return;
2736     }
2737 #endif
2738 
2739     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2740 
2741     if (r->main->count != 1) {
2742 
2743         if (r->discard_body) {
2744             r->read_event_handler = ngx_http_discarded_request_body_handler;
2745             ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2746 
2747             if (r->lingering_time == 0) {
2748                 r->lingering_time = ngx_time()
2749                                       + (time_t) (clcf->lingering_time / 1000);
2750             }
2751         }
2752 
2753         ngx_http_close_request(r, 0);
2754         return;
2755     }
2756 
2757     r = r->main;
2758 
2759     if (r->connection->read->eof) {
2760         ngx_http_close_request(r, 0);
2761         return;
2762     }
2763 
2764     if (r->reading_body) {
2765         r->keepalive = 0;
2766         r->lingering_close = 1;
2767     }
2768 
2769     if (!ngx_terminate
2770          && !ngx_exiting
2771          && r->keepalive
2772          && clcf->keepalive_timeout > 0)
2773     {
2774         ngx_http_set_keepalive(r);
2775         return;
2776     }
2777 
2778     if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2779         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2780             && (r->lingering_close
2781                 || r->header_in->pos < r->header_in->last
2782                 || r->connection->read->ready)))
2783     {
2784         ngx_http_set_lingering_close(r->connection);
2785         return;
2786     }
2787 
2788     ngx_http_close_request(r, 0);
2789 }
2790 
2791 
2792 static ngx_int_t
2793 ngx_http_set_write_handler(ngx_http_request_t *r)
2794 {
2795     ngx_event_t               *wev;
2796     ngx_http_core_loc_conf_t  *clcf;
2797 
2798     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2799 
2800     r->read_event_handler = r->discard_body ?
2801                                 ngx_http_discarded_request_body_handler:
2802                                 ngx_http_test_reading;
2803     r->write_event_handler = ngx_http_writer;
2804 
2805     wev = r->connection->write;
2806 
2807     if (wev->ready && wev->delayed) {
2808         return NGX_OK;
2809     }
2810 
2811     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2812     if (!wev->delayed) {
2813         ngx_add_timer(wev, clcf->send_timeout);
2814     }
2815 
2816     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2817         ngx_http_close_request(r, 0);
2818         return NGX_ERROR;
2819     }
2820 
2821     return NGX_OK;
2822 }
2823 
2824 
2825 static void
2826 ngx_http_writer(ngx_http_request_t *r)
2827 {
2828     ngx_int_t                  rc;
2829     ngx_event_t               *wev;
2830     ngx_connection_t          *c;
2831     ngx_http_core_loc_conf_t  *clcf;
2832 
2833     c = r->connection;
2834     wev = c->write;
2835 
2836     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2837                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2838 
2839     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2840 
2841     if (wev->timedout) {
2842         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2843                       "client timed out");
2844         c->timedout = 1;
2845 
2846         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2847         return;
2848     }
2849 
2850     if (wev->delayed || r->aio) {
2851         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2852                        "http writer delayed");
2853 
2854         if (!wev->delayed) {
2855             ngx_add_timer(wev, clcf->send_timeout);
2856         }
2857 
2858         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2859             ngx_http_close_request(r, 0);
2860         }
2861 
2862         return;
2863     }
2864 
2865     rc = ngx_http_output_filter(r, NULL);
2866 
2867     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2868                    "http writer output filter: %i, \"%V?%V\"",
2869                    rc, &r->uri, &r->args);
2870 
2871     if (rc == NGX_ERROR) {
2872         ngx_http_finalize_request(r, rc);
2873         return;
2874     }
2875 
2876     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2877 
2878         if (!wev->delayed) {
2879             ngx_add_timer(wev, clcf->send_timeout);
2880         }
2881 
2882         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2883             ngx_http_close_request(r, 0);
2884         }
2885 
2886         return;
2887     }
2888 
2889     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2890                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
2891 
2892     r->write_event_handler = ngx_http_request_empty_handler;
2893 
2894     ngx_http_finalize_request(r, rc);
2895 }
2896 
2897 
2898 static void
2899 ngx_http_request_finalizer(ngx_http_request_t *r)
2900 {
2901     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2902                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2903 
2904     ngx_http_finalize_request(r, 0);
2905 }
2906 
2907 
2908 void
2909 ngx_http_block_reading(ngx_http_request_t *r)
2910 {
2911     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2912                    "http reading blocked");
2913 
2914     /* aio does not call this handler */
2915 
2916     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2917         && r->connection->read->active)
2918     {
2919         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2920             ngx_http_close_request(r, 0);
2921         }
2922     }
2923 }
2924 
2925 
2926 void
2927 ngx_http_test_reading(ngx_http_request_t *r)
2928 {
2929     int                n;
2930     char               buf[1];
2931     ngx_err_t          err;
2932     ngx_event_t       *rev;
2933     ngx_connection_t  *c;
2934 
2935     c = r->connection;
2936     rev = c->read;
2937 
2938     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2939 
2940 #if (NGX_HTTP_V2)
2941 
2942     if (r->stream) {
2943         if (c->error) {
2944             err = 0;
2945             goto closed;
2946         }
2947 
2948         return;
2949     }
2950 
2951 #endif
2952 
2953 #if (NGX_HAVE_KQUEUE)
2954 
2955     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2956 
2957         if (!rev->pending_eof) {
2958             return;
2959         }
2960 
2961         rev->eof = 1;
2962         c->error = 1;
2963         err = rev->kq_errno;
2964 
2965         goto closed;
2966     }
2967 
2968 #endif
2969 
2970 #if (NGX_HAVE_EPOLLRDHUP)
2971 
2972     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
2973         socklen_t  len;
2974 
2975         if (!rev->pending_eof) {
2976             return;
2977         }
2978 
2979         rev->eof = 1;
2980         c->error = 1;
2981 
2982         err = 0;
2983         len = sizeof(ngx_err_t);
2984 
2985         /*
2986          * BSDs and Linux return 0 and set a pending error in err
2987          * Solaris returns -1 and sets errno
2988          */
2989 
2990         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
2991             == -1)
2992         {
2993             err = ngx_socket_errno;
2994         }
2995 
2996         goto closed;
2997     }
2998 
2999 #endif
3000 
3001     n = recv(c->fd, buf, 1, MSG_PEEK);
3002 
3003     if (n == 0) {
3004         rev->eof = 1;
3005         c->error = 1;
3006         err = 0;
3007 
3008         goto closed;
3009 
3010     } else if (n == -1) {
3011         err = ngx_socket_errno;
3012 
3013         if (err != NGX_EAGAIN) {
3014             rev->eof = 1;
3015             c->error = 1;
3016 
3017             goto closed;
3018         }
3019     }
3020 
3021     /* aio does not call this handler */
3022 
3023     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
3024 
3025         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
3026             ngx_http_close_request(r, 0);
3027         }
3028     }
3029 
3030     return;
3031 
3032 closed:
3033 
3034     if (err) {
3035         rev->error = 1;
3036     }
3037 
3038 #if (NGX_HTTP_SSL)
3039     if (c->ssl) {
3040         c->ssl->no_send_shutdown = 1;
3041     }
3042 #endif
3043 
3044     ngx_log_error(NGX_LOG_INFO, c->log, err,
3045                   "client prematurely closed connection");
3046 
3047     ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
3048 }
3049 
3050 
3051 static void
3052 ngx_http_set_keepalive(ngx_http_request_t *r)
3053 {
3054     int                        tcp_nodelay;
3055     ngx_buf_t                 *b, *f;
3056     ngx_chain_t               *cl, *ln;
3057     ngx_event_t               *rev, *wev;
3058     ngx_connection_t          *c;
3059     ngx_http_connection_t     *hc;
3060     ngx_http_core_loc_conf_t  *clcf;
3061 
3062     c = r->connection;
3063     rev = c->read;
3064 
3065     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3066 
3067     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
3068 
3069     c->log->action = "closing request";
3070 
3071     hc = r->http_connection;
3072     b = r->header_in;
3073 
3074     if (b->pos < b->last) {
3075 
3076         /* the pipelined request */
3077 
3078         if (b != c->buffer) {
3079 
3080             /*
3081              * If the large header buffers were allocated while the previous
3082              * request processing then we do not use c->buffer for
3083              * the pipelined request (see ngx_http_create_request()).
3084              *
3085              * Now we would move the large header buffers to the free list.
3086              */
3087 
3088             for (cl = hc->busy; cl; /* void */) {
3089                 ln = cl;
3090                 cl = cl->next;
3091 
3092                 if (ln->buf == b) {
3093                     ngx_free_chain(c->pool, ln);
3094                     continue;
3095                 }
3096 
3097                 f = ln->buf;
3098                 f->pos = f->start;
3099                 f->last = f->start;
3100 
3101                 ln->next = hc->free;
3102                 hc->free = ln;
3103             }
3104 
3105             cl = ngx_alloc_chain_link(c->pool);
3106             if (cl == NULL) {
3107                 ngx_http_close_request(r, 0);
3108                 return;
3109             }
3110 
3111             cl->buf = b;
3112             cl->next = NULL;
3113 
3114             hc->busy = cl;
3115             hc->nbusy = 1;
3116         }
3117     }
3118 
3119     /* guard against recursive call from ngx_http_finalize_connection() */
3120     r->keepalive = 0;
3121 
3122     ngx_http_free_request(r, 0);
3123 
3124     c->data = hc;
3125 
3126     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3127         ngx_http_close_connection(c);
3128         return;
3129     }
3130 
3131     wev = c->write;
3132     wev->handler = ngx_http_empty_handler;
3133 
3134     if (b->pos < b->last) {
3135 
3136         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
3137 
3138         c->log->action = "reading client pipelined request line";
3139 
3140         r = ngx_http_create_request(c);
3141         if (r == NULL) {
3142             ngx_http_close_connection(c);
3143             return;
3144         }
3145 
3146         r->pipeline = 1;
3147 
3148         c->data = r;
3149 
3150         c->sent = 0;
3151         c->destroyed = 0;
3152 
3153         if (rev->timer_set) {
3154             ngx_del_timer(rev);
3155         }
3156 
3157         rev->handler = ngx_http_process_request_line;
3158         ngx_post_event(rev, &ngx_posted_events);
3159         return;
3160     }
3161 
3162     /*
3163      * To keep a memory footprint as small as possible for an idle keepalive
3164      * connection we try to free c->buffer's memory if it was allocated outside
3165      * the c->pool.  The large header buffers are always allocated outside the
3166      * c->pool and are freed too.
3167      */
3168 
3169     b = c->buffer;
3170 
3171     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3172 
3173         /*
3174          * the special note for ngx_http_keepalive_handler() that
3175          * c->buffer's memory was freed
3176          */
3177 
3178         b->pos = NULL;
3179 
3180     } else {
3181         b->pos = b->start;
3182         b->last = b->start;
3183     }
3184 
3185     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
3186                    hc->free);
3187 
3188     if (hc->free) {
3189         for (cl = hc->free; cl; /* void */) {
3190             ln = cl;
3191             cl = cl->next;
3192             ngx_pfree(c->pool, ln->buf->start);
3193             ngx_free_chain(c->pool, ln);
3194         }
3195 
3196         hc->free = NULL;
3197     }
3198 
3199     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
3200                    hc->busy, hc->nbusy);
3201 
3202     if (hc->busy) {
3203         for (cl = hc->busy; cl; /* void */) {
3204             ln = cl;
3205             cl = cl->next;
3206             ngx_pfree(c->pool, ln->buf->start);
3207             ngx_free_chain(c->pool, ln);
3208         }
3209 
3210         hc->busy = NULL;
3211         hc->nbusy = 0;
3212     }
3213 
3214 #if (NGX_HTTP_SSL)
3215     if (c->ssl) {
3216         ngx_ssl_free_buffer(c);
3217     }
3218 #endif
3219 
3220     rev->handler = ngx_http_keepalive_handler;
3221 
3222     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3223         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3224             ngx_http_close_connection(c);
3225             return;
3226         }
3227     }
3228 
3229     c->log->action = "keepalive";
3230 
3231     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
3232         if (ngx_tcp_push(c->fd) == -1) {
3233             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
3234             ngx_http_close_connection(c);
3235             return;
3236         }
3237 
3238         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
3239         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
3240 
3241     } else {
3242         tcp_nodelay = 1;
3243     }
3244 
3245     if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
3246         ngx_http_close_connection(c);
3247         return;
3248     }
3249 
3250 #if 0
3251     /* if ngx_http_request_t was freed then we need some other place */
3252     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
3253 #endif
3254 
3255     c->idle = 1;
3256     ngx_reusable_connection(c, 1);
3257 
3258     ngx_add_timer(rev, clcf->keepalive_timeout);
3259 
3260     if (rev->ready) {
3261         ngx_post_event(rev, &ngx_posted_events);
3262     }
3263 }
3264 
3265 
3266 static void
3267 ngx_http_keepalive_handler(ngx_event_t *rev)
3268 {
3269     size_t             size;
3270     ssize_t            n;
3271     ngx_buf_t         *b;
3272     ngx_connection_t  *c;
3273 
3274     c = rev->data;
3275 
3276     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
3277 
3278     if (rev->timedout || c->close) {
3279         ngx_http_close_connection(c);
3280         return;
3281     }
3282 
3283 #if (NGX_HAVE_KQUEUE)
3284 
3285     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
3286         if (rev->pending_eof) {
3287             c->log->handler = NULL;
3288             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
3289                           "kevent() reported that client %V closed "
3290                           "keepalive connection", &c->addr_text);
3291 #if (NGX_HTTP_SSL)
3292             if (c->ssl) {
3293                 c->ssl->no_send_shutdown = 1;
3294             }
3295 #endif
3296             ngx_http_close_connection(c);
3297             return;
3298         }
3299     }
3300 
3301 #endif
3302 
3303     b = c->buffer;
3304     size = b->end - b->start;
3305 
3306     if (b->pos == NULL) {
3307 
3308         /*
3309          * The c->buffer's memory was freed by ngx_http_set_keepalive().
3310          * However, the c->buffer->start and c->buffer->end were not changed
3311          * to keep the buffer size.
3312          */
3313 
3314         b->pos = ngx_palloc(c->pool, size);
3315         if (b->pos == NULL) {
3316             ngx_http_close_connection(c);
3317             return;
3318         }
3319 
3320         b->start = b->pos;
3321         b->last = b->pos;
3322         b->end = b->pos + size;
3323     }
3324 
3325     /*
3326      * MSIE closes a keepalive connection with RST flag
3327      * so we ignore ECONNRESET here.
3328      */
3329 
3330     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3331     ngx_set_socket_errno(0);
3332 
3333     n = c->recv(c, b->last, size);
3334     c->log_error = NGX_ERROR_INFO;
3335 
3336     if (n == NGX_AGAIN) {
3337         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3338             ngx_http_close_connection(c);
3339             return;
3340         }
3341 
3342         /*
3343          * Like ngx_http_set_keepalive() we are trying to not hold
3344          * c->buffer's memory for a keepalive connection.
3345          */
3346 
3347         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3348 
3349             /*
3350              * the special note that c->buffer's memory was freed
3351              */
3352 
3353             b->pos = NULL;
3354         }
3355 
3356         return;
3357     }
3358 
3359     if (n == NGX_ERROR) {
3360         ngx_http_close_connection(c);
3361         return;
3362     }
3363 
3364     c->log->handler = NULL;
3365 
3366     if (n == 0) {
3367         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3368                       "client %V closed keepalive connection", &c->addr_text);
3369         ngx_http_close_connection(c);
3370         return;
3371     }
3372 
3373     b->last += n;
3374 
3375     c->log->handler = ngx_http_log_error;
3376     c->log->action = "reading client request line";
3377 
3378     c->idle = 0;
3379     ngx_reusable_connection(c, 0);
3380 
3381     c->data = ngx_http_create_request(c);
3382     if (c->data == NULL) {
3383         ngx_http_close_connection(c);
3384         return;
3385     }
3386 
3387     c->sent = 0;
3388     c->destroyed = 0;
3389 
3390     ngx_del_timer(rev);
3391 
3392     rev->handler = ngx_http_process_request_line;
3393     ngx_http_process_request_line(rev);
3394 }
3395 
3396 
3397 static void
3398 ngx_http_set_lingering_close(ngx_connection_t *c)
3399 {
3400     ngx_event_t               *rev, *wev;
3401     ngx_http_request_t        *r;
3402     ngx_http_core_loc_conf_t  *clcf;
3403 
3404     r = c->data;
3405 
3406     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3407 
3408     if (r->lingering_time == 0) {
3409         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3410     }
3411 
3412 #if (NGX_HTTP_SSL)
3413     if (c->ssl) {
3414         ngx_int_t  rc;
3415 
3416         c->ssl->shutdown_without_free = 1;
3417 
3418         rc = ngx_ssl_shutdown(c);
3419 
3420         if (rc == NGX_ERROR) {
3421             ngx_http_close_request(r, 0);
3422             return;
3423         }
3424 
3425         if (rc == NGX_AGAIN) {
3426             c->ssl->handler = ngx_http_set_lingering_close;
3427             return;
3428         }
3429     }
3430 #endif
3431 
3432     rev = c->read;
3433     rev->handler = ngx_http_lingering_close_handler;
3434 
3435     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3436         ngx_http_close_request(r, 0);
3437         return;
3438     }
3439 
3440     wev = c->write;
3441     wev->handler = ngx_http_empty_handler;
3442 
3443     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3444         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3445             ngx_http_close_request(r, 0);
3446             return;
3447         }
3448     }
3449 
3450     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3451         ngx_connection_error(c, ngx_socket_errno,
3452                              ngx_shutdown_socket_n " failed");
3453         ngx_http_close_request(r, 0);
3454         return;
3455     }
3456 
3457     c->close = 0;
3458     ngx_reusable_connection(c, 1);
3459 
3460     ngx_add_timer(rev, clcf->lingering_timeout);
3461 
3462     if (rev->ready) {
3463         ngx_http_lingering_close_handler(rev);
3464     }
3465 }
3466 
3467 
3468 static void
3469 ngx_http_lingering_close_handler(ngx_event_t *rev)
3470 {
3471     ssize_t                    n;
3472     ngx_msec_t                 timer;
3473     ngx_connection_t          *c;
3474     ngx_http_request_t        *r;
3475     ngx_http_core_loc_conf_t  *clcf;
3476     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3477 
3478     c = rev->data;
3479     r = c->data;
3480 
3481     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3482                    "http lingering close handler");
3483 
3484     if (rev->timedout || c->close) {
3485         ngx_http_close_request(r, 0);
3486         return;
3487     }
3488 
3489     timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
3490     if ((ngx_msec_int_t) timer <= 0) {
3491         ngx_http_close_request(r, 0);
3492         return;
3493     }
3494 
3495     do {
3496         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3497 
3498         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
3499 
3500         if (n == NGX_AGAIN) {
3501             break;
3502         }
3503 
3504         if (n == NGX_ERROR || n == 0) {
3505             ngx_http_close_request(r, 0);
3506             return;
3507         }
3508 
3509     } while (rev->ready);
3510 
3511     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3512         ngx_http_close_request(r, 0);
3513         return;
3514     }
3515 
3516     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3517 
3518     timer *= 1000;
3519 
3520     if (timer > clcf->lingering_timeout) {
3521         timer = clcf->lingering_timeout;
3522     }
3523 
3524     ngx_add_timer(rev, timer);
3525 }
3526 
3527 
3528 void
3529 ngx_http_empty_handler(ngx_event_t *wev)
3530 {
3531     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3532 
3533     return;
3534 }
3535 
3536 
3537 void
3538 ngx_http_request_empty_handler(ngx_http_request_t *r)
3539 {
3540     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3541                    "http request empty handler");
3542 
3543     return;
3544 }
3545 
3546 
3547 ngx_int_t
3548 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3549 {
3550     ngx_buf_t    *b;
3551     ngx_chain_t   out;
3552 
3553     b = ngx_calloc_buf(r->pool);
3554     if (b == NULL) {
3555         return NGX_ERROR;
3556     }
3557 
3558     if (flags & NGX_HTTP_LAST) {
3559 
3560         if (r == r->main && !r->post_action) {
3561             b->last_buf = 1;
3562 
3563         } else {
3564             b->sync = 1;
3565             b->last_in_chain = 1;
3566         }
3567     }
3568 
3569     if (flags & NGX_HTTP_FLUSH) {
3570         b->flush = 1;
3571     }
3572 
3573     out.buf = b;
3574     out.next = NULL;
3575 
3576     return ngx_http_output_filter(r, &out);
3577 }
3578 
3579 
3580 static ngx_int_t
3581 ngx_http_post_action(ngx_http_request_t *r)
3582 {
3583     ngx_http_core_loc_conf_t  *clcf;
3584 
3585     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3586 
3587     if (clcf->post_action.data == NULL) {
3588         return NGX_DECLINED;
3589     }
3590 
3591     if (r->post_action && r->uri_changes == 0) {
3592         return NGX_DECLINED;
3593     }
3594 
3595     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3596                    "post action: \"%V\"", &clcf->post_action);
3597 
3598     r->main->count--;
3599 
3600     r->http_version = NGX_HTTP_VERSION_9;
3601     r->header_only = 1;
3602     r->post_action = 1;
3603 
3604     r->read_event_handler = ngx_http_block_reading;
3605 
3606     if (clcf->post_action.data[0] == '/') {
3607         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3608 
3609     } else {
3610         ngx_http_named_location(r, &clcf->post_action);
3611     }
3612 
3613     return NGX_OK;
3614 }
3615 
3616 
3617 static void
3618 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3619 {
3620     ngx_connection_t  *c;
3621 
3622     r = r->main;
3623     c = r->connection;
3624 
3625     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3626                    "http request count:%d blk:%d", r->count, r->blocked);
3627 
3628     if (r->count == 0) {
3629         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3630     }
3631 
3632     r->count--;
3633 
3634     if (r->count || r->blocked) {
3635         return;
3636     }
3637 
3638 #if (NGX_HTTP_V2)
3639     if (r->stream) {
3640         ngx_http_v2_close_stream(r->stream, rc);
3641         return;
3642     }
3643 #endif
3644 
3645     ngx_http_free_request(r, rc);
3646     ngx_http_close_connection(c);
3647 }
3648 
3649 
3650 void
3651 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3652 {
3653     ngx_log_t                 *log;
3654     ngx_pool_t                *pool;
3655     struct linger              linger;
3656     ngx_http_cleanup_t        *cln;
3657     ngx_http_log_ctx_t        *ctx;
3658     ngx_http_core_loc_conf_t  *clcf;
3659 
3660     log = r->connection->log;
3661 
3662     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3663 
3664     if (r->pool == NULL) {
3665         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3666         return;
3667     }
3668 
3669     cln = r->cleanup;
3670     r->cleanup = NULL;
3671 
3672     while (cln) {
3673         if (cln->handler) {
3674             cln->handler(cln->data);
3675         }
3676 
3677         cln = cln->next;
3678     }
3679 
3680 #if (NGX_STAT_STUB)
3681 
3682     if (r->stat_reading) {
3683         (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3684     }
3685 
3686     if (r->stat_writing) {
3687         (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3688     }
3689 
3690 #endif
3691 
3692     if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3693         r->headers_out.status = rc;
3694     }
3695 
3696     if (!r->logged) {
3697         log->action = "logging request";
3698 
3699         ngx_http_log_request(r);
3700     }
3701 
3702     log->action = "closing request";
3703 
3704     if (r->connection->timedout) {
3705         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3706 
3707         if (clcf->reset_timedout_connection) {
3708             linger.l_onoff = 1;
3709             linger.l_linger = 0;
3710 
3711             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3712                            (const void *) &linger, sizeof(struct linger)) == -1)
3713             {
3714                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3715                               "setsockopt(SO_LINGER) failed");
3716             }
3717         }
3718     }
3719 
3720     /* the various request strings were allocated from r->pool */
3721     ctx = log->data;
3722     ctx->request = NULL;
3723 
3724     r->request_line.len = 0;
3725 
3726     r->connection->destroyed = 1;
3727 
3728     /*
3729      * Setting r->pool to NULL will increase probability to catch double close
3730      * of request since the request object is allocated from its own pool.
3731      */
3732 
3733     pool = r->pool;
3734     r->pool = NULL;
3735 
3736     ngx_destroy_pool(pool);
3737 }
3738 
3739 
3740 static void
3741 ngx_http_log_request(ngx_http_request_t *r)
3742 {
3743     ngx_uint_t                  i, n;
3744     ngx_http_handler_pt        *log_handler;
3745     ngx_http_core_main_conf_t  *cmcf;
3746 
3747     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3748 
3749     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3750     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3751 
3752     for (i = 0; i < n; i++) {
3753         log_handler[i](r);
3754     }
3755 }
3756 
3757 
3758 void
3759 ngx_http_close_connection(ngx_connection_t *c)
3760 {
3761     ngx_pool_t  *pool;
3762 
3763     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3764                    "close http connection: %d", c->fd);
3765 
3766 #if (NGX_HTTP_SSL)
3767 
3768     if (c->ssl) {
3769         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3770             c->ssl->handler = ngx_http_close_connection;
3771             return;
3772         }
3773     }
3774 
3775 #endif
3776 
3777 #if (NGX_STAT_STUB)
3778     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3779 #endif
3780 
3781     c->destroyed = 1;
3782 
3783     pool = c->pool;
3784 
3785     ngx_close_connection(c);
3786 
3787     ngx_destroy_pool(pool);
3788 }
3789 
3790 
3791 static u_char *
3792 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3793 {
3794     u_char              *p;
3795     ngx_http_request_t  *r;
3796     ngx_http_log_ctx_t  *ctx;
3797 
3798     if (log->action) {
3799         p = ngx_snprintf(buf, len, " while %s", log->action);
3800         len -= p - buf;
3801         buf = p;
3802     }
3803 
3804     ctx = log->data;
3805 
3806     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3807     len -= p - buf;
3808 
3809     r = ctx->request;
3810 
3811     if (r) {
3812         return r->log_handler(r, ctx->current_request, p, len);
3813 
3814     } else {
3815         p = ngx_snprintf(p, len, ", server: %V",
3816                          &ctx->connection->listening->addr_text);
3817     }
3818 
3819     return p;
3820 }
3821 
3822 
3823 static u_char *
3824 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3825     u_char *buf, size_t len)
3826 {
3827     char                      *uri_separator;
3828     u_char                    *p;
3829     ngx_http_upstream_t       *u;
3830     ngx_http_core_srv_conf_t  *cscf;
3831 
3832     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3833 
3834     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3835     len -= p - buf;
3836     buf = p;
3837 
3838     if (r->request_line.data == NULL && r->request_start) {
3839         for (p = r->request_start; p < r->header_in->last; p++) {
3840             if (*p == CR || *p == LF) {
3841                 break;
3842             }
3843         }
3844 
3845         r->request_line.len = p - r->request_start;
3846         r->request_line.data = r->request_start;
3847     }
3848 
3849     if (r->request_line.len) {
3850         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3851         len -= p - buf;
3852         buf = p;
3853     }
3854 
3855     if (r != sr) {
3856         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3857         len -= p - buf;
3858         buf = p;
3859     }
3860 
3861     u = sr->upstream;
3862 
3863     if (u && u->peer.name) {
3864 
3865         uri_separator = "";
3866 
3867 #if (NGX_HAVE_UNIX_DOMAIN)
3868         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3869             uri_separator = ":";
3870         }
3871 #endif
3872 
3873         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3874                          &u->schema, u->peer.name,
3875                          uri_separator, &u->uri);
3876         len -= p - buf;
3877         buf = p;
3878     }
3879 
3880     if (r->headers_in.host) {
3881         p = ngx_snprintf(buf, len, ", host: \"%V\"",
3882                          &r->headers_in.host->value);
3883         len -= p - buf;
3884         buf = p;
3885     }
3886 
3887     if (r->headers_in.referer) {
3888         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3889                          &r->headers_in.referer->value);
3890         buf = p;
3891     }
3892 
3893     return buf;
3894 }
3895