Mercurial > hg > nginx
annotate src/stream/ngx_stream_script.c @ 7168:46ebff8c6396
Inherit valid_unparsed_uri in cloned subrequests (ticket #1430).
Inheriting this flag will make the cloned subrequest behave consistently with
the parent. Specifically, the upstream HTTP request and cache key created by
the proxy module may depend directly on unparsed_uri if valid_unparsed_uri flag
is set. Previously, the flag was zero for cloned requests, which could make
background update proxy a request different than its parent and cache the result
with a different key. For example, if client URI contained the escaped slash
character %2F, it was used as is by the proxy module in the main request, but
was unescaped in the subrequests.
Similar problems exist in the slice module.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 20 Nov 2017 21:11:19 +0300 |
parents | 39ff6939266e |
children | 9e25a5380a21 |
rev | line source |
---|---|
6607 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_stream.h> | |
11 | |
12 | |
13 static ngx_int_t ngx_stream_script_init_arrays( | |
14 ngx_stream_script_compile_t *sc); | |
15 static ngx_int_t ngx_stream_script_done(ngx_stream_script_compile_t *sc); | |
16 static ngx_int_t ngx_stream_script_add_copy_code( | |
17 ngx_stream_script_compile_t *sc, ngx_str_t *value, ngx_uint_t last); | |
18 static ngx_int_t ngx_stream_script_add_var_code( | |
19 ngx_stream_script_compile_t *sc, ngx_str_t *name); | |
20 #if (NGX_PCRE) | |
21 static ngx_int_t ngx_stream_script_add_capture_code( | |
22 ngx_stream_script_compile_t *sc, ngx_uint_t n); | |
23 #endif | |
24 static ngx_int_t ngx_stream_script_add_full_name_code( | |
25 ngx_stream_script_compile_t *sc); | |
26 static size_t ngx_stream_script_full_name_len_code( | |
27 ngx_stream_script_engine_t *e); | |
28 static void ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e); | |
29 | |
30 | |
31 #define ngx_stream_script_exit (u_char *) &ngx_stream_script_exit_code | |
32 | |
33 static uintptr_t ngx_stream_script_exit_code = (uintptr_t) NULL; | |
34 | |
35 | |
36 void | |
37 ngx_stream_script_flush_complex_value(ngx_stream_session_t *s, | |
38 ngx_stream_complex_value_t *val) | |
39 { | |
40 ngx_uint_t *index; | |
41 | |
42 index = val->flushes; | |
43 | |
44 if (index) { | |
45 while (*index != (ngx_uint_t) -1) { | |
46 | |
47 if (s->variables[*index].no_cacheable) { | |
48 s->variables[*index].valid = 0; | |
49 s->variables[*index].not_found = 0; | |
50 } | |
51 | |
52 index++; | |
53 } | |
54 } | |
55 } | |
56 | |
57 | |
58 ngx_int_t | |
59 ngx_stream_complex_value(ngx_stream_session_t *s, | |
60 ngx_stream_complex_value_t *val, ngx_str_t *value) | |
61 { | |
62 size_t len; | |
63 ngx_stream_script_code_pt code; | |
64 ngx_stream_script_engine_t e; | |
65 ngx_stream_script_len_code_pt lcode; | |
66 | |
67 if (val->lengths == NULL) { | |
68 *value = val->value; | |
69 return NGX_OK; | |
70 } | |
71 | |
72 ngx_stream_script_flush_complex_value(s, val); | |
73 | |
74 ngx_memzero(&e, sizeof(ngx_stream_script_engine_t)); | |
75 | |
76 e.ip = val->lengths; | |
77 e.session = s; | |
78 e.flushed = 1; | |
79 | |
80 len = 0; | |
81 | |
82 while (*(uintptr_t *) e.ip) { | |
83 lcode = *(ngx_stream_script_len_code_pt *) e.ip; | |
84 len += lcode(&e); | |
85 } | |
86 | |
87 value->len = len; | |
88 value->data = ngx_pnalloc(s->connection->pool, len); | |
89 if (value->data == NULL) { | |
90 return NGX_ERROR; | |
91 } | |
92 | |
93 e.ip = val->values; | |
94 e.pos = value->data; | |
95 e.buf = *value; | |
96 | |
97 while (*(uintptr_t *) e.ip) { | |
98 code = *(ngx_stream_script_code_pt *) e.ip; | |
99 code((ngx_stream_script_engine_t *) &e); | |
100 } | |
101 | |
102 *value = e.buf; | |
103 | |
104 return NGX_OK; | |
105 } | |
106 | |
107 | |
108 ngx_int_t | |
109 ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv) | |
110 { | |
111 ngx_str_t *v; | |
112 ngx_uint_t i, n, nv, nc; | |
113 ngx_array_t flushes, lengths, values, *pf, *pl, *pv; | |
114 ngx_stream_script_compile_t sc; | |
115 | |
116 v = ccv->value; | |
117 | |
118 nv = 0; | |
119 nc = 0; | |
120 | |
121 for (i = 0; i < v->len; i++) { | |
122 if (v->data[i] == '$') { | |
123 if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') { | |
124 nc++; | |
125 | |
126 } else { | |
127 nv++; | |
128 } | |
129 } | |
130 } | |
131 | |
132 if ((v->len == 0 || v->data[0] != '$') | |
133 && (ccv->conf_prefix || ccv->root_prefix)) | |
134 { | |
135 if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) { | |
136 return NGX_ERROR; | |
137 } | |
138 | |
139 ccv->conf_prefix = 0; | |
140 ccv->root_prefix = 0; | |
141 } | |
142 | |
143 ccv->complex_value->value = *v; | |
144 ccv->complex_value->flushes = NULL; | |
145 ccv->complex_value->lengths = NULL; | |
146 ccv->complex_value->values = NULL; | |
147 | |
148 if (nv == 0 && nc == 0) { | |
149 return NGX_OK; | |
150 } | |
151 | |
152 n = nv + 1; | |
153 | |
154 if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t)) | |
155 != NGX_OK) | |
156 { | |
157 return NGX_ERROR; | |
158 } | |
159 | |
160 n = nv * (2 * sizeof(ngx_stream_script_copy_code_t) | |
161 + sizeof(ngx_stream_script_var_code_t)) | |
162 + sizeof(uintptr_t); | |
163 | |
164 if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) { | |
165 return NGX_ERROR; | |
166 } | |
167 | |
168 n = (nv * (2 * sizeof(ngx_stream_script_copy_code_t) | |
169 + sizeof(ngx_stream_script_var_code_t)) | |
170 + sizeof(uintptr_t) | |
171 + v->len | |
172 + sizeof(uintptr_t) - 1) | |
173 & ~(sizeof(uintptr_t) - 1); | |
174 | |
175 if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) { | |
176 return NGX_ERROR; | |
177 } | |
178 | |
179 pf = &flushes; | |
180 pl = &lengths; | |
181 pv = &values; | |
182 | |
183 ngx_memzero(&sc, sizeof(ngx_stream_script_compile_t)); | |
184 | |
185 sc.cf = ccv->cf; | |
186 sc.source = v; | |
187 sc.flushes = &pf; | |
188 sc.lengths = &pl; | |
189 sc.values = &pv; | |
190 sc.complete_lengths = 1; | |
191 sc.complete_values = 1; | |
192 sc.zero = ccv->zero; | |
193 sc.conf_prefix = ccv->conf_prefix; | |
194 sc.root_prefix = ccv->root_prefix; | |
195 | |
196 if (ngx_stream_script_compile(&sc) != NGX_OK) { | |
197 return NGX_ERROR; | |
198 } | |
199 | |
200 if (flushes.nelts) { | |
201 ccv->complex_value->flushes = flushes.elts; | |
202 ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1; | |
203 } | |
204 | |
205 ccv->complex_value->lengths = lengths.elts; | |
206 ccv->complex_value->values = values.elts; | |
207 | |
208 return NGX_OK; | |
209 } | |
210 | |
211 | |
212 char * | |
213 ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, | |
214 void *conf) | |
215 { | |
216 char *p = conf; | |
217 | |
218 ngx_str_t *value; | |
219 ngx_stream_complex_value_t **cv; | |
220 ngx_stream_compile_complex_value_t ccv; | |
221 | |
222 cv = (ngx_stream_complex_value_t **) (p + cmd->offset); | |
223 | |
224 if (*cv != NULL) { | |
6940
39ff6939266e
Unified error messages about duplicate directives.
Ruslan Ermilov <ru@nginx.com>
parents:
6678
diff
changeset
|
225 return "is duplicate"; |
6607 | 226 } |
227 | |
228 *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); | |
229 if (*cv == NULL) { | |
230 return NGX_CONF_ERROR; | |
231 } | |
232 | |
233 value = cf->args->elts; | |
234 | |
235 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); | |
236 | |
237 ccv.cf = cf; | |
238 ccv.value = &value[1]; | |
239 ccv.complex_value = *cv; | |
240 | |
241 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { | |
242 return NGX_CONF_ERROR; | |
243 } | |
244 | |
245 return NGX_CONF_OK; | |
246 } | |
247 | |
248 | |
249 ngx_uint_t | |
250 ngx_stream_script_variables_count(ngx_str_t *value) | |
251 { | |
252 ngx_uint_t i, n; | |
253 | |
254 for (n = 0, i = 0; i < value->len; i++) { | |
255 if (value->data[i] == '$') { | |
256 n++; | |
257 } | |
258 } | |
259 | |
260 return n; | |
261 } | |
262 | |
263 | |
264 ngx_int_t | |
265 ngx_stream_script_compile(ngx_stream_script_compile_t *sc) | |
266 { | |
267 u_char ch; | |
268 ngx_str_t name; | |
269 ngx_uint_t i, bracket; | |
270 | |
271 if (ngx_stream_script_init_arrays(sc) != NGX_OK) { | |
272 return NGX_ERROR; | |
273 } | |
274 | |
275 for (i = 0; i < sc->source->len; /* void */ ) { | |
276 | |
277 name.len = 0; | |
278 | |
279 if (sc->source->data[i] == '$') { | |
280 | |
281 if (++i == sc->source->len) { | |
282 goto invalid_variable; | |
283 } | |
284 | |
6644
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
285 if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { |
6607 | 286 #if (NGX_PCRE) |
6644
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
287 ngx_uint_t n; |
6607 | 288 |
289 n = sc->source->data[i] - '0'; | |
290 | |
291 if (ngx_stream_script_add_capture_code(sc, n) != NGX_OK) { | |
292 return NGX_ERROR; | |
293 } | |
294 | |
295 i++; | |
296 | |
297 continue; | |
6644
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
298 #else |
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
299 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, |
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
300 "using variable \"$%c\" requires " |
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
301 "PCRE library", sc->source->data[i]); |
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
302 return NGX_ERROR; |
af642539cd53
Fixed regex captures handling without PCRE.
Vladimir Homutov <vl@nginx.com>
parents:
6607
diff
changeset
|
303 #endif |
6607 | 304 } |
305 | |
306 if (sc->source->data[i] == '{') { | |
307 bracket = 1; | |
308 | |
309 if (++i == sc->source->len) { | |
310 goto invalid_variable; | |
311 } | |
312 | |
313 name.data = &sc->source->data[i]; | |
314 | |
315 } else { | |
316 bracket = 0; | |
317 name.data = &sc->source->data[i]; | |
318 } | |
319 | |
320 for ( /* void */ ; i < sc->source->len; i++, name.len++) { | |
321 ch = sc->source->data[i]; | |
322 | |
323 if (ch == '}' && bracket) { | |
324 i++; | |
325 bracket = 0; | |
326 break; | |
327 } | |
328 | |
329 if ((ch >= 'A' && ch <= 'Z') | |
330 || (ch >= 'a' && ch <= 'z') | |
331 || (ch >= '0' && ch <= '9') | |
332 || ch == '_') | |
333 { | |
334 continue; | |
335 } | |
336 | |
337 break; | |
338 } | |
339 | |
340 if (bracket) { | |
341 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, | |
342 "the closing bracket in \"%V\" " | |
343 "variable is missing", &name); | |
344 return NGX_ERROR; | |
345 } | |
346 | |
347 if (name.len == 0) { | |
348 goto invalid_variable; | |
349 } | |
350 | |
351 sc->variables++; | |
352 | |
353 if (ngx_stream_script_add_var_code(sc, &name) != NGX_OK) { | |
354 return NGX_ERROR; | |
355 } | |
356 | |
357 continue; | |
358 } | |
359 | |
360 name.data = &sc->source->data[i]; | |
361 | |
362 while (i < sc->source->len) { | |
363 | |
364 if (sc->source->data[i] == '$') { | |
365 break; | |
366 } | |
367 | |
368 i++; | |
369 name.len++; | |
370 } | |
371 | |
372 sc->size += name.len; | |
373 | |
374 if (ngx_stream_script_add_copy_code(sc, &name, (i == sc->source->len)) | |
375 != NGX_OK) | |
376 { | |
377 return NGX_ERROR; | |
378 } | |
379 } | |
380 | |
381 return ngx_stream_script_done(sc); | |
382 | |
383 invalid_variable: | |
384 | |
385 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name"); | |
386 | |
387 return NGX_ERROR; | |
388 } | |
389 | |
390 | |
6678 | 391 u_char * |
392 ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value, | |
393 void *code_lengths, size_t len, void *code_values) | |
394 { | |
395 ngx_uint_t i; | |
396 ngx_stream_script_code_pt code; | |
397 ngx_stream_script_engine_t e; | |
398 ngx_stream_core_main_conf_t *cmcf; | |
399 ngx_stream_script_len_code_pt lcode; | |
400 | |
401 cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); | |
402 | |
403 for (i = 0; i < cmcf->variables.nelts; i++) { | |
404 if (s->variables[i].no_cacheable) { | |
405 s->variables[i].valid = 0; | |
406 s->variables[i].not_found = 0; | |
407 } | |
408 } | |
409 | |
410 ngx_memzero(&e, sizeof(ngx_stream_script_engine_t)); | |
411 | |
412 e.ip = code_lengths; | |
413 e.session = s; | |
414 e.flushed = 1; | |
415 | |
416 while (*(uintptr_t *) e.ip) { | |
417 lcode = *(ngx_stream_script_len_code_pt *) e.ip; | |
418 len += lcode(&e); | |
419 } | |
420 | |
421 | |
422 value->len = len; | |
423 value->data = ngx_pnalloc(s->connection->pool, len); | |
424 if (value->data == NULL) { | |
425 return NULL; | |
426 } | |
427 | |
428 e.ip = code_values; | |
429 e.pos = value->data; | |
430 | |
431 while (*(uintptr_t *) e.ip) { | |
432 code = *(ngx_stream_script_code_pt *) e.ip; | |
433 code((ngx_stream_script_engine_t *) &e); | |
434 } | |
435 | |
436 return e.pos; | |
437 } | |
438 | |
439 | |
440 void | |
441 ngx_stream_script_flush_no_cacheable_variables(ngx_stream_session_t *s, | |
442 ngx_array_t *indices) | |
443 { | |
444 ngx_uint_t n, *index; | |
445 | |
446 if (indices) { | |
447 index = indices->elts; | |
448 for (n = 0; n < indices->nelts; n++) { | |
449 if (s->variables[index[n]].no_cacheable) { | |
450 s->variables[index[n]].valid = 0; | |
451 s->variables[index[n]].not_found = 0; | |
452 } | |
453 } | |
454 } | |
455 } | |
456 | |
457 | |
6607 | 458 static ngx_int_t |
459 ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc) | |
460 { | |
461 ngx_uint_t n; | |
462 | |
463 if (sc->flushes && *sc->flushes == NULL) { | |
464 n = sc->variables ? sc->variables : 1; | |
465 *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); | |
466 if (*sc->flushes == NULL) { | |
467 return NGX_ERROR; | |
468 } | |
469 } | |
470 | |
471 if (*sc->lengths == NULL) { | |
472 n = sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t) | |
473 + sizeof(ngx_stream_script_var_code_t)) | |
474 + sizeof(uintptr_t); | |
475 | |
476 *sc->lengths = ngx_array_create(sc->cf->pool, n, 1); | |
477 if (*sc->lengths == NULL) { | |
478 return NGX_ERROR; | |
479 } | |
480 } | |
481 | |
482 if (*sc->values == NULL) { | |
483 n = (sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t) | |
484 + sizeof(ngx_stream_script_var_code_t)) | |
485 + sizeof(uintptr_t) | |
486 + sc->source->len | |
487 + sizeof(uintptr_t) - 1) | |
488 & ~(sizeof(uintptr_t) - 1); | |
489 | |
490 *sc->values = ngx_array_create(sc->cf->pool, n, 1); | |
491 if (*sc->values == NULL) { | |
492 return NGX_ERROR; | |
493 } | |
494 } | |
495 | |
496 sc->variables = 0; | |
497 | |
498 return NGX_OK; | |
499 } | |
500 | |
501 | |
502 static ngx_int_t | |
503 ngx_stream_script_done(ngx_stream_script_compile_t *sc) | |
504 { | |
505 ngx_str_t zero; | |
506 uintptr_t *code; | |
507 | |
508 if (sc->zero) { | |
509 | |
510 zero.len = 1; | |
511 zero.data = (u_char *) "\0"; | |
512 | |
513 if (ngx_stream_script_add_copy_code(sc, &zero, 0) != NGX_OK) { | |
514 return NGX_ERROR; | |
515 } | |
516 } | |
517 | |
518 if (sc->conf_prefix || sc->root_prefix) { | |
519 if (ngx_stream_script_add_full_name_code(sc) != NGX_OK) { | |
520 return NGX_ERROR; | |
521 } | |
522 } | |
523 | |
524 if (sc->complete_lengths) { | |
525 code = ngx_stream_script_add_code(*sc->lengths, sizeof(uintptr_t), | |
526 NULL); | |
527 if (code == NULL) { | |
528 return NGX_ERROR; | |
529 } | |
530 | |
531 *code = (uintptr_t) NULL; | |
532 } | |
533 | |
534 if (sc->complete_values) { | |
535 code = ngx_stream_script_add_code(*sc->values, sizeof(uintptr_t), | |
536 &sc->main); | |
537 if (code == NULL) { | |
538 return NGX_ERROR; | |
539 } | |
540 | |
541 *code = (uintptr_t) NULL; | |
542 } | |
543 | |
544 return NGX_OK; | |
545 } | |
546 | |
547 | |
548 void * | |
549 ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code) | |
550 { | |
551 u_char *elts, **p; | |
552 void *new; | |
553 | |
554 elts = codes->elts; | |
555 | |
556 new = ngx_array_push_n(codes, size); | |
557 if (new == NULL) { | |
558 return NULL; | |
559 } | |
560 | |
561 if (code) { | |
562 if (elts != codes->elts) { | |
563 p = code; | |
564 *p += (u_char *) codes->elts - elts; | |
565 } | |
566 } | |
567 | |
568 return new; | |
569 } | |
570 | |
571 | |
572 static ngx_int_t | |
573 ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc, | |
574 ngx_str_t *value, ngx_uint_t last) | |
575 { | |
576 u_char *p; | |
577 size_t size, len, zero; | |
578 ngx_stream_script_copy_code_t *code; | |
579 | |
580 zero = (sc->zero && last); | |
581 len = value->len + zero; | |
582 | |
583 code = ngx_stream_script_add_code(*sc->lengths, | |
584 sizeof(ngx_stream_script_copy_code_t), | |
585 NULL); | |
586 if (code == NULL) { | |
587 return NGX_ERROR; | |
588 } | |
589 | |
590 code->code = (ngx_stream_script_code_pt) ngx_stream_script_copy_len_code; | |
591 code->len = len; | |
592 | |
593 size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1) | |
594 & ~(sizeof(uintptr_t) - 1); | |
595 | |
596 code = ngx_stream_script_add_code(*sc->values, size, &sc->main); | |
597 if (code == NULL) { | |
598 return NGX_ERROR; | |
599 } | |
600 | |
601 code->code = ngx_stream_script_copy_code; | |
602 code->len = len; | |
603 | |
604 p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t), | |
605 value->data, value->len); | |
606 | |
607 if (zero) { | |
608 *p = '\0'; | |
609 sc->zero = 0; | |
610 } | |
611 | |
612 return NGX_OK; | |
613 } | |
614 | |
615 | |
616 size_t | |
617 ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e) | |
618 { | |
619 ngx_stream_script_copy_code_t *code; | |
620 | |
621 code = (ngx_stream_script_copy_code_t *) e->ip; | |
622 | |
623 e->ip += sizeof(ngx_stream_script_copy_code_t); | |
624 | |
625 return code->len; | |
626 } | |
627 | |
628 | |
629 void | |
630 ngx_stream_script_copy_code(ngx_stream_script_engine_t *e) | |
631 { | |
632 u_char *p; | |
633 ngx_stream_script_copy_code_t *code; | |
634 | |
635 code = (ngx_stream_script_copy_code_t *) e->ip; | |
636 | |
637 p = e->pos; | |
638 | |
639 if (!e->skip) { | |
640 e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t), | |
641 code->len); | |
642 } | |
643 | |
644 e->ip += sizeof(ngx_stream_script_copy_code_t) | |
645 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); | |
646 | |
647 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
648 "stream script copy: \"%*s\"", e->pos - p, p); | |
649 } | |
650 | |
651 | |
652 static ngx_int_t | |
653 ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name) | |
654 { | |
655 ngx_int_t index, *p; | |
656 ngx_stream_script_var_code_t *code; | |
657 | |
658 index = ngx_stream_get_variable_index(sc->cf, name); | |
659 | |
660 if (index == NGX_ERROR) { | |
661 return NGX_ERROR; | |
662 } | |
663 | |
664 if (sc->flushes) { | |
665 p = ngx_array_push(*sc->flushes); | |
666 if (p == NULL) { | |
667 return NGX_ERROR; | |
668 } | |
669 | |
670 *p = index; | |
671 } | |
672 | |
673 code = ngx_stream_script_add_code(*sc->lengths, | |
674 sizeof(ngx_stream_script_var_code_t), | |
675 NULL); | |
676 if (code == NULL) { | |
677 return NGX_ERROR; | |
678 } | |
679 | |
680 code->code = (ngx_stream_script_code_pt) | |
681 ngx_stream_script_copy_var_len_code; | |
682 code->index = (uintptr_t) index; | |
683 | |
684 code = ngx_stream_script_add_code(*sc->values, | |
685 sizeof(ngx_stream_script_var_code_t), | |
686 &sc->main); | |
687 if (code == NULL) { | |
688 return NGX_ERROR; | |
689 } | |
690 | |
691 code->code = ngx_stream_script_copy_var_code; | |
692 code->index = (uintptr_t) index; | |
693 | |
694 return NGX_OK; | |
695 } | |
696 | |
697 | |
698 size_t | |
699 ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e) | |
700 { | |
701 ngx_stream_variable_value_t *value; | |
702 ngx_stream_script_var_code_t *code; | |
703 | |
704 code = (ngx_stream_script_var_code_t *) e->ip; | |
705 | |
706 e->ip += sizeof(ngx_stream_script_var_code_t); | |
707 | |
708 if (e->flushed) { | |
709 value = ngx_stream_get_indexed_variable(e->session, code->index); | |
710 | |
711 } else { | |
712 value = ngx_stream_get_flushed_variable(e->session, code->index); | |
713 } | |
714 | |
715 if (value && !value->not_found) { | |
716 return value->len; | |
717 } | |
718 | |
719 return 0; | |
720 } | |
721 | |
722 | |
723 void | |
724 ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e) | |
725 { | |
726 u_char *p; | |
727 ngx_stream_variable_value_t *value; | |
728 ngx_stream_script_var_code_t *code; | |
729 | |
730 code = (ngx_stream_script_var_code_t *) e->ip; | |
731 | |
732 e->ip += sizeof(ngx_stream_script_var_code_t); | |
733 | |
734 if (!e->skip) { | |
735 | |
736 if (e->flushed) { | |
737 value = ngx_stream_get_indexed_variable(e->session, code->index); | |
738 | |
739 } else { | |
740 value = ngx_stream_get_flushed_variable(e->session, code->index); | |
741 } | |
742 | |
743 if (value && !value->not_found) { | |
744 p = e->pos; | |
745 e->pos = ngx_copy(p, value->data, value->len); | |
746 | |
747 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, | |
748 e->session->connection->log, 0, | |
749 "stream script var: \"%*s\"", e->pos - p, p); | |
750 } | |
751 } | |
752 } | |
753 | |
754 | |
755 #if (NGX_PCRE) | |
756 | |
757 static ngx_int_t | |
758 ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc, | |
759 ngx_uint_t n) | |
760 { | |
761 ngx_stream_script_copy_capture_code_t *code; | |
762 | |
763 code = ngx_stream_script_add_code(*sc->lengths, | |
764 sizeof(ngx_stream_script_copy_capture_code_t), | |
765 NULL); | |
766 if (code == NULL) { | |
767 return NGX_ERROR; | |
768 } | |
769 | |
770 code->code = (ngx_stream_script_code_pt) | |
771 ngx_stream_script_copy_capture_len_code; | |
772 code->n = 2 * n; | |
773 | |
774 | |
775 code = ngx_stream_script_add_code(*sc->values, | |
776 sizeof(ngx_stream_script_copy_capture_code_t), | |
777 &sc->main); | |
778 if (code == NULL) { | |
779 return NGX_ERROR; | |
780 } | |
781 | |
782 code->code = ngx_stream_script_copy_capture_code; | |
783 code->n = 2 * n; | |
784 | |
785 if (sc->ncaptures < n) { | |
786 sc->ncaptures = n; | |
787 } | |
788 | |
789 return NGX_OK; | |
790 } | |
791 | |
792 | |
793 size_t | |
794 ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e) | |
795 { | |
796 int *cap; | |
797 ngx_uint_t n; | |
798 ngx_stream_session_t *s; | |
799 ngx_stream_script_copy_capture_code_t *code; | |
800 | |
801 s = e->session; | |
802 | |
803 code = (ngx_stream_script_copy_capture_code_t *) e->ip; | |
804 | |
805 e->ip += sizeof(ngx_stream_script_copy_capture_code_t); | |
806 | |
807 n = code->n; | |
808 | |
809 if (n < s->ncaptures) { | |
810 cap = s->captures; | |
811 return cap[n + 1] - cap[n]; | |
812 } | |
813 | |
814 return 0; | |
815 } | |
816 | |
817 | |
818 void | |
819 ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e) | |
820 { | |
821 int *cap; | |
822 u_char *p, *pos; | |
823 ngx_uint_t n; | |
824 ngx_stream_session_t *s; | |
825 ngx_stream_script_copy_capture_code_t *code; | |
826 | |
827 s = e->session; | |
828 | |
829 code = (ngx_stream_script_copy_capture_code_t *) e->ip; | |
830 | |
831 e->ip += sizeof(ngx_stream_script_copy_capture_code_t); | |
832 | |
833 n = code->n; | |
834 | |
835 pos = e->pos; | |
836 | |
837 if (n < s->ncaptures) { | |
838 cap = s->captures; | |
839 p = s->captures_data; | |
840 e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]); | |
841 } | |
842 | |
843 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
844 "stream script capture: \"%*s\"", e->pos - pos, pos); | |
845 } | |
846 | |
847 #endif | |
848 | |
849 | |
850 static ngx_int_t | |
851 ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc) | |
852 { | |
853 ngx_stream_script_full_name_code_t *code; | |
854 | |
855 code = ngx_stream_script_add_code(*sc->lengths, | |
856 sizeof(ngx_stream_script_full_name_code_t), | |
857 NULL); | |
858 if (code == NULL) { | |
859 return NGX_ERROR; | |
860 } | |
861 | |
862 code->code = (ngx_stream_script_code_pt) | |
863 ngx_stream_script_full_name_len_code; | |
864 code->conf_prefix = sc->conf_prefix; | |
865 | |
866 code = ngx_stream_script_add_code(*sc->values, | |
867 sizeof(ngx_stream_script_full_name_code_t), &sc->main); | |
868 if (code == NULL) { | |
869 return NGX_ERROR; | |
870 } | |
871 | |
872 code->code = ngx_stream_script_full_name_code; | |
873 code->conf_prefix = sc->conf_prefix; | |
874 | |
875 return NGX_OK; | |
876 } | |
877 | |
878 | |
879 static size_t | |
880 ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e) | |
881 { | |
882 ngx_stream_script_full_name_code_t *code; | |
883 | |
884 code = (ngx_stream_script_full_name_code_t *) e->ip; | |
885 | |
886 e->ip += sizeof(ngx_stream_script_full_name_code_t); | |
887 | |
888 return code->conf_prefix ? ngx_cycle->conf_prefix.len: | |
889 ngx_cycle->prefix.len; | |
890 } | |
891 | |
892 | |
893 static void | |
894 ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e) | |
895 { | |
896 ngx_stream_script_full_name_code_t *code; | |
897 | |
898 ngx_str_t value, *prefix; | |
899 | |
900 code = (ngx_stream_script_full_name_code_t *) e->ip; | |
901 | |
902 value.data = e->buf.data; | |
903 value.len = e->pos - e->buf.data; | |
904 | |
905 prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix: | |
906 (ngx_str_t *) &ngx_cycle->prefix; | |
907 | |
908 if (ngx_get_full_name(e->session->connection->pool, prefix, &value) | |
909 != NGX_OK) | |
910 { | |
911 e->ip = ngx_stream_script_exit; | |
912 return; | |
913 } | |
914 | |
915 e->buf = value; | |
916 | |
917 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
918 "stream script fullname: \"%V\"", &value); | |
919 | |
920 e->ip += sizeof(ngx_stream_script_full_name_code_t); | |
921 } |