Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / http / ngx_http_write_filter_module.c
blob5594c7faaade91464ad9f64691a305e85e22e1b8
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
13 static ngx_int_t ngx_http_write_filter_init(ngx_conf_t *cf);
16 static ngx_http_module_t ngx_http_write_filter_module_ctx = {
17 NULL, /* preconfiguration */
18 ngx_http_write_filter_init, /* postconfiguration */
20 NULL, /* create main configuration */
21 NULL, /* init main configuration */
23 NULL, /* create server configuration */
24 NULL, /* merge server configuration */
26 NULL, /* create location configuration */
27 NULL, /* merge location configuration */
31 ngx_module_t ngx_http_write_filter_module = {
32 NGX_MODULE_V1,
33 &ngx_http_write_filter_module_ctx, /* module context */
34 NULL, /* module directives */
35 NGX_HTTP_MODULE, /* module type */
36 NULL, /* init master */
37 NULL, /* init module */
38 NULL, /* init process */
39 NULL, /* init thread */
40 NULL, /* exit thread */
41 NULL, /* exit process */
42 NULL, /* exit master */
43 NGX_MODULE_V1_PADDING
47 ngx_int_t
48 ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
50 off_t size, sent, nsent, limit;
51 ngx_uint_t last, flush;
52 ngx_msec_t delay;
53 ngx_chain_t *cl, *ln, **ll, *chain;
54 ngx_connection_t *c;
55 ngx_http_core_loc_conf_t *clcf;
57 c = r->connection;
59 if (c->error) {
60 return NGX_ERROR;
63 size = 0;
64 flush = 0;
65 last = 0;
66 ll = &r->out;
68 /* find the size, the flush point and the last link of the saved chain */
70 for (cl = r->out; cl; cl = cl->next) {
71 ll = &cl->next;
73 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
74 "write old buf t:%d f:%d %p, pos %p, size: %z "
75 "file: %O, size: %z",
76 cl->buf->temporary, cl->buf->in_file,
77 cl->buf->start, cl->buf->pos,
78 cl->buf->last - cl->buf->pos,
79 cl->buf->file_pos,
80 cl->buf->file_last - cl->buf->file_pos);
82 #if 1
83 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
84 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
85 "zero size buf in writer "
86 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
87 cl->buf->temporary,
88 cl->buf->recycled,
89 cl->buf->in_file,
90 cl->buf->start,
91 cl->buf->pos,
92 cl->buf->last,
93 cl->buf->file,
94 cl->buf->file_pos,
95 cl->buf->file_last);
97 ngx_debug_point();
98 return NGX_ERROR;
100 #endif
102 size += ngx_buf_size(cl->buf);
104 if (cl->buf->flush || cl->buf->recycled) {
105 flush = 1;
108 if (cl->buf->last_buf) {
109 last = 1;
113 /* add the new chain to the existent one */
115 for (ln = in; ln; ln = ln->next) {
116 cl = ngx_alloc_chain_link(r->pool);
117 if (cl == NULL) {
118 return NGX_ERROR;
121 cl->buf = ln->buf;
122 *ll = cl;
123 ll = &cl->next;
125 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
126 "write new buf t:%d f:%d %p, pos %p, size: %z "
127 "file: %O, size: %z",
128 cl->buf->temporary, cl->buf->in_file,
129 cl->buf->start, cl->buf->pos,
130 cl->buf->last - cl->buf->pos,
131 cl->buf->file_pos,
132 cl->buf->file_last - cl->buf->file_pos);
134 #if 1
135 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
136 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
137 "zero size buf in writer "
138 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
139 cl->buf->temporary,
140 cl->buf->recycled,
141 cl->buf->in_file,
142 cl->buf->start,
143 cl->buf->pos,
144 cl->buf->last,
145 cl->buf->file,
146 cl->buf->file_pos,
147 cl->buf->file_last);
149 ngx_debug_point();
150 return NGX_ERROR;
152 #endif
154 size += ngx_buf_size(cl->buf);
156 if (cl->buf->flush || cl->buf->recycled) {
157 flush = 1;
160 if (cl->buf->last_buf) {
161 last = 1;
165 *ll = NULL;
167 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
168 "http write filter: l:%d f:%d s:%O", last, flush, size);
170 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
173 * avoid the output if there are no last buf, no flush point,
174 * there are the incoming bufs and the size of all bufs
175 * is smaller than "postpone_output" directive
178 if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
179 return NGX_OK;
182 if (c->write->delayed) {
183 c->buffered |= NGX_HTTP_WRITE_BUFFERED;
184 return NGX_AGAIN;
187 if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)) {
188 if (last || flush) {
189 for (cl = r->out; cl; /* void */) {
190 ln = cl;
191 cl = cl->next;
192 ngx_free_chain(r->pool, ln);
195 r->out = NULL;
196 c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
198 return NGX_OK;
201 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
202 "the http output chain is empty");
204 ngx_debug_point();
206 return NGX_ERROR;
209 if (r->limit_rate) {
210 limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
211 - (c->sent - clcf->limit_rate_after);
213 if (limit <= 0) {
214 c->write->delayed = 1;
215 ngx_add_timer(c->write,
216 (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1));
218 c->buffered |= NGX_HTTP_WRITE_BUFFERED;
220 return NGX_AGAIN;
223 if (clcf->sendfile_max_chunk
224 && (off_t) clcf->sendfile_max_chunk < limit)
226 limit = clcf->sendfile_max_chunk;
229 } else {
230 limit = clcf->sendfile_max_chunk;
233 sent = c->sent;
235 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
236 "http write filter limit %O", limit);
238 chain = c->send_chain(c, r->out, limit);
240 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
241 "http write filter %p", chain);
243 if (chain == NGX_CHAIN_ERROR) {
244 c->error = 1;
245 return NGX_ERROR;
248 if (r->limit_rate) {
250 nsent = c->sent;
252 if (clcf->limit_rate_after) {
254 sent -= clcf->limit_rate_after;
255 if (sent < 0) {
256 sent = 0;
259 nsent -= clcf->limit_rate_after;
260 if (nsent < 0) {
261 nsent = 0;
265 delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
267 if (delay > 0) {
268 limit = 0;
269 c->write->delayed = 1;
270 ngx_add_timer(c->write, delay);
274 if (limit
275 && c->write->ready
276 && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
278 c->write->delayed = 1;
279 ngx_add_timer(c->write, 1);
282 for (cl = r->out; cl && cl != chain; /* void */) {
283 ln = cl;
284 cl = cl->next;
285 ngx_free_chain(r->pool, ln);
288 r->out = chain;
290 if (chain) {
291 c->buffered |= NGX_HTTP_WRITE_BUFFERED;
292 return NGX_AGAIN;
295 c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
297 if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) {
298 return NGX_AGAIN;
301 return NGX_OK;
305 static ngx_int_t
306 ngx_http_write_filter_init(ngx_conf_t *cf)
308 ngx_http_top_body_filter = ngx_http_write_filter;
310 return NGX_OK;