[nginx] SPDY: body filter was replaced by c->send_chain() function.

Valentin Bartenev vbart at nginx.com
Tue Jan 14 12:58:06 UTC 2014


details:   http://hg.nginx.org/nginx/rev/311803b21504
branches:  
changeset: 5513:311803b21504
user:      Valentin Bartenev <vbart at nginx.com>
date:      Tue Jan 14 16:24:45 2014 +0400
description:
SPDY: body filter was replaced by c->send_chain() function.

It allows to use ngx_http_write_filter() and all its rate limiting logic.

diffstat:

 src/core/ngx_connection.h               |   3 +
 src/http/ngx_http_spdy_filter_module.c  |  90 ++++++++++++--------------------
 src/http/ngx_http_write_filter_module.c |   5 +-
 3 files changed, 42 insertions(+), 56 deletions(-)

diffs (232 lines):

diff -r 9fffc0c46e5c -r 311803b21504 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h	Tue Jan 14 16:24:45 2014 +0400
+++ b/src/core/ngx_connection.h	Tue Jan 14 16:24:45 2014 +0400
@@ -112,6 +112,7 @@ typedef enum {
 
 #define NGX_LOWLEVEL_BUFFERED  0x0f
 #define NGX_SSL_BUFFERED       0x01
+#define NGX_SPDY_BUFFERED      0x02
 
 
 struct ngx_connection_s {
@@ -171,6 +172,8 @@ struct ngx_connection_s {
     unsigned            tcp_nodelay:2;   /* ngx_connection_tcp_nodelay_e */
     unsigned            tcp_nopush:2;    /* ngx_connection_tcp_nopush_e */
 
+    unsigned            need_last_buf:1;
+
 #if (NGX_HAVE_IOCP)
     unsigned            accept_context_updated:1;
 #endif
diff -r 9fffc0c46e5c -r 311803b21504 src/http/ngx_http_spdy_filter_module.c
--- a/src/http/ngx_http_spdy_filter_module.c	Tue Jan 14 16:24:45 2014 +0400
+++ b/src/http/ngx_http_spdy_filter_module.c	Tue Jan 14 16:24:45 2014 +0400
@@ -14,8 +14,6 @@
 #include <zlib.h>
 
 
-#define NGX_SPDY_WRITE_BUFFERED  NGX_HTTP_WRITE_BUFFERED
-
 #define ngx_http_spdy_nv_nsize(h)  (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
 #define ngx_http_spdy_nv_vsize(h)  (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
 
@@ -29,6 +27,10 @@
 #define ngx_http_spdy_nv_write_val(p, h)                                      \
     ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
 
+
+static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc,
+    ngx_chain_t *in, off_t limit);
+
 static ngx_inline ngx_int_t ngx_http_spdy_filter_send(
     ngx_connection_t *fc, ngx_http_spdy_stream_t *stream);
 
@@ -82,7 +84,6 @@ ngx_module_t  ngx_http_spdy_filter_modul
 
 
 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static ngx_int_t
@@ -607,41 +608,35 @@ ngx_http_spdy_header_filter(ngx_http_req
 
     stream->queued = 1;
 
+    c->send_chain = ngx_http_spdy_send_chain;
+    c->need_last_buf = 1;
+
     return ngx_http_spdy_filter_send(c, stream);
 }
 
 
-static ngx_int_t
-ngx_http_spdy_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+static ngx_chain_t *
+ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
 {
     off_t                       size;
     ngx_buf_t                  *b;
     ngx_chain_t                *cl, *out, **ln;
-    ngx_connection_t           *fc;
+    ngx_http_request_t         *r;
     ngx_http_spdy_stream_t     *stream;
     ngx_http_spdy_out_frame_t  *frame;
 
+    r = fc->data;
     stream = r->spdy_stream;
 
-    if (stream == NULL) {
-        return ngx_http_next_body_filter(r, in);
-    }
-
-    fc = r->connection;
-
-    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0,
-                   "spdy body filter \"%V?%V\"", &r->uri, &r->args);
-
-    if (in == NULL || r->header_only) {
+    if (in == NULL) {
 
         if (stream->queued) {
             fc->write->delayed = 1;
-            return NGX_AGAIN;
+        } else {
+            fc->buffered &= ~NGX_SPDY_BUFFERED;
         }
 
-        fc->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
-
-        return NGX_OK;
+        return NULL;
     }
 
     size = 0;
@@ -649,28 +644,10 @@ ngx_http_spdy_body_filter(ngx_http_reque
 
     do {
         b = in->buf;
-#if 1
-        if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
-            ngx_log_error(NGX_LOG_ALERT, fc->log, 0,
-                          "zero size buf in spdy body filter "
-                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
-                          b->temporary,
-                          b->recycled,
-                          b->in_file,
-                          b->start,
-                          b->pos,
-                          b->last,
-                          b->file,
-                          b->file_pos,
-                          b->file_last);
 
-            ngx_debug_point();
-            return NGX_ERROR;
-        }
-#endif
         cl = ngx_alloc_chain_link(r->pool);
         if (cl == NULL) {
-            return NGX_ERROR;
+            return NGX_CHAIN_ERROR;
         }
 
         size += ngx_buf_size(b);
@@ -686,20 +663,24 @@ ngx_http_spdy_body_filter(ngx_http_reque
     if (size > NGX_SPDY_MAX_FRAME_SIZE) {
         ngx_log_error(NGX_LOG_ALERT, fc->log, 0,
                       "FIXME: chain too big in spdy filter: %O", size);
-        return NGX_ERROR;
+        return NGX_CHAIN_ERROR;
     }
 
     frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
                                                 out, cl);
     if (frame == NULL) {
-        return NGX_ERROR;
+        return NGX_CHAIN_ERROR;
     }
 
     ngx_http_spdy_queue_frame(stream->connection, frame);
 
     stream->queued++;
 
-    return ngx_http_spdy_filter_send(fc, stream);
+    if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) {
+        return NGX_CHAIN_ERROR;
+    }
+
+    return NULL;
 }
 
 
@@ -801,12 +782,12 @@ ngx_http_spdy_filter_send(ngx_connection
     stream->blocked = 0;
 
     if (stream->queued) {
-        fc->buffered |= NGX_SPDY_WRITE_BUFFERED;
+        fc->buffered |= NGX_SPDY_BUFFERED;
         fc->write->delayed = 1;
         return NGX_AGAIN;
     }
 
-    fc->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
+    fc->buffered &= ~NGX_SPDY_BUFFERED;
 
     return NGX_OK;
 }
@@ -939,20 +920,22 @@ static ngx_inline void
 ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
     ngx_http_spdy_stream_t *stream)
 {
-    ngx_connection_t  *fc;
-
-    fc = stream->request->connection;
-
-    fc->write->delayed = 0;
+    ngx_event_t  *wev;
 
     if (stream->handled || stream->blocked) {
         return;
     }
 
-    stream->handled = 1;
+    wev = stream->request->connection->write;
 
-    stream->next = sc->last_stream;
-    sc->last_stream = stream;
+    if (!wev->timer_set) {
+        wev->delayed = 0;
+
+        stream->handled = 1;
+
+        stream->next = sc->last_stream;
+        sc->last_stream = stream;
+    }
 }
 
 
@@ -994,8 +977,5 @@ ngx_http_spdy_filter_init(ngx_conf_t *cf
     ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_spdy_header_filter;
 
-    ngx_http_next_body_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_spdy_body_filter;
-
     return NGX_OK;
 }
diff -r 9fffc0c46e5c -r 311803b21504 src/http/ngx_http_write_filter_module.c
--- a/src/http/ngx_http_write_filter_module.c	Tue Jan 14 16:24:45 2014 +0400
+++ b/src/http/ngx_http_write_filter_module.c	Tue Jan 14 16:24:45 2014 +0400
@@ -184,7 +184,10 @@ ngx_http_write_filter(ngx_http_request_t
         return NGX_AGAIN;
     }
 
-    if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)) {
+    if (size == 0
+        && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
+        && !(last && c->need_last_buf))
+    {
         if (last || flush) {
             for (cl = r->out; cl; /* void */) {
                 ln = cl;



More information about the nginx-devel mailing list