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
ngx_http_init_connection(ngx_connection_t * c)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
ngx_http_wait_request_handler(ngx_event_t * rev)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 *
ngx_http_create_request(ngx_connection_t * c)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 *
ngx_http_alloc_request(ngx_connection_t * c)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) {
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
ngx_http_ssl_handshake(ngx_event_t * rev)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
ngx_http_ssl_handshake_handler(ngx_connection_t * c)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          || defined TLSEXT_TYPE_next_proto_neg))
811         {
812         unsigned int            len;
813         const unsigned char    *data;
814         ngx_http_connection_t  *hc;
815 
816         hc = c->data;
817 
818         if (hc->addr_conf->http2) {
819 
820 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
821             SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
822 
823 #ifdef TLSEXT_TYPE_next_proto_neg
824             if (len == 0) {
825                 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
826             }
827 #endif
828 
829 #else /* TLSEXT_TYPE_next_proto_neg */
830             SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
831 #endif
832 
833             if (len == 2 && data[0] == 'h' && data[1] == '2') {
834                 ngx_http_v2_init(c->read);
835                 return;
836             }
837         }
838         }
839 #endif
840 
841         c->log->action = "waiting for request";
842 
843         c->read->handler = ngx_http_wait_request_handler;
844         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
845 
846         ngx_reusable_connection(c, 1);
847 
848         ngx_http_wait_request_handler(c->read);
849 
850         return;
851     }
852 
853     if (c->read->timedout) {
854         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
855     }
856 
857     ngx_http_close_connection(c);
858 }
859 
860 
861 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
862 
863 int
ngx_http_ssl_servername(ngx_ssl_conn_t * ssl_conn,int * ad,void * arg)864 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
865 {
866     ngx_int_t                  rc;
867     ngx_str_t                  host;
868     const char                *servername;
869     ngx_connection_t          *c;
870     ngx_http_connection_t     *hc;
871     ngx_http_ssl_srv_conf_t   *sscf;
872     ngx_http_core_loc_conf_t  *clcf;
873     ngx_http_core_srv_conf_t  *cscf;
874 
875     c = ngx_ssl_get_connection(ssl_conn);
876 
877     if (c->ssl->handshaked) {
878         *ad = SSL_AD_NO_RENEGOTIATION;
879         return SSL_TLSEXT_ERR_ALERT_FATAL;
880     }
881 
882     hc = c->data;
883 
884     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
885 
886     if (servername == NULL) {
887         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
888                        "SSL server name: null");
889         goto done;
890     }
891 
892     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
893                    "SSL server name: \"%s\"", servername);
894 
895     host.len = ngx_strlen(servername);
896 
897     if (host.len == 0) {
898         goto done;
899     }
900 
901     host.data = (u_char *) servername;
902 
903     rc = ngx_http_validate_host(&host, c->pool, 1);
904 
905     if (rc == NGX_ERROR) {
906         goto error;
907     }
908 
909     if (rc == NGX_DECLINED) {
910         goto done;
911     }
912 
913     rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
914                                       NULL, &cscf);
915 
916     if (rc == NGX_ERROR) {
917         goto error;
918     }
919 
920     if (rc == NGX_DECLINED) {
921         goto done;
922     }
923 
924     hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
925     if (hc->ssl_servername == NULL) {
926         goto error;
927     }
928 
929     *hc->ssl_servername = host;
930 
931     hc->conf_ctx = cscf->ctx;
932 
933     clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
934 
935     ngx_set_connection_log(c, clcf->error_log);
936 
937     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
938 
939     c->ssl->buffer_size = sscf->buffer_size;
940 
941     if (sscf->ssl.ctx) {
942         if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
943             goto error;
944         }
945 
946         /*
947          * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
948          * adjust other things we care about
949          */
950 
951         SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
952                        SSL_CTX_get_verify_callback(sscf->ssl.ctx));
953 
954         SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
955 
956 #if OPENSSL_VERSION_NUMBER >= 0x009080dfL
957         /* only in 0.9.8m+ */
958         SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
959                                     ~SSL_CTX_get_options(sscf->ssl.ctx));
960 #endif
961 
962         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
963 
964 #ifdef SSL_OP_NO_RENEGOTIATION
965         SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION);
966 #endif
967     }
968 
969 done:
970 
971     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
972 
973     if (sscf->reject_handshake) {
974         c->ssl->handshake_rejected = 1;
975         *ad = SSL_AD_UNRECOGNIZED_NAME;
976         return SSL_TLSEXT_ERR_ALERT_FATAL;
977     }
978 
979     return SSL_TLSEXT_ERR_OK;
980 
981 error:
982 
983     *ad = SSL_AD_INTERNAL_ERROR;
984     return SSL_TLSEXT_ERR_ALERT_FATAL;
985 }
986 
987 #endif
988 
989 
990 #ifdef SSL_R_CERT_CB_ERROR
991 
992 int
ngx_http_ssl_certificate(ngx_ssl_conn_t * ssl_conn,void * arg)993 ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
994 {
995     ngx_str_t                  cert, key;
996     ngx_uint_t                 i, nelts;
997     ngx_connection_t          *c;
998     ngx_http_request_t        *r;
999     ngx_http_ssl_srv_conf_t   *sscf;
1000     ngx_http_complex_value_t  *certs, *keys;
1001 
1002     c = ngx_ssl_get_connection(ssl_conn);
1003 
1004     if (c->ssl->handshaked) {
1005         return 0;
1006     }
1007 
1008     r = ngx_http_alloc_request(c);
1009     if (r == NULL) {
1010         return 0;
1011     }
1012 
1013     r->logged = 1;
1014 
1015     sscf = arg;
1016 
1017     nelts = sscf->certificate_values->nelts;
1018     certs = sscf->certificate_values->elts;
1019     keys = sscf->certificate_key_values->elts;
1020 
1021     for (i = 0; i < nelts; i++) {
1022 
1023         if (ngx_http_complex_value(r, &certs[i], &cert) != NGX_OK) {
1024             goto failed;
1025         }
1026 
1027         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1028                        "ssl cert: \"%s\"", cert.data);
1029 
1030         if (ngx_http_complex_value(r, &keys[i], &key) != NGX_OK) {
1031             goto failed;
1032         }
1033 
1034         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1035                        "ssl key: \"%s\"", key.data);
1036 
1037         if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key,
1038                                            sscf->passwords)
1039             != NGX_OK)
1040         {
1041             goto failed;
1042         }
1043     }
1044 
1045     ngx_http_free_request(r, 0);
1046     c->destroyed = 0;
1047     return 1;
1048 
1049 failed:
1050 
1051     ngx_http_free_request(r, 0);
1052     c->destroyed = 0;
1053     return 0;
1054 }
1055 
1056 #endif
1057 
1058 #endif
1059 
1060 
1061 static void
ngx_http_process_request_line(ngx_event_t * rev)1062 ngx_http_process_request_line(ngx_event_t *rev)
1063 {
1064     ssize_t              n;
1065     ngx_int_t            rc, rv;
1066     ngx_str_t            host;
1067     ngx_connection_t    *c;
1068     ngx_http_request_t  *r;
1069 
1070     c = rev->data;
1071     r = c->data;
1072 
1073     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1074                    "http process request line");
1075 
1076     if (rev->timedout) {
1077         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1078         c->timedout = 1;
1079         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1080         return;
1081     }
1082 
1083     rc = NGX_AGAIN;
1084 
1085     for ( ;; ) {
1086 
1087         if (rc == NGX_AGAIN) {
1088             n = ngx_http_read_request_header(r);
1089 
1090             if (n == NGX_AGAIN || n == NGX_ERROR) {
1091                 break;
1092             }
1093         }
1094 
1095         rc = ngx_http_parse_request_line(r, r->header_in);
1096 
1097         if (rc == NGX_OK) {
1098 
1099             /* the request line has been parsed successfully */
1100 
1101             r->request_line.len = r->request_end - r->request_start;
1102             r->request_line.data = r->request_start;
1103             r->request_length = r->header_in->pos - r->request_start;
1104 
1105             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1106                            "http request line: \"%V\"", &r->request_line);
1107 
1108             r->method_name.len = r->method_end - r->request_start + 1;
1109             r->method_name.data = r->request_line.data;
1110 
1111             if (r->http_protocol.data) {
1112                 r->http_protocol.len = r->request_end - r->http_protocol.data;
1113             }
1114 
1115             if (ngx_http_process_request_uri(r) != NGX_OK) {
1116                 break;
1117             }
1118 
1119             if (r->schema_end) {
1120                 r->schema.len = r->schema_end - r->schema_start;
1121                 r->schema.data = r->schema_start;
1122             }
1123 
1124             if (r->host_end) {
1125 
1126                 host.len = r->host_end - r->host_start;
1127                 host.data = r->host_start;
1128 
1129                 rc = ngx_http_validate_host(&host, r->pool, 0);
1130 
1131                 if (rc == NGX_DECLINED) {
1132                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1133                                   "client sent invalid host in request line");
1134                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1135                     break;
1136                 }
1137 
1138                 if (rc == NGX_ERROR) {
1139                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1140                     break;
1141                 }
1142 
1143                 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1144                     break;
1145                 }
1146 
1147                 r->headers_in.server = host;
1148             }
1149 
1150             if (r->http_version < NGX_HTTP_VERSION_10) {
1151 
1152                 if (r->headers_in.server.len == 0
1153                     && ngx_http_set_virtual_server(r, &r->headers_in.server)
1154                        == NGX_ERROR)
1155                 {
1156                     break;
1157                 }
1158 
1159                 ngx_http_process_request(r);
1160                 break;
1161             }
1162 
1163 
1164             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
1165                               sizeof(ngx_table_elt_t))
1166                 != NGX_OK)
1167             {
1168                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1169                 break;
1170             }
1171 
1172             c->log->action = "reading client request headers";
1173 
1174             rev->handler = ngx_http_process_request_headers;
1175             ngx_http_process_request_headers(rev);
1176 
1177             break;
1178         }
1179 
1180         if (rc != NGX_AGAIN) {
1181 
1182             /* there was error while a request line parsing */
1183 
1184             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1185                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
1186 
1187             if (rc == NGX_HTTP_PARSE_INVALID_VERSION) {
1188                 ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED);
1189 
1190             } else {
1191                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1192             }
1193 
1194             break;
1195         }
1196 
1197         /* NGX_AGAIN: a request line parsing is still incomplete */
1198 
1199         if (r->header_in->pos == r->header_in->end) {
1200 
1201             rv = ngx_http_alloc_large_header_buffer(r, 1);
1202 
1203             if (rv == NGX_ERROR) {
1204                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1205                 break;
1206             }
1207 
1208             if (rv == NGX_DECLINED) {
1209                 r->request_line.len = r->header_in->end - r->request_start;
1210                 r->request_line.data = r->request_start;
1211 
1212                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1213                               "client sent too long URI");
1214                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
1215                 break;
1216             }
1217         }
1218     }
1219 
1220     ngx_http_run_posted_requests(c);
1221 }
1222 
1223 
1224 ngx_int_t
ngx_http_process_request_uri(ngx_http_request_t * r)1225 ngx_http_process_request_uri(ngx_http_request_t *r)
1226 {
1227     ngx_http_core_srv_conf_t  *cscf;
1228 
1229     if (r->args_start) {
1230         r->uri.len = r->args_start - 1 - r->uri_start;
1231     } else {
1232         r->uri.len = r->uri_end - r->uri_start;
1233     }
1234 
1235     if (r->complex_uri || r->quoted_uri || r->empty_path_in_uri) {
1236 
1237         if (r->empty_path_in_uri) {
1238             r->uri.len++;
1239         }
1240 
1241         r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1242         if (r->uri.data == NULL) {
1243             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1244             return NGX_ERROR;
1245         }
1246 
1247         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1248 
1249         if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1250             r->uri.len = 0;
1251 
1252             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1253                           "client sent invalid request");
1254             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1255             return NGX_ERROR;
1256         }
1257 
1258     } else {
1259         r->uri.data = r->uri_start;
1260     }
1261 
1262     r->unparsed_uri.len = r->uri_end - r->uri_start;
1263     r->unparsed_uri.data = r->uri_start;
1264 
1265     r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1;
1266 
1267     if (r->uri_ext) {
1268         if (r->args_start) {
1269             r->exten.len = r->args_start - 1 - r->uri_ext;
1270         } else {
1271             r->exten.len = r->uri_end - r->uri_ext;
1272         }
1273 
1274         r->exten.data = r->uri_ext;
1275     }
1276 
1277     if (r->args_start && r->uri_end > r->args_start) {
1278         r->args.len = r->uri_end - r->args_start;
1279         r->args.data = r->args_start;
1280     }
1281 
1282 #if (NGX_WIN32)
1283     {
1284     u_char  *p, *last;
1285 
1286     p = r->uri.data;
1287     last = r->uri.data + r->uri.len;
1288 
1289     while (p < last) {
1290 
1291         if (*p++ == ':') {
1292 
1293             /*
1294              * this check covers "::$data", "::$index_allocation" and
1295              * ":$i30:$index_allocation"
1296              */
1297 
1298             if (p < last && *p == '$') {
1299                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1300                               "client sent unsafe win32 URI");
1301                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1302                 return NGX_ERROR;
1303             }
1304         }
1305     }
1306 
1307     p = r->uri.data + r->uri.len - 1;
1308 
1309     while (p > r->uri.data) {
1310 
1311         if (*p == ' ') {
1312             p--;
1313             continue;
1314         }
1315 
1316         if (*p == '.') {
1317             p--;
1318             continue;
1319         }
1320 
1321         break;
1322     }
1323 
1324     if (p != r->uri.data + r->uri.len - 1) {
1325         r->uri.len = p + 1 - r->uri.data;
1326         ngx_http_set_exten(r);
1327     }
1328 
1329     }
1330 #endif
1331 
1332     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1333                    "http uri: \"%V\"", &r->uri);
1334 
1335     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1336                    "http args: \"%V\"", &r->args);
1337 
1338     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1339                    "http exten: \"%V\"", &r->exten);
1340 
1341     return NGX_OK;
1342 }
1343 
1344 
1345 static void
ngx_http_process_request_headers(ngx_event_t * rev)1346 ngx_http_process_request_headers(ngx_event_t *rev)
1347 {
1348     u_char                     *p;
1349     size_t                      len;
1350     ssize_t                     n;
1351     ngx_int_t                   rc, rv;
1352     ngx_table_elt_t            *h;
1353     ngx_connection_t           *c;
1354     ngx_http_header_t          *hh;
1355     ngx_http_request_t         *r;
1356     ngx_http_core_srv_conf_t   *cscf;
1357     ngx_http_core_main_conf_t  *cmcf;
1358 
1359     c = rev->data;
1360     r = c->data;
1361 
1362     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1363                    "http process request header line");
1364 
1365     if (rev->timedout) {
1366         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1367         c->timedout = 1;
1368         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1369         return;
1370     }
1371 
1372     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1373 
1374     rc = NGX_AGAIN;
1375 
1376     for ( ;; ) {
1377 
1378         if (rc == NGX_AGAIN) {
1379 
1380             if (r->header_in->pos == r->header_in->end) {
1381 
1382                 rv = ngx_http_alloc_large_header_buffer(r, 0);
1383 
1384                 if (rv == NGX_ERROR) {
1385                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1386                     break;
1387                 }
1388 
1389                 if (rv == NGX_DECLINED) {
1390                     p = r->header_name_start;
1391 
1392                     r->lingering_close = 1;
1393 
1394                     if (p == NULL) {
1395                         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1396                                       "client sent too large request");
1397                         ngx_http_finalize_request(r,
1398                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1399                         break;
1400                     }
1401 
1402                     len = r->header_in->end - p;
1403 
1404                     if (len > NGX_MAX_ERROR_STR - 300) {
1405                         len = NGX_MAX_ERROR_STR - 300;
1406                     }
1407 
1408                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1409                                 "client sent too long header line: \"%*s...\"",
1410                                 len, r->header_name_start);
1411 
1412                     ngx_http_finalize_request(r,
1413                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1414                     break;
1415                 }
1416             }
1417 
1418             n = ngx_http_read_request_header(r);
1419 
1420             if (n == NGX_AGAIN || n == NGX_ERROR) {
1421                 break;
1422             }
1423         }
1424 
1425         /* the host header could change the server configuration context */
1426         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1427 
1428         rc = ngx_http_parse_header_line(r, r->header_in,
1429                                         cscf->underscores_in_headers);
1430 
1431         if (rc == NGX_OK) {
1432 
1433             r->request_length += r->header_in->pos - r->header_name_start;
1434 
1435             if (r->invalid_header && cscf->ignore_invalid_headers) {
1436 
1437                 /* there was error while a header line parsing */
1438 
1439                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1440                               "client sent invalid header line: \"%*s\"",
1441                               r->header_end - r->header_name_start,
1442                               r->header_name_start);
1443                 continue;
1444             }
1445 
1446             /* a header line has been parsed successfully */
1447 
1448             h = ngx_list_push(&r->headers_in.headers);
1449             if (h == NULL) {
1450                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1451                 break;
1452             }
1453 
1454             h->hash = r->header_hash;
1455 
1456             h->key.len = r->header_name_end - r->header_name_start;
1457             h->key.data = r->header_name_start;
1458             h->key.data[h->key.len] = '\0';
1459 
1460             h->value.len = r->header_end - r->header_start;
1461             h->value.data = r->header_start;
1462             h->value.data[h->value.len] = '\0';
1463 
1464             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1465             if (h->lowcase_key == NULL) {
1466                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1467                 break;
1468             }
1469 
1470             if (h->key.len == r->lowcase_index) {
1471                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1472 
1473             } else {
1474                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1475             }
1476 
1477             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1478                                h->lowcase_key, h->key.len);
1479 
1480             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1481                 break;
1482             }
1483 
1484             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1485                            "http header: \"%V: %V\"",
1486                            &h->key, &h->value);
1487 
1488             continue;
1489         }
1490 
1491         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1492 
1493             /* a whole header has been parsed successfully */
1494 
1495             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1496                            "http header done");
1497 
1498             r->request_length += r->header_in->pos - r->header_name_start;
1499 
1500             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1501 
1502             rc = ngx_http_process_request_header(r);
1503 
1504             if (rc != NGX_OK) {
1505                 break;
1506             }
1507 
1508             ngx_http_process_request(r);
1509 
1510             break;
1511         }
1512 
1513         if (rc == NGX_AGAIN) {
1514 
1515             /* a header line parsing is still not complete */
1516 
1517             continue;
1518         }
1519 
1520         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
1521 
1522         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1523                       "client sent invalid header line");
1524 
1525         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1526         break;
1527     }
1528 
1529     ngx_http_run_posted_requests(c);
1530 }
1531 
1532 
1533 static ssize_t
ngx_http_read_request_header(ngx_http_request_t * r)1534 ngx_http_read_request_header(ngx_http_request_t *r)
1535 {
1536     ssize_t                    n;
1537     ngx_event_t               *rev;
1538     ngx_connection_t          *c;
1539     ngx_http_core_srv_conf_t  *cscf;
1540 
1541     c = r->connection;
1542     rev = c->read;
1543 
1544     n = r->header_in->last - r->header_in->pos;
1545 
1546     if (n > 0) {
1547         return n;
1548     }
1549 
1550     if (rev->ready) {
1551         n = c->recv(c, r->header_in->last,
1552                     r->header_in->end - r->header_in->last);
1553     } else {
1554         n = NGX_AGAIN;
1555     }
1556 
1557     if (n == NGX_AGAIN) {
1558         if (!rev->timer_set) {
1559             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1560             ngx_add_timer(rev, cscf->client_header_timeout);
1561         }
1562 
1563         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1564             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1565             return NGX_ERROR;
1566         }
1567 
1568         return NGX_AGAIN;
1569     }
1570 
1571     if (n == 0) {
1572         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1573                       "client prematurely closed connection");
1574     }
1575 
1576     if (n == 0 || n == NGX_ERROR) {
1577         c->error = 1;
1578         c->log->action = "reading client request headers";
1579 
1580         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1581         return NGX_ERROR;
1582     }
1583 
1584     r->header_in->last += n;
1585 
1586     return n;
1587 }
1588 
1589 
1590 static ngx_int_t
ngx_http_alloc_large_header_buffer(ngx_http_request_t * r,ngx_uint_t request_line)1591 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1592     ngx_uint_t request_line)
1593 {
1594     u_char                    *old, *new;
1595     ngx_buf_t                 *b;
1596     ngx_chain_t               *cl;
1597     ngx_http_connection_t     *hc;
1598     ngx_http_core_srv_conf_t  *cscf;
1599 
1600     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1601                    "http alloc large header buffer");
1602 
1603     if (request_line && r->state == 0) {
1604 
1605         /* the client fills up the buffer with "\r\n" */
1606 
1607         r->header_in->pos = r->header_in->start;
1608         r->header_in->last = r->header_in->start;
1609 
1610         return NGX_OK;
1611     }
1612 
1613     old = request_line ? r->request_start : r->header_name_start;
1614 
1615     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1616 
1617     if (r->state != 0
1618         && (size_t) (r->header_in->pos - old)
1619                                      >= cscf->large_client_header_buffers.size)
1620     {
1621         return NGX_DECLINED;
1622     }
1623 
1624     hc = r->http_connection;
1625 
1626     if (hc->free) {
1627         cl = hc->free;
1628         hc->free = cl->next;
1629 
1630         b = cl->buf;
1631 
1632         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1633                        "http large header free: %p %uz",
1634                        b->pos, b->end - b->last);
1635 
1636     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1637 
1638         b = ngx_create_temp_buf(r->connection->pool,
1639                                 cscf->large_client_header_buffers.size);
1640         if (b == NULL) {
1641             return NGX_ERROR;
1642         }
1643 
1644         cl = ngx_alloc_chain_link(r->connection->pool);
1645         if (cl == NULL) {
1646             return NGX_ERROR;
1647         }
1648 
1649         cl->buf = b;
1650 
1651         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1652                        "http large header alloc: %p %uz",
1653                        b->pos, b->end - b->last);
1654 
1655     } else {
1656         return NGX_DECLINED;
1657     }
1658 
1659     cl->next = hc->busy;
1660     hc->busy = cl;
1661     hc->nbusy++;
1662 
1663     if (r->state == 0) {
1664         /*
1665          * r->state == 0 means that a header line was parsed successfully
1666          * and we do not need to copy incomplete header line and
1667          * to relocate the parser header pointers
1668          */
1669 
1670         r->header_in = b;
1671 
1672         return NGX_OK;
1673     }
1674 
1675     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1676                    "http large header copy: %uz", r->header_in->pos - old);
1677 
1678     if (r->header_in->pos - old > b->end - b->start) {
1679         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1680                       "too large header to copy");
1681         return NGX_ERROR;
1682     }
1683 
1684     new = b->start;
1685 
1686     ngx_memcpy(new, old, r->header_in->pos - old);
1687 
1688     b->pos = new + (r->header_in->pos - old);
1689     b->last = new + (r->header_in->pos - old);
1690 
1691     if (request_line) {
1692         r->request_start = new;
1693 
1694         if (r->request_end) {
1695             r->request_end = new + (r->request_end - old);
1696         }
1697 
1698         r->method_end = new + (r->method_end - old);
1699 
1700         r->uri_start = new + (r->uri_start - old);
1701         r->uri_end = new + (r->uri_end - old);
1702 
1703         if (r->schema_start) {
1704             r->schema_start = new + (r->schema_start - old);
1705             r->schema_end = new + (r->schema_end - old);
1706         }
1707 
1708         if (r->host_start) {
1709             r->host_start = new + (r->host_start - old);
1710             if (r->host_end) {
1711                 r->host_end = new + (r->host_end - old);
1712             }
1713         }
1714 
1715         if (r->port_start) {
1716             r->port_start = new + (r->port_start - old);
1717             r->port_end = new + (r->port_end - old);
1718         }
1719 
1720         if (r->uri_ext) {
1721             r->uri_ext = new + (r->uri_ext - old);
1722         }
1723 
1724         if (r->args_start) {
1725             r->args_start = new + (r->args_start - old);
1726         }
1727 
1728         if (r->http_protocol.data) {
1729             r->http_protocol.data = new + (r->http_protocol.data - old);
1730         }
1731 
1732     } else {
1733         r->header_name_start = new;
1734         r->header_name_end = new + (r->header_name_end - old);
1735         r->header_start = new + (r->header_start - old);
1736         r->header_end = new + (r->header_end - old);
1737     }
1738 
1739     r->header_in = b;
1740 
1741     return NGX_OK;
1742 }
1743 
1744 
1745 static ngx_int_t
ngx_http_process_header_line(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1746 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1747     ngx_uint_t offset)
1748 {
1749     ngx_table_elt_t  **ph;
1750 
1751     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1752 
1753     if (*ph == NULL) {
1754         *ph = h;
1755     }
1756 
1757     return NGX_OK;
1758 }
1759 
1760 
1761 static ngx_int_t
ngx_http_process_unique_header_line(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1762 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1763     ngx_uint_t offset)
1764 {
1765     ngx_table_elt_t  **ph;
1766 
1767     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1768 
1769     if (*ph == NULL) {
1770         *ph = h;
1771         return NGX_OK;
1772     }
1773 
1774     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1775                   "client sent duplicate header line: \"%V: %V\", "
1776                   "previous value: \"%V: %V\"",
1777                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1778 
1779     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1780 
1781     return NGX_ERROR;
1782 }
1783 
1784 
1785 static ngx_int_t
ngx_http_process_host(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1786 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1787     ngx_uint_t offset)
1788 {
1789     ngx_int_t  rc;
1790     ngx_str_t  host;
1791 
1792     if (r->headers_in.host) {
1793         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1794                       "client sent duplicate host header: \"%V: %V\", "
1795                       "previous value: \"%V: %V\"",
1796                       &h->key, &h->value, &r->headers_in.host->key,
1797                       &r->headers_in.host->value);
1798         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1799         return NGX_ERROR;
1800     }
1801 
1802     r->headers_in.host = h;
1803 
1804     host = h->value;
1805 
1806     rc = ngx_http_validate_host(&host, r->pool, 0);
1807 
1808     if (rc == NGX_DECLINED) {
1809         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1810                       "client sent invalid host header");
1811         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1812         return NGX_ERROR;
1813     }
1814 
1815     if (rc == NGX_ERROR) {
1816         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1817         return NGX_ERROR;
1818     }
1819 
1820     if (r->headers_in.server.len) {
1821         return NGX_OK;
1822     }
1823 
1824     if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1825         return NGX_ERROR;
1826     }
1827 
1828     r->headers_in.server = host;
1829 
1830     return NGX_OK;
1831 }
1832 
1833 
1834 static ngx_int_t
ngx_http_process_connection(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1835 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1836     ngx_uint_t offset)
1837 {
1838     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1839         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1840 
1841     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1842         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1843     }
1844 
1845     return NGX_OK;
1846 }
1847 
1848 
1849 static ngx_int_t
ngx_http_process_user_agent(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1850 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1851     ngx_uint_t offset)
1852 {
1853     u_char  *user_agent, *msie;
1854 
1855     if (r->headers_in.user_agent) {
1856         return NGX_OK;
1857     }
1858 
1859     r->headers_in.user_agent = h;
1860 
1861     /* check some widespread browsers while the header is in CPU cache */
1862 
1863     user_agent = h->value.data;
1864 
1865     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1866 
1867     if (msie && msie + 7 < user_agent + h->value.len) {
1868 
1869         r->headers_in.msie = 1;
1870 
1871         if (msie[6] == '.') {
1872 
1873             switch (msie[5]) {
1874             case '4':
1875             case '5':
1876                 r->headers_in.msie6 = 1;
1877                 break;
1878             case '6':
1879                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1880                     r->headers_in.msie6 = 1;
1881                 }
1882                 break;
1883             }
1884         }
1885 
1886 #if 0
1887         /* MSIE ignores the SSL "close notify" alert */
1888         if (c->ssl) {
1889             c->ssl->no_send_shutdown = 1;
1890         }
1891 #endif
1892     }
1893 
1894     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1895         r->headers_in.opera = 1;
1896         r->headers_in.msie = 0;
1897         r->headers_in.msie6 = 0;
1898     }
1899 
1900     if (!r->headers_in.msie && !r->headers_in.opera) {
1901 
1902         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1903             r->headers_in.gecko = 1;
1904 
1905         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1906             r->headers_in.chrome = 1;
1907 
1908         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1909                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1910         {
1911             r->headers_in.safari = 1;
1912 
1913         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1914             r->headers_in.konqueror = 1;
1915         }
1916     }
1917 
1918     return NGX_OK;
1919 }
1920 
1921 
1922 static ngx_int_t
ngx_http_process_multi_header_lines(ngx_http_request_t * r,ngx_table_elt_t * h,ngx_uint_t offset)1923 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1924     ngx_uint_t offset)
1925 {
1926     ngx_array_t       *headers;
1927     ngx_table_elt_t  **ph;
1928 
1929     headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1930 
1931     if (headers->elts == NULL) {
1932         if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1933             != NGX_OK)
1934         {
1935             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1936             return NGX_ERROR;
1937         }
1938     }
1939 
1940     ph = ngx_array_push(headers);
1941     if (ph == NULL) {
1942         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1943         return NGX_ERROR;
1944     }
1945 
1946     *ph = h;
1947     return NGX_OK;
1948 }
1949 
1950 
1951 ngx_int_t
ngx_http_process_request_header(ngx_http_request_t * r)1952 ngx_http_process_request_header(ngx_http_request_t *r)
1953 {
1954     if (r->headers_in.server.len == 0
1955         && ngx_http_set_virtual_server(r, &r->headers_in.server)
1956            == NGX_ERROR)
1957     {
1958         return NGX_ERROR;
1959     }
1960 
1961     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1962         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1963                    "client sent HTTP/1.1 request without \"Host\" header");
1964         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1965         return NGX_ERROR;
1966     }
1967 
1968     if (r->headers_in.content_length) {
1969         r->headers_in.content_length_n =
1970                             ngx_atoof(r->headers_in.content_length->value.data,
1971                                       r->headers_in.content_length->value.len);
1972 
1973         if (r->headers_in.content_length_n == NGX_ERROR) {
1974             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1975                           "client sent invalid \"Content-Length\" header");
1976             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1977             return NGX_ERROR;
1978         }
1979     }
1980 
1981     if (r->method == NGX_HTTP_TRACE) {
1982         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1983                       "client sent TRACE method");
1984         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1985         return NGX_ERROR;
1986     }
1987 
1988     if (r->headers_in.transfer_encoding) {
1989         if (r->headers_in.transfer_encoding->value.len == 7
1990             && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1991                                (u_char *) "chunked", 7) == 0)
1992         {
1993             r->headers_in.content_length = NULL;
1994             r->headers_in.content_length_n = -1;
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     return NGX_OK;
2015 }
2016 
2017 
2018 void
ngx_http_process_request(ngx_http_request_t * r)2019 ngx_http_process_request(ngx_http_request_t *r)
2020 {
2021     ngx_connection_t  *c;
2022 
2023     c = r->connection;
2024 
2025 #if (NGX_HTTP_SSL)
2026 
2027     if (r->http_connection->ssl) {
2028         long                      rc;
2029         X509                     *cert;
2030         const char               *s;
2031         ngx_http_ssl_srv_conf_t  *sscf;
2032 
2033         if (c->ssl == NULL) {
2034             ngx_log_error(NGX_LOG_INFO, c->log, 0,
2035                           "client sent plain HTTP request to HTTPS port");
2036             ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
2037             return;
2038         }
2039 
2040         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
2041 
2042         if (sscf->verify) {
2043             rc = SSL_get_verify_result(c->ssl->connection);
2044 
2045             if (rc != X509_V_OK
2046                 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
2047             {
2048                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2049                               "client SSL certificate verify error: (%l:%s)",
2050                               rc, X509_verify_cert_error_string(rc));
2051 
2052                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
2053                                        (SSL_get0_session(c->ssl->connection)));
2054 
2055                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
2056                 return;
2057             }
2058 
2059             if (sscf->verify == 1) {
2060                 cert = SSL_get_peer_certificate(c->ssl->connection);
2061 
2062                 if (cert == NULL) {
2063                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
2064                                   "client sent no required SSL certificate");
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_NO_CERT);
2070                     return;
2071                 }
2072 
2073                 X509_free(cert);
2074             }
2075 
2076             if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
2077                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2078                               "client SSL certificate verify error: %s", s);
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_CERT_ERROR);
2084                 return;
2085             }
2086         }
2087     }
2088 
2089 #endif
2090 
2091     if (c->read->timer_set) {
2092         ngx_del_timer(c->read);
2093     }
2094 
2095 #if (NGX_STAT_STUB)
2096     (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
2097     r->stat_reading = 0;
2098     (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
2099     r->stat_writing = 1;
2100 #endif
2101 
2102     c->read->handler = ngx_http_request_handler;
2103     c->write->handler = ngx_http_request_handler;
2104     r->read_event_handler = ngx_http_block_reading;
2105 
2106     ngx_http_handler(r);
2107 }
2108 
2109 
2110 static ngx_int_t
ngx_http_validate_host(ngx_str_t * host,ngx_pool_t * pool,ngx_uint_t alloc)2111 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
2112 {
2113     u_char  *h, ch;
2114     size_t   i, dot_pos, host_len;
2115 
2116     enum {
2117         sw_usual = 0,
2118         sw_literal,
2119         sw_rest
2120     } state;
2121 
2122     dot_pos = host->len;
2123     host_len = host->len;
2124 
2125     h = host->data;
2126 
2127     state = sw_usual;
2128 
2129     for (i = 0; i < host->len; i++) {
2130         ch = h[i];
2131 
2132         switch (ch) {
2133 
2134         case '.':
2135             if (dot_pos == i - 1) {
2136                 return NGX_DECLINED;
2137             }
2138             dot_pos = i;
2139             break;
2140 
2141         case ':':
2142             if (state == sw_usual) {
2143                 host_len = i;
2144                 state = sw_rest;
2145             }
2146             break;
2147 
2148         case '[':
2149             if (i == 0) {
2150                 state = sw_literal;
2151             }
2152             break;
2153 
2154         case ']':
2155             if (state == sw_literal) {
2156                 host_len = i + 1;
2157                 state = sw_rest;
2158             }
2159             break;
2160 
2161         case '\0':
2162             return NGX_DECLINED;
2163 
2164         default:
2165 
2166             if (ngx_path_separator(ch)) {
2167                 return NGX_DECLINED;
2168             }
2169 
2170             if (ch >= 'A' && ch <= 'Z') {
2171                 alloc = 1;
2172             }
2173 
2174             break;
2175         }
2176     }
2177 
2178     if (dot_pos == host_len - 1) {
2179         host_len--;
2180     }
2181 
2182     if (host_len == 0) {
2183         return NGX_DECLINED;
2184     }
2185 
2186     if (alloc) {
2187         host->data = ngx_pnalloc(pool, host_len);
2188         if (host->data == NULL) {
2189             return NGX_ERROR;
2190         }
2191 
2192         ngx_strlow(host->data, h, host_len);
2193     }
2194 
2195     host->len = host_len;
2196 
2197     return NGX_OK;
2198 }
2199 
2200 
2201 static ngx_int_t
ngx_http_set_virtual_server(ngx_http_request_t * r,ngx_str_t * host)2202 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
2203 {
2204     ngx_int_t                  rc;
2205     ngx_http_connection_t     *hc;
2206     ngx_http_core_loc_conf_t  *clcf;
2207     ngx_http_core_srv_conf_t  *cscf;
2208 
2209 #if (NGX_SUPPRESS_WARN)
2210     cscf = NULL;
2211 #endif
2212 
2213     hc = r->http_connection;
2214 
2215 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2216 
2217     if (hc->ssl_servername) {
2218         if (hc->ssl_servername->len == host->len
2219             && ngx_strncmp(hc->ssl_servername->data,
2220                            host->data, host->len) == 0)
2221         {
2222 #if (NGX_PCRE)
2223             if (hc->ssl_servername_regex
2224                 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
2225                                           hc->ssl_servername) != NGX_OK)
2226             {
2227                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2228                 return NGX_ERROR;
2229             }
2230 #endif
2231             return NGX_OK;
2232         }
2233     }
2234 
2235 #endif
2236 
2237     rc = ngx_http_find_virtual_server(r->connection,
2238                                       hc->addr_conf->virtual_names,
2239                                       host, r, &cscf);
2240 
2241     if (rc == NGX_ERROR) {
2242         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2243         return NGX_ERROR;
2244     }
2245 
2246 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2247 
2248     if (hc->ssl_servername) {
2249         ngx_http_ssl_srv_conf_t  *sscf;
2250 
2251         if (rc == NGX_DECLINED) {
2252             cscf = hc->addr_conf->default_server;
2253             rc = NGX_OK;
2254         }
2255 
2256         sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2257 
2258         if (sscf->verify) {
2259             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2260                           "client attempted to request the server name "
2261                           "different from the one that was negotiated");
2262             ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
2263             return NGX_ERROR;
2264         }
2265     }
2266 
2267 #endif
2268 
2269     if (rc == NGX_DECLINED) {
2270         return NGX_OK;
2271     }
2272 
2273     r->srv_conf = cscf->ctx->srv_conf;
2274     r->loc_conf = cscf->ctx->loc_conf;
2275 
2276     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2277 
2278     ngx_set_connection_log(r->connection, clcf->error_log);
2279 
2280     return NGX_OK;
2281 }
2282 
2283 
2284 static ngx_int_t
ngx_http_find_virtual_server(ngx_connection_t * c,ngx_http_virtual_names_t * virtual_names,ngx_str_t * host,ngx_http_request_t * r,ngx_http_core_srv_conf_t ** cscfp)2285 ngx_http_find_virtual_server(ngx_connection_t *c,
2286     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2287     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2288 {
2289     ngx_http_core_srv_conf_t  *cscf;
2290 
2291     if (virtual_names == NULL) {
2292         return NGX_DECLINED;
2293     }
2294 
2295     cscf = ngx_hash_find_combined(&virtual_names->names,
2296                                   ngx_hash_key(host->data, host->len),
2297                                   host->data, host->len);
2298 
2299     if (cscf) {
2300         *cscfp = cscf;
2301         return NGX_OK;
2302     }
2303 
2304 #if (NGX_PCRE)
2305 
2306     if (host->len && virtual_names->nregex) {
2307         ngx_int_t                n;
2308         ngx_uint_t               i;
2309         ngx_http_server_name_t  *sn;
2310 
2311         sn = virtual_names->regex;
2312 
2313 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2314 
2315         if (r == NULL) {
2316             ngx_http_connection_t  *hc;
2317 
2318             for (i = 0; i < virtual_names->nregex; i++) {
2319 
2320                 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2321 
2322                 if (n == NGX_REGEX_NO_MATCHED) {
2323                     continue;
2324                 }
2325 
2326                 if (n >= 0) {
2327                     hc = c->data;
2328                     hc->ssl_servername_regex = sn[i].regex;
2329 
2330                     *cscfp = sn[i].server;
2331                     return NGX_OK;
2332                 }
2333 
2334                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2335                               ngx_regex_exec_n " failed: %i "
2336                               "on \"%V\" using \"%V\"",
2337                               n, host, &sn[i].regex->name);
2338 
2339                 return NGX_ERROR;
2340             }
2341 
2342             return NGX_DECLINED;
2343         }
2344 
2345 #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */
2346 
2347         for (i = 0; i < virtual_names->nregex; i++) {
2348 
2349             n = ngx_http_regex_exec(r, sn[i].regex, host);
2350 
2351             if (n == NGX_DECLINED) {
2352                 continue;
2353             }
2354 
2355             if (n == NGX_OK) {
2356                 *cscfp = sn[i].server;
2357                 return NGX_OK;
2358             }
2359 
2360             return NGX_ERROR;
2361         }
2362     }
2363 
2364 #endif /* NGX_PCRE */
2365 
2366     return NGX_DECLINED;
2367 }
2368 
2369 
2370 static void
ngx_http_request_handler(ngx_event_t * ev)2371 ngx_http_request_handler(ngx_event_t *ev)
2372 {
2373     ngx_connection_t    *c;
2374     ngx_http_request_t  *r;
2375 
2376     c = ev->data;
2377     r = c->data;
2378 
2379     ngx_http_set_log_request(c->log, r);
2380 
2381     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2382                    "http run request: \"%V?%V\"", &r->uri, &r->args);
2383 
2384     if (c->close) {
2385         r->main->count++;
2386         ngx_http_terminate_request(r, 0);
2387         ngx_http_run_posted_requests(c);
2388         return;
2389     }
2390 
2391     if (ev->delayed && ev->timedout) {
2392         ev->delayed = 0;
2393         ev->timedout = 0;
2394     }
2395 
2396     if (ev->write) {
2397         r->write_event_handler(r);
2398 
2399     } else {
2400         r->read_event_handler(r);
2401     }
2402 
2403     ngx_http_run_posted_requests(c);
2404 }
2405 
2406 
2407 void
ngx_http_run_posted_requests(ngx_connection_t * c)2408 ngx_http_run_posted_requests(ngx_connection_t *c)
2409 {
2410     ngx_http_request_t         *r;
2411     ngx_http_posted_request_t  *pr;
2412 
2413     for ( ;; ) {
2414 
2415         if (c->destroyed) {
2416             return;
2417         }
2418 
2419         r = c->data;
2420         pr = r->main->posted_requests;
2421 
2422         if (pr == NULL) {
2423             return;
2424         }
2425 
2426         r->main->posted_requests = pr->next;
2427 
2428         r = pr->request;
2429 
2430         ngx_http_set_log_request(c->log, r);
2431 
2432         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2433                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
2434 
2435         r->write_event_handler(r);
2436     }
2437 }
2438 
2439 
2440 ngx_int_t
ngx_http_post_request(ngx_http_request_t * r,ngx_http_posted_request_t * pr)2441 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2442 {
2443     ngx_http_posted_request_t  **p;
2444 
2445     if (pr == NULL) {
2446         pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2447         if (pr == NULL) {
2448             return NGX_ERROR;
2449         }
2450     }
2451 
2452     pr->request = r;
2453     pr->next = NULL;
2454 
2455     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2456 
2457     *p = pr;
2458 
2459     return NGX_OK;
2460 }
2461 
2462 
2463 void
ngx_http_finalize_request(ngx_http_request_t * r,ngx_int_t rc)2464 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2465 {
2466     ngx_connection_t          *c;
2467     ngx_http_request_t        *pr;
2468     ngx_http_core_loc_conf_t  *clcf;
2469 
2470     c = r->connection;
2471 
2472     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2473                    "http finalize request: %i, \"%V?%V\" a:%d, c:%d",
2474                    rc, &r->uri, &r->args, r == c->data, r->main->count);
2475 
2476     if (rc == NGX_DONE) {
2477         ngx_http_finalize_connection(r);
2478         return;
2479     }
2480 
2481     if (rc == NGX_OK && r->filter_finalize) {
2482         c->error = 1;
2483     }
2484 
2485     if (rc == NGX_DECLINED) {
2486         r->content_handler = NULL;
2487         r->write_event_handler = ngx_http_core_run_phases;
2488         ngx_http_core_run_phases(r);
2489         return;
2490     }
2491 
2492     if (r != r->main && r->post_subrequest) {
2493         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2494     }
2495 
2496     if (rc == NGX_ERROR
2497         || rc == NGX_HTTP_REQUEST_TIME_OUT
2498         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2499         || c->error)
2500     {
2501         if (ngx_http_post_action(r) == NGX_OK) {
2502             return;
2503         }
2504 
2505         ngx_http_terminate_request(r, rc);
2506         return;
2507     }
2508 
2509     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2510         || rc == NGX_HTTP_CREATED
2511         || rc == NGX_HTTP_NO_CONTENT)
2512     {
2513         if (rc == NGX_HTTP_CLOSE) {
2514             c->timedout = 1;
2515             ngx_http_terminate_request(r, rc);
2516             return;
2517         }
2518 
2519         if (r == r->main) {
2520             if (c->read->timer_set) {
2521                 ngx_del_timer(c->read);
2522             }
2523 
2524             if (c->write->timer_set) {
2525                 ngx_del_timer(c->write);
2526             }
2527         }
2528 
2529         c->read->handler = ngx_http_request_handler;
2530         c->write->handler = ngx_http_request_handler;
2531 
2532         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2533         return;
2534     }
2535 
2536     if (r != r->main) {
2537 
2538         if (r->buffered || r->postponed) {
2539 
2540             if (ngx_http_set_write_handler(r) != NGX_OK) {
2541                 ngx_http_terminate_request(r, 0);
2542             }
2543 
2544             return;
2545         }
2546 
2547         pr = r->parent;
2548 
2549         if (r == c->data || r->background) {
2550 
2551             if (!r->logged) {
2552 
2553                 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2554 
2555                 if (clcf->log_subrequest) {
2556                     ngx_http_log_request(r);
2557                 }
2558 
2559                 r->logged = 1;
2560 
2561             } else {
2562                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2563                               "subrequest: \"%V?%V\" logged again",
2564                               &r->uri, &r->args);
2565             }
2566 
2567             r->done = 1;
2568 
2569             if (r->background) {
2570                 ngx_http_finalize_connection(r);
2571                 return;
2572             }
2573 
2574             r->main->count--;
2575 
2576             if (pr->postponed && pr->postponed->request == r) {
2577                 pr->postponed = pr->postponed->next;
2578             }
2579 
2580             c->data = pr;
2581 
2582         } else {
2583 
2584             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2585                            "http finalize non-active request: \"%V?%V\"",
2586                            &r->uri, &r->args);
2587 
2588             r->write_event_handler = ngx_http_request_finalizer;
2589 
2590             if (r->waited) {
2591                 r->done = 1;
2592             }
2593         }
2594 
2595         if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2596             r->main->count++;
2597             ngx_http_terminate_request(r, 0);
2598             return;
2599         }
2600 
2601         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2602                        "http wake parent request: \"%V?%V\"",
2603                        &pr->uri, &pr->args);
2604 
2605         return;
2606     }
2607 
2608     if (r->buffered || c->buffered || r->postponed) {
2609 
2610         if (ngx_http_set_write_handler(r) != NGX_OK) {
2611             ngx_http_terminate_request(r, 0);
2612         }
2613 
2614         return;
2615     }
2616 
2617     if (r != c->data) {
2618         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2619                       "http finalize non-active request: \"%V?%V\"",
2620                       &r->uri, &r->args);
2621         return;
2622     }
2623 
2624     r->done = 1;
2625 
2626     r->read_event_handler = ngx_http_block_reading;
2627     r->write_event_handler = ngx_http_request_empty_handler;
2628 
2629     if (!r->post_action) {
2630         r->request_complete = 1;
2631     }
2632 
2633     if (ngx_http_post_action(r) == NGX_OK) {
2634         return;
2635     }
2636 
2637     if (c->read->timer_set) {
2638         ngx_del_timer(c->read);
2639     }
2640 
2641     if (c->write->timer_set) {
2642         c->write->delayed = 0;
2643         ngx_del_timer(c->write);
2644     }
2645 
2646     ngx_http_finalize_connection(r);
2647 }
2648 
2649 
2650 static void
ngx_http_terminate_request(ngx_http_request_t * r,ngx_int_t rc)2651 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2652 {
2653     ngx_http_cleanup_t    *cln;
2654     ngx_http_request_t    *mr;
2655     ngx_http_ephemeral_t  *e;
2656 
2657     mr = r->main;
2658 
2659     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2660                    "http terminate request count:%d", mr->count);
2661 
2662     if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2663         mr->headers_out.status = rc;
2664     }
2665 
2666     cln = mr->cleanup;
2667     mr->cleanup = NULL;
2668 
2669     while (cln) {
2670         if (cln->handler) {
2671             cln->handler(cln->data);
2672         }
2673 
2674         cln = cln->next;
2675     }
2676 
2677     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2678                    "http terminate cleanup count:%d blk:%d",
2679                    mr->count, mr->blocked);
2680 
2681     if (mr->write_event_handler) {
2682 
2683         if (mr->blocked) {
2684             r->connection->error = 1;
2685             r->write_event_handler = ngx_http_request_finalizer;
2686             return;
2687         }
2688 
2689         e = ngx_http_ephemeral(mr);
2690         mr->posted_requests = NULL;
2691         mr->write_event_handler = ngx_http_terminate_handler;
2692         (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2693         return;
2694     }
2695 
2696     ngx_http_close_request(mr, rc);
2697 }
2698 
2699 
2700 static void
ngx_http_terminate_handler(ngx_http_request_t * r)2701 ngx_http_terminate_handler(ngx_http_request_t *r)
2702 {
2703     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2704                    "http terminate handler count:%d", r->count);
2705 
2706     r->count = 1;
2707 
2708     ngx_http_close_request(r, 0);
2709 }
2710 
2711 
2712 static void
ngx_http_finalize_connection(ngx_http_request_t * r)2713 ngx_http_finalize_connection(ngx_http_request_t *r)
2714 {
2715     ngx_http_core_loc_conf_t  *clcf;
2716 
2717 #if (NGX_HTTP_V2)
2718     if (r->stream) {
2719         ngx_http_close_request(r, 0);
2720         return;
2721     }
2722 #endif
2723 
2724     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2725 
2726     if (r->main->count != 1) {
2727 
2728         if (r->discard_body) {
2729             r->read_event_handler = ngx_http_discarded_request_body_handler;
2730             ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2731 
2732             if (r->lingering_time == 0) {
2733                 r->lingering_time = ngx_time()
2734                                       + (time_t) (clcf->lingering_time / 1000);
2735             }
2736         }
2737 
2738         ngx_http_close_request(r, 0);
2739         return;
2740     }
2741 
2742     r = r->main;
2743 
2744     if (r->connection->read->eof) {
2745         ngx_http_close_request(r, 0);
2746         return;
2747     }
2748 
2749     if (r->reading_body) {
2750         r->keepalive = 0;
2751         r->lingering_close = 1;
2752     }
2753 
2754     if (!ngx_terminate
2755          && !ngx_exiting
2756          && r->keepalive
2757          && clcf->keepalive_timeout > 0)
2758     {
2759         ngx_http_set_keepalive(r);
2760         return;
2761     }
2762 
2763     if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2764         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2765             && (r->lingering_close
2766                 || r->header_in->pos < r->header_in->last
2767                 || r->connection->read->ready)))
2768     {
2769         ngx_http_set_lingering_close(r->connection);
2770         return;
2771     }
2772 
2773     ngx_http_close_request(r, 0);
2774 }
2775 
2776 
2777 static ngx_int_t
ngx_http_set_write_handler(ngx_http_request_t * r)2778 ngx_http_set_write_handler(ngx_http_request_t *r)
2779 {
2780     ngx_event_t               *wev;
2781     ngx_http_core_loc_conf_t  *clcf;
2782 
2783     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2784 
2785     r->read_event_handler = r->discard_body ?
2786                                 ngx_http_discarded_request_body_handler:
2787                                 ngx_http_test_reading;
2788     r->write_event_handler = ngx_http_writer;
2789 
2790     wev = r->connection->write;
2791 
2792     if (wev->ready && wev->delayed) {
2793         return NGX_OK;
2794     }
2795 
2796     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2797     if (!wev->delayed) {
2798         ngx_add_timer(wev, clcf->send_timeout);
2799     }
2800 
2801     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2802         ngx_http_close_request(r, 0);
2803         return NGX_ERROR;
2804     }
2805 
2806     return NGX_OK;
2807 }
2808 
2809 
2810 static void
ngx_http_writer(ngx_http_request_t * r)2811 ngx_http_writer(ngx_http_request_t *r)
2812 {
2813     ngx_int_t                  rc;
2814     ngx_event_t               *wev;
2815     ngx_connection_t          *c;
2816     ngx_http_core_loc_conf_t  *clcf;
2817 
2818     c = r->connection;
2819     wev = c->write;
2820 
2821     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2822                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2823 
2824     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2825 
2826     if (wev->timedout) {
2827         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2828                       "client timed out");
2829         c->timedout = 1;
2830 
2831         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2832         return;
2833     }
2834 
2835     if (wev->delayed || r->aio) {
2836         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2837                        "http writer delayed");
2838 
2839         if (!wev->delayed) {
2840             ngx_add_timer(wev, clcf->send_timeout);
2841         }
2842 
2843         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2844             ngx_http_close_request(r, 0);
2845         }
2846 
2847         return;
2848     }
2849 
2850     rc = ngx_http_output_filter(r, NULL);
2851 
2852     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2853                    "http writer output filter: %i, \"%V?%V\"",
2854                    rc, &r->uri, &r->args);
2855 
2856     if (rc == NGX_ERROR) {
2857         ngx_http_finalize_request(r, rc);
2858         return;
2859     }
2860 
2861     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2862 
2863         if (!wev->delayed) {
2864             ngx_add_timer(wev, clcf->send_timeout);
2865         }
2866 
2867         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2868             ngx_http_close_request(r, 0);
2869         }
2870 
2871         return;
2872     }
2873 
2874     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2875                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
2876 
2877     r->write_event_handler = ngx_http_request_empty_handler;
2878 
2879     ngx_http_finalize_request(r, rc);
2880 }
2881 
2882 
2883 static void
ngx_http_request_finalizer(ngx_http_request_t * r)2884 ngx_http_request_finalizer(ngx_http_request_t *r)
2885 {
2886     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2887                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2888 
2889     ngx_http_finalize_request(r, 0);
2890 }
2891 
2892 
2893 void
ngx_http_block_reading(ngx_http_request_t * r)2894 ngx_http_block_reading(ngx_http_request_t *r)
2895 {
2896     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2897                    "http reading blocked");
2898 
2899     /* aio does not call this handler */
2900 
2901     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2902         && r->connection->read->active)
2903     {
2904         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2905             ngx_http_close_request(r, 0);
2906         }
2907     }
2908 }
2909 
2910 
2911 void
ngx_http_test_reading(ngx_http_request_t * r)2912 ngx_http_test_reading(ngx_http_request_t *r)
2913 {
2914     int                n;
2915     char               buf[1];
2916     ngx_err_t          err;
2917     ngx_event_t       *rev;
2918     ngx_connection_t  *c;
2919 
2920     c = r->connection;
2921     rev = c->read;
2922 
2923     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2924 
2925 #if (NGX_HTTP_V2)
2926 
2927     if (r->stream) {
2928         if (c->error) {
2929             err = 0;
2930             goto closed;
2931         }
2932 
2933         return;
2934     }
2935 
2936 #endif
2937 
2938 #if (NGX_HAVE_KQUEUE)
2939 
2940     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2941 
2942         if (!rev->pending_eof) {
2943             return;
2944         }
2945 
2946         rev->eof = 1;
2947         c->error = 1;
2948         err = rev->kq_errno;
2949 
2950         goto closed;
2951     }
2952 
2953 #endif
2954 
2955 #if (NGX_HAVE_EPOLLRDHUP)
2956 
2957     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
2958         socklen_t  len;
2959 
2960         if (!rev->pending_eof) {
2961             return;
2962         }
2963 
2964         rev->eof = 1;
2965         c->error = 1;
2966 
2967         err = 0;
2968         len = sizeof(ngx_err_t);
2969 
2970         /*
2971          * BSDs and Linux return 0 and set a pending error in err
2972          * Solaris returns -1 and sets errno
2973          */
2974 
2975         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
2976             == -1)
2977         {
2978             err = ngx_socket_errno;
2979         }
2980 
2981         goto closed;
2982     }
2983 
2984 #endif
2985 
2986     n = recv(c->fd, buf, 1, MSG_PEEK);
2987 
2988     if (n == 0) {
2989         rev->eof = 1;
2990         c->error = 1;
2991         err = 0;
2992 
2993         goto closed;
2994 
2995     } else if (n == -1) {
2996         err = ngx_socket_errno;
2997 
2998         if (err != NGX_EAGAIN) {
2999             rev->eof = 1;
3000             c->error = 1;
3001 
3002             goto closed;
3003         }
3004     }
3005 
3006     /* aio does not call this handler */
3007 
3008     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
3009 
3010         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
3011             ngx_http_close_request(r, 0);
3012         }
3013     }
3014 
3015     return;
3016 
3017 closed:
3018 
3019     if (err) {
3020         rev->error = 1;
3021     }
3022 
3023 #if (NGX_HTTP_SSL)
3024     if (c->ssl) {
3025         c->ssl->no_send_shutdown = 1;
3026     }
3027 #endif
3028 
3029     ngx_log_error(NGX_LOG_INFO, c->log, err,
3030                   "client prematurely closed connection");
3031 
3032     ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
3033 }
3034 
3035 
3036 static void
ngx_http_set_keepalive(ngx_http_request_t * r)3037 ngx_http_set_keepalive(ngx_http_request_t *r)
3038 {
3039     int                        tcp_nodelay;
3040     ngx_buf_t                 *b, *f;
3041     ngx_chain_t               *cl, *ln;
3042     ngx_event_t               *rev, *wev;
3043     ngx_connection_t          *c;
3044     ngx_http_connection_t     *hc;
3045     ngx_http_core_loc_conf_t  *clcf;
3046 
3047     c = r->connection;
3048     rev = c->read;
3049 
3050     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3051 
3052     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
3053 
3054     c->log->action = "closing request";
3055 
3056     hc = r->http_connection;
3057     b = r->header_in;
3058 
3059     if (b->pos < b->last) {
3060 
3061         /* the pipelined request */
3062 
3063         if (b != c->buffer) {
3064 
3065             /*
3066              * If the large header buffers were allocated while the previous
3067              * request processing then we do not use c->buffer for
3068              * the pipelined request (see ngx_http_create_request()).
3069              *
3070              * Now we would move the large header buffers to the free list.
3071              */
3072 
3073             for (cl = hc->busy; cl; /* void */) {
3074                 ln = cl;
3075                 cl = cl->next;
3076 
3077                 if (ln->buf == b) {
3078                     ngx_free_chain(c->pool, ln);
3079                     continue;
3080                 }
3081 
3082                 f = ln->buf;
3083                 f->pos = f->start;
3084                 f->last = f->start;
3085 
3086                 ln->next = hc->free;
3087                 hc->free = ln;
3088             }
3089 
3090             cl = ngx_alloc_chain_link(c->pool);
3091             if (cl == NULL) {
3092                 ngx_http_close_request(r, 0);
3093                 return;
3094             }
3095 
3096             cl->buf = b;
3097             cl->next = NULL;
3098 
3099             hc->busy = cl;
3100             hc->nbusy = 1;
3101         }
3102     }
3103 
3104     /* guard against recursive call from ngx_http_finalize_connection() */
3105     r->keepalive = 0;
3106 
3107     ngx_http_free_request(r, 0);
3108 
3109     c->data = hc;
3110 
3111     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3112         ngx_http_close_connection(c);
3113         return;
3114     }
3115 
3116     wev = c->write;
3117     wev->handler = ngx_http_empty_handler;
3118 
3119     if (b->pos < b->last) {
3120 
3121         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
3122 
3123         c->log->action = "reading client pipelined request line";
3124 
3125         r = ngx_http_create_request(c);
3126         if (r == NULL) {
3127             ngx_http_close_connection(c);
3128             return;
3129         }
3130 
3131         r->pipeline = 1;
3132 
3133         c->data = r;
3134 
3135         c->sent = 0;
3136         c->destroyed = 0;
3137 
3138         if (rev->timer_set) {
3139             ngx_del_timer(rev);
3140         }
3141 
3142         rev->handler = ngx_http_process_request_line;
3143         ngx_post_event(rev, &ngx_posted_events);
3144         return;
3145     }
3146 
3147     /*
3148      * To keep a memory footprint as small as possible for an idle keepalive
3149      * connection we try to free c->buffer's memory if it was allocated outside
3150      * the c->pool.  The large header buffers are always allocated outside the
3151      * c->pool and are freed too.
3152      */
3153 
3154     b = c->buffer;
3155 
3156     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3157 
3158         /*
3159          * the special note for ngx_http_keepalive_handler() that
3160          * c->buffer's memory was freed
3161          */
3162 
3163         b->pos = NULL;
3164 
3165     } else {
3166         b->pos = b->start;
3167         b->last = b->start;
3168     }
3169 
3170     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
3171                    hc->free);
3172 
3173     if (hc->free) {
3174         for (cl = hc->free; cl; /* void */) {
3175             ln = cl;
3176             cl = cl->next;
3177             ngx_pfree(c->pool, ln->buf->start);
3178             ngx_free_chain(c->pool, ln);
3179         }
3180 
3181         hc->free = NULL;
3182     }
3183 
3184     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
3185                    hc->busy, hc->nbusy);
3186 
3187     if (hc->busy) {
3188         for (cl = hc->busy; cl; /* void */) {
3189             ln = cl;
3190             cl = cl->next;
3191             ngx_pfree(c->pool, ln->buf->start);
3192             ngx_free_chain(c->pool, ln);
3193         }
3194 
3195         hc->busy = NULL;
3196         hc->nbusy = 0;
3197     }
3198 
3199 #if (NGX_HTTP_SSL)
3200     if (c->ssl) {
3201         ngx_ssl_free_buffer(c);
3202     }
3203 #endif
3204 
3205     rev->handler = ngx_http_keepalive_handler;
3206 
3207     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3208         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3209             ngx_http_close_connection(c);
3210             return;
3211         }
3212     }
3213 
3214     c->log->action = "keepalive";
3215 
3216     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
3217         if (ngx_tcp_push(c->fd) == -1) {
3218             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
3219             ngx_http_close_connection(c);
3220             return;
3221         }
3222 
3223         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
3224         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
3225 
3226     } else {
3227         tcp_nodelay = 1;
3228     }
3229 
3230     if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
3231         ngx_http_close_connection(c);
3232         return;
3233     }
3234 
3235 #if 0
3236     /* if ngx_http_request_t was freed then we need some other place */
3237     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
3238 #endif
3239 
3240     c->idle = 1;
3241     ngx_reusable_connection(c, 1);
3242 
3243     ngx_add_timer(rev, clcf->keepalive_timeout);
3244 
3245     if (rev->ready) {
3246         ngx_post_event(rev, &ngx_posted_events);
3247     }
3248 }
3249 
3250 
3251 static void
ngx_http_keepalive_handler(ngx_event_t * rev)3252 ngx_http_keepalive_handler(ngx_event_t *rev)
3253 {
3254     size_t             size;
3255     ssize_t            n;
3256     ngx_buf_t         *b;
3257     ngx_connection_t  *c;
3258 
3259     c = rev->data;
3260 
3261     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
3262 
3263     if (rev->timedout || c->close) {
3264         ngx_http_close_connection(c);
3265         return;
3266     }
3267 
3268 #if (NGX_HAVE_KQUEUE)
3269 
3270     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
3271         if (rev->pending_eof) {
3272             c->log->handler = NULL;
3273             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
3274                           "kevent() reported that client %V closed "
3275                           "keepalive connection", &c->addr_text);
3276 #if (NGX_HTTP_SSL)
3277             if (c->ssl) {
3278                 c->ssl->no_send_shutdown = 1;
3279             }
3280 #endif
3281             ngx_http_close_connection(c);
3282             return;
3283         }
3284     }
3285 
3286 #endif
3287 
3288     b = c->buffer;
3289     size = b->end - b->start;
3290 
3291     if (b->pos == NULL) {
3292 
3293         /*
3294          * The c->buffer's memory was freed by ngx_http_set_keepalive().
3295          * However, the c->buffer->start and c->buffer->end were not changed
3296          * to keep the buffer size.
3297          */
3298 
3299         b->pos = ngx_palloc(c->pool, size);
3300         if (b->pos == NULL) {
3301             ngx_http_close_connection(c);
3302             return;
3303         }
3304 
3305         b->start = b->pos;
3306         b->last = b->pos;
3307         b->end = b->pos + size;
3308     }
3309 
3310     /*
3311      * MSIE closes a keepalive connection with RST flag
3312      * so we ignore ECONNRESET here.
3313      */
3314 
3315     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3316     ngx_set_socket_errno(0);
3317 
3318     n = c->recv(c, b->last, size);
3319     c->log_error = NGX_ERROR_INFO;
3320 
3321     if (n == NGX_AGAIN) {
3322         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3323             ngx_http_close_connection(c);
3324             return;
3325         }
3326 
3327         /*
3328          * Like ngx_http_set_keepalive() we are trying to not hold
3329          * c->buffer's memory for a keepalive connection.
3330          */
3331 
3332         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3333 
3334             /*
3335              * the special note that c->buffer's memory was freed
3336              */
3337 
3338             b->pos = NULL;
3339         }
3340 
3341         return;
3342     }
3343 
3344     if (n == NGX_ERROR) {
3345         ngx_http_close_connection(c);
3346         return;
3347     }
3348 
3349     c->log->handler = NULL;
3350 
3351     if (n == 0) {
3352         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3353                       "client %V closed keepalive connection", &c->addr_text);
3354         ngx_http_close_connection(c);
3355         return;
3356     }
3357 
3358     b->last += n;
3359 
3360     c->log->handler = ngx_http_log_error;
3361     c->log->action = "reading client request line";
3362 
3363     c->idle = 0;
3364     ngx_reusable_connection(c, 0);
3365 
3366     c->data = ngx_http_create_request(c);
3367     if (c->data == NULL) {
3368         ngx_http_close_connection(c);
3369         return;
3370     }
3371 
3372     c->sent = 0;
3373     c->destroyed = 0;
3374 
3375     ngx_del_timer(rev);
3376 
3377     rev->handler = ngx_http_process_request_line;
3378     ngx_http_process_request_line(rev);
3379 }
3380 
3381 
3382 static void
ngx_http_set_lingering_close(ngx_connection_t * c)3383 ngx_http_set_lingering_close(ngx_connection_t *c)
3384 {
3385     ngx_event_t               *rev, *wev;
3386     ngx_http_request_t        *r;
3387     ngx_http_core_loc_conf_t  *clcf;
3388 
3389     r = c->data;
3390 
3391     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3392 
3393     if (r->lingering_time == 0) {
3394         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3395     }
3396 
3397 #if (NGX_HTTP_SSL)
3398     if (c->ssl) {
3399         ngx_int_t  rc;
3400 
3401         c->ssl->shutdown_without_free = 1;
3402 
3403         rc = ngx_ssl_shutdown(c);
3404 
3405         if (rc == NGX_ERROR) {
3406             ngx_http_close_request(r, 0);
3407             return;
3408         }
3409 
3410         if (rc == NGX_AGAIN) {
3411             c->ssl->handler = ngx_http_set_lingering_close;
3412             return;
3413         }
3414     }
3415 #endif
3416 
3417     rev = c->read;
3418     rev->handler = ngx_http_lingering_close_handler;
3419 
3420     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3421         ngx_http_close_request(r, 0);
3422         return;
3423     }
3424 
3425     wev = c->write;
3426     wev->handler = ngx_http_empty_handler;
3427 
3428     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3429         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3430             ngx_http_close_request(r, 0);
3431             return;
3432         }
3433     }
3434 
3435     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3436         ngx_connection_error(c, ngx_socket_errno,
3437                              ngx_shutdown_socket_n " failed");
3438         ngx_http_close_request(r, 0);
3439         return;
3440     }
3441 
3442     c->close = 0;
3443     ngx_reusable_connection(c, 1);
3444 
3445     ngx_add_timer(rev, clcf->lingering_timeout);
3446 
3447     if (rev->ready) {
3448         ngx_http_lingering_close_handler(rev);
3449     }
3450 }
3451 
3452 
3453 static void
ngx_http_lingering_close_handler(ngx_event_t * rev)3454 ngx_http_lingering_close_handler(ngx_event_t *rev)
3455 {
3456     ssize_t                    n;
3457     ngx_msec_t                 timer;
3458     ngx_connection_t          *c;
3459     ngx_http_request_t        *r;
3460     ngx_http_core_loc_conf_t  *clcf;
3461     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3462 
3463     c = rev->data;
3464     r = c->data;
3465 
3466     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3467                    "http lingering close handler");
3468 
3469     if (rev->timedout || c->close) {
3470         ngx_http_close_request(r, 0);
3471         return;
3472     }
3473 
3474     timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
3475     if ((ngx_msec_int_t) timer <= 0) {
3476         ngx_http_close_request(r, 0);
3477         return;
3478     }
3479 
3480     do {
3481         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3482 
3483         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
3484 
3485         if (n == NGX_AGAIN) {
3486             break;
3487         }
3488 
3489         if (n == NGX_ERROR || n == 0) {
3490             ngx_http_close_request(r, 0);
3491             return;
3492         }
3493 
3494     } while (rev->ready);
3495 
3496     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3497         ngx_http_close_request(r, 0);
3498         return;
3499     }
3500 
3501     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3502 
3503     timer *= 1000;
3504 
3505     if (timer > clcf->lingering_timeout) {
3506         timer = clcf->lingering_timeout;
3507     }
3508 
3509     ngx_add_timer(rev, timer);
3510 }
3511 
3512 
3513 void
ngx_http_empty_handler(ngx_event_t * wev)3514 ngx_http_empty_handler(ngx_event_t *wev)
3515 {
3516     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3517 
3518     return;
3519 }
3520 
3521 
3522 void
ngx_http_request_empty_handler(ngx_http_request_t * r)3523 ngx_http_request_empty_handler(ngx_http_request_t *r)
3524 {
3525     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3526                    "http request empty handler");
3527 
3528     return;
3529 }
3530 
3531 
3532 ngx_int_t
ngx_http_send_special(ngx_http_request_t * r,ngx_uint_t flags)3533 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3534 {
3535     ngx_buf_t    *b;
3536     ngx_chain_t   out;
3537 
3538     b = ngx_calloc_buf(r->pool);
3539     if (b == NULL) {
3540         return NGX_ERROR;
3541     }
3542 
3543     if (flags & NGX_HTTP_LAST) {
3544 
3545         if (r == r->main && !r->post_action) {
3546             b->last_buf = 1;
3547 
3548         } else {
3549             b->sync = 1;
3550             b->last_in_chain = 1;
3551         }
3552     }
3553 
3554     if (flags & NGX_HTTP_FLUSH) {
3555         b->flush = 1;
3556     }
3557 
3558     out.buf = b;
3559     out.next = NULL;
3560 
3561     return ngx_http_output_filter(r, &out);
3562 }
3563 
3564 
3565 static ngx_int_t
ngx_http_post_action(ngx_http_request_t * r)3566 ngx_http_post_action(ngx_http_request_t *r)
3567 {
3568     ngx_http_core_loc_conf_t  *clcf;
3569 
3570     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3571 
3572     if (clcf->post_action.data == NULL) {
3573         return NGX_DECLINED;
3574     }
3575 
3576     if (r->post_action && r->uri_changes == 0) {
3577         return NGX_DECLINED;
3578     }
3579 
3580     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3581                    "post action: \"%V\"", &clcf->post_action);
3582 
3583     r->main->count--;
3584 
3585     r->http_version = NGX_HTTP_VERSION_9;
3586     r->header_only = 1;
3587     r->post_action = 1;
3588 
3589     r->read_event_handler = ngx_http_block_reading;
3590 
3591     if (clcf->post_action.data[0] == '/') {
3592         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3593 
3594     } else {
3595         ngx_http_named_location(r, &clcf->post_action);
3596     }
3597 
3598     return NGX_OK;
3599 }
3600 
3601 
3602 static void
ngx_http_close_request(ngx_http_request_t * r,ngx_int_t rc)3603 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3604 {
3605     ngx_connection_t  *c;
3606 
3607     r = r->main;
3608     c = r->connection;
3609 
3610     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3611                    "http request count:%d blk:%d", r->count, r->blocked);
3612 
3613     if (r->count == 0) {
3614         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3615     }
3616 
3617     r->count--;
3618 
3619     if (r->count || r->blocked) {
3620         return;
3621     }
3622 
3623 #if (NGX_HTTP_V2)
3624     if (r->stream) {
3625         ngx_http_v2_close_stream(r->stream, rc);
3626         return;
3627     }
3628 #endif
3629 
3630     ngx_http_free_request(r, rc);
3631     ngx_http_close_connection(c);
3632 }
3633 
3634 
3635 void
ngx_http_free_request(ngx_http_request_t * r,ngx_int_t rc)3636 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3637 {
3638     ngx_log_t                 *log;
3639     ngx_pool_t                *pool;
3640     struct linger              linger;
3641     ngx_http_cleanup_t        *cln;
3642     ngx_http_log_ctx_t        *ctx;
3643     ngx_http_core_loc_conf_t  *clcf;
3644 
3645     log = r->connection->log;
3646 
3647     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3648 
3649     if (r->pool == NULL) {
3650         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3651         return;
3652     }
3653 
3654     cln = r->cleanup;
3655     r->cleanup = NULL;
3656 
3657     while (cln) {
3658         if (cln->handler) {
3659             cln->handler(cln->data);
3660         }
3661 
3662         cln = cln->next;
3663     }
3664 
3665 #if (NGX_STAT_STUB)
3666 
3667     if (r->stat_reading) {
3668         (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3669     }
3670 
3671     if (r->stat_writing) {
3672         (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3673     }
3674 
3675 #endif
3676 
3677     if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3678         r->headers_out.status = rc;
3679     }
3680 
3681     if (!r->logged) {
3682         log->action = "logging request";
3683 
3684         ngx_http_log_request(r);
3685     }
3686 
3687     log->action = "closing request";
3688 
3689     if (r->connection->timedout) {
3690         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3691 
3692         if (clcf->reset_timedout_connection) {
3693             linger.l_onoff = 1;
3694             linger.l_linger = 0;
3695 
3696             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3697                            (const void *) &linger, sizeof(struct linger)) == -1)
3698             {
3699                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3700                               "setsockopt(SO_LINGER) failed");
3701             }
3702         }
3703     }
3704 
3705     /* the various request strings were allocated from r->pool */
3706     ctx = log->data;
3707     ctx->request = NULL;
3708 
3709     r->request_line.len = 0;
3710 
3711     r->connection->destroyed = 1;
3712 
3713     /*
3714      * Setting r->pool to NULL will increase probability to catch double close
3715      * of request since the request object is allocated from its own pool.
3716      */
3717 
3718     pool = r->pool;
3719     r->pool = NULL;
3720 
3721     ngx_destroy_pool(pool);
3722 }
3723 
3724 
3725 static void
ngx_http_log_request(ngx_http_request_t * r)3726 ngx_http_log_request(ngx_http_request_t *r)
3727 {
3728     ngx_uint_t                  i, n;
3729     ngx_http_handler_pt        *log_handler;
3730     ngx_http_core_main_conf_t  *cmcf;
3731 
3732     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3733 
3734     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3735     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3736 
3737     for (i = 0; i < n; i++) {
3738         log_handler[i](r);
3739     }
3740 }
3741 
3742 
3743 void
ngx_http_close_connection(ngx_connection_t * c)3744 ngx_http_close_connection(ngx_connection_t *c)
3745 {
3746     ngx_pool_t  *pool;
3747 
3748     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3749                    "close http connection: %d", c->fd);
3750 
3751 #if (NGX_HTTP_SSL)
3752 
3753     if (c->ssl) {
3754         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3755             c->ssl->handler = ngx_http_close_connection;
3756             return;
3757         }
3758     }
3759 
3760 #endif
3761 
3762 #if (NGX_STAT_STUB)
3763     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3764 #endif
3765 
3766     c->destroyed = 1;
3767 
3768     pool = c->pool;
3769 
3770     ngx_close_connection(c);
3771 
3772     ngx_destroy_pool(pool);
3773 }
3774 
3775 
3776 static u_char *
ngx_http_log_error(ngx_log_t * log,u_char * buf,size_t len)3777 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3778 {
3779     u_char              *p;
3780     ngx_http_request_t  *r;
3781     ngx_http_log_ctx_t  *ctx;
3782 
3783     if (log->action) {
3784         p = ngx_snprintf(buf, len, " while %s", log->action);
3785         len -= p - buf;
3786         buf = p;
3787     }
3788 
3789     ctx = log->data;
3790 
3791     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3792     len -= p - buf;
3793 
3794     r = ctx->request;
3795 
3796     if (r) {
3797         return r->log_handler(r, ctx->current_request, p, len);
3798 
3799     } else {
3800         p = ngx_snprintf(p, len, ", server: %V",
3801                          &ctx->connection->listening->addr_text);
3802     }
3803 
3804     return p;
3805 }
3806 
3807 
3808 static u_char *
ngx_http_log_error_handler(ngx_http_request_t * r,ngx_http_request_t * sr,u_char * buf,size_t len)3809 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3810     u_char *buf, size_t len)
3811 {
3812     char                      *uri_separator;
3813     u_char                    *p;
3814     ngx_http_upstream_t       *u;
3815     ngx_http_core_srv_conf_t  *cscf;
3816 
3817     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3818 
3819     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3820     len -= p - buf;
3821     buf = p;
3822 
3823     if (r->request_line.data == NULL && r->request_start) {
3824         for (p = r->request_start; p < r->header_in->last; p++) {
3825             if (*p == CR || *p == LF) {
3826                 break;
3827             }
3828         }
3829 
3830         r->request_line.len = p - r->request_start;
3831         r->request_line.data = r->request_start;
3832     }
3833 
3834     if (r->request_line.len) {
3835         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3836         len -= p - buf;
3837         buf = p;
3838     }
3839 
3840     if (r != sr) {
3841         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3842         len -= p - buf;
3843         buf = p;
3844     }
3845 
3846     u = sr->upstream;
3847 
3848     if (u && u->peer.name) {
3849 
3850         uri_separator = "";
3851 
3852 #if (NGX_HAVE_UNIX_DOMAIN)
3853         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3854             uri_separator = ":";
3855         }
3856 #endif
3857 
3858         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3859                          &u->schema, u->peer.name,
3860                          uri_separator, &u->uri);
3861         len -= p - buf;
3862         buf = p;
3863     }
3864 
3865     if (r->headers_in.host) {
3866         p = ngx_snprintf(buf, len, ", host: \"%V\"",
3867                          &r->headers_in.host->value);
3868         len -= p - buf;
3869         buf = p;
3870     }
3871 
3872     if (r->headers_in.referer) {
3873         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3874                          &r->headers_in.referer->value);
3875         buf = p;
3876     }
3877 
3878     return buf;
3879 }
3880