Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.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 1
0108         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0109             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0110                           "zero size buf in writer "
0111                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0112                           cl->buf->temporary,
0113                           cl->buf->recycled,
0114                           cl->buf->in_file,
0115                           cl->buf->start,
0116                           cl->buf->pos,
0117                           cl->buf->last,
0118                           cl->buf->file,
0119                           cl->buf->file_pos,
0120                           cl->buf->file_last);
0121 
0122             ngx_debug_point();
0123             return NGX_ERROR;
0124         }
0125 #endif
0126 
0127         size += ngx_buf_size(cl->buf);
0128 
0129         if (cl->buf->flush || cl->buf->recycled) {
0130             flush = 1;
0131         }
0132 
0133         if (cl->buf->sync) {
0134             sync = 1;
0135         }
0136 
0137         if (cl->buf->last_buf) {
0138             last = 1;
0139         }
0140     }
0141 
0142     /* add the new chain to the existent one */
0143 
0144     for (ln = in; ln; ln = ln->next) {
0145         cl = ngx_alloc_chain_link(c->pool);
0146         if (cl == NULL) {
0147             return NGX_ERROR;
0148         }
0149 
0150         cl->buf = ln->buf;
0151         *ll = cl;
0152         ll = &cl->next;
0153 
0154         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
0155                        "write new buf t:%d f:%d %p, pos %p, size: %z "
0156                        "file: %O, size: %O",
0157                        cl->buf->temporary, cl->buf->in_file,
0158                        cl->buf->start, cl->buf->pos,
0159                        cl->buf->last - cl->buf->pos,
0160                        cl->buf->file_pos,
0161                        cl->buf->file_last - cl->buf->file_pos);
0162 
0163 #if 1
0164         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0165             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0166                           "zero size buf in writer "
0167                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0168                           cl->buf->temporary,
0169                           cl->buf->recycled,
0170                           cl->buf->in_file,
0171                           cl->buf->start,
0172                           cl->buf->pos,
0173                           cl->buf->last,
0174                           cl->buf->file,
0175                           cl->buf->file_pos,
0176                           cl->buf->file_last);
0177 
0178             ngx_debug_point();
0179             return NGX_ERROR;
0180         }
0181 #endif
0182 
0183         size += ngx_buf_size(cl->buf);
0184 
0185         if (cl->buf->flush || cl->buf->recycled) {
0186             flush = 1;
0187         }
0188 
0189         if (cl->buf->sync) {
0190             sync = 1;
0191         }
0192 
0193         if (cl->buf->last_buf) {
0194             last = 1;
0195         }
0196     }
0197 
0198     *ll = NULL;
0199 
0200     ngx_log_debug3(NGX_LOG_DEBUG_STREAM, c->log, 0,
0201                    "stream write filter: l:%ui f:%ui s:%O", last, flush, size);
0202 
0203     if (size == 0
0204         && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
0205         && !(last && c->need_last_buf))
0206     {
0207         if (last || flush || sync) {
0208             for (cl = *out; cl; /* void */) {
0209                 ln = cl;
0210                 cl = cl->next;
0211                 ngx_free_chain(c->pool, ln);
0212             }
0213 
0214             *out = NULL;
0215             c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
0216 
0217             return NGX_OK;
0218         }
0219 
0220         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0221                       "the stream output chain is empty");
0222 
0223         ngx_debug_point();
0224 
0225         return NGX_ERROR;
0226     }
0227 
0228     chain = c->send_chain(c, *out, 0);
0229 
0230     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
0231                    "stream write filter %p", chain);
0232 
0233     if (chain == NGX_CHAIN_ERROR) {
0234         c->error = 1;
0235         return NGX_ERROR;
0236     }
0237 
0238     for (cl = *out; cl && cl != chain; /* void */) {
0239         ln = cl;
0240         cl = cl->next;
0241         ngx_free_chain(c->pool, ln);
0242     }
0243 
0244     *out = chain;
0245 
0246     if (chain) {
0247         if (c->shared) {
0248             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0249                           "shared connection is busy");
0250             return NGX_ERROR;
0251         }
0252 
0253         c->buffered |= NGX_STREAM_WRITE_BUFFERED;
0254         return NGX_AGAIN;
0255     }
0256 
0257     c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
0258 
0259     if (c->buffered & NGX_LOWLEVEL_BUFFERED) {
0260         return NGX_AGAIN;
0261     }
0262 
0263     return NGX_OK;
0264 }
0265 
0266 
0267 static ngx_int_t
0268 ngx_stream_write_filter_init(ngx_conf_t *cf)
0269 {
0270     ngx_stream_top_filter = ngx_stream_write_filter;
0271 
0272     return NGX_OK;
0273 }