Mercurial > hg > nginx-quic
comparison src/http/ngx_http_filter.c @ 4:c5f071d376e5
nginx-0.0.1-2002-08-22-19:24:03 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 22 Aug 2002 15:24:03 +0000 |
parents | 34a521b1a148 |
children | 62b1a364857c |
comparison
equal
deleted
inserted
replaced
3:34a521b1a148 | 4:c5f071d376e5 |
---|---|
1 | 1 |
2 | |
3 #include <ngx_hunk.h> | |
4 #include <ngx_http.h> | |
5 #include <ngx_http_filter.h> | |
2 | 6 |
3 | 7 |
4 ngx_http_module_t ngx_http_filter_module; | 8 ngx_http_module_t ngx_http_filter_module; |
5 | 9 |
6 | 10 |
7 /* STUB */ | 11 /* STUB */ |
8 static ngx_http_filter_ctx_t module_ctx; | 12 static ngx_http_filter_ctx_t module_ctx; |
9 | 13 |
10 void ngx_http_filter_init() | 14 void ngx_http_filter_init() |
11 { | 15 { |
12 module_ctx.buffer_output = 10240; | 16 module_ctx.hunk_size = 32 * 1024; |
13 module_ctx.out = NULL; | 17 module_ctx.out.hunk = NULL; |
18 module_ctx.out.next = NULL; | |
14 module_ctx.next_filter = ngx_http_write_filter; | 19 module_ctx.next_filter = ngx_http_write_filter; |
15 | 20 |
16 ngx_http_filter_module.ctx = &module_ctx; | 21 ngx_http_filter_module.ctx = &module_ctx; |
17 } | 22 } |
18 /* */ | 23 /* */ |
26 flags NGX_HUNK_RECYCLED, NGX_HUNK_FLUSH, NGX_HUNK_LAST | 31 flags NGX_HUNK_RECYCLED, NGX_HUNK_FLUSH, NGX_HUNK_LAST |
27 */ | 32 */ |
28 | 33 |
29 int ngx_http_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) | 34 int ngx_http_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) |
30 { | 35 { |
31 enum { NO = 0, COPY, FILE } temp; | 36 int rc; |
32 | 37 size_t size; |
33 ngx_http_write_ctx_t *ctx; | 38 ssize_t n; |
39 ngx_chain_t *ce; | |
40 ngx_http_filter_ctx_t *ctx; | |
34 | 41 |
35 ctx = (ngx_http_filter_ctx_t *) | 42 ctx = (ngx_http_filter_ctx_t *) |
36 ngx_get_module_ctx(r->main ? r->main : r, | 43 ngx_get_module_ctx(r->main ? r->main : r, |
37 &ngx_http_filter_module); | 44 &ngx_http_filter_module); |
38 | 45 |
39 | 46 if (hunk && (hunk->type & NGX_HUNK_LAST)) |
40 | 47 ctx->last = 1; |
41 if (hunk == NULL) | 48 |
42 if (in == NULL) | 49 /* input chain is not empty */ |
43 next_filter(NULL); | 50 if (ctx->in) { |
44 else | 51 |
45 | 52 while (ctx->in) { |
46 | 53 |
47 | 54 /* add hunk to input chain */ |
48 | 55 if (hunk) { |
49 | 56 for (ce = ctx->in; ce->next; ce = ce->next) |
50 if (hunk != NULL) | 57 /* void */ ; |
51 if (in == NULL) | 58 |
52 if (temp == NO) | 59 ngx_add_hunk_to_chain(ce->next, hunk, r->pool, |
53 fast_chain = hunk; | 60 NGX_ERROR); |
54 next_filter(fast_chain); | 61 } |
62 | |
63 /* our hunk is still busy */ | |
64 if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { | |
65 rc = ctx->next_filter(r, NULL); | |
66 | |
67 /* our hunk is free */ | |
68 } else { | |
69 ctx->out.hunk = ctx->hunk; | |
70 | |
71 rc = ngx_http_filter_copy_hunk(ctx->hunk, ctx->in->hunk); | |
72 #if (NGX_FILE_AIO) | |
73 if (rc == NGX_AGAIN) | |
74 return rc; | |
75 #endif | |
76 if (rc == NGX_ERROR) | |
77 return rc; | |
78 | |
79 /* whole hunk is copied so we send to next filter chain part | |
80 up to next hunk that need to be copied */ | |
81 if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) { | |
82 ctx->out.next = ctx->in->next; | |
83 | |
84 for (ce = ctx->in->next; ce; ce = ce->next) { | |
85 if (ce->type & NGX_HUNK_FILE) | |
86 break; | |
87 | |
88 if ((ce->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP) | |
89 && (r->filter & NGX_HTTP_FILTER_NEED_TEMP)) | |
90 break; | |
91 } | |
92 | |
93 ctx->out.next = ce; | |
94 | |
95 } else { | |
96 ctx->out.next = NULL; | |
97 } | |
98 | |
99 rc = ctx->next_filter(r, &ctx->out); | |
100 } | |
101 | |
102 if (rc == NGX_OK) | |
103 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | |
55 else | 104 else |
56 if (ctx->hunk busy) | 105 return rc; |
57 add hunk to ctx->in | 106 } |
58 next_filter(NULL); | 107 |
59 else | 108 /* input chain is empty */ |
60 if (hunk > ctx->hunk) | 109 } else { |
61 copy hunk part to ctx->hunk | 110 |
62 add hunk to ctx->in | 111 if (hunk == NULL) { |
63 else | 112 rc = ctx->next_filter(r, NULL); |
64 copy hunk to ctx->hunk | |
65 fast_chain = ctx->hunk | |
66 next_filter(fast_chain); | |
67 | |
68 else /* in != NULL */ | |
69 add hunk to ctx->in | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 if ((r->filter & NGX_FILT_NEED_IN_MEMORY) && (hunk->type & NGX_HUNK_FILE)) | |
80 temp = FILE; | |
81 | |
82 else if ((r->filter & NGX_FILT_NEED_TEMP) | |
83 && (hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) | |
84 temp = COPY; | |
85 | |
86 if (temp) { | |
87 size = hunk->last.mem - hunk->pos.mem; | |
88 | |
89 if (hunk->type & NGX_HUNK_LAST) { | |
90 if (size > ctx->hunk_size) | |
91 size = ctx->hunk_size; | |
92 | |
93 hunk_size = size; | |
94 | 113 |
95 } else { | 114 } else { |
96 hunk_size = ctx->hunk_size; | 115 |
116 /* we need to copy hunk to our hunk */ | |
117 if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) | |
118 && (hunk->type & NGX_HUNK_FILE)) | |
119 || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) | |
120 && (hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) | |
121 ) { | |
122 | |
123 /* out hunk is still busy */ | |
124 if (ctx->hunk && ctx->hunk->pos.mem < ctx->hunk->last.mem) { | |
125 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, | |
126 NGX_ERROR); | |
127 | |
128 rc = ctx->next_filter(r, NULL); | |
129 | |
130 } else { | |
131 if (ctx->hunk == NULL) { | |
132 | |
133 if (hunk->type & NGX_HUNK_LAST) { | |
134 size = hunk->last.mem - hunk->pos.mem; | |
135 if (size > ctx->hunk_size) | |
136 size = ctx->hunk_size; | |
137 | |
138 } else { | |
139 size = ctx->hunk_size; | |
140 } | |
141 | |
142 ngx_test_null(ctx->hunk, | |
143 ngx_create_temp_hunk(r->pool, size, | |
144 50, 50), | |
145 NGX_ERROR); | |
146 | |
147 rc = ngx_http_filter_copy_hunk(ctx->hunk, | |
148 ctx->in->hunk); | |
149 #if (NGX_FILE_AIO) | |
150 if (rc == NGX_AGAIN) { | |
151 /* add hunk to input chain */ | |
152 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, | |
153 NGX_ERROR); | |
154 | |
155 return rc; | |
156 } | |
157 #endif | |
158 if (rc == NGX_ERROR) | |
159 return rc; | |
160 | |
161 if (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem) | |
162 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, | |
163 NGX_ERROR); | |
164 | |
165 ctx->out.hunk = ctx->hunk; | |
166 ctx->out.next = NULL; | |
167 | |
168 rc = ctx->next_filter(r, &ctx->out); | |
169 } | |
170 } | |
171 | |
172 } else { | |
173 ctx->out.hunk = hunk; | |
174 ctx->out.next = NULL; | |
175 | |
176 rc = ctx->next_filter(r, &ctx->out); | |
177 | |
178 } | |
97 } | 179 } |
98 } | 180 } |
99 | 181 |
100 if (!ctx->hunk) | 182 if (rc == NGX_OK && ctx->last) { |
101 ngx_test_null(ctx->hunk, ngx_create_temp_hunk(hunk_size), ...); | 183 /* STUB */ |
102 | 184 return NGX_ERROR; |
103 if (temp == FILE) { | 185 } |
104 n = ngx_read_file(hunk->fd, ctx->hunk->pos.mem, size); | 186 |
105 | 187 if (rc == NGX_OK) { |
106 if (n == -1) { | 188 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; |
107 ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, | 189 #if level_event |
190 ngx_del_event(r->connection->write, NGX_WRITE_EVENT); | |
191 #endif | |
192 } | |
193 | |
194 return rc; | |
195 } | |
196 | |
197 | |
198 int ngx_http_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src, ngx_log_t *log) | |
199 { | |
200 size_t size; | |
201 | |
202 size = hunk->last.mem - hunk->pos.mem; | |
203 if (size > dst->end - dst->pos.mem) | |
204 size = dst->end - dst->pos.mem; | |
205 | |
206 if (src->type & NGX_HUNK_FILE) { | |
207 n = ngx_read_file(src->handle, dst->pos.mem, size); | |
208 | |
209 if (n == NGX_ERROR) { | |
210 ngx_log_error(NGX_LOG_ERR, log, ngx_errno, | |
108 ngx_read_file_n " failed for client"); | 211 ngx_read_file_n " failed for client"); |
109 return -1; | 212 return NGX_ERROR; |
110 | 213 |
111 } else { | 214 } else { |
112 ngx_assert((n == size), /* void */ ; , | 215 ngx_assert((n == size), /* void */ ; , log, |
113 r->connection->log, 0, | 216 ngx_read_file_n " reads only %d of %d for client" _ |
114 ngx_read_file_n " reads only %d of %d for client", | 217 n _ size); |
115 n, size); | |
116 } | 218 } |
117 | 219 |
118 hunk->pos.mem += n; | 220 src->pos.mem += n; |
119 ctx->hunk->last.mem += n; | 221 dst->last.mem += n; |
120 | 222 |
121 } else if (temp == COPY) { | 223 } else { |
122 ngx_memcpy(ctx->hunk->pos.mem, hunk->pos.mem, size); | 224 ngx_memcpy(src->pos.mem, dst->pos.mem, size); |
123 | 225 |
124 hunk->pos.mem += size; | 226 src->pos.mem += size; |
125 ctx->hunk->last.mem += size; | 227 dst->last.mem += size; |
126 } | 228 } |
127 | 229 |
230 return NGX_OK; | |
231 } | |
128 | 232 |
129 | 233 |
130 | 234 |
131 | 235 |
132 | 236 |
138 && (ctx->hunk->pos.mem < ctx->hunk->last.mem)) | 242 && (ctx->hunk->pos.mem < ctx->hunk->last.mem)) |
139 ) | 243 ) |
140 ) | 244 ) |
141 ctx->next_filter(r, NULL); | 245 ctx->next_filter(r, NULL); |
142 } | 246 } |
143 | 247 } |
144 /* hunk != NULL || ctx->hunk->pos.mem == ctx->hunk->last.mem */ | |
145 | |
146 /* find last link of saved chain */ | |
147 prev = &ctx->out; | |
148 for (ch = ctx->out; ch; ch = ch->next) { | |
149 prev = &ch->next; | |
150 } | |
151 | |
152 if hunk | |
153 if need our hunk - alloc it and add to our queue | |
154 else add hunk to our queue | |
155 | |
156 /* | |
157 size += ch->hunk->last.file - ch->hunk->pos.file; | |
158 | |
159 ngx_log_debug(r->connection->log, "old chunk: %x %qx %qd" _ | |
160 ch->hunk->type _ ch->hunk->pos.file _ | |
161 ch->hunk->last.file - ch->hunk->pos.file); | |
162 | |
163 if (ch->hunk->type & NGX_HUNK_FLUSH) | |
164 flush = size; | |
165 | |
166 if (ch->hunk->type & NGX_HUNK_LAST) | |
167 last = 1; | |
168 } | |
169 */ | |
170 | |
171 /* add new chain to existent one */ | |
172 for (/* void */; in; in = in->next) { | |
173 ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), | |
174 NGX_HTTP_FILTER_ERROR); | |
175 | |
176 ch->hunk = h; | |
177 ch->next = NULL; | |
178 *prev = ch; | |
179 prev = &ch->next; | |
180 size += ch->hunk->last.file - ch->hunk->pos.file; | |
181 | |
182 ngx_log_debug(r->connection->log, "new chunk: %x %qx %qd" _ | |
183 ch->hunk->type _ ch->hunk->pos.file _ | |
184 ch->hunk->last.file - ch->hunk->pos.file); | |
185 | |
186 if (ch->hunk->type & NGX_HUNK_FLUSH) | |
187 flush = size; | |
188 | |
189 if (ch->hunk->type & NGX_HUNK_LAST) | |
190 last = 1; | |
191 } | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 /* | |
198 !(HAVE_SENDFILE) == NGX_FILT_NEED_IN_MEMORY | |
199 */ | |
200 | |
201 if ((r->filter & NGX_FILT_NEED_IN_MEMORY) && (h->type & NGX_HUNK_FILE)) { | |
202 | |
203 size = h->last.mem - h->pos.mem; | |
204 if (size > ctx->hunk_size) | |
205 size = ctx->hunk_size; | |
206 | |
207 if (!ctx->hunk) | |
208 ngx_test_null(ctx->hunk, ngx_create_temp_hunk(size), ...); | |
209 | |
210 ngx_read_file(h->fd, ctx->hunk->pos.mem, size); | |
211 | |
212 h->hunk->pos.mem += size; | |
213 } | |
214 | |
215 if ((r->filter & NGX_FILT_NEED_TEMP) | |
216 && (h->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) | |
217 { | |
218 size = h->last.mem - h->pos.mem; | |
219 if (size > ctx->hunk_size) | |
220 size = ctx->hunk_size; | |
221 | |
222 if (!ctx->hunk) | |
223 ngx_test_null(ctx->hunk, ngx_create_temp_hunk(size), ...); | |
224 | |
225 ngx_memcpy(ctx->hunk->pos.mem, h->pos.mem, size); | |
226 | |
227 h->hunk->pos.mem += size; | |
228 } | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 rc = ctx->next_filter(r, ch); | |
236 | |
237 /* STUB */ | |
238 rc = ngx_http_write_filter(r, ch); | |
239 } |