comparison src/stream/ngx_stream_core_module.c @ 6694:ea9dfe2f62e7

Stream: preread phase. In this phase, head of a stream is read and analysed before proceeding to the content phase. Amount of data read is controlled by the module implementing the phase, but not more than defined by the "preread_buffer_size" directive. The time spent on processing preread is controlled by the "preread_timeout" directive. The typical preread phase module will parse the beginning of a stream and set variable that may be used by the content phase, for example to make routing decision.
author Vladimir Homutov <vl@nginx.com>
date Thu, 15 Sep 2016 14:56:02 +0300
parents 3908156a51fa
children cebf5fed00bf
comparison
equal deleted inserted replaced
6693:3908156a51fa 6694:ea9dfe2f62e7
89 ngx_conf_set_flag_slot, 89 ngx_conf_set_flag_slot,
90 NGX_STREAM_SRV_CONF_OFFSET, 90 NGX_STREAM_SRV_CONF_OFFSET,
91 offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay), 91 offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay),
92 NULL }, 92 NULL },
93 93
94 { ngx_string("preread_buffer_size"),
95 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
96 ngx_conf_set_size_slot,
97 NGX_STREAM_SRV_CONF_OFFSET,
98 offsetof(ngx_stream_core_srv_conf_t, preread_buffer_size),
99 NULL },
100
101 { ngx_string("preread_timeout"),
102 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
103 ngx_conf_set_msec_slot,
104 NGX_STREAM_SRV_CONF_OFFSET,
105 offsetof(ngx_stream_core_srv_conf_t, preread_timeout),
106 NULL },
107
94 ngx_null_command 108 ngx_null_command
95 }; 109 };
96 110
97 111
98 static ngx_stream_module_t ngx_stream_core_module_ctx = { 112 static ngx_stream_module_t ngx_stream_core_module_ctx = {
151 { 165 {
152 ngx_int_t rc; 166 ngx_int_t rc;
153 167
154 /* 168 /*
155 * generic phase checker, 169 * generic phase checker,
156 * used by all phases, except for content 170 * used by all phases, except for preread and content
157 */ 171 */
158 172
159 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, 173 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
160 "generic phase: %ui", s->phase_handler); 174 "generic phase: %ui", s->phase_handler);
161 175
170 s->phase_handler++; 184 s->phase_handler++;
171 return NGX_AGAIN; 185 return NGX_AGAIN;
172 } 186 }
173 187
174 if (rc == NGX_AGAIN || rc == NGX_DONE) { 188 if (rc == NGX_AGAIN || rc == NGX_DONE) {
189 return NGX_OK;
190 }
191
192 if (rc == NGX_ERROR) {
193 rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
194 }
195
196 ngx_stream_finalize_session(s, rc);
197
198 return NGX_OK;
199 }
200
201
202 ngx_int_t
203 ngx_stream_core_preread_phase(ngx_stream_session_t *s,
204 ngx_stream_phase_handler_t *ph)
205 {
206 size_t size;
207 ssize_t n;
208 ngx_int_t rc;
209 ngx_connection_t *c;
210 ngx_stream_core_srv_conf_t *cscf;
211
212 c = s->connection;
213
214 c->log->action = "prereading client data";
215
216 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
217
218 if (c->read->timedout) {
219 rc = NGX_STREAM_OK;
220
221 } else if (c->read->timer_set) {
222 rc = NGX_AGAIN;
223
224 } else {
225 rc = ph->handler(s);
226 }
227
228 while (rc == NGX_AGAIN) {
229
230 if (c->buffer == NULL) {
231 c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
232 if (c->buffer == NULL) {
233 rc = NGX_ERROR;
234 break;
235 }
236 }
237
238 size = c->buffer->end - c->buffer->last;
239
240 if (size == 0) {
241 ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
242 rc = NGX_STREAM_BAD_REQUEST;
243 break;
244 }
245
246 if (c->read->eof) {
247 rc = NGX_STREAM_OK;
248 break;
249 }
250
251 if (!c->read->ready) {
252 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
253 rc = NGX_ERROR;
254 break;
255 }
256
257 if (!c->read->timer_set) {
258 ngx_add_timer(c->read, cscf->preread_timeout);
259 }
260
261 c->read->handler = ngx_stream_session_handler;
262
263 return NGX_OK;
264 }
265
266 n = c->recv(c, c->buffer->last, size);
267
268 if (n == NGX_ERROR) {
269 rc = NGX_STREAM_OK;
270 break;
271 }
272
273 if (n > 0) {
274 c->buffer->last += n;
275 }
276
277 rc = ph->handler(s);
278 }
279
280 if (c->read->timer_set) {
281 ngx_del_timer(c->read);
282 }
283
284 if (rc == NGX_OK) {
285 s->phase_handler = ph->next;
286 return NGX_AGAIN;
287 }
288
289 if (rc == NGX_DECLINED) {
290 s->phase_handler++;
291 return NGX_AGAIN;
292 }
293
294 if (rc == NGX_DONE) {
175 return NGX_OK; 295 return NGX_OK;
176 } 296 }
177 297
178 if (rc == NGX_ERROR) { 298 if (rc == NGX_ERROR) {
179 rc = NGX_STREAM_INTERNAL_SERVER_ERROR; 299 rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
301 cscf->file_name = cf->conf_file->file.name.data; 421 cscf->file_name = cf->conf_file->file.name.data;
302 cscf->line = cf->conf_file->line; 422 cscf->line = cf->conf_file->line;
303 cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; 423 cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
304 cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC; 424 cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC;
305 cscf->tcp_nodelay = NGX_CONF_UNSET; 425 cscf->tcp_nodelay = NGX_CONF_UNSET;
426 cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
427 cscf->preread_timeout = NGX_CONF_UNSET_MSEC;
306 428
307 return cscf; 429 return cscf;
308 } 430 }
309 431
310 432
352 474
353 ngx_conf_merge_msec_value(conf->proxy_protocol_timeout, 475 ngx_conf_merge_msec_value(conf->proxy_protocol_timeout,
354 prev->proxy_protocol_timeout, 30000); 476 prev->proxy_protocol_timeout, 30000);
355 477
356 ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); 478 ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
479
480 ngx_conf_merge_size_value(conf->preread_buffer_size,
481 prev->preread_buffer_size, 16384);
482
483 ngx_conf_merge_msec_value(conf->preread_timeout,
484 prev->preread_timeout, 30000);
357 485
358 return NGX_CONF_OK; 486 return NGX_CONF_OK;
359 } 487 }
360 488
361 489