changeset 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 d6f0d7a8d752
files ngx_http_bytes_filter_module.c
diffstat 1 files changed, 46 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/ngx_http_bytes_filter_module.c	Mon Aug 04 03:23:06 2008 +0400
+++ b/ngx_http_bytes_filter_module.c	Mon Aug 04 04:06:29 2008 +0400
@@ -296,7 +296,7 @@
 {
     off_t                  size;
     ngx_uint_t             i;
-    ngx_chain_t          **ll, *cl, *dcl;
+    ngx_chain_t          **ll, *cl, *dcl, *out;
     ngx_buf_t             *buf, *b;
     ngx_http_bytes_ctx_t  *ctx;
     ngx_http_bytes_t      *range, *last;
@@ -392,38 +392,56 @@
         return ngx_http_next_body_filter(r, in);
     }
 
-    for (ll = &in, cl = in; cl; cl = cl->next, ctx->offset += size) {
+    out = NULL;
+
+    for (ll = &out, cl = in; cl; cl = cl->next, ctx->offset += size) {
 
         buf = cl->buf;
         size = ngx_buf_size(buf);
 
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "bytes body filter: b %d", size);
+        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "bytes body filter: b %O, offset %O, range %O-%O",
+                       size, ctx->offset, range->start, range->end);
 
         if (ngx_buf_special(buf)) {
-            /* pass out anyway */
             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                            "bytes body filter: special buffer");
-            ll = &cl->next;
+
+            /* pass out anyway */
+
+            dcl = ngx_alloc_chain_link(r->pool);
+            if (dcl == NULL) {
+                return NGX_ERROR;
+            }
+
+            *ll = dcl;
+            dcl->buf = buf;
+            dcl->next = NULL;
+            ll = &dcl->next;
+
+            continue;
+        }
+
+        if (range->start > ctx->offset + size || range->end < ctx->offset) {
+            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "bytes body filter: fully ignored buffer");
+            buf->pos = buf->last;
             continue;
         }
 
 next:
-        if (range->start > ctx->offset + size || range->end < ctx->offset) {
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "bytes body filter: fully ignored buffer");
-            buf->pos = buf->last;
-            *ll = cl->next;
-            continue;
-        }
-
         /* we should either free or reuse original buffer */
 
         if (range == last - 1 || range[1].start > ctx->offset + size) {
+            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "bytes body filter: reusing original buffer");
             b = buf;
             goto fixup;
         }
 
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "bytes body filter: creating new buffer");
+
         b = ngx_calloc_buf(r->pool);
         if (b == NULL) {
             return NGX_ERROR;
@@ -445,6 +463,11 @@
             b->last = buf->last;
         }
 
+        if (buf->last_buf && range == last - 1) {
+            b->last_buf = 1;
+        }
+
+fixup:
         dcl = ngx_alloc_chain_link(r->pool);
         if (dcl == NULL) {
             return NGX_ERROR;
@@ -452,14 +475,9 @@
 
         *ll = dcl;
         dcl->buf = b;
-        dcl->next = cl->next;
+        dcl->next = NULL;
         ll = &dcl->next;
 
-        if (buf->last_buf && range == last - 1) {
-            b->last_buf = 1;
-        }
-
-fixup:
         if (b->in_file) {
 
             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -499,14 +517,19 @@
         if (range->end < ctx->offset + size) {
             range++;
             if (range < last) {
+                ctx->range = range;
+
+                if (range->start > ctx->offset + size) {
+                    continue;
+                }
+
+                /* next range in same buffer */
                 goto next;
             }
         }
-
-        ll = &cl->next;
     }
 
-    return ngx_http_next_body_filter(r, in);
+    return ngx_http_next_body_filter(r, out);
 }