Mercurial > hg > nginx
annotate src/stream/ngx_stream_script.c @ 7349:f6047a579ca1
gRPC: improved keepalive handling.
The code is now able to parse additional control frames after
the response is received, and can send control frames as well.
This fixes keepalive problems as observed with grpc-c, which can
send window update and ping frames after the response, see
http://mailman.nginx.org/pipermail/nginx/2018-August/056620.html.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 03 Sep 2018 19:34:01 +0300 |
parents | 9e25a5380a21 |
children | b82162b8496a |
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 | |
7271
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
590 code->code = (ngx_stream_script_code_pt) (void *) |
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
591 ngx_stream_script_copy_len_code; |
6607 | 592 code->len = len; |
593 | |
594 size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1) | |
595 & ~(sizeof(uintptr_t) - 1); | |
596 | |
597 code = ngx_stream_script_add_code(*sc->values, size, &sc->main); | |
598 if (code == NULL) { | |
599 return NGX_ERROR; | |
600 } | |
601 | |
602 code->code = ngx_stream_script_copy_code; | |
603 code->len = len; | |
604 | |
605 p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t), | |
606 value->data, value->len); | |
607 | |
608 if (zero) { | |
609 *p = '\0'; | |
610 sc->zero = 0; | |
611 } | |
612 | |
613 return NGX_OK; | |
614 } | |
615 | |
616 | |
617 size_t | |
618 ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e) | |
619 { | |
620 ngx_stream_script_copy_code_t *code; | |
621 | |
622 code = (ngx_stream_script_copy_code_t *) e->ip; | |
623 | |
624 e->ip += sizeof(ngx_stream_script_copy_code_t); | |
625 | |
626 return code->len; | |
627 } | |
628 | |
629 | |
630 void | |
631 ngx_stream_script_copy_code(ngx_stream_script_engine_t *e) | |
632 { | |
633 u_char *p; | |
634 ngx_stream_script_copy_code_t *code; | |
635 | |
636 code = (ngx_stream_script_copy_code_t *) e->ip; | |
637 | |
638 p = e->pos; | |
639 | |
640 if (!e->skip) { | |
641 e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t), | |
642 code->len); | |
643 } | |
644 | |
645 e->ip += sizeof(ngx_stream_script_copy_code_t) | |
646 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); | |
647 | |
648 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
649 "stream script copy: \"%*s\"", e->pos - p, p); | |
650 } | |
651 | |
652 | |
653 static ngx_int_t | |
654 ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name) | |
655 { | |
656 ngx_int_t index, *p; | |
657 ngx_stream_script_var_code_t *code; | |
658 | |
659 index = ngx_stream_get_variable_index(sc->cf, name); | |
660 | |
661 if (index == NGX_ERROR) { | |
662 return NGX_ERROR; | |
663 } | |
664 | |
665 if (sc->flushes) { | |
666 p = ngx_array_push(*sc->flushes); | |
667 if (p == NULL) { | |
668 return NGX_ERROR; | |
669 } | |
670 | |
671 *p = index; | |
672 } | |
673 | |
674 code = ngx_stream_script_add_code(*sc->lengths, | |
675 sizeof(ngx_stream_script_var_code_t), | |
676 NULL); | |
677 if (code == NULL) { | |
678 return NGX_ERROR; | |
679 } | |
680 | |
7271
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
681 code->code = (ngx_stream_script_code_pt) (void *) |
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
682 ngx_stream_script_copy_var_len_code; |
6607 | 683 code->index = (uintptr_t) index; |
684 | |
685 code = ngx_stream_script_add_code(*sc->values, | |
686 sizeof(ngx_stream_script_var_code_t), | |
687 &sc->main); | |
688 if (code == NULL) { | |
689 return NGX_ERROR; | |
690 } | |
691 | |
692 code->code = ngx_stream_script_copy_var_code; | |
693 code->index = (uintptr_t) index; | |
694 | |
695 return NGX_OK; | |
696 } | |
697 | |
698 | |
699 size_t | |
700 ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e) | |
701 { | |
702 ngx_stream_variable_value_t *value; | |
703 ngx_stream_script_var_code_t *code; | |
704 | |
705 code = (ngx_stream_script_var_code_t *) e->ip; | |
706 | |
707 e->ip += sizeof(ngx_stream_script_var_code_t); | |
708 | |
709 if (e->flushed) { | |
710 value = ngx_stream_get_indexed_variable(e->session, code->index); | |
711 | |
712 } else { | |
713 value = ngx_stream_get_flushed_variable(e->session, code->index); | |
714 } | |
715 | |
716 if (value && !value->not_found) { | |
717 return value->len; | |
718 } | |
719 | |
720 return 0; | |
721 } | |
722 | |
723 | |
724 void | |
725 ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e) | |
726 { | |
727 u_char *p; | |
728 ngx_stream_variable_value_t *value; | |
729 ngx_stream_script_var_code_t *code; | |
730 | |
731 code = (ngx_stream_script_var_code_t *) e->ip; | |
732 | |
733 e->ip += sizeof(ngx_stream_script_var_code_t); | |
734 | |
735 if (!e->skip) { | |
736 | |
737 if (e->flushed) { | |
738 value = ngx_stream_get_indexed_variable(e->session, code->index); | |
739 | |
740 } else { | |
741 value = ngx_stream_get_flushed_variable(e->session, code->index); | |
742 } | |
743 | |
744 if (value && !value->not_found) { | |
745 p = e->pos; | |
746 e->pos = ngx_copy(p, value->data, value->len); | |
747 | |
748 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, | |
749 e->session->connection->log, 0, | |
750 "stream script var: \"%*s\"", e->pos - p, p); | |
751 } | |
752 } | |
753 } | |
754 | |
755 | |
756 #if (NGX_PCRE) | |
757 | |
758 static ngx_int_t | |
759 ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc, | |
760 ngx_uint_t n) | |
761 { | |
762 ngx_stream_script_copy_capture_code_t *code; | |
763 | |
764 code = ngx_stream_script_add_code(*sc->lengths, | |
765 sizeof(ngx_stream_script_copy_capture_code_t), | |
766 NULL); | |
767 if (code == NULL) { | |
768 return NGX_ERROR; | |
769 } | |
770 | |
7271
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
771 code->code = (ngx_stream_script_code_pt) (void *) |
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
772 ngx_stream_script_copy_capture_len_code; |
6607 | 773 code->n = 2 * n; |
774 | |
775 | |
776 code = ngx_stream_script_add_code(*sc->values, | |
777 sizeof(ngx_stream_script_copy_capture_code_t), | |
778 &sc->main); | |
779 if (code == NULL) { | |
780 return NGX_ERROR; | |
781 } | |
782 | |
783 code->code = ngx_stream_script_copy_capture_code; | |
784 code->n = 2 * n; | |
785 | |
786 if (sc->ncaptures < n) { | |
787 sc->ncaptures = n; | |
788 } | |
789 | |
790 return NGX_OK; | |
791 } | |
792 | |
793 | |
794 size_t | |
795 ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e) | |
796 { | |
797 int *cap; | |
798 ngx_uint_t n; | |
799 ngx_stream_session_t *s; | |
800 ngx_stream_script_copy_capture_code_t *code; | |
801 | |
802 s = e->session; | |
803 | |
804 code = (ngx_stream_script_copy_capture_code_t *) e->ip; | |
805 | |
806 e->ip += sizeof(ngx_stream_script_copy_capture_code_t); | |
807 | |
808 n = code->n; | |
809 | |
810 if (n < s->ncaptures) { | |
811 cap = s->captures; | |
812 return cap[n + 1] - cap[n]; | |
813 } | |
814 | |
815 return 0; | |
816 } | |
817 | |
818 | |
819 void | |
820 ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e) | |
821 { | |
822 int *cap; | |
823 u_char *p, *pos; | |
824 ngx_uint_t n; | |
825 ngx_stream_session_t *s; | |
826 ngx_stream_script_copy_capture_code_t *code; | |
827 | |
828 s = e->session; | |
829 | |
830 code = (ngx_stream_script_copy_capture_code_t *) e->ip; | |
831 | |
832 e->ip += sizeof(ngx_stream_script_copy_capture_code_t); | |
833 | |
834 n = code->n; | |
835 | |
836 pos = e->pos; | |
837 | |
838 if (n < s->ncaptures) { | |
839 cap = s->captures; | |
840 p = s->captures_data; | |
841 e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]); | |
842 } | |
843 | |
844 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
845 "stream script capture: \"%*s\"", e->pos - pos, pos); | |
846 } | |
847 | |
848 #endif | |
849 | |
850 | |
851 static ngx_int_t | |
852 ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc) | |
853 { | |
854 ngx_stream_script_full_name_code_t *code; | |
855 | |
856 code = ngx_stream_script_add_code(*sc->lengths, | |
857 sizeof(ngx_stream_script_full_name_code_t), | |
858 NULL); | |
859 if (code == NULL) { | |
860 return NGX_ERROR; | |
861 } | |
862 | |
7271
9e25a5380a21
Silenced -Wcast-function-type warnings (closes #1546).
Sergey Kandaurov <pluknet@nginx.com>
parents:
6940
diff
changeset
|
863 code->code = (ngx_stream_script_code_pt) (void *) |
6607 | 864 ngx_stream_script_full_name_len_code; |
865 code->conf_prefix = sc->conf_prefix; | |
866 | |
867 code = ngx_stream_script_add_code(*sc->values, | |
868 sizeof(ngx_stream_script_full_name_code_t), &sc->main); | |
869 if (code == NULL) { | |
870 return NGX_ERROR; | |
871 } | |
872 | |
873 code->code = ngx_stream_script_full_name_code; | |
874 code->conf_prefix = sc->conf_prefix; | |
875 | |
876 return NGX_OK; | |
877 } | |
878 | |
879 | |
880 static size_t | |
881 ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e) | |
882 { | |
883 ngx_stream_script_full_name_code_t *code; | |
884 | |
885 code = (ngx_stream_script_full_name_code_t *) e->ip; | |
886 | |
887 e->ip += sizeof(ngx_stream_script_full_name_code_t); | |
888 | |
889 return code->conf_prefix ? ngx_cycle->conf_prefix.len: | |
890 ngx_cycle->prefix.len; | |
891 } | |
892 | |
893 | |
894 static void | |
895 ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e) | |
896 { | |
897 ngx_stream_script_full_name_code_t *code; | |
898 | |
899 ngx_str_t value, *prefix; | |
900 | |
901 code = (ngx_stream_script_full_name_code_t *) e->ip; | |
902 | |
903 value.data = e->buf.data; | |
904 value.len = e->pos - e->buf.data; | |
905 | |
906 prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix: | |
907 (ngx_str_t *) &ngx_cycle->prefix; | |
908 | |
909 if (ngx_get_full_name(e->session->connection->pool, prefix, &value) | |
910 != NGX_OK) | |
911 { | |
912 e->ip = ngx_stream_script_exit; | |
913 return; | |
914 } | |
915 | |
916 e->buf = value; | |
917 | |
918 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, | |
919 "stream script fullname: \"%V\"", &value); | |
920 | |
921 e->ip += sizeof(ngx_stream_script_full_name_code_t); | |
922 } |