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