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