src/stream/ngx_stream_script.c - nginx source code

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 (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
  115.                 nc++;

  116.             } else {
  117.                 nv++;
  118.             }
  119.         }
  120.     }

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

  127.         ccv->conf_prefix = 0;
  128.         ccv->root_prefix = 0;
  129.     }

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

  134.     if (nv == 0 && nc == 0) {
  135.         return NGX_OK;
  136.     }

  137.     n = nv + 1;

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

  143.     n = nv * (2 * sizeof(ngx_stream_script_copy_code_t)
  144.                   + sizeof(ngx_stream_script_var_code_t))
  145.         + sizeof(uintptr_t);

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

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

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

  158.     pf = &flushes;
  159.     pl = &lengths;
  160.     pv = &values;

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

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

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

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

  179.     ccv->complex_value->lengths = lengths.elts;
  180.     ccv->complex_value->values = values.elts;

  181.     return NGX_OK;
  182. }


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

  188.     ngx_str_t                            *value;
  189.     ngx_stream_complex_value_t          **cv;
  190.     ngx_stream_compile_complex_value_t    ccv;

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

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

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

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

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

  201.     ccv.cf = cf;
  202.     ccv.value = &value[1];
  203.     ccv.complex_value = *cv;

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

  207.     return NGX_CONF_OK;
  208. }


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

  214.     ngx_str_t                            *value;
  215.     ngx_stream_complex_value_t          **cv;
  216.     ngx_stream_compile_complex_value_t    ccv;

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

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

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

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

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

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

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

  234.     return NGX_CONF_OK;
  235. }


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

  241.     char                        *rv;
  242.     ngx_stream_complex_value_t  *cv;

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

  244.     if (rv != NGX_CONF_OK) {
  245.         return rv;
  246.     }

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

  248.     if (cv->lengths) {
  249.         return NGX_CONF_OK;
  250.     }

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

  255.     return NGX_CONF_OK;
  256. }


  257. ngx_uint_t
  258. ngx_stream_script_variables_count(ngx_str_t *value)
  259. {
  260.     ngx_uint_t  i, n;

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

  266.     return n;
  267. }


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

  274.     if (ngx_stream_script_init_arrays(sc) != NGX_OK) {
  275.         return NGX_ERROR;
  276.     }

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

  278.         name.len = 0;

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

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

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

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

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

  290.                 i++;

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

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

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

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

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

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

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

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

  323.                 break;
  324.             }

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

  331.             if (name.len == 0) {
  332.                 goto invalid_variable;
  333.             }

  334.             sc->variables++;

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

  338.             continue;
  339.         }

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

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

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

  345.             i++;
  346.             name.len++;
  347.         }

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

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

  355.     return ngx_stream_script_done(sc);

  356. invalid_variable:

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

  358.     return NGX_ERROR;
  359. }


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

  369.     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

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

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

  377.     e.ip = code_lengths;
  378.     e.session = s;
  379.     e.flushed = 1;

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


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

  389.     e.ip = code_values;
  390.     e.pos = value->data;

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

  395.     return e.pos;
  396. }


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

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


  412. static ngx_int_t
  413. ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc)
  414. {
  415.     ngx_uint_t   n;

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

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

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

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

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

  444.     sc->variables = 0;

  445.     return NGX_OK;
  446. }


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

  452.     if (sc->zero) {

  453.         zero.len = 1;
  454.         zero.data = (u_char *) "\0";

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

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

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

  470.         *code = (uintptr_t) NULL;
  471.     }

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

  478.         *code = (uintptr_t) NULL;
  479.     }

  480.     return NGX_OK;
  481. }


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

  487.     elts = codes->elts;

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

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

  498.     return new;
  499. }


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

  507.     zero = (sc->zero && last);
  508.     len = value->len + zero;

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

  515.     code->code = (ngx_stream_script_code_pt) (void *)
  516.                                                ngx_stream_script_copy_len_code;
  517.     code->len = len;

  518.     size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  519.             & ~(sizeof(uintptr_t) - 1);

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

  524.     code->code = ngx_stream_script_copy_code;
  525.     code->len = len;

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

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

  532.     return NGX_OK;
  533. }


  534. size_t
  535. ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e)
  536. {
  537.     ngx_stream_script_copy_code_t  *code;

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

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

  540.     return code->len;
  541. }


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

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

  548.     p = e->pos;

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

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

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


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

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

  564.     if (index == NGX_ERROR) {
  565.         return NGX_ERROR;
  566.     }

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

  572.         *p = index;
  573.     }

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

  580.     code->code = (ngx_stream_script_code_pt) (void *)
  581.                                            ngx_stream_script_copy_var_len_code;
  582.     code->index = (uintptr_t) index;

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

  589.     code->code = ngx_stream_script_copy_var_code;
  590.     code->index = (uintptr_t) index;

  591.     return NGX_OK;
  592. }


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

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

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

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

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

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

  608.     return 0;
  609. }


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

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

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

  618.     if (!e->skip) {

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

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

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

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


  633. #if (NGX_PCRE)

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

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

  645.     code->code = (ngx_stream_script_code_pt) (void *)
  646.                                        ngx_stream_script_copy_capture_len_code;
  647.     code->n = 2 * n;


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

  654.     code->code = ngx_stream_script_copy_capture_code;
  655.     code->n = 2 * n;

  656.     if (sc->ncaptures < n) {
  657.         sc->ncaptures = n;
  658.     }

  659.     return NGX_OK;
  660. }


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

  668.     s = e->session;

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

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

  671.     n = code->n;

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

  676.     return 0;
  677. }


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

  686.     s = e->session;

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

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

  689.     n = code->n;

  690.     pos = e->pos;

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

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

  699. #endif


  700. static ngx_int_t
  701. ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
  702. {
  703.     ngx_stream_script_full_name_code_t  *code;

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

  710.     code->code = (ngx_stream_script_code_pt) (void *)
  711.                                           ngx_stream_script_full_name_len_code;
  712.     code->conf_prefix = sc->conf_prefix;

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

  718.     code->code = ngx_stream_script_full_name_code;
  719.     code->conf_prefix = sc->conf_prefix;

  720.     return NGX_OK;
  721. }


  722. static size_t
  723. ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e)
  724. {
  725.     ngx_stream_script_full_name_code_t  *code;

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

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

  728.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  729.                                ngx_cycle->prefix.len;
  730. }


  731. static void
  732. ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e)
  733. {
  734.     ngx_stream_script_full_name_code_t  *code;

  735.     ngx_str_t  value, *prefix;

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

  737.     value.data = e->buf.data;
  738.     value.len = e->pos - e->buf.data;

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

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

  747.     e->buf = value;

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

  750.     e->ip += sizeof(ngx_stream_script_full_name_code_t);
  751. }