Mercurial > hg > nginx
comparison src/http/ngx_http_event.c @ 64:34d647deb1da
nginx-0.0.1-2003-03-04-09:33:48 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 04 Mar 2003 06:33:48 +0000 |
parents | 50186b49f2ad |
children | 4222c496acb3 |
comparison
equal
deleted
inserted
replaced
63:36d2c25cc9bb | 64:34d647deb1da |
---|---|
42 | 42 |
43 static char *header_errors[] = { | 43 static char *header_errors[] = { |
44 "client %s sent invalid method", | 44 "client %s sent invalid method", |
45 "client %s sent invalid request", | 45 "client %s sent invalid request", |
46 "client %s sent too long URI", | 46 "client %s sent too long URI", |
47 "client %s sent HEAD method in HTTP/0.9 request" | 47 "client %s sent HEAD method in HTTP/0.9 request", |
48 | |
49 "client %s sent invalid header, URL: %s", | |
50 "client %s sent too long header line, URL: %s", | |
51 "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s" | |
48 }; | 52 }; |
53 | |
49 | 54 |
50 | 55 |
51 static ngx_http_header_t headers_in[] = { | 56 static ngx_http_header_t headers_in[] = { |
52 { 4, "Host", offsetof(ngx_http_headers_in_t, host) }, | 57 { 4, "Host", offsetof(ngx_http_headers_in_t, host) }, |
53 { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) }, | 58 { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) }, |
111 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); | 116 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); |
112 } | 117 } |
113 | 118 |
114 #endif | 119 #endif |
115 | 120 |
116 /* THINK: should ngx_edge_add_event() be moved to accept part ? */ | 121 #if (HAVE_EDGE_EVENT) /* epoll */ || (HAVE_AIO_EVENT) /* aio, iocp */ |
117 #if (HAVE_EDGE_EVENT) /* epoll */ | 122 |
118 | 123 if (ngx_event_flags & (NGX_HAVE_EDGE_EVENT|NGX_HAVE_AIO_EVENT)) { |
119 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { | |
120 if (ngx_edge_add_event(ev) == NGX_ERROR) { | |
121 return NGX_ERROR; | |
122 } | |
123 return ngx_http_init_request(ev); | |
124 } | |
125 | |
126 #endif | |
127 | |
128 #if (HAVE_AIO_EVENT) /* aio, iocp */ | |
129 | |
130 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | |
131 return ngx_http_init_request(ev); | 124 return ngx_http_init_request(ev); |
132 } | 125 } |
133 | 126 |
134 #endif | 127 #endif |
135 | 128 |
191 } | 184 } |
192 | 185 |
193 | 186 |
194 static int ngx_http_process_request_header(ngx_event_t *ev) | 187 static int ngx_http_process_request_header(ngx_event_t *ev) |
195 { | 188 { |
196 int n, rc; | 189 int n, rc, offset; |
197 ngx_connection_t *c; | 190 ngx_connection_t *c; |
198 ngx_http_request_t *r; | 191 ngx_http_request_t *r; |
192 ngx_http_log_ctx_t *ctx; | |
199 | 193 |
200 c = (ngx_connection_t *) ev->data; | 194 c = (ngx_connection_t *) ev->data; |
201 r = (ngx_http_request_t *) c->data; | 195 r = (ngx_http_request_t *) c->data; |
202 | 196 |
203 ngx_log_debug(ev->log, "http process request"); | 197 ngx_log_debug(ev->log, "http process request"); |
247 /* state_handlers are called in following order: | 241 /* state_handlers are called in following order: |
248 ngx_http_process_request_line(r) | 242 ngx_http_process_request_line(r) |
249 ngx_http_process_request_headers(r) */ | 243 ngx_http_process_request_headers(r) */ |
250 | 244 |
251 do { | 245 do { |
246 /* state_handlers return NGX_OK when whole header done */ | |
252 rc = (r->state_handler)(r); | 247 rc = (r->state_handler)(r); |
253 | 248 |
254 if (rc == NGX_ERROR) | 249 if (rc == NGX_ERROR) |
255 return rc; | 250 return rc; |
256 | 251 |
257 } while (rc == NGX_AGAIN | 252 } while (rc == NGX_AGAIN |
258 && r->header_in->pos.mem < r->header_in->last.mem); | 253 && r->header_in->pos.mem < r->header_in->last.mem); |
254 | |
255 /* if large client header is supported then | |
256 we need to compact r->header_in hunk */ | |
257 | |
258 if (ngx_http_large_client_header | |
259 && rc == NGX_AGAIN | |
260 && r->header_in->last.mem == r->header_in->end | |
261 && r->header_in->pos.mem == r->header_in->last.mem) | |
262 { | |
263 offset = r->header_name_start - r->header_in->start; | |
264 | |
265 if (offset == 0) { | |
266 ctx = r->connection->log->data; | |
267 r->connection->log->handler = NULL; | |
268 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
269 "client %s sent too long header line, URL: %s", | |
270 ctx->client, ctx->url); | |
271 r->connection->log->handler = ngx_http_log_error; | |
272 | |
273 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); | |
274 } | |
275 | |
276 ngx_memcpy(r->header_in->start, r->header_name_start, | |
277 r->header_in->last.mem - r->header_name_start); | |
278 | |
279 r->header_name_start = r->header_in->start; | |
280 r->header_in->last.mem -= offset; | |
281 r->header_in->pos.mem -= offset; | |
282 r->header_name_end -= offset; | |
283 r->header_start -= offset; | |
284 r->header_end -= offset; | |
285 } | |
259 | 286 |
260 #if (HAVE_AIO_EVENT) /* aio, iocp */ | 287 #if (HAVE_AIO_EVENT) /* aio, iocp */ |
261 } while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT); | 288 } while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT); |
262 #endif | 289 #endif |
263 | 290 |
299 rc = ngx_read_http_request_line(r); | 326 rc = ngx_read_http_request_line(r); |
300 | 327 |
301 c = r->connection; | 328 c = r->connection; |
302 | 329 |
303 if (rc == NGX_OK) { | 330 if (rc == NGX_OK) { |
331 /* copy URI */ | |
304 r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end) | 332 r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end) |
305 - r->uri_start; | 333 - r->uri_start; |
306 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), | 334 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), |
307 ngx_http_close_request(r)); | 335 ngx_http_close_request(r)); |
308 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); | 336 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); |
309 | 337 |
338 /* if large client headers is supported then | |
339 we need to copy request line */ | |
340 | |
310 r->request_line.len = r->request_end - r->header_in->start; | 341 r->request_line.len = r->request_end - r->header_in->start; |
311 ngx_test_null(r->request_line.data, | 342 if (ngx_http_large_client_header) { |
312 ngx_palloc(r->pool, r->request_line.len + 1), | 343 ngx_test_null(r->request_line.data, |
313 ngx_http_close_request(r)); | 344 ngx_palloc(r->pool, r->request_line.len + 1), |
314 ngx_cpystrn(r->request_line.data, r->header_in->start, | 345 ngx_http_close_request(r)); |
315 r->request_line.len + 1); | 346 ngx_cpystrn(r->request_line.data, r->header_in->start, |
316 | 347 r->request_line.len + 1); |
348 | |
349 } else { | |
350 r->request_line.data = r->header_in->start; | |
351 r->request_line.data[r->request_line.len] = '\0'; | |
352 } | |
353 | |
354 /* copy URI extention if it exists */ | |
317 if (r->uri_ext) { | 355 if (r->uri_ext) { |
318 r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end) | 356 r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end) |
319 - r->uri_ext; | 357 - r->uri_ext; |
320 ngx_test_null(r->exten.data, | 358 ngx_test_null(r->exten.data, |
321 ngx_palloc(r->pool, r->exten.len + 1), | 359 ngx_palloc(r->pool, r->exten.len + 1), |
327 ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s %s" _ | 365 ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s %s" _ |
328 r->method _ r->http_version _ | 366 r->method _ r->http_version _ |
329 r->uri.data _ r->exten.data); | 367 r->uri.data _ r->exten.data); |
330 #endif | 368 #endif |
331 | 369 |
332 if (r->http_version == 9) | 370 ctx = r->connection->log->data; |
371 if (ngx_http_url_in_error_log) { | |
372 ngx_test_null(ctx->url, | |
373 ngx_palloc(r->pool, r->uri_end - r->uri_start + 1), | |
374 ngx_http_close_request(r)); | |
375 ngx_cpystrn(ctx->url, r->uri_start, r->uri_end - r->uri_start + 1); | |
376 } | |
377 | |
378 if (r->http_version == NGX_HTTP_VERSION_9) | |
333 return NGX_OK; | 379 return NGX_OK; |
334 | 380 |
335 /* TODO: check too long URI - no space for header, compact buffer */ | |
336 | |
337 r->headers_in.headers = ngx_create_table(r->pool, 10); | 381 r->headers_in.headers = ngx_create_table(r->pool, 10); |
338 | 382 |
339 r->state_handler = ngx_http_process_request_headers; | 383 r->state_handler = ngx_http_process_request_headers; |
340 ctx = r->connection->log->data; | |
341 ctx->action = "reading client request headers"; | 384 ctx->action = "reading client request headers"; |
342 | 385 |
343 return NGX_AGAIN; | 386 return NGX_AGAIN; |
344 } | 387 } |
345 | 388 |
346 if (r->header_in->last.mem >= r->header_in->end) { | 389 if (r->header_in->last.mem == r->header_in->end) { |
347 rc = NGX_HTTP_PARSE_TOO_LONG_URI; | 390 rc = NGX_HTTP_PARSE_TOO_LONG_URI; |
348 | 391 |
349 } else if (rc == NGX_AGAIN) { | 392 } else if (rc == NGX_AGAIN) { |
350 return NGX_AGAIN; | 393 return NGX_AGAIN; |
351 } | 394 } |
370 ngx_http_log_ctx_t *ctx; | 413 ngx_http_log_ctx_t *ctx; |
371 | 414 |
372 for ( ;; ) { | 415 for ( ;; ) { |
373 rc = ngx_read_http_header_line(r, r->header_in); | 416 rc = ngx_read_http_header_line(r, r->header_in); |
374 | 417 |
375 /* TODO: check too long header, compact buffer */ | |
376 | |
377 if (rc == NGX_OK) { /* header line is ready */ | 418 if (rc == NGX_OK) { /* header line is ready */ |
378 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { | 419 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { |
379 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); | 420 return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
380 } | 421 } |
381 | 422 |
382 return NGX_AGAIN; | 423 return NGX_AGAIN; |
383 | 424 |
384 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | 425 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
389 if (r->headers_in.host->value.data[len] == ':') { | 430 if (r->headers_in.host->value.data[len] == ':') { |
390 break; | 431 break; |
391 } | 432 } |
392 } | 433 } |
393 r->headers_in.host_name_len = len; | 434 r->headers_in.host_name_len = len; |
435 return NGX_OK; | |
394 | 436 |
395 } else { | 437 } else { |
396 if (r->http_version > NGX_HTTP_VERSION_10) { | 438 if (r->http_version < NGX_HTTP_VERSION_11) { |
397 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); | 439 r->headers_in.host_name_len = 0; |
440 return NGX_OK; | |
398 } | 441 } |
399 r->headers_in.host_name_len = 0; | |
400 } | 442 } |
401 | 443 |
402 return NGX_OK; | 444 rc = NGX_HTTP_PARSE_NO_HOST_HEADER; |
445 | |
446 } else if (!ngx_http_large_client_header | |
447 && r->header_in->last.mem == r->header_in->end) { | |
448 rc = NGX_HTTP_PARSE_TOO_LONG_HEADER; | |
403 | 449 |
404 } else if (rc == NGX_AGAIN) { | 450 } else if (rc == NGX_AGAIN) { |
405 return NGX_AGAIN; | 451 return NGX_AGAIN; |
406 | 452 } |
407 } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { | 453 |
408 ctx = r->connection->log->data; | 454 ctx = r->connection->log->data; |
409 r->connection->log->handler = NULL; | 455 r->connection->log->handler = NULL; |
410 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 456 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
411 "client %s sent invalid header", ctx->client); | 457 header_errors[rc - NGX_HTTP_PARSE_INVALID_METHOD], |
412 r->connection->log->handler = ngx_http_log_error; | 458 ctx->client, ctx->url); |
413 | 459 r->connection->log->handler = ngx_http_log_error; |
414 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); | 460 |
415 } | 461 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); |
416 } | 462 } |
417 } | 463 } |
418 | 464 |
419 | 465 |
420 static int ngx_http_process_request_header_line(ngx_http_request_t *r) | 466 static int ngx_http_process_request_header_line(ngx_http_request_t *r) |
422 int i; | 468 int i; |
423 ngx_table_elt_t *h; | 469 ngx_table_elt_t *h; |
424 | 470 |
425 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); | 471 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); |
426 | 472 |
473 /* if large client headers is supported then | |
474 we need to copy header name and value */ | |
475 | |
427 h->key.len = r->header_name_end - r->header_name_start; | 476 h->key.len = r->header_name_end - r->header_name_start; |
428 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), NGX_ERROR); | |
429 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
430 | |
431 h->value.len = r->header_end - r->header_start; | 477 h->value.len = r->header_end - r->header_start; |
432 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1), | 478 |
433 NGX_ERROR); | 479 if (ngx_http_large_client_header) { |
434 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | 480 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), |
481 NGX_ERROR); | |
482 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1), | |
483 NGX_ERROR); | |
484 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
485 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
486 | |
487 } else { | |
488 h->key.data = r->header_name_start; | |
489 h->key.data[h->key.len] = '\0'; | |
490 h->value.data = r->header_start; | |
491 h->value.data[h->value.len] = '\0'; | |
492 } | |
435 | 493 |
436 for (i = 0; headers_in[i].len != 0; i++) { | 494 for (i = 0; headers_in[i].len != 0; i++) { |
437 if (headers_in[i].len != h->key.len) { | 495 if (headers_in[i].len != h->key.len) { |
438 continue; | 496 continue; |
439 } | 497 } |
451 } | 509 } |
452 | 510 |
453 | 511 |
454 static int ngx_http_event_request_handler(ngx_http_request_t *r) | 512 static int ngx_http_event_request_handler(ngx_http_request_t *r) |
455 { | 513 { |
456 int rc, event; | 514 int rc, event; |
457 ngx_msec_t timeout; | 515 ngx_msec_t timeout; |
458 ngx_event_t *rev, *wev; | 516 ngx_event_t *rev, *wev; |
517 ngx_http_log_ctx_t *ctx; | |
459 | 518 |
460 rev = r->connection->read; | 519 rev = r->connection->read; |
461 wev = r->connection->write; | 520 wev = r->connection->write; |
462 | 521 |
463 if (rev->timer_set) { | 522 if (rev->timer_set) { |
466 } | 525 } |
467 | 526 |
468 r->state_handler = NULL; | 527 r->state_handler = NULL; |
469 rev->event_handler = ngx_http_block_read; | 528 rev->event_handler = ngx_http_block_read; |
470 | 529 |
530 ctx = r->connection->log->data; | |
531 ctx->action = "processing client request"; | |
532 | |
471 rc = ngx_http_handler(r); | 533 rc = ngx_http_handler(r); |
472 | 534 |
473 /* handler is still busy */ | 535 /* handler is still busy */ |
474 if (rc == NGX_WAITING) | 536 if (rc == NGX_WAITING) |
475 return rc; | 537 return rc; |
476 | 538 |
477 /* handler has done its work but transfer is still not completed */ | 539 /* handler has done its work but transfer is still not completed */ |
478 if (rc == NGX_AGAIN) { | 540 if (rc == NGX_AGAIN) { |
479 | 541 |
542 /* STUB: timeouts should be reworked */ | |
480 if (r->connection->sent > 0) { | 543 if (r->connection->sent > 0) { |
481 ngx_log_debug(r->connection->log, "sent: " OFF_FMT _ | 544 ngx_log_debug(r->connection->log, "sent: " OFF_FMT _ |
482 r->connection->sent); | 545 r->connection->sent); |
483 timeout = (ngx_msec_t) (r->connection->sent * 10); | 546 timeout = (ngx_msec_t) (r->connection->sent * 10); |
484 ngx_log_debug(r->connection->log, "timeout: %d" _ timeout); | 547 ngx_log_debug(r->connection->log, "timeout: %d" _ timeout); |
490 | 553 |
491 wev->event_handler = ngx_http_writer; | 554 wev->event_handler = ngx_http_writer; |
492 | 555 |
493 #if (USE_KQUEUE) | 556 #if (USE_KQUEUE) |
494 | 557 |
558 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ | |
559 wev->lowat = /* STUB */ NGX_LOWAT; | |
560 #endif | |
561 | |
495 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { | 562 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { |
496 return ngx_http_close_request(r); | 563 return ngx_http_close_request(r); |
497 } | 564 } |
498 | 565 |
499 return rc; | 566 return rc; |
502 | 569 |
503 #if (HAVE_AIO_EVENT) || (HAVE_EDGE_EVENT) /* aio, iocp, epoll */ | 570 #if (HAVE_AIO_EVENT) || (HAVE_EDGE_EVENT) /* aio, iocp, epoll */ |
504 | 571 |
505 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { | 572 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { |
506 return rc; | 573 return rc; |
574 } | |
575 | |
576 #endif | |
577 | |
578 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ | |
579 | |
580 if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) { | |
581 wev->lowat = /* STUB */ NGX_LOWAT; | |
507 } | 582 } |
508 | 583 |
509 #endif | 584 #endif |
510 | 585 |
511 #if (HAVE_CLEAR_EVENT) /* kqueue */ | 586 #if (HAVE_CLEAR_EVENT) /* kqueue */ |
544 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) | 619 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) |
545 return ngx_http_special_response(r, rc); | 620 return ngx_http_special_response(r, rc); |
546 | 621 |
547 /* rc == NGX_OK */ | 622 /* rc == NGX_OK */ |
548 | 623 |
549 if (!r->keepalive) { | 624 if (r->keepalive == 0) { |
550 if (r->lingering_close) { | 625 if (r->lingering_close) { |
551 return ngx_http_set_lingering_close(r); | 626 return ngx_http_set_lingering_close(r); |
552 | 627 |
553 } else { | 628 } else { |
554 return ngx_http_close_request(r); | 629 return ngx_http_close_request(r); |
576 | 651 |
577 ngx_log_debug(ev->log, "output filter in writer: %d" _ rc); | 652 ngx_log_debug(ev->log, "output filter in writer: %d" _ rc); |
578 | 653 |
579 if (rc == NGX_AGAIN) { | 654 if (rc == NGX_AGAIN) { |
580 | 655 |
656 /* STUB: timeouts should be reworked */ | |
581 if (c->sent > 0) { | 657 if (c->sent > 0) { |
582 conf = (ngx_http_core_loc_conf_t *) | 658 conf = (ngx_http_core_loc_conf_t *) |
583 ngx_http_get_module_loc_conf(r->main ? r->main : r, | 659 ngx_http_get_module_loc_conf(r->main ? r->main : r, |
584 ngx_http_core_module_ctx); | 660 ngx_http_core_module_ctx); |
585 | 661 |
605 | 681 |
606 /* rc == NGX_OK */ | 682 /* rc == NGX_OK */ |
607 | 683 |
608 ngx_log_debug(ev->log, "http writer done"); | 684 ngx_log_debug(ev->log, "http writer done"); |
609 | 685 |
610 if (!r->keepalive) { | 686 if (r->keepalive == 0) { |
611 if (r->lingering_close) { | 687 if (r->lingering_close) { |
612 return ngx_http_set_lingering_close(r); | 688 return ngx_http_set_lingering_close(r); |
613 | 689 |
614 } else { | 690 } else { |
615 return ngx_http_close_request(r); | 691 return ngx_http_close_request(r); |
729 | 805 |
730 /* TODO: if c->read->blocked */ | 806 /* TODO: if c->read->blocked */ |
731 static int ngx_http_set_keepalive(ngx_http_request_t *r) | 807 static int ngx_http_set_keepalive(ngx_http_request_t *r) |
732 { | 808 { |
733 ngx_connection_t *c; | 809 ngx_connection_t *c; |
810 ngx_http_log_ctx_t *ctx; | |
734 | 811 |
735 c = (ngx_connection_t *) r->connection; | 812 c = (ngx_connection_t *) r->connection; |
736 | 813 |
737 c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start; | 814 c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start; |
738 c->read->event_handler = ngx_http_keepalive_handler; | 815 c->read->event_handler = ngx_http_keepalive_handler; |
741 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) { | 818 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
742 return NGX_ERROR; | 819 return NGX_ERROR; |
743 } | 820 } |
744 } | 821 } |
745 | 822 |
823 ctx = (ngx_http_log_ctx_t *) c->log->data; | |
824 ctx->action = "closing request"; | |
825 | |
746 ngx_http_close_request(r); | 826 ngx_http_close_request(r); |
827 | |
828 ctx->action = "keepalive"; | |
747 | 829 |
748 #if (HAVE_AIO_EVENT) /* aio, iocp */ | 830 #if (HAVE_AIO_EVENT) /* aio, iocp */ |
749 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | 831 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { |
750 return ngx_http_keepalive_handler(c->read); | 832 return ngx_http_keepalive_handler(c->read); |
751 } | 833 } |
766 ngx_log_debug(ev->log, "http keepalive handler"); | 848 ngx_log_debug(ev->log, "http keepalive handler"); |
767 | 849 |
768 if (ev->timedout) | 850 if (ev->timedout) |
769 return NGX_DONE; | 851 return NGX_DONE; |
770 | 852 |
853 /* TODO: MSIE closes keepalive connection with ECONNRESET | |
854 so we need to handle here this error | |
855 1) in INFO (not ERR) level, 2) with time elapsed */ | |
771 n = ngx_event_recv(c, c->buffer->last.mem, | 856 n = ngx_event_recv(c, c->buffer->last.mem, |
772 c->buffer->end - c->buffer->last.mem); | 857 c->buffer->end - c->buffer->last.mem); |
773 | 858 |
774 if (n == NGX_AGAIN || n == NGX_ERROR) | 859 if (n == NGX_AGAIN || n == NGX_ERROR) |
775 return n; | 860 return n; |
813 } | 898 } |
814 | 899 |
815 ngx_add_timer(ev, lcf->lingering_timeout); | 900 ngx_add_timer(ev, lcf->lingering_timeout); |
816 | 901 |
817 if (ev->blocked) { | 902 if (ev->blocked) { |
818 if (ngx_add_event(ev, NGX_READ_EVENT, | 903 if (ngx_event_flags & NGX_HAVE_LEVEL_EVENT) { |
819 #if (HAVE_CLEAR_EVENT) | 904 if (ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT) |
820 NGX_CLEAR_EVENT) == NGX_ERROR) | 905 == NGX_ERROR) { |
821 #else | 906 return ngx_http_close_request(r); |
822 NGX_ONESHOT_EVENT) == NGX_ERROR) | 907 } |
823 #endif | |
824 { | |
825 return ngx_http_close_request(r); | |
826 } | 908 } |
827 } | 909 } |
828 | 910 |
829 if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) { | 911 if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) { |
830 ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, | 912 ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, |
836 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { | 918 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { |
837 return ngx_http_lingering_close_handler(ev); | 919 return ngx_http_lingering_close_handler(ev); |
838 } | 920 } |
839 #endif | 921 #endif |
840 | 922 |
841 #if (HAVE_CLEAR_EVENT) || (HAVE_EDGE_EVENT) /* kqueue, epoll */ | 923 #if (HAVE_CLEAR_EVENT) /* kqueue */ || (HAVE_EDGE_EVENT) /* epoll */ |
842 if (ngx_event_flags & (NGX_HAVE_CLEAR_EVENT|NGX_HAVE_EDGE_EVENT)) { | 924 if (ngx_event_flags & (NGX_HAVE_CLEAR_EVENT|NGX_HAVE_EDGE_EVENT)) { |
843 return NGX_OK; | 925 return NGX_OK; |
844 } | 926 } |
845 #endif | 927 #endif |
846 | 928 |