Mercurial > hg > nginx
comparison src/http/modules/ngx_http_range_filter_module.c @ 960:20279ed90b19
fix range in $r->sendfile
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 28 Dec 2006 20:55:25 +0000 |
parents | e17adcf2a633 |
children | 0d5ec8432efc |
comparison
equal
deleted
inserted
replaced
959:e17adcf2a633 | 960:20279ed90b19 |
---|---|
334 r->headers_out.content_length_n) | 334 r->headers_out.content_length_n) |
335 - content_range->value.data; | 335 - content_range->value.data; |
336 | 336 |
337 r->headers_out.content_length_n = range->end - range->start; | 337 r->headers_out.content_length_n = range->end - range->start; |
338 | 338 |
339 if (r->headers_out.content_length) { | |
340 r->headers_out.content_length->hash = 0; | |
341 r->headers_out.content_length = NULL; | |
342 } | |
343 | |
339 return ngx_http_next_header_filter(r); | 344 return ngx_http_next_header_filter(r); |
340 } | 345 } |
341 | 346 |
342 | 347 |
343 /* TODO: what if no content_type ?? */ | 348 /* TODO: what if no content_type ?? */ |
439 len += ctx->boundary_header.len + range[i].content_range.len | 444 len += ctx->boundary_header.len + range[i].content_range.len |
440 + (size_t) (range[i].end - range[i].start); | 445 + (size_t) (range[i].end - range[i].start); |
441 } | 446 } |
442 | 447 |
443 r->headers_out.content_length_n = len; | 448 r->headers_out.content_length_n = len; |
444 r->headers_out.content_length = NULL; | 449 |
450 if (r->headers_out.content_length) { | |
451 r->headers_out.content_length->hash = 0; | |
452 r->headers_out.content_length = NULL; | |
453 } | |
445 | 454 |
446 return ngx_http_next_header_filter(r); | 455 return ngx_http_next_header_filter(r); |
447 } | 456 } |
448 | 457 |
458 | |
459 /* | |
460 * TODO: | |
461 * buffer or buffers is in memory | |
462 * range or ranges are overlapped in buffers | |
463 */ | |
449 | 464 |
450 static ngx_int_t | 465 static ngx_int_t |
451 ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 466 ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
452 { | 467 { |
453 ngx_uint_t i; | 468 ngx_uint_t i; |
454 ngx_buf_t *b; | 469 ngx_buf_t *b, *buf; |
455 ngx_chain_t *out, *hcl, *rcl, *dcl, **ll; | 470 ngx_chain_t *out, *hcl, *rcl, *dcl, **ll; |
456 ngx_http_range_t *range; | 471 ngx_http_range_t *range; |
457 ngx_http_range_filter_ctx_t *ctx; | 472 ngx_http_range_filter_ctx_t *ctx; |
458 | 473 |
459 if (r->headers_out.ranges.nelts == 0) { | 474 if (in == NULL || r->headers_out.ranges.nelts == 0) { |
460 return ngx_http_next_body_filter(r, in); | 475 return ngx_http_next_body_filter(r, in); |
476 } | |
477 | |
478 range = r->headers_out.ranges.elts; | |
479 buf = in->buf; | |
480 | |
481 if (!buf->in_file) { | |
482 goto in_memory; | |
483 } | |
484 | |
485 if (!buf->last_buf) { | |
486 for (i = 0; i < r->headers_out.ranges.nelts; i++) { | |
487 if (buf->file_pos > range[i].start | |
488 || buf->file_last < range[i].end) | |
489 { | |
490 goto overlapped; | |
491 } | |
492 } | |
461 } | 493 } |
462 | 494 |
463 /* | 495 /* |
464 * the optimized version for the static files only | 496 * the optimized version for the static files only |
465 * that are passed in the single file buf | 497 * that are passed in the single file buffer |
466 */ | 498 */ |
467 | 499 |
468 if (in && in->buf->in_file && in->buf->last_buf) { | 500 if (r->headers_out.ranges.nelts == 1) { |
469 range = r->headers_out.ranges.elts; | 501 |
470 | 502 buf->file_pos = range->start; |
471 if (r->headers_out.ranges.nelts == 1) { | 503 buf->file_last = range->end; |
472 in->buf->file_pos = range->start; | 504 |
473 in->buf->file_last = range->end; | 505 return ngx_http_next_body_filter(r, in); |
474 | 506 } |
475 return ngx_http_next_body_filter(r, in); | 507 |
476 } | 508 ctx = ngx_http_get_module_ctx(r, ngx_http_range_body_filter_module); |
477 | 509 ll = &out; |
478 ctx = ngx_http_get_module_ctx(r, ngx_http_range_body_filter_module); | 510 |
479 ll = &out; | 511 for (i = 0; i < r->headers_out.ranges.nelts; i++) { |
480 | 512 |
481 for (i = 0; i < r->headers_out.ranges.nelts; i++) { | 513 /* |
482 | 514 * The boundary header of the range: |
483 /* | 515 * CRLF |
484 * The boundary header of the range: | 516 * "--0123456789" CRLF |
485 * CRLF | 517 * "Content-Type: image/jpeg" CRLF |
486 * "--0123456789" CRLF | 518 * "Content-Range: bytes " |
487 * "Content-Type: image/jpeg" CRLF | 519 */ |
488 * "Content-Range: bytes " | |
489 */ | |
490 | |
491 b = ngx_calloc_buf(r->pool); | |
492 if (b == NULL) { | |
493 return NGX_ERROR; | |
494 } | |
495 | |
496 b->memory = 1; | |
497 b->pos = ctx->boundary_header.data; | |
498 b->last = ctx->boundary_header.data + ctx->boundary_header.len; | |
499 | |
500 hcl = ngx_alloc_chain_link(r->pool); | |
501 if (hcl == NULL) { | |
502 return NGX_ERROR; | |
503 } | |
504 | |
505 hcl->buf = b; | |
506 | |
507 | |
508 /* "SSSS-EEEE/TTTT" CRLF CRLF */ | |
509 | |
510 b = ngx_calloc_buf(r->pool); | |
511 if (b == NULL) { | |
512 return NGX_ERROR; | |
513 } | |
514 | |
515 b->temporary = 1; | |
516 b->pos = range[i].content_range.data; | |
517 b->last = range[i].content_range.data + range[i].content_range.len; | |
518 | |
519 rcl = ngx_alloc_chain_link(r->pool); | |
520 if (rcl == NULL) { | |
521 return NGX_ERROR; | |
522 } | |
523 | |
524 rcl->buf = b; | |
525 | |
526 | |
527 /* the range data */ | |
528 | |
529 b = ngx_calloc_buf(r->pool); | |
530 if (b == NULL) { | |
531 return NGX_ERROR; | |
532 } | |
533 | |
534 b->in_file = 1; | |
535 b->file_pos = range[i].start; | |
536 b->file_last = range[i].end; | |
537 b->file = in->buf->file; | |
538 | |
539 dcl = ngx_alloc_chain_link(r->pool); | |
540 if (dcl == NULL) { | |
541 return NGX_ERROR; | |
542 } | |
543 | |
544 dcl->buf = b; | |
545 | |
546 *ll = hcl; | |
547 hcl->next = rcl; | |
548 rcl->next = dcl; | |
549 ll = &dcl->next; | |
550 } | |
551 | |
552 /* the last boundary CRLF "--0123456789--" CRLF */ | |
553 | 520 |
554 b = ngx_calloc_buf(r->pool); | 521 b = ngx_calloc_buf(r->pool); |
555 if (b == NULL) { | 522 if (b == NULL) { |
556 return NGX_ERROR; | 523 return NGX_ERROR; |
557 } | 524 } |
558 | 525 |
559 b->temporary = 1; | 526 b->memory = 1; |
560 b->last_buf = 1; | 527 b->pos = ctx->boundary_header.data; |
561 | 528 b->last = ctx->boundary_header.data + ctx->boundary_header.len; |
562 b->pos = ngx_palloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN | |
563 + sizeof("--" CRLF) - 1); | |
564 if (b->pos == NULL) { | |
565 return NGX_ERROR; | |
566 } | |
567 | |
568 b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, 4 + 10); | |
569 *b->last++ = '-'; *b->last++ = '-'; | |
570 *b->last++ = CR; *b->last++ = LF; | |
571 | 529 |
572 hcl = ngx_alloc_chain_link(r->pool); | 530 hcl = ngx_alloc_chain_link(r->pool); |
573 if (hcl == NULL) { | 531 if (hcl == NULL) { |
574 return NGX_ERROR; | 532 return NGX_ERROR; |
575 } | 533 } |
576 | 534 |
577 hcl->buf = b; | 535 hcl->buf = b; |
578 hcl->next = NULL; | 536 |
537 | |
538 /* "SSSS-EEEE/TTTT" CRLF CRLF */ | |
539 | |
540 b = ngx_calloc_buf(r->pool); | |
541 if (b == NULL) { | |
542 return NGX_ERROR; | |
543 } | |
544 | |
545 b->temporary = 1; | |
546 b->pos = range[i].content_range.data; | |
547 b->last = range[i].content_range.data + range[i].content_range.len; | |
548 | |
549 rcl = ngx_alloc_chain_link(r->pool); | |
550 if (rcl == NULL) { | |
551 return NGX_ERROR; | |
552 } | |
553 | |
554 rcl->buf = b; | |
555 | |
556 | |
557 /* the range data */ | |
558 | |
559 b = ngx_calloc_buf(r->pool); | |
560 if (b == NULL) { | |
561 return NGX_ERROR; | |
562 } | |
563 | |
564 b->in_file = 1; | |
565 b->file_pos = range[i].start; | |
566 b->file_last = range[i].end; | |
567 b->file = buf->file; | |
568 | |
569 dcl = ngx_alloc_chain_link(r->pool); | |
570 if (dcl == NULL) { | |
571 return NGX_ERROR; | |
572 } | |
573 | |
574 dcl->buf = b; | |
579 | 575 |
580 *ll = hcl; | 576 *ll = hcl; |
581 | 577 hcl->next = rcl; |
582 return ngx_http_next_body_filter(r, out); | 578 rcl->next = dcl; |
583 } | 579 ll = &dcl->next; |
584 | 580 } |
585 /* TODO: alert */ | 581 |
586 | 582 /* the last boundary CRLF "--0123456789--" CRLF */ |
587 return ngx_http_next_body_filter(r, in); | 583 |
584 b = ngx_calloc_buf(r->pool); | |
585 if (b == NULL) { | |
586 return NGX_ERROR; | |
587 } | |
588 | |
589 b->temporary = 1; | |
590 b->last_buf = 1; | |
591 | |
592 b->pos = ngx_palloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN | |
593 + sizeof("--" CRLF) - 1); | |
594 if (b->pos == NULL) { | |
595 return NGX_ERROR; | |
596 } | |
597 | |
598 b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, 4 + 10); | |
599 *b->last++ = '-'; *b->last++ = '-'; | |
600 *b->last++ = CR; *b->last++ = LF; | |
601 | |
602 hcl = ngx_alloc_chain_link(r->pool); | |
603 if (hcl == NULL) { | |
604 return NGX_ERROR; | |
605 } | |
606 | |
607 hcl->buf = b; | |
608 hcl->next = NULL; | |
609 | |
610 *ll = hcl; | |
611 | |
612 return ngx_http_next_body_filter(r, out); | |
613 | |
614 in_memory: | |
615 | |
616 overlapped: | |
617 | |
618 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
619 "range in memory buffer or in overlapped buffers"); | |
620 | |
621 return NGX_ERROR; | |
588 } | 622 } |
589 | 623 |
590 | 624 |
591 static ngx_int_t | 625 static ngx_int_t |
592 ngx_http_range_header_filter_init(ngx_conf_t *cf) | 626 ngx_http_range_header_filter_init(ngx_conf_t *cf) |