Coverage Report

Created: 2023-06-07 06:06

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