# HG changeset patch # User Maxim Dounin # Date 1216603894 -14400 # Node ID a5f67d82aea3939b52c5cc0cd8350923449cc1ab # Parent 930e48a26dde5a1f5c8771789d6cce5b841be40d Range filter: support for multiple buffers (single range only). This partially allows range support for replies that aren't sent in single buffer. More work still required to support multipart/byteranges replies (when client asks for multiple ranges in one request). diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -489,7 +489,7 @@ ngx_http_range_body_filter(ngx_http_requ off_t start, last; ngx_buf_t *b, *buf; ngx_uint_t i; - ngx_chain_t *out, *hcl, *rcl, *dcl, **ll; + ngx_chain_t *out, *cl, *hcl, *rcl, *dcl, **ll; ngx_http_range_t *range; ngx_http_range_filter_ctx_t *ctx; @@ -509,12 +509,91 @@ ngx_http_range_body_filter(ngx_http_requ return ngx_http_next_body_filter(r, in); } + range = ctx->ranges.elts; + + if (ctx->ranges.nelts > 1) { + goto multipart; + } + + /* + * the optimized version for the responses + * that are passed in the single buffer + */ + + out = NULL; + ll = &out; + + for (cl = in; cl; cl = cl->next) { + + buf = cl->buf; + + start = ctx->offset; + last = ctx->offset + ngx_buf_size(buf); + + ctx->offset = last; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "range body filter: %O-%O", start, last); + + if (ngx_buf_special(buf)) { + /* pass anyway */ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "range body filter: pass special"); + *ll = cl; + ll = &cl->next; + continue; + } + + if (range->end <= start || range->start >= last) { + /* skip buffer */ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "range body filter: skip"); + buf->pos = buf->last; + continue; + } + + if (range->start > start) { + if (buf->in_file) { + buf->file_pos += range->start - start; + } + if (ngx_buf_in_memory(buf)) { + buf->pos += (size_t) (range->start - start); + } + } + + if (range->end <= last) { + if (buf->in_file) { + buf->file_last -= last - range->end; + } + if (ngx_buf_in_memory(buf)) { + buf->last -= (size_t) (last - range->end); + } + + /* we are done */ + + buf->last_buf = 1; + *ll = cl; + cl->next = NULL; + + break; + } + + *ll = cl; + ll = &cl->next; + } + + if (out == NULL) { + return NGX_OK; + } + + return ngx_http_next_body_filter(r, out); + +multipart: + if (ctx->offset) { goto overlapped; } - range = ctx->ranges.elts; - if (!buf->last_buf) { if (buf->in_file) { @@ -533,28 +612,8 @@ ngx_http_range_body_filter(ngx_http_requ } } - /* - * the optimized version for the responses - * that are passed in the single buffer - */ - ctx->offset = ngx_buf_size(buf); - if (ctx->ranges.nelts == 1) { - - if (buf->in_file) { - buf->file_pos = range->start; - buf->file_last = range->end; - } - - if (ngx_buf_in_memory(buf)) { - buf->pos = buf->start + (size_t) range->start; - buf->last = buf->start + (size_t) range->end; - } - - return ngx_http_next_body_filter(r, in); - } - ll = &out; for (i = 0; i < ctx->ranges.nelts; i++) {