comparison ngx_http_bytes_filter_module.c @ 4:ab9f96327bb6

Handle multiple ranges.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 03 Jul 2008 13:16:03 +0400
parents 3e8648918913
children be5e612dd602
comparison
equal deleted inserted replaced
3:3e8648918913 4:ab9f96327bb6
7 #include <ngx_core.h> 7 #include <ngx_core.h>
8 #include <ngx_http.h> 8 #include <ngx_http.h>
9 9
10 10
11 typedef struct { 11 typedef struct {
12 ngx_flag_t enable; 12 ngx_flag_t enable;
13 } ngx_http_bytes_conf_t; 13 } ngx_http_bytes_conf_t;
14 14
15 15
16 typedef struct { 16 typedef struct {
17 off_t start; 17 off_t start;
18 off_t end; 18 off_t end;
19 } ngx_http_bytes_t; 19 } ngx_http_bytes_t;
20 20
21 21
22 typedef struct { 22 typedef struct {
23 off_t offset; 23 off_t offset;
24 ngx_array_t ranges; 24 ngx_array_t ranges;
25 ngx_http_bytes_t *range;
25 } ngx_http_bytes_ctx_t; 26 } ngx_http_bytes_ctx_t;
26 27
27 28
28 static void *ngx_http_bytes_create_conf(ngx_conf_t *cf); 29 static void *ngx_http_bytes_create_conf(ngx_conf_t *cf);
29 static char *ngx_http_bytes_merge_conf(ngx_conf_t *cf, void *parent, 30 static char *ngx_http_bytes_merge_conf(ngx_conf_t *cf, void *parent,
280 static ngx_int_t 281 static ngx_int_t
281 ngx_http_bytes_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 282 ngx_http_bytes_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
282 { 283 {
283 off_t size; 284 off_t size;
284 ngx_uint_t i; 285 ngx_uint_t i;
285 ngx_chain_t *cl, **ll; 286 ngx_chain_t **ll, *cl, *dcl;
286 ngx_buf_t *buf; 287 ngx_buf_t *buf, *b;
287 ngx_http_bytes_ctx_t *ctx; 288 ngx_http_bytes_ctx_t *ctx;
288 ngx_http_bytes_t *range; 289 ngx_http_bytes_t *range, *last;
289 290
290 if (in == NULL) { 291 if (in == NULL) {
291 return ngx_http_next_body_filter(r, in); 292 return ngx_http_next_body_filter(r, in);
292 } 293 }
293 294
312 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 313 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
313 "bytes body filter: %O-%O", range->start, range->end); 314 "bytes body filter: %O-%O", range->start, range->end);
314 range++; 315 range++;
315 } 316 }
316 317
317 range = ctx->ranges.elts; 318 range = ctx->range;
319
320 if (range == NULL) {
321 range = ctx->range = ctx->ranges.elts;
322 }
323
324 last = ctx->ranges.elts;
325 last += ctx->ranges.nelts;
318 326
319 #if 0 327 #if 0
320 /* ... temp, rewrite */ 328 /* ... temp, rewrite */
321 329
322 if (ctx->ranges.nelts == 1) { 330 if (ctx->ranges.nelts == 1) {
335 } 343 }
336 #endif 344 #endif
337 345
338 /* ... */ 346 /* ... */
339 347
340 for (ll = &in, cl = in; cl; ll = &cl->next, cl = cl->next) { 348 for (ll = &in, cl = in; cl; ll = &cl->next, cl = cl->next,
349 ctx->offset += size)
350 {
341 351
342 buf = cl->buf; 352 buf = cl->buf;
343 size = ngx_buf_size(buf); 353 size = ngx_buf_size(buf);
344 354
345 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 355 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
350 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 360 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
351 "bytes body filter: special buffer"); 361 "bytes body filter: special buffer");
352 continue; 362 continue;
353 } 363 }
354 364
365 next:
355 if (range->start > ctx->offset + size) { 366 if (range->start > ctx->offset + size) {
356 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 367 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
357 "bytes body filter: fully ignored buffer"); 368 "bytes body filter: fully ignored buffer");
358 *ll = cl->next; 369 *ll = cl->next;
359 buf->pos = buf->last; 370 buf->pos = buf->last;
360 continue; 371 continue;
361 } 372 }
362 373
363 /* XXX multiple ranges */ 374 /* todo: do not create buffers/links if not needed */
364 /* XXX we should create new buffers/links for multiple ranges */ 375
376 b = ngx_calloc_buf(r->pool);
377 if (b == NULL) {
378 return NGX_ERROR;
379 }
380
381 b->in_file = buf->in_file;
382 b->temporary = buf->temporary;
383 b->memory = buf->memory;
384 b->mmap = buf->mmap;
385 b->file = buf->file;
365 386
366 if (buf->in_file) { 387 if (buf->in_file) {
388 b->file_pos = buf->file_pos;
389 b->file_last = buf->file_last;
390 }
391
392 if (ngx_buf_in_memory(buf)) {
393 b->pos = buf->pos;
394 b->last = buf->last;
395 }
396
397 dcl = ngx_alloc_chain_link(r->pool);
398 if (dcl == NULL) {
399 return NGX_ERROR;
400 }
401
402 *ll = dcl;
403 dcl->buf = b;
404 dcl->next = cl->next;
405 ll = &dcl->next;
406
407 if (buf->last_buf && range == last - 1) {
408 b->last_buf = 1;
409 }
410
411 if (b->in_file) {
367 412
368 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 413 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
369 "bytes body filter: in file, %O-%O", 414 "bytes body filter: in file, %O-%O",
370 buf->file_pos, buf->file_last); 415 b->file_pos, b->file_last);
371 416
372 if (range->start > ctx->offset) { 417 if (range->start > ctx->offset) {
373 buf->file_pos += range->start - ctx->offset; 418 b->file_pos += range->start - ctx->offset;
374 } 419 }
375 if (range->end - ctx->offset < size) { 420 if (range->end - ctx->offset < size) {
376 buf->file_last -= size - (range->end - ctx->offset); 421 b->file_last -= size - (range->end - ctx->offset);
377 } 422 }
378 423
379 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 424 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
380 "bytes body filter: in file fixed, %O-%O", 425 "bytes body filter: in file fixed, %O-%O",
381 buf->file_pos, buf->file_last); 426 b->file_pos, b->file_last);
382 } 427 }
383 428
384 if (ngx_buf_in_memory(buf)) { 429 if (ngx_buf_in_memory(b)) {
385 430
386 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 431 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
387 "bytes body filter: in memory, %p-%p", 432 "bytes body filter: in memory, %p-%p",
388 buf->pos, buf->last); 433 b->pos, b->last);
389 434
390 if (range->start > ctx->offset) { 435 if (range->start > ctx->offset) {
391 buf->pos += (size_t) (range->start - ctx->offset); 436 b->pos += (size_t) (range->start - ctx->offset);
392 } 437 }
393 if (range->end - ctx->offset < size) { 438 if (range->end - ctx->offset < size) {
394 buf->last -= (size_t) (size - (range->end - ctx->offset)); 439 b->last -= (size_t) (size - (range->end - ctx->offset));
395 } 440 }
396 441
397 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 442 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
398 "bytes body filter: in memory fixed, %p-%p", 443 "bytes body filter: in memory fixed, %p-%p",
399 buf->pos, buf->last); 444 b->pos, b->last);
400 } 445 }
401 446
402 ctx->offset += size; 447 if (range->end < ctx->offset + size) {
448 range++;
449 if (range < last) {
450 goto next;
451 }
452 }
403 } 453 }
404 454
405 return ngx_http_next_body_filter(r, in); 455 return ngx_http_next_body_filter(r, in);
406 } 456 }
407 457