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)