Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 typedef struct {
0014     ngx_chain_t  *from_upstream;
0015     ngx_chain_t  *from_downstream;
0016 } ngx_stream_write_filter_ctx_t;
0017 
0018 
0019 static ngx_int_t ngx_stream_write_filter(ngx_stream_session_t *s,
0020     ngx_chain_t *in, ngx_uint_t from_upstream);
0021 static ngx_int_t ngx_stream_write_filter_init(ngx_conf_t *cf);
0022 
0023 
0024 static ngx_stream_module_t  ngx_stream_write_filter_module_ctx = {
0025     NULL,                                  /* preconfiguration */
0026     ngx_stream_write_filter_init,          /* postconfiguration */
0027 
0028     NULL,                                  /* create main configuration */
0029     NULL,                                  /* init main configuration */
0030 
0031     NULL,                                  /* create server configuration */
0032     NULL                                   /* merge server configuration */
0033 };
0034 
0035 
0036 ngx_module_t  ngx_stream_write_filter_module = {
0037     NGX_MODULE_V1,
0038     &ngx_stream_write_filter_module_ctx,   /* module context */
0039     NULL,                                  /* module directives */
0040     NGX_STREAM_MODULE,                     /* module type */
0041     NULL,                                  /* init master */
0042     NULL,                                  /* init module */
0043     NULL,                                  /* init process */
0044     NULL,                                  /* init thread */
0045     NULL,                                  /* exit thread */
0046     NULL,                                  /* exit process */
0047     NULL,                                  /* exit master */
0048     NGX_MODULE_V1_PADDING
0049 };
0050 
0051 
0052 static ngx_int_t
0053 ngx_stream_write_filter(ngx_stream_session_t *s, ngx_chain_t *in,
0054     ngx_uint_t from_upstream)
0055 {
0056     off_t                           size;
0057     ngx_uint_t                      last, flush, sync;
0058     ngx_chain_t                    *cl, *ln, **ll, **out, *chain;
0059     ngx_connection_t               *c;
0060     ngx_stream_write_filter_ctx_t  *ctx;
0061 
0062     ctx = ngx_stream_get_module_ctx(s, ngx_stream_write_filter_module);
0063 
0064     if (ctx == NULL) {
0065         ctx = ngx_pcalloc(s->connection->pool,
0066                           sizeof(ngx_stream_write_filter_ctx_t));
0067         if (ctx == NULL) {
0068             return NGX_ERROR;
0069         }
0070 
0071         ngx_stream_set_ctx(s, ctx, ngx_stream_write_filter_module);
0072     }
0073 
0074     if (from_upstream) {
0075         c = s->connection;
0076         out = &ctx->from_upstream;
0077 
0078     } else {
0079         c = s->upstream->peer.connection;
0080         out = &ctx->from_downstream;
0081     }
0082 
0083     if (c->error) {
0084         return NGX_ERROR;
0085     }
0086 
0087     size = 0;
0088     flush = 0;
0089     sync = 0;
0090     last = 0;
0091     ll = out;
0092 
0093     /* find the size, the flush point and the last link of the saved chain */
0094 
0095     for (cl = *out; cl; cl = cl->next) {
0096         ll = &cl->next;
0097 
0098         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
0099                        "write old buf t:%d f:%d %p, pos %p, size: %z "
0100                        "file: %O, size: %O",
0101                        cl->buf->temporary, cl->buf->in_file,
0102                        cl->buf->start, cl->buf->pos,
0103                        cl->buf->last - cl->buf->pos,
0104                        cl->buf->file_pos,
0105                        cl->buf->file_last - cl->buf->file_pos);
0106 
0107         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0108             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0109                           "zero size buf in writer "
0110                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0111                           cl->buf->temporary,
0112                           cl->buf->recycled,
0113                           cl->buf->in_file,
0114                           cl->buf->start,
0115                           cl->buf->pos,
0116                           cl->buf->last,
0117                           cl->buf->file,
0118                           cl->buf->file_pos,
0119                           cl->buf->file_last);
0120 
0121             ngx_debug_point();
0122             return NGX_ERROR;
0123         }
0124 
0125         if (ngx_buf_size(cl->buf) < 0) {
0126             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0127                           "negative size buf in writer "
0128                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0129                           cl->buf->temporary,
0130                           cl->buf->recycled,
0131                           cl->buf->in_file,
0132                           cl->buf->start,
0133                           cl->buf->pos,
0134                           cl->buf->last,
0135                           cl->buf->file,
0136                           cl->buf->file_pos,
0137                           cl->buf->file_last);
0138 
0139             ngx_debug_point();
0140             return NGX_ERROR;
0141         }
0142 
0143         size += ngx_buf_size(cl->buf);
0144 
0145         if (cl->buf->flush || cl->buf->recycled) {
0146             flush = 1;
0147         }
0148 
0149         if (cl->buf->sync) {
0150             sync = 1;
0151         }
0152 
0153         if (cl->buf->last_buf) {
0154             last = 1;
0155         }
0156     }
0157 
0158     /* add the new chain to the existent one */
0159 
0160     for (ln = in; ln; ln = ln->next) {
0161         cl = ngx_alloc_chain_link(c->pool);
0162         if (cl == NULL) {
0163             return NGX_ERROR;
0164         }
0165 
0166         cl->buf = ln->buf;
0167         *ll = cl;
0168         ll = &cl->next;
0169 
0170         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
0171                        "write new buf t:%d f:%d %p, pos %p, size: %z "
0172                        "file: %O, size: %O",
0173                        cl->buf->temporary, cl->buf->in_file,
0174                        cl->buf->start, cl->buf->pos,
0175                        cl->buf->last - cl->buf->pos,
0176                        cl->buf->file_pos,
0177                        cl->buf->file_last - cl->buf->file_pos);
0178 
0179         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0180             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0181                           "zero size buf in writer "
0182                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0183                           cl->buf->temporary,
0184                           cl->buf->recycled,
0185                           cl->buf->in_file,
0186                           cl->buf->start,
0187                           cl->buf->pos,
0188                           cl->buf->last,
0189                           cl->buf->file,
0190                           cl->buf->file_pos,
0191                           cl->buf->file_last);
0192 
0193             ngx_debug_point();
0194             return NGX_ERROR;
0195         }
0196 
0197         if (ngx_buf_size(cl->buf) < 0) {
0198             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0199                           "negative size buf in writer "
0200                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0201                           cl->buf->temporary,
0202                           cl->buf->recycled,
0203                           cl->buf->in_file,
0204                           cl->buf->start,
0205                           cl->buf->pos,
0206                           cl->buf->last,
0207                           cl->buf->file,
0208                           cl->buf->file_pos,
0209                           cl->buf->file_last);
0210 
0211             ngx_debug_point();
0212             return NGX_ERROR;
0213         }
0214 
0215         size += ngx_buf_size(cl->buf);
0216 
0217         if (cl->buf->flush || cl->buf->recycled) {
0218             flush = 1;
0219         }
0220 
0221         if (cl->buf->sync) {
0222             sync = 1;
0223         }
0224 
0225         if (cl->buf->last_buf) {
0226             last = 1;
0227         }
0228     }
0229 
0230     *ll = NULL;
0231 
0232     ngx_log_debug3(NGX_LOG_DEBUG_STREAM, c->log, 0,
0233                    "stream write filter: l:%ui f:%ui s:%O", last, flush, size);
0234 
0235     if (size == 0
0236         && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
0237         && !(last && c->need_last_buf))
0238     {
0239         if (last || flush || sync) {
0240             for (cl = *out; cl; /* void */) {
0241                 ln = cl;
0242                 cl = cl->next;
0243                 ngx_free_chain(c->pool, ln);
0244             }
0245 
0246             *out = NULL;
0247             c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
0248 
0249             return NGX_OK;
0250         }
0251 
0252         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0253                       "the stream output chain is empty");
0254 
0255         ngx_debug_point();
0256 
0257         return NGX_ERROR;
0258     }
0259 
0260     chain = c->send_chain(c, *out, 0);
0261 
0262     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
0263                    "stream write filter %p", chain);
0264 
0265     if (chain == NGX_CHAIN_ERROR) {
0266         c->error = 1;
0267         return NGX_ERROR;
0268     }
0269 
0270     for (cl = *out; cl && cl != chain; /* void */) {
0271         ln = cl;
0272         cl = cl->next;
0273         ngx_free_chain(c->pool, ln);
0274     }
0275 
0276     *out = chain;
0277 
0278     if (chain) {
0279         if (c->shared) {
0280             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0281                           "shared connection is busy");
0282             return NGX_ERROR;
0283         }
0284 
0285         c->buffered |= NGX_STREAM_WRITE_BUFFERED;
0286         return NGX_AGAIN;
0287     }
0288 
0289     c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
0290 
0291     if (c->buffered & NGX_LOWLEVEL_BUFFERED) {
0292         return NGX_AGAIN;
0293     }
0294 
0295     return NGX_OK;
0296 }
0297 
0298 
0299 static ngx_int_t
0300 ngx_stream_write_filter_init(ngx_conf_t *cf)
0301 {
0302     ngx_stream_top_filter = ngx_stream_write_filter;
0303 
0304     return NGX_OK;
0305 }