Mercurial > hg > nginx
comparison src/http/ngx_http_event.c @ 87:5f6d848dcbef
nginx-0.0.1-2003-05-13-20:02:32 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 13 May 2003 16:02:32 +0000 |
parents | 3973260705cc |
children | 29bf798b583f |
comparison
equal
deleted
inserted
replaced
86:3973260705cc | 87:5f6d848dcbef |
---|---|
19 | 19 |
20 | 20 |
21 static void ngx_http_init_request(ngx_event_t *ev); | 21 static void ngx_http_init_request(ngx_event_t *ev); |
22 static void ngx_http_process_request_line(ngx_event_t *rev); | 22 static void ngx_http_process_request_line(ngx_event_t *rev); |
23 static void ngx_http_process_request_headers(ngx_event_t *rev); | 23 static void ngx_http_process_request_headers(ngx_event_t *rev); |
24 | |
25 | |
26 | |
27 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); | 24 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); |
28 | 25 |
29 | 26 static void ngx_http_writer(ngx_event_t *ev); |
30 | 27 |
31 static int ngx_http_process_request(ngx_event_t *ev); | |
32 static int ngx_http_process_request_header_line(ngx_http_request_t *r); | |
33 static int ngx_http_request_handler(ngx_http_request_t *r, int error); | |
34 | |
35 static int ngx_http_writer(ngx_event_t *ev); | |
36 static int ngx_http_block_read(ngx_event_t *ev); | 28 static int ngx_http_block_read(ngx_event_t *ev); |
37 static int ngx_http_read_discarded_body(ngx_event_t *ev); | 29 static int ngx_http_read_discarded_body(ngx_event_t *ev); |
38 static int ngx_http_set_keepalive(ngx_http_request_t *r); | 30 |
39 static int ngx_http_keepalive_handler(ngx_event_t *ev); | 31 static void ngx_http_set_keepalive(ngx_http_request_t *r); |
40 static int ngx_http_set_lingering_close(ngx_http_request_t *r); | 32 static void ngx_http_keepalive_handler(ngx_event_t *ev); |
41 static int ngx_http_lingering_close_handler(ngx_event_t *ev); | 33 static void ngx_http_set_lingering_close(ngx_http_request_t *r); |
42 | 34 static void ngx_http_lingering_close_handler(ngx_event_t *ev); |
43 static int ngx_http_close_connection(ngx_connection_t *c); | 35 |
44 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err); | 36 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err); |
45 static size_t ngx_http_log_error(void *data, char *buf, size_t len); | 37 static size_t ngx_http_log_error(void *data, char *buf, size_t len); |
46 | 38 |
47 | 39 |
48 /* NGX_HTTP_PARSE_ ... errors */ | 40 /* NGX_HTTP_PARSE_ ... errors */ |
67 { ngx_string("If-Modified-Since"), | 59 { ngx_string("If-Modified-Since"), |
68 offsetof(ngx_http_headers_in_t, if_modified_since) }, | 60 offsetof(ngx_http_headers_in_t, if_modified_since) }, |
69 { ngx_string("Content-Length"), | 61 { ngx_string("Content-Length"), |
70 offsetof(ngx_http_headers_in_t, content_length) }, | 62 offsetof(ngx_http_headers_in_t, content_length) }, |
71 | 63 |
64 #if 0 | |
65 | |
72 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) }, | 66 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) }, |
67 | |
68 #endif | |
73 | 69 |
74 { ngx_null_string, 0 } | 70 { ngx_null_string, 0 } |
75 }; | 71 }; |
76 | 72 |
77 | 73 |
133 } | 129 } |
134 | 130 |
135 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) { | 131 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) { |
136 ngx_http_close_connection(c); | 132 ngx_http_close_connection(c); |
137 } | 133 } |
138 | |
139 return; | |
140 } | 134 } |
141 | 135 |
142 | 136 |
143 static void ngx_http_init_request(ngx_event_t *rev) | 137 static void ngx_http_init_request(ngx_event_t *rev) |
144 { | 138 { |
200 r->headers_out.content_length = -1; | 194 r->headers_out.content_length = -1; |
201 r->headers_out.last_modified_time = -1; | 195 r->headers_out.last_modified_time = -1; |
202 | 196 |
203 rev->event_handler = ngx_http_process_request_line; | 197 rev->event_handler = ngx_http_process_request_line; |
204 ngx_http_process_request_line(rev); | 198 ngx_http_process_request_line(rev); |
205 | |
206 return; | |
207 } | 199 } |
208 | 200 |
209 | 201 |
210 static void ngx_http_process_request_line(ngx_event_t *rev) | 202 static void ngx_http_process_request_line(ngx_event_t *rev) |
211 { | 203 { |
266 | 258 |
267 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); | 259 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); |
268 | 260 |
269 r->request_line.len = r->request_end - r->request_start; | 261 r->request_line.len = r->request_end - r->request_start; |
270 | 262 |
271 /* if the large client header is enabled then | 263 /* if the large client headers are enabled then |
272 we need to copy a request line */ | 264 we need to copy a request line */ |
273 | 265 |
274 if (ngx_http_large_client_header) { | 266 if (ngx_http_large_client_header) { |
275 | 267 |
276 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1); | 268 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1); |
344 | 336 |
345 ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1); | 337 ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1); |
346 } | 338 } |
347 | 339 |
348 if (r->http_version == NGX_HTTP_VERSION_9) { | 340 if (r->http_version == NGX_HTTP_VERSION_9) { |
349 /* STUB */ return; | 341 ngx_http_handler(r); |
342 return; | |
350 } | 343 } |
351 | 344 |
352 lcx->action = "reading client request headers"; | 345 lcx->action = "reading client request headers"; |
353 r->headers_in.headers = ngx_create_table(r->pool, 10); | 346 r->headers_in.headers = ngx_create_table(r->pool, 10); |
354 | 347 |
356 && r->header_in->pos == r->header_in->last) | 349 && r->header_in->pos == r->header_in->last) |
357 { | 350 { |
358 r->header_in->pos = r->header_in->last = r->header_in->start; | 351 r->header_in->pos = r->header_in->last = r->header_in->start; |
359 } | 352 } |
360 | 353 |
354 rev->event_handler = ngx_http_process_request_headers; | |
355 ngx_http_process_request_headers(rev); | |
356 | |
357 return; | |
358 | |
361 } else if (rc != NGX_AGAIN) { | 359 } else if (rc != NGX_AGAIN) { |
362 | 360 |
363 /* there was error while a request line parsing */ | 361 /* there was error while a request line parsing */ |
364 | 362 |
365 ngx_http_header_parse_error(r, rc); | 363 ngx_http_header_parse_error(r, rc); |
366 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | 364 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
365 | |
367 return; | 366 return; |
368 } | 367 } |
369 | 368 |
370 /* NGX_AGAIN: a request line parsing is still not complete */ | 369 /* NGX_AGAIN: a request line parsing is still not complete */ |
371 | 370 |
381 offset = r->request_start - r->header_in->start; | 380 offset = r->request_start - r->header_in->start; |
382 | 381 |
383 if (offset == 0) { | 382 if (offset == 0) { |
384 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); | 383 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); |
385 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); | 384 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); |
385 | |
386 return; | 386 return; |
387 } | 387 } |
388 | 388 |
389 ngx_memcpy(r->header_in->start, r->request_start, | 389 ngx_memcpy(r->header_in->start, r->request_start, |
390 r->header_in->last - r->request_start); | 390 r->header_in->last - r->request_start); |
403 } | 403 } |
404 | 404 |
405 } else { | 405 } else { |
406 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); | 406 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); |
407 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); | 407 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); |
408 return; | 408 } |
409 } | 409 } |
410 } | |
411 | |
412 rev->event_handler = ngx_http_process_request_headers; | |
413 ngx_http_process_request_headers(rev); | |
414 | 410 |
415 return; | 411 return; |
416 } | 412 } |
417 | 413 |
418 | 414 |
419 static void ngx_http_process_request_headers(ngx_event_t *rev) | 415 static void ngx_http_process_request_headers(ngx_event_t *rev) |
420 { | 416 { |
421 int rc, offset; | 417 int rc, i, offset; |
422 size_t len; | 418 size_t len; |
423 ssize_t n; | 419 ssize_t n; |
420 ngx_table_elt_t *h; | |
424 ngx_connection_t *c; | 421 ngx_connection_t *c; |
425 ngx_http_request_t *r; | 422 ngx_http_request_t *r; |
426 ngx_http_log_ctx_t *ctx; | 423 ngx_http_log_ctx_t *ctx; |
427 | 424 |
425 c = (ngx_connection_t *) rev->data; | |
426 r = (ngx_http_request_t *) c->data; | |
427 | |
428 ngx_log_debug(rev->log, "http process request header line"); | |
429 | |
428 if (rev->timedout) { | 430 if (rev->timedout) { |
429 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); | 431 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); |
430 ngx_http_close_connection(c); | 432 ngx_http_close_connection(c); |
431 return; | 433 return; |
432 } | 434 } |
433 | 435 |
434 n = ngx_http_read_request_header(r); | 436 rc = NGX_AGAIN; |
435 | |
436 if (n == NGX_AGAIN || n == NGX_ERROR) { | |
437 return; | |
438 } | |
439 | 437 |
440 for ( ;; ) { | 438 for ( ;; ) { |
439 if (rc == NGX_AGAIN) { | |
440 n = ngx_http_read_request_header(r); | |
441 | |
442 if (n == NGX_AGAIN || n == NGX_ERROR) { | |
443 return; | |
444 } | |
445 } | |
446 | |
441 rc = ngx_parse_http_header_line(r, r->header_in); | 447 rc = ngx_parse_http_header_line(r, r->header_in); |
442 | 448 |
443 /* a header line has been parsed successfully */ | |
444 | |
445 if (rc == NGX_OK) { | 449 if (rc == NGX_OK) { |
446 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { | 450 |
447 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 451 /* a header line has been parsed successfully */ |
448 } | 452 |
453 h = ngx_push_table(r->headers_in.headers); | |
454 if (h == NULL) { | |
455 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
456 ngx_http_close_connection(c); | |
457 return; | |
458 } | |
459 | |
460 h->key.len = r->header_name_end - r->header_name_start; | |
461 h->value.len = r->header_end - r->header_start; | |
462 | |
463 /* if the large client headers are enabled then | |
464 we need to copy the header name and value */ | |
465 | |
466 if (ngx_http_large_client_header) { | |
467 h->key.data = ngx_palloc(r->pool, | |
468 h->key.len + 1 + h->value.len + 1); | |
469 if (h->key.data == NULL) { | |
470 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
471 ngx_http_close_connection(c); | |
472 return; | |
473 } | |
474 | |
475 h->value.data = h->key.data + h->key.len + 1; | |
476 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
477 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
478 | |
479 } else { | |
480 h->key.data = r->header_name_start; | |
481 h->key.data[h->key.len] = '\0'; | |
482 h->value.data = r->header_start; | |
483 h->value.data[h->value.len] = '\0'; | |
484 } | |
485 | |
486 for (i = 0; headers_in[i].name.len != 0; i++) { | |
487 if (headers_in[i].name.len != h->key.len) { | |
488 continue; | |
489 } | |
490 | |
491 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { | |
492 *((ngx_table_elt_t **) | |
493 ((char *) &r->headers_in + headers_in[i].offset)) = h; | |
494 } | |
495 } | |
496 | |
497 ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ | |
498 h->key.data _ h->value.data); | |
449 | 499 |
450 if (ngx_http_large_client_header | 500 if (ngx_http_large_client_header |
451 && r->header_in->pos == r->header_in->last) | 501 && r->header_in->pos == r->header_in->last) |
452 { | 502 { |
453 r->header_in->pos = r->header_in->last = r->header_in->start; | 503 r->header_in->pos = r->header_in->last = r->header_in->start; |
454 } | 504 } |
455 | 505 |
456 return NGX_AGAIN; | |
457 | |
458 /* a whole header has been parsed successfully */ | |
459 | |
460 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | 506 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
507 | |
508 /* a whole header has been parsed successfully */ | |
509 | |
461 ngx_log_debug(r->connection->log, "HTTP header done"); | 510 ngx_log_debug(r->connection->log, "HTTP header done"); |
462 | 511 |
463 if (r->headers_in.host) { | 512 if (r->headers_in.host) { |
464 for (len = 0; len < r->headers_in.host->value.len; len++) { | 513 for (len = 0; len < r->headers_in.host->value.len; len++) { |
465 if (r->headers_in.host->value.data[len] == ':') { | 514 if (r->headers_in.host->value.data[len] == ':') { |
470 | 519 |
471 } else { | 520 } else { |
472 if (r->http_version > NGX_HTTP_VERSION_10) { | 521 if (r->http_version > NGX_HTTP_VERSION_10) { |
473 ngx_http_header_parse_error(r, | 522 ngx_http_header_parse_error(r, |
474 NGX_HTTP_PARSE_NO_HOST_HEADER); | 523 NGX_HTTP_PARSE_NO_HOST_HEADER); |
475 return NGX_HTTP_BAD_REQUEST; | 524 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
525 return; | |
476 } | 526 } |
477 r->headers_in.host_name_len = 0; | 527 r->headers_in.host_name_len = 0; |
478 } | 528 } |
479 | 529 |
480 if (r->headers_in.content_length) { | 530 if (r->headers_in.content_length) { |
482 ngx_atoi(r->headers_in.content_length->value.data, | 532 ngx_atoi(r->headers_in.content_length->value.data, |
483 r->headers_in.content_length->value.len); | 533 r->headers_in.content_length->value.len); |
484 if (r->headers_in.content_length_n == NGX_ERROR) { | 534 if (r->headers_in.content_length_n == NGX_ERROR) { |
485 ngx_http_header_parse_error(r, | 535 ngx_http_header_parse_error(r, |
486 NGX_HTTP_PARSE_INVALID_CL_HEADER); | 536 NGX_HTTP_PARSE_INVALID_CL_HEADER); |
487 return NGX_HTTP_BAD_REQUEST; | 537 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
538 return; | |
488 } | 539 } |
489 } | 540 } |
490 | 541 |
491 r->state_handler = NULL; | 542 ngx_http_handler(r); |
492 return NGX_OK; | 543 return; |
493 | |
494 /* there was error while a header line parsing */ | |
495 | 544 |
496 } else if (rc != NGX_AGAIN) { | 545 } else if (rc != NGX_AGAIN) { |
546 | |
547 /* there was error while a header line parsing */ | |
548 | |
497 ngx_http_header_parse_error(r, rc); | 549 ngx_http_header_parse_error(r, rc); |
498 return NGX_HTTP_BAD_REQUEST; | 550 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
551 | |
552 return; | |
499 } | 553 } |
500 | 554 |
501 /* NGX_AGAIN: a header line parsing is still not complete */ | 555 /* NGX_AGAIN: a header line parsing is still not complete */ |
502 | 556 |
503 if (r->header_in->last == r->header_in->end) { | 557 if (r->header_in->last == r->header_in->end) { |
509 offset = r->header_name_start - r->header_in->start; | 563 offset = r->header_name_start - r->header_in->start; |
510 | 564 |
511 if (offset == 0) { | 565 if (offset == 0) { |
512 ngx_http_header_parse_error(r, | 566 ngx_http_header_parse_error(r, |
513 NGX_HTTP_PARSE_TOO_LONG_HEADER); | 567 NGX_HTTP_PARSE_TOO_LONG_HEADER); |
514 return NGX_HTTP_BAD_REQUEST; | 568 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
569 return; | |
515 } | 570 } |
516 | 571 |
517 ngx_memcpy(r->header_in->start, r->header_name_start, | 572 ngx_memcpy(r->header_in->start, r->header_name_start, |
518 r->header_in->last - r->header_name_start); | 573 r->header_in->last - r->header_name_start); |
519 | 574 |
524 r->header_start -= offset; | 579 r->header_start -= offset; |
525 r->header_end -= offset; | 580 r->header_end -= offset; |
526 | 581 |
527 } else { | 582 } else { |
528 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER); | 583 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER); |
529 return NGX_HTTP_BAD_REQUEST; | 584 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
530 } | 585 return; |
531 | 586 } |
587 } | |
588 } | |
589 } | |
590 | |
591 | |
592 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r) | |
593 { | |
594 int event; | |
595 ssize_t n; | |
596 ngx_event_t *rev; | |
597 | |
598 n = r->header_in->last - r->header_in->pos; | |
599 | |
600 if (n > 0) { | |
601 return n; | |
602 } | |
603 | |
604 n = ngx_event_recv(r->connection, r->header_in->last, | |
605 r->header_in->end - r->header_in->last); | |
606 | |
607 if (n == NGX_AGAIN) { | |
608 if (!r->header_timeout_set) { | |
609 rev = r->connection->read; | |
610 | |
611 if (rev->timer_set) { | |
612 ngx_del_timer(rev); | |
613 } else { | |
614 rev->timer_set = 1; | |
615 } | |
616 | |
617 ngx_add_timer(rev, ngx_http_client_header_timeout); | |
618 r->header_timeout_set = 1; | |
619 } | |
620 | |
621 if (!rev->active) { | |
622 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { | |
623 /* kqueue */ | |
624 event = NGX_CLEAR_EVENT; | |
625 | |
626 } else { | |
627 /* select, poll, /dev/poll */ | |
628 event = NGX_LEVEL_EVENT; | |
629 } | |
630 | |
631 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) { | |
632 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
633 ngx_http_close_connection(r->connection); | |
634 return NGX_ERROR; | |
635 } | |
532 } | 636 } |
533 | 637 |
534 return NGX_AGAIN; | 638 return NGX_AGAIN; |
535 } | 639 } |
536 } | 640 |
537 | 641 if (n == 0) { |
538 | 642 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, |
539 static int ngx_http_process_request_header_line(ngx_http_request_t *r) | 643 "client closed prematurely connection"); |
540 { | 644 } |
541 int i; | 645 |
542 ngx_table_elt_t *h; | 646 if (n == 0 || n == NGX_ERROR) { |
543 | 647 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); |
544 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); | 648 ngx_http_close_connection(r->connection); |
545 | 649 return NGX_ERROR; |
546 h->key.len = r->header_name_end - r->header_name_start; | 650 } |
547 h->value.len = r->header_end - r->header_start; | 651 |
548 | 652 r->header_in->last += n; |
549 /* if the large client headers are enabled then | 653 |
550 we need to copy the header name and value */ | 654 return n; |
551 | 655 } |
552 if (ngx_http_large_client_header) { | 656 |
553 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), | 657 |
554 NGX_ERROR); | 658 void ngx_http_finalize_request(ngx_http_request_t *r, int error) |
555 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1), | 659 { |
556 NGX_ERROR); | 660 int rc, event; |
557 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | 661 ngx_msec_t timeout; |
558 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | 662 ngx_event_t *rev, *wev; |
559 | |
560 } else { | |
561 h->key.data = r->header_name_start; | |
562 h->key.data[h->key.len] = '\0'; | |
563 h->value.data = r->header_start; | |
564 h->value.data[h->value.len] = '\0'; | |
565 } | |
566 | |
567 for (i = 0; headers_in[i].name.len != 0; i++) { | |
568 if (headers_in[i].name.len != h->key.len) { | |
569 continue; | |
570 } | |
571 | |
572 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { | |
573 *((ngx_table_elt_t **) | |
574 ((char *) &r->headers_in + headers_in[i].offset)) = h; | |
575 } | |
576 } | |
577 | |
578 ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ | |
579 h->key.data _ h->value.data); | |
580 | |
581 return NGX_OK; | |
582 } | |
583 | |
584 | |
585 int ngx_http_finalize_request(ngx_http_request_t *r, int error) | |
586 { | |
587 int rc, event; | |
588 ngx_msec_t timeout; | |
589 ngx_event_t *rev, *wev; | |
590 ngx_http_core_loc_conf_t *lcf; | |
591 | 663 |
592 rc = error; | 664 rc = error; |
593 | 665 |
594 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | 666 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
595 | 667 |
602 } | 674 } |
603 | 675 |
604 rc = ngx_http_special_response_handler(r, rc); | 676 rc = ngx_http_special_response_handler(r, rc); |
605 } | 677 } |
606 | 678 |
607 /* a handler has done its work completely */ | 679 rev = r->connection->read; |
608 | 680 if (rev->timer_set) { |
609 if (rc == NGX_OK) { | 681 ngx_del_timer(rev); |
610 | 682 rev->timer_set = 0; |
611 if (r->keepalive != 0) { | 683 } |
612 return ngx_http_set_keepalive(r); | 684 |
613 } | 685 wev = r->connection->write; |
614 | 686 if (wev->timer_set) { |
615 if (r->lingering_close) { | 687 ngx_del_timer(wev); |
616 return ngx_http_set_lingering_close(r); | 688 wev->timer_set = 0; |
617 } | 689 } |
618 | 690 |
619 return ngx_http_close_request(r, 0); | 691 if (r->keepalive != 0) { |
620 } | 692 ngx_http_set_keepalive(r); |
621 | 693 |
622 /* NGX_AGAIN: a handler has done its work | 694 } else if (r->lingering_close) { |
623 but the transfer is still not completed */ | 695 ngx_http_set_lingering_close(r); |
696 | |
697 } else { | |
698 ngx_http_close_request(r, 0); | |
699 ngx_http_close_connection(r->connection); | |
700 } | |
701 } | |
702 | |
703 | |
704 void ngx_http_set_write_handler(ngx_http_request_t *r) | |
705 { | |
706 int event; | |
707 ngx_event_t *wev; | |
708 ngx_http_core_loc_conf_t *lcf; | |
624 | 709 |
625 wev = r->connection->write; | 710 wev = r->connection->write; |
626 wev->event_handler = ngx_http_writer; | 711 wev->event_handler = ngx_http_writer; |
627 | 712 |
628 if (wev->delayed && wev->ready) { | 713 if (wev->delayed && wev->ready) { |
629 return NGX_AGAIN; | 714 return; |
630 } | 715 } |
631 | 716 |
632 lcf = (ngx_http_core_loc_conf_t *) | 717 lcf = (ngx_http_core_loc_conf_t *) |
633 ngx_http_get_module_loc_conf(r->main ? r->main : r, | 718 ngx_http_get_module_loc_conf(r->main ? r->main : r, |
634 ngx_http_core_module_ctx); | 719 ngx_http_core_module_ctx); |
635 ngx_add_timer(wev, lcf->send_timeout); | 720 ngx_add_timer(wev, lcf->send_timeout); |
636 wev->timer_set = 1; | 721 wev->timer_set = 1; |
637 | 722 |
638 #if (USE_KQUEUE) | |
639 | |
640 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ | |
641 wev->lowat = lcf->send_lowat; | |
642 #endif | |
643 | |
644 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { | |
645 return ngx_http_close_request(r, 0); | |
646 } | |
647 | |
648 return rc; | |
649 | |
650 #else | |
651 | |
652 /* aio, iocp, epoll */ | |
653 | |
654 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { | 723 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { |
655 return rc; | 724 /* aio, iocp, epoll */ |
725 return; | |
656 } | 726 } |
657 | 727 |
658 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ | 728 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ |
659 | 729 |
660 if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) { | 730 if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) { |
661 wev->lowat = lcf->send_lowat; | 731 wev->lowat = lcf->send_lowat; |
662 } | 732 } |
663 | 733 |
664 #endif | 734 #endif |
665 | 735 |
666 /* kqueue */ | |
667 | |
668 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { | 736 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { |
737 /* kqueue */ | |
669 event = NGX_CLEAR_EVENT; | 738 event = NGX_CLEAR_EVENT; |
670 | 739 |
671 /* select, poll, /dev/poll */ | |
672 | |
673 } else { | 740 } else { |
741 /* select, poll, /dev/poll */ | |
674 event = NGX_LEVEL_EVENT; | 742 event = NGX_LEVEL_EVENT; |
675 } | 743 } |
676 | 744 |
677 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { | 745 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { |
678 return ngx_http_close_request(r, 0); | 746 ngx_http_close_request(r, 0); |
679 } | 747 ngx_http_close_connection(r->connection); |
680 | 748 } |
681 return rc; | 749 } |
682 | 750 |
683 #endif /* USE_KQUEUE */ | 751 |
684 } | 752 static void ngx_http_writer(ngx_event_t *wev) |
685 | |
686 | |
687 static int ngx_http_writer(ngx_event_t *wev) | |
688 { | 753 { |
689 int rc; | 754 int rc; |
690 ngx_msec_t timeout; | 755 ngx_msec_t timeout; |
756 ngx_event_t *rev; | |
691 ngx_connection_t *c; | 757 ngx_connection_t *c; |
692 ngx_http_request_t *r; | 758 ngx_http_request_t *r; |
693 ngx_http_core_loc_conf_t *lcf; | 759 ngx_http_core_loc_conf_t *lcf; |
694 | 760 |
695 c = (ngx_connection_t *) wev->data; | 761 c = (ngx_connection_t *) wev->data; |
696 r = (ngx_http_request_t *) c->data; | 762 r = (ngx_http_request_t *) c->data; |
697 | 763 |
698 rc = ngx_http_output_filter(r, NULL); | 764 rc = ngx_http_output_filter(r, NULL); |
699 | 765 |
700 ngx_log_debug(c->log, "output filter in writer: %d" _ rc); | 766 ngx_log_debug(c->log, "writer output filter: %d" _ rc); |
701 | 767 |
702 if (rc == NGX_AGAIN) { | 768 if (rc == NGX_AGAIN) { |
703 | 769 |
704 lcf = (ngx_http_core_loc_conf_t *) | 770 lcf = (ngx_http_core_loc_conf_t *) |
705 ngx_http_get_module_loc_conf(r->main ? r->main : r, | 771 ngx_http_get_module_loc_conf(r->main ? r->main : r, |
710 wev->timer_set = 1; | 776 wev->timer_set = 1; |
711 } | 777 } |
712 | 778 |
713 ngx_add_timer(wev, lcf->send_timeout); | 779 ngx_add_timer(wev, lcf->send_timeout); |
714 | 780 |
715 return rc; | 781 return; |
716 } | 782 } |
717 | 783 |
718 if (rc == NGX_ERROR) | 784 if (rc == NGX_ERROR) { |
719 return rc; | 785 ngx_http_close_request(r, 0); |
786 ngx_http_close_connection(c); | |
787 return; | |
788 } | |
720 | 789 |
721 /* rc == NGX_OK */ | 790 /* rc == NGX_OK */ |
722 | 791 |
723 ngx_log_debug(c->log, "http writer done"); | 792 ngx_log_debug(c->log, "http writer done"); |
724 | 793 |
794 rev = r->connection->read; | |
795 if (rev->timer_set) { | |
796 ngx_del_timer(rev); | |
797 rev->timer_set = 0; | |
798 } | |
799 | |
800 if (wev->timer_set) { | |
801 ngx_del_timer(wev); | |
802 wev->timer_set = 0; | |
803 } | |
804 | |
725 if (r->keepalive != 0) { | 805 if (r->keepalive != 0) { |
726 return ngx_http_set_keepalive(r); | 806 ngx_http_set_keepalive(r); |
727 } | 807 } |
728 | 808 |
729 if (r->lingering_close) { | 809 if (r->lingering_close) { |
730 return ngx_http_set_lingering_close(r); | 810 ngx_http_set_lingering_close(r); |
731 } | 811 |
732 | 812 } else { |
733 return ngx_http_close_request(r, 0); | 813 ngx_http_close_request(r, 0); |
734 } | 814 } |
735 | |
736 | |
737 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r) | |
738 { | |
739 ssize_t n; | |
740 ngx_event_t *rev; | |
741 | |
742 n = r->header_in->last - r->header_in->pos; | |
743 | |
744 if (n > 0) { | |
745 return n; | |
746 } | |
747 | |
748 n = ngx_event_recv(r->connection, r->header_in->last, | |
749 r->header_in->end - r->header_in->last); | |
750 | |
751 if (n == NGX_AGAIN) { | |
752 if (!r->header_timeout_set) { | |
753 rev = r->connection->read; | |
754 | |
755 if (rev->timer_set) { | |
756 ngx_del_timer(rev); | |
757 } else { | |
758 rev->timer_set = 1; | |
759 } | |
760 | |
761 ngx_add_timer(rev, ngx_http_client_header_timeout); | |
762 r->header_timeout_set = 1; | |
763 } | |
764 | |
765 return NGX_AGAIN; | |
766 } | |
767 | |
768 if (n == 0) { | |
769 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
770 "client closed prematurely connection"); | |
771 | |
772 if (n == 0 || n == NGX_ERROR) { | |
773 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); | |
774 ngx_http_close_connection(c); | |
775 return NGX_ERROR; | |
776 } | |
777 | |
778 r->header_in->last += n; | |
779 | |
780 return n; | |
781 } | 815 } |
782 | 816 |
783 | 817 |
784 static int ngx_http_block_read(ngx_event_t *ev) | 818 static int ngx_http_block_read(ngx_event_t *ev) |
785 { | 819 { |
803 | 837 |
804 #endif /* USE_KQUEUE */ | 838 #endif /* USE_KQUEUE */ |
805 } | 839 } |
806 | 840 |
807 | 841 |
842 /* STUB */ | |
843 int ngx_http_discard_body(ngx_http_request_t *r) | |
844 { | |
845 return NGX_OK; | |
846 } | |
847 | |
848 #if 0 | |
808 /* TODO */ | 849 /* TODO */ |
809 int ngx_http_discard_body(ngx_http_request_t *r) | 850 int ngx_http_discard_body(ngx_http_request_t *r) |
810 { | 851 { |
811 ngx_event_t *ev; | 852 ngx_event_t *ev; |
812 | 853 |
872 | 913 |
873 r->headers_in.content_length_n -= n; | 914 r->headers_in.content_length_n -= n; |
874 /* XXX: what if r->client_content_length == 0 ? */ | 915 /* XXX: what if r->client_content_length == 0 ? */ |
875 return NGX_OK; | 916 return NGX_OK; |
876 } | 917 } |
877 | 918 #endif |
878 | 919 |
879 static int ngx_http_set_keepalive(ngx_http_request_t *r) | 920 |
921 static void ngx_http_set_keepalive(ngx_http_request_t *r) | |
880 { | 922 { |
881 int len, blocked; | 923 int len, blocked; |
882 ngx_hunk_t *h; | 924 ngx_hunk_t *h; |
883 ngx_event_t *rev, *wev; | 925 ngx_event_t *rev, *wev; |
884 ngx_connection_t *c; | 926 ngx_connection_t *c; |
891 ctx->action = "closing request"; | 933 ctx->action = "closing request"; |
892 ngx_http_close_request(r, 0); | 934 ngx_http_close_request(r, 0); |
893 | 935 |
894 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | 936 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
895 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { | 937 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { |
896 return NGX_ERROR; | 938 ngx_http_close_connection(c); |
897 } | 939 return; |
940 } | |
941 | |
898 blocked = 1; | 942 blocked = 1; |
899 rev->blocked = 0; | 943 rev->blocked = 0; |
900 | 944 |
901 } else { | 945 } else { |
902 blocked = 0; | 946 blocked = 0; |
920 h->last = h->start + len; | 964 h->last = h->start + len; |
921 } | 965 } |
922 | 966 |
923 c->pipeline = 1; | 967 c->pipeline = 1; |
924 ctx->action = "reading client pipelined request line"; | 968 ctx->action = "reading client pipelined request line"; |
925 return ngx_http_init_request(rev); | 969 ngx_http_init_request(rev); |
970 return; | |
926 } | 971 } |
927 | 972 |
928 c->pipeline = 0; | 973 c->pipeline = 0; |
929 | 974 |
930 h->pos = h->last = h->start; | 975 h->pos = h->last = h->start; |
931 rev->event_handler = ngx_http_keepalive_handler; | 976 rev->event_handler = ngx_http_keepalive_handler; |
932 wev = c->write; | 977 wev = c->write; |
933 | 978 |
934 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | 979 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
935 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | 980 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
936 return NGX_ERROR; | 981 ngx_http_close_connection(c); |
982 return; | |
937 } | 983 } |
938 } | 984 } |
939 | 985 |
940 ctx->action = "keepalive"; | 986 ctx->action = "keepalive"; |
941 | 987 |
942 #if (HAVE_AIO_EVENT) /* aio, iocp */ | |
943 | |
944 if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { | 988 if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { |
945 return ngx_http_keepalive_handler(rev); | 989 ngx_http_keepalive_handler(rev); |
946 } | 990 } |
947 | 991 } |
948 #else | 992 |
949 | 993 |
950 if (blocked) { | 994 static void ngx_http_keepalive_handler(ngx_event_t *rev) |
951 return ngx_http_keepalive_handler(rev); | |
952 } | |
953 | |
954 #endif | |
955 | |
956 return NGX_OK; | |
957 } | |
958 | |
959 | |
960 static int ngx_http_keepalive_handler(ngx_event_t *rev) | |
961 { | 995 { |
962 ssize_t n; | 996 ssize_t n; |
963 ngx_connection_t *c; | 997 ngx_connection_t *c; |
964 ngx_http_log_ctx_t *lctx; | 998 ngx_http_log_ctx_t *lctx; |
965 | 999 |
966 c = (ngx_connection_t *) rev->data; | 1000 c = (ngx_connection_t *) rev->data; |
967 | 1001 |
968 ngx_log_debug(c->log, "http keepalive handler"); | 1002 ngx_log_debug(c->log, "http keepalive handler"); |
969 | 1003 |
970 if (rev->timedout) { | 1004 if (rev->timedout) { |
971 return NGX_ERROR; /* to close connection */ | 1005 ngx_http_close_connection(c); |
1006 return; | |
972 } | 1007 } |
973 | 1008 |
974 /* MSIE closes a keepalive connection with RST flag | 1009 /* MSIE closes a keepalive connection with RST flag |
975 so we ignore ECONNRESET here */ | 1010 so we ignore ECONNRESET here */ |
976 | 1011 |
977 rev->ignore_econnreset = 1; | 1012 rev->ignore_econnreset = 1; |
978 ngx_set_socket_errno(0); | 1013 ngx_set_socket_errno(0); |
979 n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last); | 1014 n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last); |
980 rev->ignore_econnreset = 0; | 1015 rev->ignore_econnreset = 0; |
981 | 1016 |
982 if (n == NGX_AGAIN || n == NGX_ERROR) { | 1017 if (n == NGX_AGAIN) { |
983 return n; | 1018 return; |
1019 } | |
1020 | |
1021 if (n == NGX_ERROR) { | |
1022 ngx_http_close_connection(c); | |
1023 return; | |
984 } | 1024 } |
985 | 1025 |
986 lctx = (ngx_http_log_ctx_t *) rev->log->data; | 1026 lctx = (ngx_http_log_ctx_t *) rev->log->data; |
987 rev->log->handler = NULL; | 1027 rev->log->handler = NULL; |
988 | 1028 |
989 if (n == 0) { | 1029 if (n == 0) { |
990 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, | 1030 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, |
991 "client %s closed keepalive connection", lctx->client); | 1031 "client %s closed keepalive connection", lctx->client); |
992 return NGX_ERROR; /* to close connection */ | 1032 ngx_http_close_connection(c); |
1033 return; | |
993 } | 1034 } |
994 | 1035 |
995 c->buffer->last += n; | 1036 c->buffer->last += n; |
996 rev->log->handler = ngx_http_log_error; | 1037 rev->log->handler = ngx_http_log_error; |
997 lctx->action = "reading client request line"; | 1038 lctx->action = "reading client request line"; |
998 | 1039 |
999 return ngx_http_init_request(rev); | 1040 ngx_http_init_request(rev); |
1000 } | 1041 } |
1001 | 1042 |
1002 | 1043 |
1003 static int ngx_http_set_lingering_close(ngx_http_request_t *r) | 1044 static void ngx_http_set_lingering_close(ngx_http_request_t *r) |
1004 { | 1045 { |
1005 ngx_event_t *rev; | 1046 ngx_event_t *rev; |
1006 ngx_connection_t *c; | 1047 ngx_connection_t *c; |
1007 ngx_http_core_loc_conf_t *lcf; | 1048 ngx_http_core_loc_conf_t *lcf; |
1008 | 1049 |
1011 | 1052 |
1012 lcf = (ngx_http_core_loc_conf_t *) | 1053 lcf = (ngx_http_core_loc_conf_t *) |
1013 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); | 1054 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
1014 | 1055 |
1015 r->lingering_time = ngx_time() + lcf->lingering_time / 1000; | 1056 r->lingering_time = ngx_time() + lcf->lingering_time / 1000; |
1016 r->connection->read->event_handler = ngx_http_lingering_close_handler; | 1057 rev->event_handler = ngx_http_lingering_close_handler; |
1017 | 1058 |
1018 if (rev->timer_set) { | 1059 if (rev->timer_set) { |
1019 ngx_del_timer(rev); | 1060 ngx_del_timer(rev); |
1020 } else { | 1061 } else { |
1021 rev->timer_set = 1; | 1062 rev->timer_set = 1; |
1023 | 1064 |
1024 ngx_add_timer(rev, lcf->lingering_timeout); | 1065 ngx_add_timer(rev, lcf->lingering_timeout); |
1025 | 1066 |
1026 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | 1067 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
1027 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { | 1068 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { |
1028 return ngx_http_close_request(r, 0); | 1069 ngx_http_close_request(r, 0); |
1070 ngx_http_close_connection(c); | |
1071 return; | |
1029 } | 1072 } |
1030 rev->blocked = 0; | 1073 rev->blocked = 0; |
1031 } | 1074 } |
1032 | |
1033 #if !(USE_KQUEUE) | |
1034 | 1075 |
1035 if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | 1076 if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
1036 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | 1077 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
1037 return ngx_http_close_request(r, 0); | 1078 ngx_http_close_request(r, 0); |
1038 } | 1079 ngx_http_close_connection(c); |
1039 } | 1080 return; |
1040 | 1081 } |
1041 #endif | 1082 } |
1042 | 1083 |
1043 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { | 1084 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { |
1044 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, | 1085 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, |
1045 ngx_shutdown_socket_n " failed"); | 1086 ngx_shutdown_socket_n " failed"); |
1046 return ngx_http_close_request(r, 0); | 1087 ngx_http_close_request(r, 0); |
1047 } | 1088 ngx_http_close_connection(c); |
1048 | 1089 return; |
1049 #if (USE_KQUEUE) | 1090 } |
1050 | |
1051 if (rev->ready) { | |
1052 return ngx_http_lingering_close_handler(rev); | |
1053 } | |
1054 | |
1055 #else | |
1056 | 1091 |
1057 if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) { | 1092 if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) { |
1058 return ngx_http_lingering_close_handler(rev); | 1093 ngx_http_lingering_close_handler(rev); |
1059 } | 1094 } |
1060 | 1095 } |
1061 #endif | 1096 |
1062 | 1097 |
1063 return NGX_OK; | 1098 static void ngx_http_lingering_close_handler(ngx_event_t *rev) |
1064 } | |
1065 | |
1066 | |
1067 static int ngx_http_lingering_close_handler(ngx_event_t *rev) | |
1068 { | 1099 { |
1069 ssize_t n; | 1100 ssize_t n; |
1070 ngx_msec_t timer; | 1101 ngx_msec_t timer; |
1071 ngx_connection_t *c; | 1102 ngx_connection_t *c; |
1072 ngx_http_request_t *r; | 1103 ngx_http_request_t *r; |
1076 r = (ngx_http_request_t *) c->data; | 1107 r = (ngx_http_request_t *) c->data; |
1077 | 1108 |
1078 ngx_log_debug(c->log, "http lingering close handler"); | 1109 ngx_log_debug(c->log, "http lingering close handler"); |
1079 | 1110 |
1080 if (rev->timedout) { | 1111 if (rev->timedout) { |
1081 return ngx_http_close_request(r, 0); | 1112 ngx_http_close_request(r, 0); |
1113 ngx_http_close_connection(c); | |
1114 return; | |
1082 } | 1115 } |
1083 | 1116 |
1084 timer = r->lingering_time - ngx_time(); | 1117 timer = r->lingering_time - ngx_time(); |
1085 if (timer <= 0) { | 1118 if (timer <= 0) { |
1086 return ngx_http_close_request(r, 0); | 1119 ngx_http_close_request(r, 0); |
1120 ngx_http_close_connection(c); | |
1121 return; | |
1087 } | 1122 } |
1088 | 1123 |
1089 lcf = (ngx_http_core_loc_conf_t *) | 1124 lcf = (ngx_http_core_loc_conf_t *) |
1090 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); | 1125 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
1091 | 1126 |
1098 if ((size_t)(r->header_in->end - r->header_in->last) | 1133 if ((size_t)(r->header_in->end - r->header_in->last) |
1099 >= lcf->discarded_buffer_size) { | 1134 >= lcf->discarded_buffer_size) { |
1100 r->discarded_buffer = r->header_in->last; | 1135 r->discarded_buffer = r->header_in->last; |
1101 | 1136 |
1102 } else { | 1137 } else { |
1103 ngx_test_null(r->discarded_buffer, | 1138 r->discarded_buffer = ngx_palloc(c->pool, |
1104 ngx_palloc(c->pool, lcf->discarded_buffer_size), | 1139 lcf->discarded_buffer_size); |
1105 ngx_http_close_request(r, 0)); | 1140 if (r->discarded_buffer) { |
1141 ngx_http_close_request(r, 0); | |
1142 ngx_http_close_connection(c); | |
1143 return; | |
1144 } | |
1106 } | 1145 } |
1107 } | 1146 } |
1108 | 1147 |
1109 do { | 1148 do { |
1110 n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size); | 1149 n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size); |
1111 | 1150 |
1112 ngx_log_debug(c->log, "lingering read: %d" _ n); | 1151 ngx_log_debug(c->log, "lingering read: %d" _ n); |
1113 | 1152 |
1114 if (n == NGX_ERROR || n == 0) { | 1153 if (n == NGX_ERROR || n == 0) { |
1115 return ngx_http_close_request(r, 0); | 1154 ngx_http_close_request(r, 0); |
1155 ngx_http_close_connection(c); | |
1156 return; | |
1116 } | 1157 } |
1117 | 1158 |
1118 } while (rev->ready); | 1159 } while (rev->ready); |
1119 | 1160 |
1120 timer *= 1000; | 1161 timer *= 1000; |
1127 } else { | 1168 } else { |
1128 rev->timer_set = 1; | 1169 rev->timer_set = 1; |
1129 } | 1170 } |
1130 ngx_add_timer(rev, timer); | 1171 ngx_add_timer(rev, timer); |
1131 | 1172 |
1132 return NGX_OK; | 1173 return; |
1133 } | 1174 } |
1134 | 1175 |
1135 | 1176 |
1136 static void ngx_http_close_connection(ngx_connection_t *c) | 1177 void ngx_http_close_request(ngx_http_request_t *r, int error) |
1178 { | |
1179 ngx_http_log_ctx_t *ctx; | |
1180 | |
1181 ngx_log_debug(r->connection->log, "close http request"); | |
1182 | |
1183 if (r->pool == NULL) { | |
1184 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
1185 "http already closed"); | |
1186 return; | |
1187 } | |
1188 | |
1189 if (error) { | |
1190 r->headers_out.status = error; | |
1191 } | |
1192 | |
1193 ngx_http_log_handler(r); | |
1194 | |
1195 if (r->file.fd != NGX_INVALID_FILE) { | |
1196 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { | |
1197 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, | |
1198 ngx_close_file_n " \"%s\" failed", r->file.name.data); | |
1199 } | |
1200 } | |
1201 | |
1202 /* ctx->url was allocated from r->pool */ | |
1203 ctx = (ngx_http_log_ctx_t *) r->connection->log->data; | |
1204 ctx->url = NULL; | |
1205 | |
1206 ngx_destroy_pool(r->pool); | |
1207 } | |
1208 | |
1209 | |
1210 void ngx_http_close_connection(ngx_connection_t *c) | |
1137 { | 1211 { |
1138 ngx_log_debug(c->log, "close connection: %d" _ c->fd); | 1212 ngx_log_debug(c->log, "close connection: %d" _ c->fd); |
1139 | 1213 |
1140 if (c->fd == -1) { | 1214 if (c->pool == NULL) { |
1141 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); | 1215 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); |
1142 return; | 1216 return; |
1143 } | 1217 } |
1144 | 1218 |
1145 if (c->read->timer_set) { | 1219 if (c->read->timer_set) { |
1166 } | 1240 } |
1167 | 1241 |
1168 c->fd = -1; | 1242 c->fd = -1; |
1169 | 1243 |
1170 ngx_destroy_pool(c->pool); | 1244 ngx_destroy_pool(c->pool); |
1171 | |
1172 return; | |
1173 } | |
1174 | |
1175 static int ngx_http_close_connection0(ngx_event_t *ev) | |
1176 { | |
1177 return ngx_event_close_connection(ev); | |
1178 } | 1245 } |
1179 | 1246 |
1180 | 1247 |
1181 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err) | 1248 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err) |
1182 { | 1249 { |