Mercurial > hg > nginx-ranges
comparison src/http/modules/ngx_http_range_filter_module.c @ 390:a5f67d82aea3
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).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 21 Jul 2008 05:31:34 +0400 |
parents | 984bb0b1399b |
children | 1d9bef53cd8e |
comparison
equal
deleted
inserted
replaced
389:930e48a26dde | 390:a5f67d82aea3 |
---|---|
487 ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 487 ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
488 { | 488 { |
489 off_t start, last; | 489 off_t start, last; |
490 ngx_buf_t *b, *buf; | 490 ngx_buf_t *b, *buf; |
491 ngx_uint_t i; | 491 ngx_uint_t i; |
492 ngx_chain_t *out, *hcl, *rcl, *dcl, **ll; | 492 ngx_chain_t *out, *cl, *hcl, *rcl, *dcl, **ll; |
493 ngx_http_range_t *range; | 493 ngx_http_range_t *range; |
494 ngx_http_range_filter_ctx_t *ctx; | 494 ngx_http_range_filter_ctx_t *ctx; |
495 | 495 |
496 if (in == NULL) { | 496 if (in == NULL) { |
497 return ngx_http_next_body_filter(r, in); | 497 return ngx_http_next_body_filter(r, in); |
507 | 507 |
508 if (ngx_buf_special(in->buf)) { | 508 if (ngx_buf_special(in->buf)) { |
509 return ngx_http_next_body_filter(r, in); | 509 return ngx_http_next_body_filter(r, in); |
510 } | 510 } |
511 | 511 |
512 if (ctx->offset) { | |
513 goto overlapped; | |
514 } | |
515 | |
516 range = ctx->ranges.elts; | 512 range = ctx->ranges.elts; |
517 | 513 |
518 if (!buf->last_buf) { | 514 if (ctx->ranges.nelts > 1) { |
519 | 515 goto multipart; |
520 if (buf->in_file) { | |
521 start = buf->file_pos + ctx->offset; | |
522 last = buf->file_last + ctx->offset; | |
523 | |
524 } else { | |
525 start = buf->pos - buf->start + ctx->offset; | |
526 last = buf->last - buf->start + ctx->offset; | |
527 } | |
528 | |
529 for (i = 0; i < ctx->ranges.nelts; i++) { | |
530 if (start > range[i].start || last < range[i].end) { | |
531 goto overlapped; | |
532 } | |
533 } | |
534 } | 516 } |
535 | 517 |
536 /* | 518 /* |
537 * the optimized version for the responses | 519 * the optimized version for the responses |
538 * that are passed in the single buffer | 520 * that are passed in the single buffer |
539 */ | 521 */ |
540 | 522 |
523 out = NULL; | |
524 ll = &out; | |
525 | |
526 for (cl = in; cl; cl = cl->next) { | |
527 | |
528 buf = cl->buf; | |
529 | |
530 start = ctx->offset; | |
531 last = ctx->offset + ngx_buf_size(buf); | |
532 | |
533 ctx->offset = last; | |
534 | |
535 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
536 "range body filter: %O-%O", start, last); | |
537 | |
538 if (ngx_buf_special(buf)) { | |
539 /* pass anyway */ | |
540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
541 "range body filter: pass special"); | |
542 *ll = cl; | |
543 ll = &cl->next; | |
544 continue; | |
545 } | |
546 | |
547 if (range->end <= start || range->start >= last) { | |
548 /* skip buffer */ | |
549 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
550 "range body filter: skip"); | |
551 buf->pos = buf->last; | |
552 continue; | |
553 } | |
554 | |
555 if (range->start > start) { | |
556 if (buf->in_file) { | |
557 buf->file_pos += range->start - start; | |
558 } | |
559 if (ngx_buf_in_memory(buf)) { | |
560 buf->pos += (size_t) (range->start - start); | |
561 } | |
562 } | |
563 | |
564 if (range->end <= last) { | |
565 if (buf->in_file) { | |
566 buf->file_last -= last - range->end; | |
567 } | |
568 if (ngx_buf_in_memory(buf)) { | |
569 buf->last -= (size_t) (last - range->end); | |
570 } | |
571 | |
572 /* we are done */ | |
573 | |
574 buf->last_buf = 1; | |
575 *ll = cl; | |
576 cl->next = NULL; | |
577 | |
578 break; | |
579 } | |
580 | |
581 *ll = cl; | |
582 ll = &cl->next; | |
583 } | |
584 | |
585 if (out == NULL) { | |
586 return NGX_OK; | |
587 } | |
588 | |
589 return ngx_http_next_body_filter(r, out); | |
590 | |
591 multipart: | |
592 | |
593 if (ctx->offset) { | |
594 goto overlapped; | |
595 } | |
596 | |
597 if (!buf->last_buf) { | |
598 | |
599 if (buf->in_file) { | |
600 start = buf->file_pos + ctx->offset; | |
601 last = buf->file_last + ctx->offset; | |
602 | |
603 } else { | |
604 start = buf->pos - buf->start + ctx->offset; | |
605 last = buf->last - buf->start + ctx->offset; | |
606 } | |
607 | |
608 for (i = 0; i < ctx->ranges.nelts; i++) { | |
609 if (start > range[i].start || last < range[i].end) { | |
610 goto overlapped; | |
611 } | |
612 } | |
613 } | |
614 | |
541 ctx->offset = ngx_buf_size(buf); | 615 ctx->offset = ngx_buf_size(buf); |
542 | |
543 if (ctx->ranges.nelts == 1) { | |
544 | |
545 if (buf->in_file) { | |
546 buf->file_pos = range->start; | |
547 buf->file_last = range->end; | |
548 } | |
549 | |
550 if (ngx_buf_in_memory(buf)) { | |
551 buf->pos = buf->start + (size_t) range->start; | |
552 buf->last = buf->start + (size_t) range->end; | |
553 } | |
554 | |
555 return ngx_http_next_body_filter(r, in); | |
556 } | |
557 | 616 |
558 ll = &out; | 617 ll = &out; |
559 | 618 |
560 for (i = 0; i < ctx->ranges.nelts; i++) { | 619 for (i = 0; i < ctx->ranges.nelts; i++) { |
561 | 620 |