diff src/core/ngx_output_chain.c @ 18:6f8b0dc0f8dd NGINX_0_1_9

nginx 0.1.9 *) Bugfix: the proxied request was sent without arguments if the request contains "//", "/./", "/../" or "%XX". *) Bugfix: the large compressed responses may be transferred not completely. *) Bugfix: the files bigger than 2G was not transferred on Linux that does not support sendfile64(). *) Bugfix: while the build configuration on Linux the --with-poll_module parameter was required; bug appeared in 0.1.8.
author Igor Sysoev <http://sysoev.ru>
date Thu, 25 Nov 2004 00:00:00 +0300
parents 74b1868dd3cd
children 8b6db3bda591
line wrap: on
line diff
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -9,11 +9,18 @@
 #include <ngx_event.h>
 
 
-#define NGX_NONE      1
+#if 0
+#define NGX_SENDFILE_LIMIT  4096
+#endif
+
+
+#define NGX_NONE            1
 
 
 static ngx_inline ngx_int_t
     ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf);
+static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool,
+                                          ngx_chain_t **chain, ngx_chain_t *in);
 static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src,
                                            ngx_uint_t sendfile);
 
@@ -26,17 +33,20 @@ ngx_int_t ngx_output_chain(ngx_output_ch
 
     if (ctx->in == NULL && ctx->busy == NULL) {
 
-       /*
-        * the short path for the case when the ctx->in and ctx->busy chains
-        * are empty, the incoming chain is empty too or has the single buf
-        * that does not require the copy
-        */
+        /*
+         * the short path for the case when the ctx->in and ctx->busy chains
+         * are empty, the incoming chain is empty too or has the single buf
+         * that does not require the copy
+         */
 
         if (in == NULL) {
             return ctx->output_filter(ctx->filter_ctx, in);
         }
 
         if (in->next == NULL
+#if (NGX_SENDFILE_LIMIT)
+            && !(in->buf->in_file && in->buf->file_last > NGX_SENDFILE_LIMIT)
+#endif
             && (!ngx_output_chain_need_to_copy(ctx, in->buf)))
         {
             return ctx->output_filter(ctx->filter_ctx, in);
@@ -46,7 +56,7 @@ ngx_int_t ngx_output_chain(ngx_output_ch
     /* add the incoming buf to the chain ctx->in */
 
     if (in) {
-        if (ngx_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) {
+        if (ngx_output_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) {
             return NGX_ERROR;
         }
     }
@@ -191,11 +201,23 @@ ngx_int_t ngx_output_chain(ngx_output_ch
 static ngx_inline ngx_int_t
     ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
 {
+    ngx_uint_t  sendfile;
+
     if (ngx_buf_special(buf)) {
         return 0;
     }
 
-    if (!ctx->sendfile) {
+    sendfile = ctx->sendfile;
+
+#if (NGX_SENDFILE_LIMIT)
+
+    if (buf->in_file && buf->file_pos >= NGX_SENDFILE_LIMIT) {
+        sendfile = 0;
+    }
+
+#endif
+
+    if (!sendfile) {
 
         if (!ngx_buf_in_memory(buf)) {
             return 1;
@@ -216,6 +238,71 @@ static ngx_inline ngx_int_t
 }
 
 
+static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool,
+                                           ngx_chain_t **chain, ngx_chain_t *in)
+{
+    ngx_chain_t  *cl, **ll;
+#if (NGX_SENDFILE_LIMIT)
+    ngx_buf_t    *b, *buf;
+#endif
+
+    ll = chain;
+
+    for (cl = *chain; cl; cl = cl->next) {
+        ll = &cl->next;
+    }
+
+    while (in) {
+
+        if (!(cl = ngx_alloc_chain_link(pool))) {
+            return NGX_ERROR;
+        }
+
+#if (NGX_SENDFILE_LIMIT)
+
+        buf = in->buf;
+
+        if (buf->in_file
+            && buf->file_pos < NGX_SENDFILE_LIMIT
+            && buf->file_last > NGX_SENDFILE_LIMIT)
+        {
+            if (!(b = ngx_calloc_buf(pool))) {
+                return NGX_ERROR;
+            }
+
+            ngx_memcpy(b, buf, sizeof(ngx_buf_t));
+
+            if (ngx_buf_in_memory(buf)) {
+                buf->pos += (ssize_t) (NGX_SENDFILE_LIMIT - buf->file_pos);
+                b->last = buf->pos;
+            }
+
+            buf->file_pos = NGX_SENDFILE_LIMIT;
+            b->file_last = NGX_SENDFILE_LIMIT;
+
+            cl->buf = b;
+
+        } else {
+            cl->buf = buf;
+            in = in->next;
+        }
+
+#else
+        cl->buf = in->buf;
+        in = in->next;
+
+#endif
+
+        *ll = cl;
+        ll = &cl->next;
+    }
+
+    *ll = NULL;
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src,
                                            ngx_uint_t sendfile)
 {
@@ -228,6 +315,14 @@ static ngx_int_t ngx_output_chain_copy_b
         size = dst->end - dst->pos;
     }
 
+#if (NGX_SENDFILE_LIMIT)
+
+    if (src->in_file && src->file_pos >= NGX_SENDFILE_LIMIT) {
+        sendfile = 0;
+    }
+
+#endif
+
     if (ngx_buf_in_memory(src)) {
         ngx_memcpy(dst->pos, src->pos, size);
         src->pos += size;