comparison src/http/ngx_http_event.c @ 65:4222c496acb3

nginx-0.0.1-2003-03-05-09:37:42 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 05 Mar 2003 06:37:42 +0000
parents 34d647deb1da
children 4876cd4a36bb
comparison
equal deleted inserted replaced
64:34d647deb1da 65:4222c496acb3
34 static int ngx_http_keepalive_handler(ngx_event_t *ev); 34 static int ngx_http_keepalive_handler(ngx_event_t *ev);
35 static int ngx_http_set_lingering_close(ngx_http_request_t *r); 35 static int ngx_http_set_lingering_close(ngx_http_request_t *r);
36 static int ngx_http_lingering_close_handler(ngx_event_t *ev); 36 static int ngx_http_lingering_close_handler(ngx_event_t *ev);
37 37
38 static int ngx_http_close_connection(ngx_event_t *ev); 38 static int ngx_http_close_connection(ngx_event_t *ev);
39 static int ngx_http_header_parse_error(ngx_http_request_t *r,
40 int parse_err, int err);
39 static size_t ngx_http_log_error(void *data, char *buf, size_t len); 41 static size_t ngx_http_log_error(void *data, char *buf, size_t len);
40 42
41 43
42 44
43 static char *header_errors[] = { 45 static char *header_errors[] = {
126 128
127 #endif 129 #endif
128 130
129 /* select, poll, /dev/poll */ 131 /* select, poll, /dev/poll */
130 132
133 ev->level = 1;
131 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); 134 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
132 135
133 #endif /* USE_KQUEUE */ 136 #endif /* USE_KQUEUE */
134 } 137 }
135 138
158 NGX_ERROR); 161 NGX_ERROR);
159 } else { 162 } else {
160 r->header_read = 1; 163 r->header_read = 1;
161 } 164 }
162 165
166 r->pipeline = c->pipeline;
163 r->header_in = c->buffer; 167 r->header_in = c->buffer;
164 168
165 ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, ev->log), 169 ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, ev->log),
166 ngx_http_close_request(r)); 170 ngx_http_close_request(r));
167 171
184 } 188 }
185 189
186 190
187 static int ngx_http_process_request_header(ngx_event_t *ev) 191 static int ngx_http_process_request_header(ngx_event_t *ev)
188 { 192 {
189 int n, rc, offset; 193 int n, rc;
190 ngx_connection_t *c; 194 ngx_connection_t *c;
191 ngx_http_request_t *r; 195 ngx_http_request_t *r;
192 ngx_http_log_ctx_t *ctx; 196 ngx_http_log_ctx_t *ctx;
193 197
194 c = (ngx_connection_t *) ev->data; 198 c = (ngx_connection_t *) ev->data;
250 return rc; 254 return rc;
251 255
252 } while (rc == NGX_AGAIN 256 } while (rc == NGX_AGAIN
253 && r->header_in->pos.mem < r->header_in->last.mem); 257 && r->header_in->pos.mem < r->header_in->last.mem);
254 258
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 }
286
287 #if (HAVE_AIO_EVENT) /* aio, iocp */ 259 #if (HAVE_AIO_EVENT) /* aio, iocp */
288 } while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT); 260 } while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT);
289 #endif 261 #endif
290 262
291 if (rc == NGX_OK) { 263 if (rc == NGX_OK) {
317 } 289 }
318 290
319 291
320 static int ngx_http_process_request_line(ngx_http_request_t *r) 292 static int ngx_http_process_request_line(ngx_http_request_t *r)
321 { 293 {
322 int rc; 294 int rc, offset;
323 ngx_connection_t *c; 295 ngx_connection_t *c;
324 ngx_http_log_ctx_t *ctx; 296 ngx_http_log_ctx_t *ctx;
325 297
326 rc = ngx_read_http_request_line(r); 298 rc = ngx_read_http_request_line(r);
299
300 /* If it's a pipelined request and a request line is not complete
301 then we need to copy it to the start of r->header_in hunk.
302 We need to copy it here only if the large client headers are enabled
303 otherwise a request line had already copied to start
304 of r->header_in hunk in ngx_http_set_keepalive() */
305
306 if (ngx_http_large_client_header
307 && rc == NGX_AGAIN
308 && r->header_in->last.mem == r->header_in->end)
309 {
310 offset = r->request_start - r->header_in->start;
311
312 if (offset == 0) {
313 return ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
314 NGX_HTTP_REQUEST_URI_TOO_LARGE);
315 }
316
317 ngx_memcpy(r->header_in->start, r->request_start,
318 r->header_in->last.mem - r->request_start);
319
320 r->header_in->pos.mem -= offset;
321 r->header_in->last.mem -= offset;
322 r->request_start = r->header_in->start;
323 r->request_end -= offset;
324 r->uri_start -= offset;
325 r->uri_end -= offset;
326 if (r->uri_ext) {
327 r->uri_ext -= offset;
328 }
329 if (r->args_start) {
330 r->args_start -= offset;
331 }
332 }
327 333
328 c = r->connection; 334 c = r->connection;
329 335
330 if (rc == NGX_OK) { 336 if (rc == NGX_OK) {
331 /* copy URI */ 337 /* copy URI */
336 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); 342 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
337 343
338 /* if large client headers is supported then 344 /* if large client headers is supported then
339 we need to copy request line */ 345 we need to copy request line */
340 346
341 r->request_line.len = r->request_end - r->header_in->start; 347 r->request_line.len = r->request_end - r->request_start;
342 if (ngx_http_large_client_header) { 348 if (ngx_http_large_client_header) {
343 ngx_test_null(r->request_line.data, 349 ngx_test_null(r->request_line.data,
344 ngx_palloc(r->pool, r->request_line.len + 1), 350 ngx_palloc(r->pool, r->request_line.len + 1),
345 ngx_http_close_request(r)); 351 ngx_http_close_request(r));
346 ngx_cpystrn(r->request_line.data, r->header_in->start, 352 ngx_cpystrn(r->request_line.data, r->request_start,
347 r->request_line.len + 1); 353 r->request_line.len + 1);
348 354
349 } else { 355 } else {
350 r->request_line.data = r->header_in->start; 356 r->request_line.data = r->request_start;
351 r->request_line.data[r->request_line.len] = '\0'; 357 r->request_line.data[r->request_line.len] = '\0';
352 } 358 }
353 359
354 /* copy URI extention if it exists */ 360 /* copy URI extention if it exists */
355 if (r->uri_ext) { 361 if (r->uri_ext) {
359 ngx_palloc(r->pool, r->exten.len + 1), 365 ngx_palloc(r->pool, r->exten.len + 1),
360 ngx_http_close_request(r)); 366 ngx_http_close_request(r));
361 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); 367 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
362 } 368 }
363 369
364 #if 0 370 #if 1
365 ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s %s" _ 371 if (r->exten.data == NULL) {
372 r->exten.data = "";
373 }
374 ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s'" _
366 r->method _ r->http_version _ 375 r->method _ r->http_version _
367 r->uri.data _ r->exten.data); 376 r->uri.data _ r->exten.data);
377 if (r->exten.data[0] == '\0') {
378 r->exten.data = NULL;
379 }
368 #endif 380 #endif
369 381
370 ctx = r->connection->log->data; 382 ctx = r->connection->log->data;
371 if (ngx_http_url_in_error_log) { 383 if (ngx_http_url_in_error_log) {
372 ngx_test_null(ctx->url, 384 ngx_test_null(ctx->url,
385 397
386 return NGX_AGAIN; 398 return NGX_AGAIN;
387 } 399 }
388 400
389 if (r->header_in->last.mem == r->header_in->end) { 401 if (r->header_in->last.mem == r->header_in->end) {
390 rc = NGX_HTTP_PARSE_TOO_LONG_URI; 402 return ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
403 NGX_HTTP_REQUEST_URI_TOO_LARGE);
391 404
392 } else if (rc == NGX_AGAIN) { 405 } else if (rc == NGX_AGAIN) {
393 return NGX_AGAIN; 406 return NGX_AGAIN;
394 } 407 }
395 408
396 ctx = r->connection->log->data; 409 return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
397 r->connection->log->handler = NULL;
398 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
399 header_errors[rc - NGX_HTTP_PARSE_INVALID_METHOD],
400 ctx->client);
401 r->connection->log->handler = ngx_http_log_error;
402
403 return ngx_http_error(r, (rc == NGX_HTTP_PARSE_TOO_LONG_URI) ?
404 NGX_HTTP_REQUEST_URI_TOO_LARGE:
405 NGX_HTTP_BAD_REQUEST);
406 } 410 }
407 411
408 412
409 static int ngx_http_process_request_headers(ngx_http_request_t *r) 413 static int ngx_http_process_request_headers(ngx_http_request_t *r)
410 { 414 {
411 int rc; 415 int rc, offset;
412 size_t len; 416 size_t len;
413 ngx_http_log_ctx_t *ctx; 417 ngx_http_log_ctx_t *ctx;
414 418
415 for ( ;; ) { 419 for ( ;; ) {
416 rc = ngx_read_http_header_line(r, r->header_in); 420 rc = ngx_read_http_header_line(r, r->header_in);
421
422 /* if large client header is supported then
423 we need to compact r->header_in hunk */
424
425 if (ngx_http_large_client_header
426 && rc == NGX_AGAIN
427 && r->header_in->pos.mem == r->header_in->end)
428 {
429 offset = r->header_name_start - r->header_in->start;
430
431 if (offset == 0) {
432 return ngx_http_header_parse_error(r,
433 NGX_HTTP_PARSE_TOO_LONG_HEADER,
434 NGX_HTTP_BAD_REQUEST);
435 }
436
437 ngx_memcpy(r->header_in->start, r->header_name_start,
438 r->header_in->last.mem - r->header_name_start);
439
440 r->header_in->last.mem -= offset;
441 r->header_in->pos.mem -= offset;
442 r->header_name_start = r->header_in->start;
443 r->header_name_end -= offset;
444 r->header_start -= offset;
445 r->header_end -= offset;
446 }
417 447
418 if (rc == NGX_OK) { /* header line is ready */ 448 if (rc == NGX_OK) { /* header line is ready */
419 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { 449 if (ngx_http_process_request_header_line(r) == NGX_ERROR) {
420 return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 450 return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
421 } 451 }
424 454
425 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { 455 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
426 ngx_log_debug(r->connection->log, "HTTP header done"); 456 ngx_log_debug(r->connection->log, "HTTP header done");
427 457
428 if (r->headers_in.host) { 458 if (r->headers_in.host) {
429 for (len = 0; len < r->headers_in.host->value.len; len++) { 459 for (len = 0; len < r->headers_in.host->value.len; len++) {
430 if (r->headers_in.host->value.data[len] == ':') { 460 if (r->headers_in.host->value.data[len] == ':') {
431 break; 461 break;
432 } 462 }
433 } 463 }
434 r->headers_in.host_name_len = len; 464 r->headers_in.host_name_len = len;
435 return NGX_OK;
436 465
437 } else { 466 } else {
438 if (r->http_version < NGX_HTTP_VERSION_11) { 467 if (r->http_version > NGX_HTTP_VERSION_10) {
439 r->headers_in.host_name_len = 0; 468 return ngx_http_header_parse_error(r,
440 return NGX_OK; 469 NGX_HTTP_PARSE_NO_HOST_HEADER,
441 } 470 NGX_HTTP_BAD_REQUEST);
471 }
472 r->headers_in.host_name_len = 0;
442 } 473 }
443 474
444 rc = NGX_HTTP_PARSE_NO_HOST_HEADER; 475 return NGX_OK;
445 476
446 } else if (!ngx_http_large_client_header 477 } else if (!ngx_http_large_client_header
447 && r->header_in->last.mem == r->header_in->end) { 478 && r->header_in->last.mem == r->header_in->end) {
448 rc = NGX_HTTP_PARSE_TOO_LONG_HEADER; 479 return ngx_http_header_parse_error(r,
480 NGX_HTTP_PARSE_TOO_LONG_HEADER,
481 NGX_HTTP_BAD_REQUEST);
449 482
450 } else if (rc == NGX_AGAIN) { 483 } else if (rc == NGX_AGAIN) {
451 return NGX_AGAIN; 484 return NGX_AGAIN;
452 } 485 }
453
454 ctx = r->connection->log->data;
455 r->connection->log->handler = NULL;
456 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
457 header_errors[rc - NGX_HTTP_PARSE_INVALID_METHOD],
458 ctx->client, ctx->url);
459 r->connection->log->handler = ngx_http_log_error;
460
461 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
462 } 486 }
463 } 487 }
464 488
465 489
466 static int ngx_http_process_request_header_line(ngx_http_request_t *r) 490 static int ngx_http_process_request_header_line(ngx_http_request_t *r)
588 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { 612 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
589 event = NGX_CLEAR_EVENT; 613 event = NGX_CLEAR_EVENT;
590 614
591 } else { 615 } else {
592 event = NGX_LEVEL_EVENT; 616 event = NGX_LEVEL_EVENT;
593 r->write_level_event = 1; 617 wev->level = 1;
594 } 618 }
595 619
596 #else /* select, poll, /dev/poll */ 620 #else /* select, poll, /dev/poll */
597 621
598 event = NGX_LEVEL_EVENT; 622 event = NGX_LEVEL_EVENT;
599 r->write_level_event = 1; 623 wev->level = 1;
600 624
601 #endif 625 #endif
602 626
603 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { 627 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
604 return ngx_http_close_request(r); 628 return ngx_http_close_request(r);
696 720
697 return ngx_http_set_keepalive(r); 721 return ngx_http_set_keepalive(r);
698 } 722 }
699 723
700 724
701 /* TODO */
702 static int ngx_http_block_read(ngx_event_t *ev) 725 static int ngx_http_block_read(ngx_event_t *ev)
703 { 726 {
704 ngx_log_debug(ev->log, "http read blocked"); 727 ngx_log_debug(ev->log, "http read blocked");
705 728
706 /* aio does not call this handler */ 729 /* aio does not call this handler */
709 732
710 return NGX_OK; 733 return NGX_OK;
711 734
712 #else 735 #else
713 736
714 #if (HAVE_CLEAR_EVENT) /* kqueue */ 737 if (ev->level) { /* select, poll, /dev/poll */
715 738 ev->blocked = 1;
716 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { 739 return ngx_del_event(ev, NGX_READ_EVENT, 0);
740
741 } else { /* kqueue, epoll */
717 return NGX_OK; 742 return NGX_OK;
718 } 743 }
719
720 #endif
721
722 #if (HAVE_EDGE_EVENT) /* epoll */
723
724 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) {
725 return NGX_OK;
726 }
727
728 #endif
729
730 /* select, poll, /dev/poll */
731
732 ev->blocked = 1;
733
734 return ngx_del_event(ev, NGX_READ_EVENT, 0);
735 744
736 #endif /* USE_KQUEUE */ 745 #endif /* USE_KQUEUE */
737 } 746 }
738 747
739 748
801 /* XXX: what if r->client_content_length == 0 ? */ 810 /* XXX: what if r->client_content_length == 0 ? */
802 return NGX_OK; 811 return NGX_OK;
803 } 812 }
804 813
805 814
806 /* TODO: if c->read->blocked */
807 static int ngx_http_set_keepalive(ngx_http_request_t *r) 815 static int ngx_http_set_keepalive(ngx_http_request_t *r)
808 { 816 {
817 int len;
818 ngx_hunk_t *h;
819 ngx_event_t *rev, *wev;
809 ngx_connection_t *c; 820 ngx_connection_t *c;
810 ngx_http_log_ctx_t *ctx; 821 ngx_http_log_ctx_t *ctx;
811 822
812 c = (ngx_connection_t *) r->connection; 823 c = (ngx_connection_t *) r->connection;
813 824 rev = c->read;
814 c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start; 825 wev = c->write;
815 c->read->event_handler = ngx_http_keepalive_handler; 826
816 827 if (rev->blocked && rev->level) {
817 if (r->write_level_event) { 828 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
818 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
819 return NGX_ERROR; 829 return NGX_ERROR;
820 } 830 }
831 rev->blocked = 0;
821 } 832 }
822 833
823 ctx = (ngx_http_log_ctx_t *) c->log->data; 834 ctx = (ngx_http_log_ctx_t *) c->log->data;
824 ctx->action = "closing request"; 835 ctx->action = "closing request";
825
826 ngx_http_close_request(r); 836 ngx_http_close_request(r);
827 837
838 h = c->buffer;
839
840 /* pipelined request */
841 if (h->pos.mem < h->last.mem) {
842
843 /* clients that support pipelined requests (Mozilla 1.x, Opera 6.x)
844 are rare now so this copy should also be rare */
845
846 if (!ngx_http_large_client_header) {
847 len = h->last.mem - h->pos.mem;
848 ngx_memcpy(h->start, h->pos.mem, len);
849 h->pos.mem = h->start;
850 h->last.mem = h->start + len;
851 }
852
853 c->pipeline = 1;
854 ctx->action = "reading client pipelined request line";
855 return ngx_http_init_request(rev);
856 }
857
858 c->pipeline = 0;
859
860 h->pos.mem = h->last.mem = h->start;
861 rev->event_handler = ngx_http_keepalive_handler;
862
863 if (wev->active && wev->level) {
864 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
865 return NGX_ERROR;
866 }
867 }
868
828 ctx->action = "keepalive"; 869 ctx->action = "keepalive";
829 870
830 #if (HAVE_AIO_EVENT) /* aio, iocp */ 871 #if (HAVE_AIO_EVENT) /* aio, iocp */
872
831 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { 873 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
832 return ngx_http_keepalive_handler(c->read); 874 return ngx_http_keepalive_handler(rev);
833 } 875 }
876
834 #endif 877 #endif
835 878
836 return NGX_OK; 879 return NGX_OK;
837 } 880 }
838 881
997 { 1040 {
998 return ngx_event_close_connection(ev); 1041 return ngx_event_close_connection(ev);
999 } 1042 }
1000 1043
1001 1044
1045 static int ngx_http_header_parse_error(ngx_http_request_t *r,
1046 int parse_err, int err)
1047 {
1048 ngx_http_log_ctx_t *ctx;
1049
1050 ctx = r->connection->log->data;
1051 r->connection->log->handler = NULL;
1052
1053 if (ctx->url) {
1054 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1055 header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD],
1056 ctx->client, ctx->url);
1057
1058 } else {
1059 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1060 header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD],
1061 ctx->client);
1062 }
1063
1064 r->connection->log->handler = ngx_http_log_error;
1065
1066 return ngx_http_error(r, err);
1067 }
1068
1069
1002 static size_t ngx_http_log_error(void *data, char *buf, size_t len) 1070 static size_t ngx_http_log_error(void *data, char *buf, size_t len)
1003 { 1071 {
1004 ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data; 1072 ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
1005 1073
1006 if (ctx->url) 1074 if (ctx->url)