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