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
13static ngx_int_t ngx_stream_script_init_arrays(
14    ngx_stream_script_compile_t *sc);
15static ngx_int_t ngx_stream_script_done(ngx_stream_script_compile_t *sc);
16static ngx_int_t ngx_stream_script_add_copy_code(
17    ngx_stream_script_compile_t *sc, ngx_str_t *value, ngx_uint_t last);
18static ngx_int_t ngx_stream_script_add_var_code(
19    ngx_stream_script_compile_t *sc, ngx_str_t *name);
20#if (NGX_PCRE)
21static ngx_int_t ngx_stream_script_add_capture_code(
22    ngx_stream_script_compile_t *sc, ngx_uint_t n);
23#endif
24static ngx_int_t ngx_stream_script_add_full_name_code(
25    ngx_stream_script_compile_t *sc);
26static size_t ngx_stream_script_full_name_len_code(
27    ngx_stream_script_engine_t *e);
28static 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
33static uintptr_t ngx_stream_script_exit_code = (uintptr_t) NULL;
34
35
36void
37ngx_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
58ngx_int_t
59ngx_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
108ngx_int_t
109ngx_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
212char *
213ngx_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) {
225        return "is duplicate";
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
249ngx_uint_t
250ngx_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
264ngx_int_t
265ngx_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
285            if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
286#if (NGX_PCRE)
287                ngx_uint_t  n;
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;
298#else
299                ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
300                                   "using variable \"$%c\" requires "
301                                   "PCRE library", sc->source->data[i]);
302                return NGX_ERROR;
303#endif
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
383invalid_variable:
384
385    ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
386
387    return NGX_ERROR;
388}
389
390
391u_char *
392ngx_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
440void
441ngx_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
458static ngx_int_t
459ngx_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
502static ngx_int_t
503ngx_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
548void *
549ngx_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
572static ngx_int_t
573ngx_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
616size_t
617ngx_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
629void
630ngx_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
652static ngx_int_t
653ngx_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
698size_t
699ngx_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
723void
724ngx_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
757static ngx_int_t
758ngx_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
793size_t
794ngx_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
818void
819ngx_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
850static ngx_int_t
851ngx_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
879static size_t
880ngx_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
893static void
894ngx_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}
922