Mercurial > hg > nginx
comparison src/http/modules/ngx_http_range_filter_module.c @ 2121:b39c0040b3e4
support several buf's for single-part range
patch by Maxim Dounin
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 29 Jul 2008 13:58:13 +0000 |
parents | 0799703985ef |
children | 7155dbb2317e |
comparison
equal
deleted
inserted
replaced
2120:2f2052fdd882 | 2121:b39c0040b3e4 |
---|---|
62 ngx_http_range_filter_ctx_t *ctx); | 62 ngx_http_range_filter_ctx_t *ctx); |
63 static ngx_int_t ngx_http_range_singlepart_header(ngx_http_request_t *r, | 63 static ngx_int_t ngx_http_range_singlepart_header(ngx_http_request_t *r, |
64 ngx_http_range_filter_ctx_t *ctx); | 64 ngx_http_range_filter_ctx_t *ctx); |
65 static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, | 65 static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, |
66 ngx_http_range_filter_ctx_t *ctx); | 66 ngx_http_range_filter_ctx_t *ctx); |
67 static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); | |
67 static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, | 68 static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, |
68 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); | 69 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); |
69 static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, | 70 static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, |
70 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); | 71 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); |
71 static ngx_int_t ngx_http_range_multipart_body(ngx_http_request_t *r, | 72 static ngx_int_t ngx_http_range_multipart_body(ngx_http_request_t *r, |
72 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); | 73 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); |
73 static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); | |
74 | 74 |
75 static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); | 75 static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); |
76 static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); | 76 static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); |
77 | 77 |
78 | 78 |
549 | 549 |
550 if (ctx == NULL) { | 550 if (ctx == NULL) { |
551 return ngx_http_next_body_filter(r, in); | 551 return ngx_http_next_body_filter(r, in); |
552 } | 552 } |
553 | 553 |
554 if (ctx->ranges.nelts == 1) { | |
555 return ngx_http_range_singlepart_body(r, ctx, in); | |
556 } | |
557 | |
558 /* | |
559 * multipart ranges are supported only if whole body is in a single buffer | |
560 */ | |
561 | |
554 if (ngx_buf_special(in->buf)) { | 562 if (ngx_buf_special(in->buf)) { |
555 return ngx_http_next_body_filter(r, in); | 563 return ngx_http_next_body_filter(r, in); |
556 } | 564 } |
557 | 565 |
558 if (ngx_http_range_test_overlapped(r, ctx, in) != NGX_OK) { | 566 if (ngx_http_range_test_overlapped(r, ctx, in) != NGX_OK) { |
559 return NGX_ERROR; | 567 return NGX_ERROR; |
560 } | |
561 | |
562 if (ctx->ranges.nelts == 1) { | |
563 | |
564 /* | |
565 * the optimized version for the responses | |
566 * that are passed in the single buffer | |
567 */ | |
568 | |
569 return ngx_http_range_singlepart_body(r, ctx, in); | |
570 } | 568 } |
571 | 569 |
572 return ngx_http_range_multipart_body(r, ctx, in); | 570 return ngx_http_range_multipart_body(r, ctx, in); |
573 } | 571 } |
574 | 572 |
622 | 620 |
623 static ngx_int_t | 621 static ngx_int_t |
624 ngx_http_range_singlepart_body(ngx_http_request_t *r, | 622 ngx_http_range_singlepart_body(ngx_http_request_t *r, |
625 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in) | 623 ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in) |
626 { | 624 { |
625 off_t start, last; | |
627 ngx_buf_t *buf; | 626 ngx_buf_t *buf; |
627 ngx_chain_t *out, *cl, **ll; | |
628 ngx_http_range_t *range; | 628 ngx_http_range_t *range; |
629 | 629 |
630 buf = in->buf; | 630 out = NULL; |
631 ll = &out; | |
631 range = ctx->ranges.elts; | 632 range = ctx->ranges.elts; |
632 | 633 |
633 if (buf->in_file) { | 634 for (cl = in; cl; cl = cl->next) { |
634 buf->file_pos = range->start; | 635 |
635 buf->file_last = range->end; | 636 buf = cl->buf; |
636 } | 637 |
637 | 638 start = ctx->offset; |
638 if (ngx_buf_in_memory(buf)) { | 639 last = ctx->offset + ngx_buf_size(buf); |
639 buf->pos = buf->start + (size_t) range->start; | 640 |
640 buf->last = buf->start + (size_t) range->end; | 641 ctx->offset = last; |
641 } | 642 |
642 | 643 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
643 return ngx_http_next_body_filter(r, in); | 644 "http range body buf: %O-%O", start, last); |
645 | |
646 if (ngx_buf_special(buf)) { | |
647 *ll = cl; | |
648 ll = &cl->next; | |
649 continue; | |
650 } | |
651 | |
652 if (range->end <= start || range->start >= last) { | |
653 | |
654 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
655 "http range body skip"); | |
656 | |
657 buf->pos = buf->last; | |
658 continue; | |
659 } | |
660 | |
661 if (range->start > start) { | |
662 | |
663 if (buf->in_file) { | |
664 buf->file_pos += range->start - start; | |
665 } | |
666 | |
667 if (ngx_buf_in_memory(buf)) { | |
668 buf->pos += (size_t) (range->start - start); | |
669 } | |
670 } | |
671 | |
672 if (range->end <= last) { | |
673 | |
674 if (buf->in_file) { | |
675 buf->file_last -= last - range->end; | |
676 } | |
677 | |
678 if (ngx_buf_in_memory(buf)) { | |
679 buf->last -= (size_t) (last - range->end); | |
680 } | |
681 | |
682 buf->last_buf = 1; | |
683 *ll = cl; | |
684 cl->next = NULL; | |
685 | |
686 break; | |
687 } | |
688 | |
689 *ll = cl; | |
690 ll = &cl->next; | |
691 } | |
692 | |
693 if (out == NULL) { | |
694 return NGX_OK; | |
695 } | |
696 | |
697 return ngx_http_next_body_filter(r, out); | |
644 } | 698 } |
645 | 699 |
646 | 700 |
647 static ngx_int_t | 701 static ngx_int_t |
648 ngx_http_range_multipart_body(ngx_http_request_t *r, | 702 ngx_http_range_multipart_body(ngx_http_request_t *r, |