Mercurial > hg > ngx_http_bytes_filter_module
comparison ngx_http_bytes_filter_module.c @ 14:2a8b38acb895
Don't modify chain links passed to us, it's unsafe.
Allocate new chain links instead. And finally save current range into module
context.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 04 Aug 2008 04:06:29 +0400 |
parents | b85e679606f4 |
children | 314242bda1c1 |
comparison
equal
deleted
inserted
replaced
13:b85e679606f4 | 14:2a8b38acb895 |
---|---|
294 static ngx_int_t | 294 static ngx_int_t |
295 ngx_http_bytes_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 295 ngx_http_bytes_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
296 { | 296 { |
297 off_t size; | 297 off_t size; |
298 ngx_uint_t i; | 298 ngx_uint_t i; |
299 ngx_chain_t **ll, *cl, *dcl; | 299 ngx_chain_t **ll, *cl, *dcl, *out; |
300 ngx_buf_t *buf, *b; | 300 ngx_buf_t *buf, *b; |
301 ngx_http_bytes_ctx_t *ctx; | 301 ngx_http_bytes_ctx_t *ctx; |
302 ngx_http_bytes_t *range, *last; | 302 ngx_http_bytes_t *range, *last; |
303 | 303 |
304 if (in == NULL) { | 304 if (in == NULL) { |
390 } | 390 } |
391 | 391 |
392 return ngx_http_next_body_filter(r, in); | 392 return ngx_http_next_body_filter(r, in); |
393 } | 393 } |
394 | 394 |
395 for (ll = &in, cl = in; cl; cl = cl->next, ctx->offset += size) { | 395 out = NULL; |
396 | |
397 for (ll = &out, cl = in; cl; cl = cl->next, ctx->offset += size) { | |
396 | 398 |
397 buf = cl->buf; | 399 buf = cl->buf; |
398 size = ngx_buf_size(buf); | 400 size = ngx_buf_size(buf); |
399 | 401 |
400 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 402 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
401 "bytes body filter: b %d", size); | 403 "bytes body filter: b %O, offset %O, range %O-%O", |
404 size, ctx->offset, range->start, range->end); | |
402 | 405 |
403 if (ngx_buf_special(buf)) { | 406 if (ngx_buf_special(buf)) { |
404 /* pass out anyway */ | |
405 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 407 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
406 "bytes body filter: special buffer"); | 408 "bytes body filter: special buffer"); |
407 ll = &cl->next; | 409 |
410 /* pass out anyway */ | |
411 | |
412 dcl = ngx_alloc_chain_link(r->pool); | |
413 if (dcl == NULL) { | |
414 return NGX_ERROR; | |
415 } | |
416 | |
417 *ll = dcl; | |
418 dcl->buf = buf; | |
419 dcl->next = NULL; | |
420 ll = &dcl->next; | |
421 | |
408 continue; | 422 continue; |
409 } | 423 } |
410 | 424 |
411 next: | |
412 if (range->start > ctx->offset + size || range->end < ctx->offset) { | 425 if (range->start > ctx->offset + size || range->end < ctx->offset) { |
413 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 426 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
414 "bytes body filter: fully ignored buffer"); | 427 "bytes body filter: fully ignored buffer"); |
415 buf->pos = buf->last; | 428 buf->pos = buf->last; |
416 *ll = cl->next; | |
417 continue; | 429 continue; |
418 } | 430 } |
419 | 431 |
432 next: | |
420 /* we should either free or reuse original buffer */ | 433 /* we should either free or reuse original buffer */ |
421 | 434 |
422 if (range == last - 1 || range[1].start > ctx->offset + size) { | 435 if (range == last - 1 || range[1].start > ctx->offset + size) { |
436 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
437 "bytes body filter: reusing original buffer"); | |
423 b = buf; | 438 b = buf; |
424 goto fixup; | 439 goto fixup; |
425 } | 440 } |
441 | |
442 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
443 "bytes body filter: creating new buffer"); | |
426 | 444 |
427 b = ngx_calloc_buf(r->pool); | 445 b = ngx_calloc_buf(r->pool); |
428 if (b == NULL) { | 446 if (b == NULL) { |
429 return NGX_ERROR; | 447 return NGX_ERROR; |
430 } | 448 } |
443 if (ngx_buf_in_memory(buf)) { | 461 if (ngx_buf_in_memory(buf)) { |
444 b->pos = buf->pos; | 462 b->pos = buf->pos; |
445 b->last = buf->last; | 463 b->last = buf->last; |
446 } | 464 } |
447 | 465 |
466 if (buf->last_buf && range == last - 1) { | |
467 b->last_buf = 1; | |
468 } | |
469 | |
470 fixup: | |
448 dcl = ngx_alloc_chain_link(r->pool); | 471 dcl = ngx_alloc_chain_link(r->pool); |
449 if (dcl == NULL) { | 472 if (dcl == NULL) { |
450 return NGX_ERROR; | 473 return NGX_ERROR; |
451 } | 474 } |
452 | 475 |
453 *ll = dcl; | 476 *ll = dcl; |
454 dcl->buf = b; | 477 dcl->buf = b; |
455 dcl->next = cl->next; | 478 dcl->next = NULL; |
456 ll = &dcl->next; | 479 ll = &dcl->next; |
457 | 480 |
458 if (buf->last_buf && range == last - 1) { | |
459 b->last_buf = 1; | |
460 } | |
461 | |
462 fixup: | |
463 if (b->in_file) { | 481 if (b->in_file) { |
464 | 482 |
465 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 483 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
466 "bytes body filter: in file, %O-%O", | 484 "bytes body filter: in file, %O-%O", |
467 b->file_pos, b->file_last); | 485 b->file_pos, b->file_last); |
497 } | 515 } |
498 | 516 |
499 if (range->end < ctx->offset + size) { | 517 if (range->end < ctx->offset + size) { |
500 range++; | 518 range++; |
501 if (range < last) { | 519 if (range < last) { |
520 ctx->range = range; | |
521 | |
522 if (range->start > ctx->offset + size) { | |
523 continue; | |
524 } | |
525 | |
526 /* next range in same buffer */ | |
502 goto next; | 527 goto next; |
503 } | 528 } |
504 } | 529 } |
505 | 530 } |
506 ll = &cl->next; | 531 |
507 } | 532 return ngx_http_next_body_filter(r, out); |
508 | |
509 return ngx_http_next_body_filter(r, in); | |
510 } | 533 } |
511 | 534 |
512 | 535 |
513 static void * | 536 static void * |
514 ngx_http_bytes_create_conf(ngx_conf_t *cf) | 537 ngx_http_bytes_create_conf(ngx_conf_t *cf) |