Mercurial > hg > nginx-quic
comparison src/http/ngx_http_event.c @ 67:5a7d1aaa1618
nginx-0.0.1-2003-03-11-23:38:13 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 11 Mar 2003 20:38:13 +0000 |
parents | 4876cd4a36bb |
children | d549fdc17d7e |
comparison
equal
deleted
inserted
replaced
66:4876cd4a36bb | 67:5a7d1aaa1618 |
---|---|
128 | 128 |
129 #endif | 129 #endif |
130 | 130 |
131 /* select, poll, /dev/poll */ | 131 /* select, poll, /dev/poll */ |
132 | 132 |
133 ev->level = 1; | |
134 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); | 133 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); |
135 | 134 |
136 #endif /* USE_KQUEUE */ | 135 #endif /* USE_KQUEUE */ |
137 } | 136 } |
138 | 137 |
188 } | 187 } |
189 | 188 |
190 | 189 |
191 static int ngx_http_process_request_header(ngx_event_t *ev) | 190 static int ngx_http_process_request_header(ngx_event_t *ev) |
192 { | 191 { |
193 int n, rc; | 192 int n, rc, again; |
194 ngx_connection_t *c; | 193 ngx_connection_t *c; |
195 ngx_http_request_t *r; | 194 ngx_http_request_t *r; |
196 ngx_http_log_ctx_t *ctx; | 195 ngx_http_log_ctx_t *ctx; |
197 | 196 |
198 c = (ngx_connection_t *) ev->data; | 197 c = (ngx_connection_t *) ev->data; |
199 r = (ngx_http_request_t *) c->data; | 198 r = (ngx_http_request_t *) c->data; |
200 | 199 |
201 ngx_log_debug(ev->log, "http process request"); | 200 ngx_log_debug(ev->log, "http process request"); |
202 | 201 |
203 #if (HAVE_AIO_EVENT) | |
204 do { | 202 do { |
205 #endif | |
206 | 203 |
207 if (r->header_read) { | 204 if (r->header_read) { |
205 if (r->header_in->end - r->header_in->last == 0) { | |
206 again = 1; | |
207 } else { | |
208 again = 0; | |
209 } | |
210 | |
208 r->header_read = 0; | 211 r->header_read = 0; |
209 ngx_log_debug(ev->log, "http preread %d" _ | 212 ngx_log_debug(ev->log, "http preread %d" _ |
210 r->header_in->last.mem - r->header_in->pos.mem); | 213 r->header_in->last - r->header_in->pos); |
211 | 214 |
212 } else { | 215 } else { |
213 n = ngx_event_recv(c, r->header_in->last.mem, | 216 n = ngx_event_recv(c, r->header_in->last, |
214 r->header_in->end - r->header_in->last.mem); | 217 r->header_in->end - r->header_in->last); |
215 | 218 |
216 if (n == NGX_AGAIN) { | 219 if (n == NGX_AGAIN) { |
217 if (!r->header_timeout_set) { | 220 if (!r->header_timeout_set) { |
218 | 221 |
219 if (ev->timer_set) { | 222 if (ev->timer_set) { |
226 r->header_timeout_set = 1; | 229 r->header_timeout_set = 1; |
227 } | 230 } |
228 return NGX_AGAIN; | 231 return NGX_AGAIN; |
229 } | 232 } |
230 | 233 |
231 if (n == NGX_ERROR) | 234 if (n == NGX_ERROR) { |
232 return ngx_http_close_request(r); | 235 return ngx_http_close_request(r); |
236 } | |
233 | 237 |
234 ngx_log_debug(ev->log, "http read %d" _ n); | 238 ngx_log_debug(ev->log, "http read %d" _ n); |
235 | 239 |
236 if (n == 0) { | 240 if (n == 0) { |
237 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 241 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
238 "client has prematurely closed connection"); | 242 "client has prematurely closed connection"); |
239 return ngx_http_close_request(r); | 243 return ngx_http_close_request(r); |
240 } | 244 } |
241 | 245 |
242 r->header_in->last.mem += n; | 246 r->header_in->last += n; |
247 | |
248 if (ngx_http_large_client_header | |
249 && r->header_in->end == r->header_in->last) { | |
250 again = 1; | |
251 } else { | |
252 again = 0; | |
253 } | |
243 } | 254 } |
244 | 255 |
245 /* the state_handlers are called in the following order: | 256 /* the state_handlers are called in the following order: |
246 ngx_http_process_request_line(r) | 257 ngx_http_process_request_line(r) |
247 ngx_http_process_request_headers(r) */ | 258 ngx_http_process_request_headers(r) */ |
248 | 259 |
249 do { | 260 do { |
250 /* state_handlers return NGX_OK when the whole header done */ | 261 /* state_handlers return NGX_OK when the whole header done */ |
251 rc = (r->state_handler)(r); | 262 rc = (r->state_handler)(r); |
252 | 263 |
253 if (rc == NGX_ERROR) | 264 if (rc == NGX_ERROR) { |
254 return rc; | 265 return rc; |
255 | 266 } |
256 } while (rc == NGX_AGAIN | 267 |
257 && r->header_in->pos.mem < r->header_in->last.mem); | 268 } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last); |
258 | 269 |
259 #if (HAVE_AIO_EVENT) /* aio, iocp */ | 270 #if (HAVE_AIO_EVENT) /* aio, iocp */ |
260 } while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT); | 271 |
272 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | |
273 again = 1; | |
274 } | |
275 | |
261 #endif | 276 #endif |
277 | |
278 } while (rc == NGX_AGAIN && again); | |
262 | 279 |
263 if (rc == NGX_OK) { | 280 if (rc == NGX_OK) { |
264 /* HTTP header done */ | 281 /* HTTP header done */ |
265 | 282 |
266 if (ev->timer_set) { | 283 if (ev->timer_set) { |
306 - r->uri_start; | 323 - r->uri_start; |
307 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), | 324 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), |
308 ngx_http_close_request(r)); | 325 ngx_http_close_request(r)); |
309 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); | 326 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); |
310 | 327 |
311 /* if the large client headers is enabled then | 328 /* if the large client headers are enabled then |
312 we need to copy a request line */ | 329 we need to copy a request line */ |
313 | 330 |
314 r->request_line.len = r->request_end - r->request_start; | 331 r->request_line.len = r->request_end - r->request_start; |
315 if (ngx_http_large_client_header) { | 332 if (ngx_http_large_client_header) { |
316 ngx_test_null(r->request_line.data, | 333 ngx_test_null(r->request_line.data, |
374 return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); | 391 return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); |
375 } | 392 } |
376 | 393 |
377 /* NGX_AGAIN: a request line parsing is still not complete */ | 394 /* NGX_AGAIN: a request line parsing is still not complete */ |
378 | 395 |
379 if (r->header_in->last.mem == r->header_in->end) { | 396 if (r->header_in->last == r->header_in->end) { |
380 | 397 |
381 /* If it's a pipelined request and a request line is not complete | 398 /* If it's a pipelined request and a request line is not complete |
382 then we need to copy it to the start of r->header_in hunk. | 399 then we need to copy it to the start of r->header_in hunk. |
383 We need to copy it here only if the large client header | 400 We need to copy it here only if the large client headers |
384 is enabled otherwise a request line had been already copied | 401 are enabled otherwise a request line had been already copied |
385 to the start of r->header_in hunk in ngx_http_set_keepalive() */ | 402 to the start of r->header_in hunk in ngx_http_set_keepalive() */ |
386 | 403 |
387 if (ngx_http_large_client_header) { | 404 if (ngx_http_large_client_header) { |
388 offset = r->request_start - r->header_in->start; | 405 offset = r->request_start - r->header_in->start; |
389 | 406 |
392 NGX_HTTP_PARSE_TOO_LONG_URI, | 409 NGX_HTTP_PARSE_TOO_LONG_URI, |
393 NGX_HTTP_REQUEST_URI_TOO_LARGE); | 410 NGX_HTTP_REQUEST_URI_TOO_LARGE); |
394 } | 411 } |
395 | 412 |
396 ngx_memcpy(r->header_in->start, r->request_start, | 413 ngx_memcpy(r->header_in->start, r->request_start, |
397 r->header_in->last.mem - r->request_start); | 414 r->header_in->last - r->request_start); |
398 | 415 |
399 r->header_in->pos.mem -= offset; | 416 r->header_in->pos -= offset; |
400 r->header_in->last.mem -= offset; | 417 r->header_in->last -= offset; |
401 r->request_start = r->header_in->start; | 418 r->request_start = r->header_in->start; |
402 r->request_end -= offset; | 419 r->request_end -= offset; |
403 r->uri_start -= offset; | 420 r->uri_start -= offset; |
404 r->uri_end -= offset; | 421 r->uri_end -= offset; |
405 if (r->uri_ext) { | 422 if (r->uri_ext) { |
435 return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 452 return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
436 } | 453 } |
437 | 454 |
438 return NGX_AGAIN; | 455 return NGX_AGAIN; |
439 | 456 |
440 /* the whole header has been parsed successfully */ | 457 /* a whole header has been parsed successfully */ |
441 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | 458 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
442 ngx_log_debug(r->connection->log, "HTTP header done"); | 459 ngx_log_debug(r->connection->log, "HTTP header done"); |
443 | 460 |
444 if (r->headers_in.host) { | 461 if (r->headers_in.host) { |
445 for (len = 0; len < r->headers_in.host->value.len; len++) { | 462 for (len = 0; len < r->headers_in.host->value.len; len++) { |
466 return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); | 483 return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); |
467 } | 484 } |
468 | 485 |
469 /* NGX_AGAIN: a header line parsing is still not complete */ | 486 /* NGX_AGAIN: a header line parsing is still not complete */ |
470 | 487 |
471 if (r->header_in->last.mem == r->header_in->end) { | 488 if (r->header_in->last == r->header_in->end) { |
472 | 489 |
473 /* if the large client header is enabled then | 490 /* if the large client headers are enabled then |
474 we need to compact r->header_in hunk */ | 491 we need to compact r->header_in hunk */ |
475 | 492 |
476 if (ngx_http_large_client_header) { | 493 if (ngx_http_large_client_header) { |
477 offset = r->header_name_start - r->header_in->start; | 494 offset = r->header_name_start - r->header_in->start; |
478 | 495 |
481 NGX_HTTP_PARSE_TOO_LONG_HEADER, | 498 NGX_HTTP_PARSE_TOO_LONG_HEADER, |
482 NGX_HTTP_BAD_REQUEST); | 499 NGX_HTTP_BAD_REQUEST); |
483 } | 500 } |
484 | 501 |
485 ngx_memcpy(r->header_in->start, r->header_name_start, | 502 ngx_memcpy(r->header_in->start, r->header_name_start, |
486 r->header_in->last.mem - r->header_name_start); | 503 r->header_in->last - r->header_name_start); |
487 | 504 |
488 r->header_in->last.mem -= offset; | 505 r->header_in->last -= offset; |
489 r->header_in->pos.mem -= offset; | 506 r->header_in->pos -= offset; |
490 r->header_name_start = r->header_in->start; | 507 r->header_name_start = r->header_in->start; |
491 r->header_name_end -= offset; | 508 r->header_name_end -= offset; |
492 r->header_start -= offset; | 509 r->header_start -= offset; |
493 r->header_end -= offset; | 510 r->header_end -= offset; |
494 | 511 |
510 int i; | 527 int i; |
511 ngx_table_elt_t *h; | 528 ngx_table_elt_t *h; |
512 | 529 |
513 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); | 530 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); |
514 | 531 |
515 /* if large client header is enabled then | 532 /* if large client headers are enabled then |
516 we need to copy header name and value */ | 533 we need to copy header name and value */ |
517 | 534 |
518 h->key.len = r->header_name_end - r->header_name_start; | 535 h->key.len = r->header_name_end - r->header_name_start; |
519 h->value.len = r->header_end - r->header_start; | 536 h->value.len = r->header_end - r->header_start; |
520 | 537 |
629 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { | 646 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { |
630 event = NGX_CLEAR_EVENT; | 647 event = NGX_CLEAR_EVENT; |
631 | 648 |
632 } else { | 649 } else { |
633 event = NGX_LEVEL_EVENT; | 650 event = NGX_LEVEL_EVENT; |
634 wev->level = 1; | |
635 } | 651 } |
636 | 652 |
637 #else /* select, poll, /dev/poll */ | 653 #else /* select, poll, /dev/poll */ |
638 | 654 |
639 event = NGX_LEVEL_EVENT; | 655 event = NGX_LEVEL_EVENT; |
640 wev->level = 1; | |
641 | 656 |
642 #endif | 657 #endif |
643 | 658 |
644 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { | 659 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { |
645 return ngx_http_close_request(r); | 660 return ngx_http_close_request(r); |
749 | 764 |
750 return NGX_OK; | 765 return NGX_OK; |
751 | 766 |
752 #else | 767 #else |
753 | 768 |
754 if (ev->level) { /* select, poll, /dev/poll */ | 769 if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */ |
755 ev->blocked = 1; | 770 ev->blocked = 1; |
756 return ngx_del_event(ev, NGX_READ_EVENT, 0); | 771 return ngx_del_event(ev, NGX_READ_EVENT, 0); |
757 | 772 |
758 } else { /* kqueue, epoll */ | 773 } else { /* kqueue, epoll */ |
759 return NGX_OK; | 774 return NGX_OK; |
760 } | 775 } |
761 | 776 |
762 #endif /* USE_KQUEUE */ | 777 #endif /* USE_KQUEUE */ |
763 } | 778 } |
829 } | 844 } |
830 | 845 |
831 | 846 |
832 static int ngx_http_set_keepalive(ngx_http_request_t *r) | 847 static int ngx_http_set_keepalive(ngx_http_request_t *r) |
833 { | 848 { |
834 int len; | 849 int len, blocked; |
835 ngx_hunk_t *h; | 850 ngx_hunk_t *h; |
836 ngx_event_t *rev, *wev; | 851 ngx_event_t *rev, *wev; |
837 ngx_connection_t *c; | 852 ngx_connection_t *c; |
838 ngx_http_log_ctx_t *ctx; | 853 ngx_http_log_ctx_t *ctx; |
839 | 854 |
840 c = (ngx_connection_t *) r->connection; | 855 c = (ngx_connection_t *) r->connection; |
841 rev = c->read; | 856 rev = c->read; |
842 wev = c->write; | 857 wev = c->write; |
843 | 858 |
844 if (rev->blocked && rev->level) { | |
845 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { | |
846 return NGX_ERROR; | |
847 } | |
848 rev->blocked = 0; | |
849 } | |
850 | |
851 ctx = (ngx_http_log_ctx_t *) c->log->data; | 859 ctx = (ngx_http_log_ctx_t *) c->log->data; |
852 ctx->action = "closing request"; | 860 ctx->action = "closing request"; |
853 ngx_http_close_request(r); | 861 ngx_http_close_request(r); |
854 | 862 |
863 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | |
864 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { | |
865 return NGX_ERROR; | |
866 } | |
867 blocked = 1; | |
868 rev->blocked = 0; | |
869 | |
870 } else { | |
871 blocked = 0; | |
872 } | |
873 | |
855 h = c->buffer; | 874 h = c->buffer; |
856 | 875 |
857 /* pipelined request */ | 876 /* pipelined request */ |
858 if (h->pos.mem < h->last.mem) { | 877 if (h->pos < h->last) { |
859 | 878 |
860 /* We do not know here whether pipelined request is complete | 879 /* We do not know here whether pipelined request is complete |
861 so we need to copy it to the start of c->buffer if the large | 880 so if large client headers are not enabled |
862 client header is not enabled. This copy should be rare | 881 we need to copy the data to the start of c->buffer. |
863 because clients that support pipelined requests (Mozilla 1.x, | 882 This copy should be rare because clients that support |
864 Opera 6.x) are still rare */ | 883 pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */ |
865 | 884 |
866 if (!ngx_http_large_client_header) { | 885 if (!ngx_http_large_client_header) { |
867 len = h->last.mem - h->pos.mem; | 886 len = h->last - h->pos; |
868 ngx_memcpy(h->start, h->pos.mem, len); | 887 ngx_memcpy(h->start, h->pos, len); |
869 h->pos.mem = h->start; | 888 h->pos = h->start; |
870 h->last.mem = h->start + len; | 889 h->last = h->start + len; |
871 } | 890 } |
872 | 891 |
873 c->pipeline = 1; | 892 c->pipeline = 1; |
874 ctx->action = "reading client pipelined request line"; | 893 ctx->action = "reading client pipelined request line"; |
875 return ngx_http_init_request(rev); | 894 return ngx_http_init_request(rev); |
876 } | 895 } |
877 | 896 |
878 c->pipeline = 0; | 897 c->pipeline = 0; |
879 | 898 |
880 h->pos.mem = h->last.mem = h->start; | 899 h->pos = h->last = h->start; |
881 rev->event_handler = ngx_http_keepalive_handler; | 900 rev->event_handler = ngx_http_keepalive_handler; |
882 | 901 |
883 if (wev->active && wev->level) { | 902 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
884 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | 903 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
885 return NGX_ERROR; | 904 return NGX_ERROR; |
886 } | 905 } |
887 } | 906 } |
888 | 907 |
889 ctx->action = "keepalive"; | 908 ctx->action = "keepalive"; |
890 | 909 |
891 #if (HAVE_AIO_EVENT) /* aio, iocp */ | 910 #if (HAVE_AIO_EVENT) /* aio, iocp */ |
892 | 911 |
893 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | 912 if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { |
913 return ngx_http_keepalive_handler(rev); | |
914 } | |
915 | |
916 #else | |
917 | |
918 if (blocked) { | |
894 return ngx_http_keepalive_handler(rev); | 919 return ngx_http_keepalive_handler(rev); |
895 } | 920 } |
896 | 921 |
897 #endif | 922 #endif |
898 | 923 |
911 ngx_log_debug(ev->log, "http keepalive handler"); | 936 ngx_log_debug(ev->log, "http keepalive handler"); |
912 | 937 |
913 if (ev->timedout) | 938 if (ev->timedout) |
914 return NGX_DONE; | 939 return NGX_DONE; |
915 | 940 |
916 /* TODO: MSIE closes keepalive connection with ECONNRESET | 941 /* MSIE closes keepalive connection with RST flag |
917 so we need to handle here this error | 942 so we ignore ECONNRESET here */ |
918 1) in INFO (not ERR) level, 2) with time elapsed */ | 943 |
919 n = ngx_event_recv(c, c->buffer->last.mem, | 944 ev->ignore_econnreset = 1; |
920 c->buffer->end - c->buffer->last.mem); | 945 ngx_set_socket_errno(0); |
946 n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last); | |
947 ev->ignore_econnreset = 0; | |
921 | 948 |
922 if (n == NGX_AGAIN || n == NGX_ERROR) | 949 if (n == NGX_AGAIN || n == NGX_ERROR) |
923 return n; | 950 return n; |
924 | 951 |
925 ctx = (ngx_http_log_ctx_t *) ev->log->data; | 952 ctx = (ngx_http_log_ctx_t *) ev->log->data; |
926 ev->log->handler = NULL; | 953 ev->log->handler = NULL; |
927 | 954 |
928 if (n == 0) { | 955 if (n == 0) { |
929 ngx_log_error(NGX_LOG_INFO, ev->log, 0, | 956 ngx_log_error(NGX_LOG_INFO, ev->log, ngx_socket_errno, |
930 "client %s closed keepalive connection", ctx->client); | 957 "client %s closed keepalive connection", ctx->client); |
931 return NGX_DONE; | 958 return NGX_DONE; |
932 } | 959 } |
933 | 960 |
934 c->buffer->last.mem += n; | 961 c->buffer->last += n; |
935 ev->log->handler = ngx_http_log_error; | 962 ev->log->handler = ngx_http_log_error; |
936 ctx->action = "reading client request line"; | 963 ctx->action = "reading client request line"; |
937 | 964 |
938 return ngx_http_init_request(ev); | 965 return ngx_http_init_request(ev); |
939 } | 966 } |
940 | 967 |
941 | 968 |
942 static int ngx_http_set_lingering_close(ngx_http_request_t *r) | 969 static int ngx_http_set_lingering_close(ngx_http_request_t *r) |
943 { | 970 { |
944 ngx_event_t *ev; | 971 int blocked; |
945 ngx_connection_t *c; | 972 ngx_event_t *rev, *wev; |
973 ngx_connection_t *c; | |
946 ngx_http_core_loc_conf_t *lcf; | 974 ngx_http_core_loc_conf_t *lcf; |
947 | 975 |
948 c = r->connection; | 976 c = r->connection; |
949 ev = r->connection->read; | 977 rev = c->read; |
978 wev = c->write; | |
950 | 979 |
951 lcf = (ngx_http_core_loc_conf_t *) | 980 lcf = (ngx_http_core_loc_conf_t *) |
952 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); | 981 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
953 | 982 |
954 r->lingering_time = ngx_time() + lcf->lingering_time; | 983 r->lingering_time = ngx_time() + lcf->lingering_time / 1000; |
955 r->connection->read->event_handler = ngx_http_lingering_close_handler; | 984 r->connection->read->event_handler = ngx_http_lingering_close_handler; |
956 | 985 |
957 if (ev->timer_set) { | 986 if (rev->timer_set) { |
958 ngx_del_timer(ev); | 987 ngx_del_timer(rev); |
959 } else { | 988 } else { |
960 ev->timer_set = 1; | 989 rev->timer_set = 1; |
961 } | 990 } |
962 | 991 |
963 ngx_add_timer(ev, lcf->lingering_timeout); | 992 ngx_add_timer(rev, lcf->lingering_timeout); |
964 | 993 |
965 if (ev->blocked) { | 994 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
966 if (ngx_event_flags & NGX_HAVE_LEVEL_EVENT) { | 995 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { |
967 if (ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT) | 996 return ngx_http_close_request(r); |
968 == NGX_ERROR) { | 997 } |
969 return ngx_http_close_request(r); | 998 blocked = 1; |
970 } | 999 rev->blocked = 0; |
971 } | 1000 |
972 } | 1001 } else { |
973 | 1002 blocked = 0; |
974 if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) { | 1003 } |
975 ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, | 1004 |
1005 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { | |
1006 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | |
1007 return ngx_http_close_request(r); | |
1008 } | |
1009 } | |
1010 | |
1011 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { | |
1012 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, | |
976 ngx_shutdown_socket_n " failed"); | 1013 ngx_shutdown_socket_n " failed"); |
977 return ngx_http_close_request(r); | 1014 return ngx_http_close_request(r); |
978 } | 1015 } |
979 | 1016 |
980 #if (HAVE_AIO_EVENT) /* aio, iocp */ | 1017 #if (HAVE_AIO_EVENT) /* aio, iocp */ |
981 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | 1018 |
982 return ngx_http_lingering_close_handler(ev); | 1019 if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { |
983 } | 1020 return ngx_http_lingering_close_handler(rev); |
1021 } | |
1022 | |
1023 #else | |
1024 | |
1025 if (blocked) { | |
1026 return ngx_http_lingering_close_handler(rev); | |
1027 } | |
1028 | |
984 #endif | 1029 #endif |
985 | 1030 |
986 #if (HAVE_CLEAR_EVENT) /* kqueue */ || (HAVE_EDGE_EVENT) /* epoll */ | 1031 return NGX_OK; |
987 if (ngx_event_flags & (NGX_HAVE_CLEAR_EVENT|NGX_HAVE_EDGE_EVENT)) { | |
988 return NGX_OK; | |
989 } | |
990 #endif | |
991 | |
992 /* select, poll, /dev/poll */ | |
993 | |
994 return ngx_del_event(c->write, NGX_WRITE_EVENT, 0); | |
995 } | 1032 } |
996 | 1033 |
997 | 1034 |
998 static int ngx_http_lingering_close_handler(ngx_event_t *ev) | 1035 static int ngx_http_lingering_close_handler(ngx_event_t *ev) |
999 { | 1036 { |
1019 | 1056 |
1020 lcf = (ngx_http_core_loc_conf_t *) | 1057 lcf = (ngx_http_core_loc_conf_t *) |
1021 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); | 1058 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
1022 | 1059 |
1023 if (r->discarded_buffer == NULL) { | 1060 if (r->discarded_buffer == NULL) { |
1024 if ((size_t)(r->header_in->end - r->header_in->last.mem) | 1061 |
1062 /* TODO: r->header_in->start (if large headers are enabled) | |
1063 or the end of parsed header (otherwise) | |
1064 instead of r->header_in->last */ | |
1065 | |
1066 if ((size_t)(r->header_in->end - r->header_in->last) | |
1025 >= lcf->discarded_buffer_size) { | 1067 >= lcf->discarded_buffer_size) { |
1026 r->discarded_buffer = r->header_in->last.mem; | 1068 r->discarded_buffer = r->header_in->last; |
1027 | 1069 |
1028 } else { | 1070 } else { |
1029 ngx_test_null(r->discarded_buffer, | 1071 ngx_test_null(r->discarded_buffer, |
1030 ngx_palloc(c->pool, lcf->discarded_buffer_size), | 1072 ngx_palloc(c->pool, lcf->discarded_buffer_size), |
1031 ngx_http_close_request(r)); | 1073 ngx_http_close_request(r)); |