src/stream/ngx_stream_script.c - nginx-1.31.3 nginx/ @ 42f8df65b

Global variables defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_stream.h>


  8. static ngx_int_t ngx_stream_script_init_arrays(
  9.     ngx_stream_script_compile_t *sc);
  10. static ngx_int_t ngx_stream_script_done(ngx_stream_script_compile_t *sc);
  11. static ngx_int_t ngx_stream_script_add_copy_code(
  12.     ngx_stream_script_compile_t *sc, ngx_str_t *value, ngx_uint_t last);
  13. static ngx_int_t ngx_stream_script_add_var_code(
  14.     ngx_stream_script_compile_t *sc, ngx_str_t *name);
  15. #if (NGX_PCRE)
  16. static ngx_int_t ngx_stream_script_add_capture_code(
  17.     ngx_stream_script_compile_t *sc, ngx_uint_t n);
  18. #endif
  19. static ngx_int_t ngx_stream_script_add_full_name_code(
  20.     ngx_stream_script_compile_t *sc);
  21. static size_t ngx_stream_script_full_name_len_code(
  22.     ngx_stream_script_engine_t *e);
  23. static void ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e);


  24. #define ngx_stream_script_exit  (u_char *) &ngx_stream_script_exit_code

  25. static uintptr_t ngx_stream_script_exit_code = (uintptr_t) NULL;


  26. void
  27. ngx_stream_script_flush_complex_value(ngx_stream_session_t *s,
  28.     ngx_stream_complex_value_t *val)
  29. {
  30.     ngx_uint_t *index;

  31.     index = val->flushes;

  32.     if (index) {
  33.         while (*index != (ngx_uint_t) -1) {

  34.             if (s->variables[*index].no_cacheable) {
  35.                 s->variables[*index].valid = 0;
  36.                 s->variables[*index].not_found = 0;
  37.             }

  38.             index++;
  39.         }
  40.     }
  41. }


  42. ngx_int_t
  43. ngx_stream_complex_value(ngx_stream_session_t *s,
  44.     ngx_stream_complex_value_t *val, ngx_str_t *value)
  45. {
  46.     size_t                         len;
  47.     ngx_stream_script_code_pt      code;
  48.     ngx_stream_script_engine_t     e;
  49.     ngx_stream_script_len_code_pt  lcode;

  50.     if (val->lengths == NULL) {
  51.         *value = val->value;
  52.         return NGX_OK;
  53.     }

  54.     ngx_stream_script_flush_complex_value(s, val);

  55.     ngx_memzero(&e, sizeof(ngx_stream_script_engine_t));

  56.     e.ip = val->lengths;
  57.     e.session = s;
  58.     e.flushed = 1;

  59.     len = 0;

  60.     while (*(uintptr_t *) e.ip) {
  61.         lcode = *(ngx_stream_script_len_code_pt *) e.ip;
  62.         len += lcode(&e);
  63.     }

  64.     value->len = len;
  65.     value->data = ngx_pnalloc(s->connection->pool, len);
  66.     if (value->data == NULL) {
  67.         return NGX_ERROR;
  68.     }

  69.     e.ip = val->values;
  70.     e.pos = value->data;
  71.     e.buf = *value;

  72.     while (*(uintptr_t *) e.ip) {
  73.         code = *(ngx_stream_script_code_pt *) e.ip;
  74.         code((ngx_stream_script_engine_t *) &e);
  75.     }

  76.     *value = e.buf;

  77.     return NGX_OK;
  78. }


  79. size_t
  80. ngx_stream_complex_value_size(ngx_stream_session_t *s,
  81.     ngx_stream_complex_value_t *val, size_t default_value)
  82. {
  83.     size_t     size;
  84.     ngx_str_t  value;

  85.     if (val == NULL) {
  86.         return default_value;
  87.     }

  88.     if (val->lengths == NULL) {
  89.         return val->u.size;
  90.     }

  91.     if (ngx_stream_complex_value(s, val, &value) != NGX_OK) {
  92.         return default_value;
  93.     }

  94.     size = ngx_parse_size(&value);

  95.     if (size == (size_t) NGX_ERROR) {
  96.         ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
  97.                       "invalid size \"%V\"", &value);
  98.         return default_value;
  99.     }

  100.     return size;
  101. }


  102. ngx_int_t
  103. ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv)
  104. {
  105.     ngx_str_t                    *v;
  106.     ngx_uint_t                    i, n, nv, nc;
  107.     ngx_array_t                   flushes, lengths, values, *pf, *pl, *pv;
  108.     ngx_stream_script_compile_t   sc;

  109.     v = ccv->value;

  110.     nv = 0;
  111.     nc = 0;

  112.     for (i = 0; i < v->len; i++) {
  113.         if (v->data[i] == '$') {
  114.             if (i + 1 < v->len
  115.                 && v->data[i + 1] >= '1' && v->data[i + 1] <= '9')
  116.             {
  117.                 nc++;

  118.             } else {
  119.                 nv++;
  120.             }
  121.         }
  122.     }

  123.     if ((v->len == 0 || v->data[0] != '$')
  124.         && (ccv->conf_prefix || ccv->root_prefix))
  125.     {
  126.         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
  127.             return NGX_ERROR;
  128.         }

  129.         ccv->conf_prefix = 0;
  130.         ccv->root_prefix = 0;
  131.     }

  132.     ccv->complex_value->value = *v;
  133.     ccv->complex_value->flushes = NULL;
  134.     ccv->complex_value->lengths = NULL;
  135.     ccv->complex_value->values = NULL;

  136.     if (nv == 0 && nc == 0) {
  137.         return NGX_OK;
  138.     }

  139.     n = nv + 1;

  140.     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
  141.         != NGX_OK)
  142.     {
  143.         return NGX_ERROR;
  144.     }

  145.     n = nv * (2 * sizeof(ngx_stream_script_copy_code_t)
  146.                   + sizeof(ngx_stream_script_var_code_t))
  147.         + sizeof(uintptr_t);

  148.     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
  149.         return NGX_ERROR;
  150.     }

  151.     n = (nv * (2 * sizeof(ngx_stream_script_copy_code_t)
  152.                    + sizeof(ngx_stream_script_var_code_t))
  153.                 + sizeof(uintptr_t)
  154.                 + v->len
  155.                 + sizeof(uintptr_t) - 1)
  156.             & ~(sizeof(uintptr_t) - 1);

  157.     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
  158.         return NGX_ERROR;
  159.     }

  160.     pf = &flushes;
  161.     pl = &lengths;
  162.     pv = &values;

  163.     ngx_memzero(&sc, sizeof(ngx_stream_script_compile_t));

  164.     sc.cf = ccv->cf;
  165.     sc.source = v;
  166.     sc.flushes = &pf;
  167.     sc.lengths = &pl;
  168.     sc.values = &pv;
  169.     sc.complete_lengths = 1;
  170.     sc.complete_values = 1;
  171.     sc.zero = ccv->zero;
  172.     sc.conf_prefix = ccv->conf_prefix;
  173.     sc.root_prefix = ccv->root_prefix;

  174.     if (ngx_stream_script_compile(&sc) != NGX_OK) {
  175.         return NGX_ERROR;
  176.     }

  177.     if (flushes.nelts) {
  178.         ccv->complex_value->flushes = flushes.elts;
  179.         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
  180.     }

  181.     ccv->complex_value->lengths = lengths.elts;
  182.     ccv->complex_value->values = values.elts;

  183.     return NGX_OK;
  184. }


  185. char *
  186. ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  187.     void *conf)
  188. {
  189.     char  *p = conf;

  190.     ngx_str_t                            *value;
  191.     ngx_stream_complex_value_t          **cv;
  192.     ngx_stream_compile_complex_value_t    ccv;

  193.     cv = (ngx_stream_complex_value_t **) (p + cmd->offset);

  194.     if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
  195.         return "is duplicate";
  196.     }

  197.     *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
  198.     if (*cv == NULL) {
  199.         return NGX_CONF_ERROR;
  200.     }

  201.     value = cf->args->elts;

  202.     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));

  203.     ccv.cf = cf;
  204.     ccv.value = &value[1];
  205.     ccv.complex_value = *cv;

  206.     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
  207.         return NGX_CONF_ERROR;
  208.     }

  209.     return NGX_CONF_OK;
  210. }


  211. char *
  212. ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  213.     void *conf)
  214. {
  215.     char  *p = conf;

  216.     ngx_str_t                            *value;
  217.     ngx_stream_complex_value_t          **cv;
  218.     ngx_stream_compile_complex_value_t    ccv;

  219.     cv = (ngx_stream_complex_value_t **) (p + cmd->offset);

  220.     if (*cv != NGX_CONF_UNSET_PTR) {
  221.         return "is duplicate";
  222.     }

  223.     *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
  224.     if (*cv == NULL) {
  225.         return NGX_CONF_ERROR;
  226.     }

  227.     value = cf->args->elts;

  228.     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));

  229.     ccv.cf = cf;
  230.     ccv.value = &value[1];
  231.     ccv.complex_value = *cv;
  232.     ccv.zero = 1;

  233.     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
  234.         return NGX_CONF_ERROR;
  235.     }

  236.     return NGX_CONF_OK;
  237. }


  238. char *
  239. ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  240.     void *conf)
  241. {
  242.     char  *p = conf;

  243.     char                        *rv;
  244.     ngx_stream_complex_value_t  *cv;

  245.     rv = ngx_stream_set_complex_value_slot(cf, cmd, conf);

  246.     if (rv != NGX_CONF_OK) {
  247.         return rv;
  248.     }

  249.     cv = *(ngx_stream_complex_value_t **) (p + cmd->offset);

  250.     if (cv->lengths) {
  251.         return NGX_CONF_OK;
  252.     }

  253.     cv->u.size = ngx_parse_size(&cv->value);
  254.     if (cv->u.size == (size_t) NGX_ERROR) {
  255.         return "invalid value";
  256.     }

  257.     return NGX_CONF_OK;
  258. }


  259. ngx_uint_t
  260. ngx_stream_script_variables_count(ngx_str_t *value)
  261. {
  262.     ngx_uint_t  i, n;

  263.     for (n = 0, i = 0; i < value->len; i++) {
  264.         if (value->data[i] == '$') {
  265.             n++;
  266.         }
  267.     }

  268.     return n;
  269. }


  270. ngx_int_t
  271. ngx_stream_script_compile(ngx_stream_script_compile_t *sc)
  272. {
  273.     u_char       ch;
  274.     ngx_str_t    name;
  275.     ngx_uint_t   i, bracket;

  276.     if (ngx_stream_script_init_arrays(sc) != NGX_OK) {
  277.         return NGX_ERROR;
  278.     }

  279.     for (i = 0; i < sc->source->len; /* void */ ) {

  280.         name.len = 0;

  281.         if (sc->source->data[i] == '$') {

  282.             if (++i == sc->source->len) {
  283.                 goto invalid_variable;
  284.             }

  285.             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
  286. #if (NGX_PCRE)
  287.                 ngx_uint_t  n;

  288.                 n = sc->source->data[i] - '0';

  289.                 if (ngx_stream_script_add_capture_code(sc, n) != NGX_OK) {
  290.                     return NGX_ERROR;
  291.                 }

  292.                 i++;

  293.                 continue;
  294. #else
  295.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  296.                                    "using variable \"$%c\" requires "
  297.                                    "PCRE library", sc->source->data[i]);
  298.                 return NGX_ERROR;
  299. #endif
  300.             }

  301.             if (sc->source->data[i] == '{') {
  302.                 bracket = 1;

  303.                 if (++i == sc->source->len) {
  304.                     goto invalid_variable;
  305.                 }

  306.                 name.data = &sc->source->data[i];

  307.             } else {
  308.                 bracket = 0;
  309.                 name.data = &sc->source->data[i];
  310.             }

  311.             for ( /* void */ ; i < sc->source->len; i++, name.len++) {
  312.                 ch = sc->source->data[i];

  313.                 if (ch == '}' && bracket) {
  314.                     i++;
  315.                     bracket = 0;
  316.                     break;
  317.                 }

  318.                 if ((ch >= 'A' && ch <= 'Z')
  319.                     || (ch >= 'a' && ch <= 'z')
  320.                     || (ch >= '0' && ch <= '9')
  321.                     || ch == '_')
  322.                 {
  323.                     continue;
  324.                 }

  325.                 break;
  326.             }

  327.             if (bracket) {
  328.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  329.                                    "the closing bracket in \"%V\" "
  330.                                    "variable is missing", &name);
  331.                 return NGX_ERROR;
  332.             }

  333.             if (name.len == 0) {
  334.                 goto invalid_variable;
  335.             }

  336.             sc->variables++;

  337.             if (ngx_stream_script_add_var_code(sc, &name) != NGX_OK) {
  338.                 return NGX_ERROR;
  339.             }

  340.             continue;
  341.         }

  342.         name.data = &sc->source->data[i];

  343.         while (i < sc->source->len) {

  344.             if (sc->source->data[i] == '$') {
  345.                 break;
  346.             }

  347.             i++;
  348.             name.len++;
  349.         }

  350.         sc->size += name.len;

  351.         if (ngx_stream_script_add_copy_code(sc, &name, (i == sc->source->len))
  352.             != NGX_OK)
  353.         {
  354.             return NGX_ERROR;
  355.         }
  356.     }

  357.     return ngx_stream_script_done(sc);

  358. invalid_variable:

  359.     ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");

  360.     return NGX_ERROR;
  361. }


  362. u_char *
  363. ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value,
  364.     void *code_lengths, size_t len, void *code_values)
  365. {
  366.     ngx_uint_t                      i;
  367.     ngx_stream_script_code_pt       code;
  368.     ngx_stream_script_engine_t      e;
  369.     ngx_stream_core_main_conf_t    *cmcf;
  370.     ngx_stream_script_len_code_pt   lcode;

  371.     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

  372.     for (i = 0; i < cmcf->variables.nelts; i++) {
  373.         if (s->variables[i].no_cacheable) {
  374.             s->variables[i].valid = 0;
  375.             s->variables[i].not_found = 0;
  376.         }
  377.     }

  378.     ngx_memzero(&e, sizeof(ngx_stream_script_engine_t));

  379.     e.ip = code_lengths;
  380.     e.session = s;
  381.     e.flushed = 1;

  382.     while (*(uintptr_t *) e.ip) {
  383.         lcode = *(ngx_stream_script_len_code_pt *) e.ip;
  384.         len += lcode(&e);
  385.     }


  386.     value->len = len;
  387.     value->data = ngx_pnalloc(s->connection->pool, len);
  388.     if (value->data == NULL) {
  389.         return NULL;
  390.     }

  391.     e.ip = code_values;
  392.     e.pos = value->data;

  393.     while (*(uintptr_t *) e.ip) {
  394.         code = *(ngx_stream_script_code_pt *) e.ip;
  395.         code((ngx_stream_script_engine_t *) &e);
  396.     }

  397.     return e.pos;
  398. }


  399. void
  400. ngx_stream_script_flush_no_cacheable_variables(ngx_stream_session_t *s,
  401.     ngx_array_t *indices)
  402. {
  403.     ngx_uint_t  n, *index;

  404.     if (indices) {
  405.         index = indices->elts;
  406.         for (n = 0; n < indices->nelts; n++) {
  407.             if (s->variables[index[n]].no_cacheable) {
  408.                 s->variables[index[n]].valid = 0;
  409.                 s->variables[index[n]].not_found = 0;
  410.             }
  411.         }
  412.     }
  413. }


  414. static ngx_int_t
  415. ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc)
  416. {
  417.     ngx_uint_t   n;

  418.     if (sc->flushes && *sc->flushes == NULL) {
  419.         n = sc->variables ? sc->variables : 1;
  420.         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
  421.         if (*sc->flushes == NULL) {
  422.             return NGX_ERROR;
  423.         }
  424.     }

  425.     if (*sc->lengths == NULL) {
  426.         n = sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
  427.                              + sizeof(ngx_stream_script_var_code_t))
  428.             + sizeof(uintptr_t);

  429.         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
  430.         if (*sc->lengths == NULL) {
  431.             return NGX_ERROR;
  432.         }
  433.     }

  434.     if (*sc->values == NULL) {
  435.         n = (sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
  436.                               + sizeof(ngx_stream_script_var_code_t))
  437.                 + sizeof(uintptr_t)
  438.                 + sc->source->len
  439.                 + sizeof(uintptr_t) - 1)
  440.             & ~(sizeof(uintptr_t) - 1);

  441.         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
  442.         if (*sc->values == NULL) {
  443.             return NGX_ERROR;
  444.         }
  445.     }

  446.     sc->variables = 0;

  447.     return NGX_OK;
  448. }


  449. static ngx_int_t
  450. ngx_stream_script_done(ngx_stream_script_compile_t *sc)
  451. {
  452.     ngx_str_t    zero;
  453.     uintptr_t   *code;

  454.     if (sc->zero) {

  455.         zero.len = 1;
  456.         zero.data = (u_char *) "\0";

  457.         if (ngx_stream_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
  458.             return NGX_ERROR;
  459.         }
  460.     }

  461.     if (sc->conf_prefix || sc->root_prefix) {
  462.         if (ngx_stream_script_add_full_name_code(sc) != NGX_OK) {
  463.             return NGX_ERROR;
  464.         }
  465.     }

  466.     if (sc->complete_lengths) {
  467.         code = ngx_stream_script_add_code(*sc->lengths, sizeof(uintptr_t),
  468.                                           NULL);
  469.         if (code == NULL) {
  470.             return NGX_ERROR;
  471.         }

  472.         *code = (uintptr_t) NULL;
  473.     }

  474.     if (sc->complete_values) {
  475.         code = ngx_stream_script_add_code(*sc->values, sizeof(uintptr_t),
  476.                                           &sc->main);
  477.         if (code == NULL) {
  478.             return NGX_ERROR;
  479.         }

  480.         *code = (uintptr_t) NULL;
  481.     }

  482.     return NGX_OK;
  483. }


  484. void *
  485. ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code)
  486. {
  487.     u_char  *elts, **p;
  488.     void    *new;

  489.     elts = codes->elts;

  490.     new = ngx_array_push_n(codes, size);
  491.     if (new == NULL) {
  492.         return NULL;
  493.     }

  494.     if (code) {
  495.         if (elts != codes->elts) {
  496.             p = code;
  497.             *p += (u_char *) codes->elts - elts;
  498.         }
  499.     }

  500.     return new;
  501. }


  502. static ngx_int_t
  503. ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc,
  504.     ngx_str_t *value, ngx_uint_t last)
  505. {
  506.     u_char                         *p;
  507.     size_t                          size, len, zero;
  508.     ngx_stream_script_copy_code_t  *code;

  509.     zero = (sc->zero && last);
  510.     len = value->len + zero;

  511.     code = ngx_stream_script_add_code(*sc->lengths,
  512.                                       sizeof(ngx_stream_script_copy_code_t),
  513.                                       NULL);
  514.     if (code == NULL) {
  515.         return NGX_ERROR;
  516.     }

  517.     code->code = (ngx_stream_script_code_pt) (void *)
  518.                                                ngx_stream_script_copy_len_code;
  519.     code->len = len;

  520.     size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  521.             & ~(sizeof(uintptr_t) - 1);

  522.     code = ngx_stream_script_add_code(*sc->values, size, &sc->main);
  523.     if (code == NULL) {
  524.         return NGX_ERROR;
  525.     }

  526.     code->code = ngx_stream_script_copy_code;
  527.     code->len = len;

  528.     p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t),
  529.                    value->data, value->len);

  530.     if (zero) {
  531.         *p = '\0';
  532.         sc->zero = 0;
  533.     }

  534.     return NGX_OK;
  535. }


  536. size_t
  537. ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e)
  538. {
  539.     ngx_stream_script_copy_code_t  *code;

  540.     code = (ngx_stream_script_copy_code_t *) e->ip;

  541.     e->ip += sizeof(ngx_stream_script_copy_code_t);

  542.     return code->len;
  543. }


  544. void
  545. ngx_stream_script_copy_code(ngx_stream_script_engine_t *e)
  546. {
  547.     u_char                         *p;
  548.     ngx_stream_script_copy_code_t  *code;

  549.     code = (ngx_stream_script_copy_code_t *) e->ip;

  550.     p = e->pos;

  551.     if (!e->skip) {
  552.         e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t),
  553.                           code->len);
  554.     }

  555.     e->ip += sizeof(ngx_stream_script_copy_code_t)
  556.           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));

  557.     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
  558.                    "stream script copy: \"%*s\"", e->pos - p, p);
  559. }


  560. static ngx_int_t
  561. ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name)
  562. {
  563.     ngx_int_t                      index, *p;
  564.     ngx_stream_script_var_code_t  *code;

  565.     index = ngx_stream_get_variable_index(sc->cf, name);

  566.     if (index == NGX_ERROR) {
  567.         return NGX_ERROR;
  568.     }

  569.     if (sc->flushes) {
  570.         p = ngx_array_push(*sc->flushes);
  571.         if (p == NULL) {
  572.             return NGX_ERROR;
  573.         }

  574.         *p = index;
  575.     }

  576.     code = ngx_stream_script_add_code(*sc->lengths,
  577.                                       sizeof(ngx_stream_script_var_code_t),
  578.                                       NULL);
  579.     if (code == NULL) {
  580.         return NGX_ERROR;
  581.     }

  582.     code->code = (ngx_stream_script_code_pt) (void *)
  583.                                            ngx_stream_script_copy_var_len_code;
  584.     code->index = (uintptr_t) index;

  585.     code = ngx_stream_script_add_code(*sc->values,
  586.                                       sizeof(ngx_stream_script_var_code_t),
  587.                                       &sc->main);
  588.     if (code == NULL) {
  589.         return NGX_ERROR;
  590.     }

  591.     code->code = ngx_stream_script_copy_var_code;
  592.     code->index = (uintptr_t) index;

  593.     return NGX_OK;
  594. }


  595. size_t
  596. ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e)
  597. {
  598.     ngx_stream_variable_value_t   *value;
  599.     ngx_stream_script_var_code_t  *code;

  600.     code = (ngx_stream_script_var_code_t *) e->ip;

  601.     e->ip += sizeof(ngx_stream_script_var_code_t);

  602.     if (e->flushed) {
  603.         value = ngx_stream_get_indexed_variable(e->session, code->index);

  604.     } else {
  605.         value = ngx_stream_get_flushed_variable(e->session, code->index);
  606.     }

  607.     if (value && !value->not_found) {
  608.         return value->len;
  609.     }

  610.     return 0;
  611. }


  612. void
  613. ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e)
  614. {
  615.     u_char                        *p;
  616.     ngx_stream_variable_value_t   *value;
  617.     ngx_stream_script_var_code_t  *code;

  618.     code = (ngx_stream_script_var_code_t *) e->ip;

  619.     e->ip += sizeof(ngx_stream_script_var_code_t);

  620.     if (!e->skip) {

  621.         if (e->flushed) {
  622.             value = ngx_stream_get_indexed_variable(e->session, code->index);

  623.         } else {
  624.             value = ngx_stream_get_flushed_variable(e->session, code->index);
  625.         }

  626.         if (value && !value->not_found) {
  627.             p = e->pos;
  628.             e->pos = ngx_copy(p, value->data, value->len);

  629.             ngx_log_debug2(NGX_LOG_DEBUG_STREAM,
  630.                            e->session->connection->log, 0,
  631.                            "stream script var: \"%*s\"", e->pos - p, p);
  632.         }
  633.     }
  634. }


  635. #if (NGX_PCRE)

  636. static ngx_int_t
  637. ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc,
  638.     ngx_uint_t n)
  639. {
  640.     ngx_stream_script_copy_capture_code_t  *code;

  641.     code = ngx_stream_script_add_code(*sc->lengths,
  642.                                   sizeof(ngx_stream_script_copy_capture_code_t),
  643.                                   NULL);
  644.     if (code == NULL) {
  645.         return NGX_ERROR;
  646.     }

  647.     code->code = (ngx_stream_script_code_pt) (void *)
  648.                                        ngx_stream_script_copy_capture_len_code;
  649.     code->n = 2 * n;


  650.     code = ngx_stream_script_add_code(*sc->values,
  651.                                   sizeof(ngx_stream_script_copy_capture_code_t),
  652.                                   &sc->main);
  653.     if (code == NULL) {
  654.         return NGX_ERROR;
  655.     }

  656.     code->code = ngx_stream_script_copy_capture_code;
  657.     code->n = 2 * n;

  658.     if (sc->ncaptures < n) {
  659.         sc->ncaptures = n;
  660.     }

  661.     return NGX_OK;
  662. }


  663. size_t
  664. ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e)
  665. {
  666.     int                                    *cap;
  667.     ngx_uint_t                              n;
  668.     ngx_stream_session_t                   *s;
  669.     ngx_stream_script_copy_capture_code_t  *code;

  670.     s = e->session;

  671.     code = (ngx_stream_script_copy_capture_code_t *) e->ip;

  672.     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);

  673.     n = code->n;

  674.     if (n < s->ncaptures) {
  675.         cap = s->captures;
  676.         return cap[n + 1] - cap[n];
  677.     }

  678.     return 0;
  679. }


  680. void
  681. ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e)
  682. {
  683.     int                                    *cap;
  684.     u_char                                 *p, *pos;
  685.     ngx_uint_t                              n;
  686.     ngx_stream_session_t                   *s;
  687.     ngx_stream_script_copy_capture_code_t  *code;

  688.     s = e->session;

  689.     code = (ngx_stream_script_copy_capture_code_t *) e->ip;

  690.     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);

  691.     n = code->n;

  692.     pos = e->pos;

  693.     if (n < s->ncaptures) {
  694.         cap = s->captures;
  695.         p = s->captures_data;
  696.         e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
  697.     }

  698.     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
  699.                    "stream script capture: \"%*s\"", e->pos - pos, pos);
  700. }

  701. #endif


  702. static ngx_int_t
  703. ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
  704. {
  705.     ngx_stream_script_full_name_code_t  *code;

  706.     code = ngx_stream_script_add_code(*sc->lengths,
  707.                                     sizeof(ngx_stream_script_full_name_code_t),
  708.                                     NULL);
  709.     if (code == NULL) {
  710.         return NGX_ERROR;
  711.     }

  712.     code->code = (ngx_stream_script_code_pt) (void *)
  713.                                           ngx_stream_script_full_name_len_code;
  714.     code->conf_prefix = sc->conf_prefix;

  715.     code = ngx_stream_script_add_code(*sc->values,
  716.                         sizeof(ngx_stream_script_full_name_code_t), &sc->main);
  717.     if (code == NULL) {
  718.         return NGX_ERROR;
  719.     }

  720.     code->code = ngx_stream_script_full_name_code;
  721.     code->conf_prefix = sc->conf_prefix;

  722.     return NGX_OK;
  723. }


  724. static size_t
  725. ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e)
  726. {
  727.     ngx_stream_script_full_name_code_t  *code;

  728.     code = (ngx_stream_script_full_name_code_t *) e->ip;

  729.     e->ip += sizeof(ngx_stream_script_full_name_code_t);

  730.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  731.                                ngx_cycle->prefix.len;
  732. }


  733. static void
  734. ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e)
  735. {
  736.     ngx_stream_script_full_name_code_t  *code;

  737.     ngx_str_t  value, *prefix;

  738.     code = (ngx_stream_script_full_name_code_t *) e->ip;

  739.     value.data = e->buf.data;
  740.     value.len = e->pos - e->buf.data;

  741.     prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
  742.                                  (ngx_str_t *) &ngx_cycle->prefix;

  743.     if (ngx_get_full_name(e->session->connection->pool, prefix, &value)
  744.         != NGX_OK)
  745.     {
  746.         e->ip = ngx_stream_script_exit;
  747.         return;
  748.     }

  749.     e->buf = value;

  750.     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
  751.                    "stream script fullname: \"%V\"", &value);

  752.     e->ip += sizeof(ngx_stream_script_full_name_code_t);
  753. }