Mercurial > hg > nginx-mail
comparison src/http/ngx_http_write_filter.c @ 0:f0b350454894 NGINX_0_1_0
nginx 0.1.0
*) The first public version.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 04 Oct 2004 00:00:00 +0400 |
parents | |
children | 4b2dafa26fe2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0b350454894 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_chain_t *out; | |
15 } ngx_http_write_filter_ctx_t; | |
16 | |
17 | |
18 static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle); | |
19 | |
20 | |
21 ngx_http_module_t ngx_http_write_filter_module_ctx = { | |
22 NULL, /* pre conf */ | |
23 | |
24 NULL, /* create main configuration */ | |
25 NULL, /* init main configuration */ | |
26 | |
27 NULL, /* create server configuration */ | |
28 NULL, /* merge server configuration */ | |
29 | |
30 NULL, /* create location configuration */ | |
31 NULL, /* merge location configuration */ | |
32 }; | |
33 | |
34 | |
35 ngx_module_t ngx_http_write_filter_module = { | |
36 NGX_MODULE, | |
37 &ngx_http_write_filter_module_ctx, /* module context */ | |
38 NULL, /* module directives */ | |
39 NGX_HTTP_MODULE, /* module type */ | |
40 ngx_http_write_filter_init, /* init module */ | |
41 NULL /* init process */ | |
42 }; | |
43 | |
44 | |
45 ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
46 { | |
47 int last; | |
48 off_t size, flush, sent; | |
49 ngx_chain_t *cl, *ln, **ll, *chain; | |
50 ngx_connection_t *c; | |
51 ngx_http_core_loc_conf_t *clcf; | |
52 ngx_http_write_filter_ctx_t *ctx; | |
53 | |
54 ctx = ngx_http_get_module_ctx(r->main ? r->main : r, | |
55 ngx_http_write_filter_module); | |
56 | |
57 if (ctx == NULL) { | |
58 ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module, | |
59 sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR); | |
60 } | |
61 | |
62 size = 0; | |
63 flush = 0; | |
64 last = 0; | |
65 ll = &ctx->out; | |
66 | |
67 /* find the size, the flush point and the last link of the saved chain */ | |
68 | |
69 for (cl = ctx->out; cl; cl = cl->next) { | |
70 ll = &cl->next; | |
71 | |
72 size += ngx_buf_size(cl->buf); | |
73 | |
74 if (cl->buf->flush || cl->buf->recycled) { | |
75 flush = size; | |
76 } | |
77 | |
78 if (cl->buf->last_buf) { | |
79 last = 1; | |
80 } | |
81 } | |
82 | |
83 /* add the new chain to the existent one */ | |
84 | |
85 for (ln = in; ln; ln = ln->next) { | |
86 ngx_alloc_link_and_set_buf(cl, ln->buf, r->pool, NGX_ERROR); | |
87 *ll = cl; | |
88 ll = &cl->next; | |
89 | |
90 size += ngx_buf_size(cl->buf); | |
91 | |
92 if (cl->buf->flush || cl->buf->recycled) { | |
93 flush = size; | |
94 } | |
95 | |
96 if (cl->buf->last_buf) { | |
97 last = 1; | |
98 } | |
99 } | |
100 | |
101 c = r->connection; | |
102 | |
103 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
104 "http write filter: l:%d f:" OFF_T_FMT " s:" OFF_T_FMT, | |
105 last, flush, size); | |
106 | |
107 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, | |
108 ngx_http_core_module); | |
109 | |
110 /* | |
111 * avoid the output if there is no last buf, no flush point, | |
112 * there are the incoming bufs and the size of all bufs | |
113 * is smaller than "postpone_output" directive | |
114 */ | |
115 | |
116 if (!last && flush == 0 && in && size < (off_t) clcf->postpone_output) { | |
117 return NGX_OK; | |
118 } | |
119 | |
120 if (c->write->delayed) { | |
121 return NGX_AGAIN; | |
122 } | |
123 | |
124 if (size == 0 && !c->buffered) { | |
125 if (!last) { | |
126 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
127 "the http output chain is empty"); | |
128 } | |
129 return NGX_OK; | |
130 } | |
131 | |
132 sent = c->sent; | |
133 | |
134 chain = c->send_chain(c, ctx->out, | |
135 clcf->limit_rate ? clcf->limit_rate: OFF_T_MAX_VALUE); | |
136 | |
137 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
138 "http write filter %X", chain); | |
139 | |
140 if (clcf->limit_rate) { | |
141 sent = c->sent - sent; | |
142 c->write->delayed = 1; | |
143 ngx_add_timer(r->connection->write, | |
144 (ngx_msec_t) (sent * 1000 / clcf->limit_rate)); | |
145 } | |
146 | |
147 if (chain == NGX_CHAIN_ERROR) { | |
148 return NGX_ERROR; | |
149 } | |
150 | |
151 ctx->out = chain; | |
152 | |
153 if (chain || c->buffered) { | |
154 return NGX_AGAIN; | |
155 } | |
156 | |
157 return NGX_OK; | |
158 } | |
159 | |
160 | |
161 static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle) | |
162 { | |
163 ngx_http_top_body_filter = ngx_http_write_filter; | |
164 | |
165 return NGX_OK; | |
166 } |