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)