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_http.h>
0011 
0012 
0013 static ngx_int_t ngx_http_write_filter_init(ngx_conf_t *cf);
0014 
0015 
0016 static ngx_http_module_t  ngx_http_write_filter_module_ctx = {
0017     NULL,                                  /* preconfiguration */
0018     ngx_http_write_filter_init,            /* postconfiguration */
0019 
0020     NULL,                                  /* create main configuration */
0021     NULL,                                  /* init main configuration */
0022 
0023     NULL,                                  /* create server configuration */
0024     NULL,                                  /* merge server configuration */
0025 
0026     NULL,                                  /* create location configuration */
0027     NULL,                                  /* merge location configuration */
0028 };
0029 
0030 
0031 ngx_module_t  ngx_http_write_filter_module = {
0032     NGX_MODULE_V1,
0033     &ngx_http_write_filter_module_ctx,     /* module context */
0034     NULL,                                  /* module directives */
0035     NGX_HTTP_MODULE,                       /* module type */
0036     NULL,                                  /* init master */
0037     NULL,                                  /* init module */
0038     NULL,                                  /* init process */
0039     NULL,                                  /* init thread */
0040     NULL,                                  /* exit thread */
0041     NULL,                                  /* exit process */
0042     NULL,                                  /* exit master */
0043     NGX_MODULE_V1_PADDING
0044 };
0045 
0046 
0047 ngx_int_t
0048 ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
0049 {
0050     off_t                      size, sent, nsent, limit;
0051     ngx_uint_t                 last, flush, sync;
0052     ngx_msec_t                 delay;
0053     ngx_chain_t               *cl, *ln, **ll, *chain;
0054     ngx_connection_t          *c;
0055     ngx_http_core_loc_conf_t  *clcf;
0056 
0057     c = r->connection;
0058 
0059     if (c->error) {
0060         return NGX_ERROR;
0061     }
0062 
0063     size = 0;
0064     flush = 0;
0065     sync = 0;
0066     last = 0;
0067     ll = &r->out;
0068 
0069     /* find the size, the flush point and the last link of the saved chain */
0070 
0071     for (cl = r->out; cl; cl = cl->next) {
0072         ll = &cl->next;
0073 
0074         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
0075                        "write old buf t:%d f:%d %p, pos %p, size: %z "
0076                        "file: %O, size: %O",
0077                        cl->buf->temporary, cl->buf->in_file,
0078                        cl->buf->start, cl->buf->pos,
0079                        cl->buf->last - cl->buf->pos,
0080                        cl->buf->file_pos,
0081                        cl->buf->file_last - cl->buf->file_pos);
0082 
0083 #if 1
0084         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0085             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0086                           "zero size buf in writer "
0087                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0088                           cl->buf->temporary,
0089                           cl->buf->recycled,
0090                           cl->buf->in_file,
0091                           cl->buf->start,
0092                           cl->buf->pos,
0093                           cl->buf->last,
0094                           cl->buf->file,
0095                           cl->buf->file_pos,
0096                           cl->buf->file_last);
0097 
0098             ngx_debug_point();
0099             return NGX_ERROR;
0100         }
0101 #endif
0102 
0103         size += ngx_buf_size(cl->buf);
0104 
0105         if (cl->buf->flush || cl->buf->recycled) {
0106             flush = 1;
0107         }
0108 
0109         if (cl->buf->sync) {
0110             sync = 1;
0111         }
0112 
0113         if (cl->buf->last_buf) {
0114             last = 1;
0115         }
0116     }
0117 
0118     /* add the new chain to the existent one */
0119 
0120     for (ln = in; ln; ln = ln->next) {
0121         cl = ngx_alloc_chain_link(r->pool);
0122         if (cl == NULL) {
0123             return NGX_ERROR;
0124         }
0125 
0126         cl->buf = ln->buf;
0127         *ll = cl;
0128         ll = &cl->next;
0129 
0130         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
0131                        "write new buf t:%d f:%d %p, pos %p, size: %z "
0132                        "file: %O, size: %O",
0133                        cl->buf->temporary, cl->buf->in_file,
0134                        cl->buf->start, cl->buf->pos,
0135                        cl->buf->last - cl->buf->pos,
0136                        cl->buf->file_pos,
0137                        cl->buf->file_last - cl->buf->file_pos);
0138 
0139 #if 1
0140         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
0141             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0142                           "zero size buf in writer "
0143                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
0144                           cl->buf->temporary,
0145                           cl->buf->recycled,
0146                           cl->buf->in_file,
0147                           cl->buf->start,
0148                           cl->buf->pos,
0149                           cl->buf->last,
0150                           cl->buf->file,
0151                           cl->buf->file_pos,
0152                           cl->buf->file_last);
0153 
0154             ngx_debug_point();
0155             return NGX_ERROR;
0156         }
0157 #endif
0158 
0159         size += ngx_buf_size(cl->buf);
0160 
0161         if (cl->buf->flush || cl->buf->recycled) {
0162             flush = 1;
0163         }
0164 
0165         if (cl->buf->sync) {
0166             sync = 1;
0167         }
0168 
0169         if (cl->buf->last_buf) {
0170             last = 1;
0171         }
0172     }
0173 
0174     *ll = NULL;
0175 
0176     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
0177                    "http write filter: l:%ui f:%ui s:%O", last, flush, size);
0178 
0179     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0180 
0181     /*
0182      * avoid the output if there are no last buf, no flush point,
0183      * there are the incoming bufs and the size of all bufs
0184      * is smaller than "postpone_output" directive
0185      */
0186 
0187     if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
0188         return NGX_OK;
0189     }
0190 
0191     if (c->write->delayed) {
0192         c->buffered |= NGX_HTTP_WRITE_BUFFERED;
0193         return NGX_AGAIN;
0194     }
0195 
0196     if (size == 0
0197         && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
0198         && !(last && c->need_last_buf))
0199     {
0200         if (last || flush || sync) {
0201             for (cl = r->out; cl; /* void */) {
0202                 ln = cl;
0203                 cl = cl->next;
0204                 ngx_free_chain(r->pool, ln);
0205             }
0206 
0207             r->out = NULL;
0208             c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
0209 
0210             return NGX_OK;
0211         }
0212 
0213         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0214                       "the http output chain is empty");
0215 
0216         ngx_debug_point();
0217 
0218         return NGX_ERROR;
0219     }
0220 
0221     if (r->limit_rate) {
0222         if (r->limit_rate_after == 0) {
0223             r->limit_rate_after = clcf->limit_rate_after;
0224         }
0225 
0226         limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
0227                 - (c->sent - r->limit_rate_after);
0228 
0229         if (limit <= 0) {
0230             c->write->delayed = 1;
0231             delay = (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1);
0232             ngx_add_timer(c->write, delay);
0233 
0234             c->buffered |= NGX_HTTP_WRITE_BUFFERED;
0235 
0236             return NGX_AGAIN;
0237         }
0238 
0239         if (clcf->sendfile_max_chunk
0240             && (off_t) clcf->sendfile_max_chunk < limit)
0241         {
0242             limit = clcf->sendfile_max_chunk;
0243         }
0244 
0245     } else {
0246         limit = clcf->sendfile_max_chunk;
0247     }
0248 
0249     sent = c->sent;
0250 
0251     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0252                    "http write filter limit %O", limit);
0253 
0254     chain = c->send_chain(c, r->out, limit);
0255 
0256     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0257                    "http write filter %p", chain);
0258 
0259     if (chain == NGX_CHAIN_ERROR) {
0260         c->error = 1;
0261         return NGX_ERROR;
0262     }
0263 
0264     if (r->limit_rate) {
0265 
0266         nsent = c->sent;
0267 
0268         if (r->limit_rate_after) {
0269 
0270             sent -= r->limit_rate_after;
0271             if (sent < 0) {
0272                 sent = 0;
0273             }
0274 
0275             nsent -= r->limit_rate_after;
0276             if (nsent < 0) {
0277                 nsent = 0;
0278             }
0279         }
0280 
0281         delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
0282 
0283         if (delay > 0) {
0284             limit = 0;
0285             c->write->delayed = 1;
0286             ngx_add_timer(c->write, delay);
0287         }
0288     }
0289 
0290     if (limit
0291         && c->write->ready
0292         && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
0293     {
0294         c->write->delayed = 1;
0295         ngx_add_timer(c->write, 1);
0296     }
0297 
0298     for (cl = r->out; cl && cl != chain; /* void */) {
0299         ln = cl;
0300         cl = cl->next;
0301         ngx_free_chain(r->pool, ln);
0302     }
0303 
0304     r->out = chain;
0305 
0306     if (chain) {
0307         c->buffered |= NGX_HTTP_WRITE_BUFFERED;
0308         return NGX_AGAIN;
0309     }
0310 
0311     c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
0312 
0313     if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) {
0314         return NGX_AGAIN;
0315     }
0316 
0317     return NGX_OK;
0318 }
0319 
0320 
0321 static ngx_int_t
0322 ngx_http_write_filter_init(ngx_conf_t *cf)
0323 {
0324     ngx_http_top_body_filter = ngx_http_write_filter;
0325 
0326     return NGX_OK;
0327 }