Mercurial > hg > ngx_http_bytes_filter_module
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 |