~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_request.c

Version: ~ [ nginx-1.4.1 ] ~ [ nginx-1.5.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.