src/stream/ngx_stream_script.c - nginx-1.31.4 nginx/ @ 8d9666701

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.end = value->data + len;
  72.     e.buf = *value;

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

  77.     if (e.status) {
  78.         return NGX_ERROR;
  79.     }

  80.     value->data = e.buf.data;
  81.     value->len = e.pos - e.buf.data;

  82.     return NGX_OK;
  83. }


  84. size_t
  85. ngx_stream_complex_value_size(ngx_stream_session_t *s,
  86.     ngx_stream_complex_value_t *val, size_t default_value)
  87. {
  88.     size_t     size;
  89.     ngx_str_t  value;

  90.     if (val == NULL) {
  91.         return default_value;
  92.     }

  93.     if (val->lengths == NULL) {
  94.         return val->u.size;
  95.     }

  96.     if (ngx_stream_complex_value(s, val, &value) != NGX_OK) {
  97.         return default_value;
  98.     }

  99.     size = ngx_parse_size(&value);

  100.     if (size == (size_t) NGX_ERROR) {
  101.         ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
  102.                       "invalid size \"%V\"", &value);
  103.         return default_value;
  104.     }

  105.     return size;
  106. }


  107. ngx_int_t
  108. ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv)
  109. {
  110.     ngx_str_t                    *v;
  111.     ngx_uint_t                    i, n, nv, nc;
  112.     ngx_array_t                   flushes, lengths, values, *pf, *pl, *pv;
  113.     ngx_stream_script_compile_t   sc;

  114.     v = ccv->value;

  115.     nv = 0;
  116.     nc = 0;

  117.     for (i = 0; i < v->len; i++) {
  118.         if (v->data[i] == '$') {
  119.             if (i + 1 < v->len
  120.                 && v->data[i + 1] >= '1' && v->data[i + 1] <= '9')
  121.             {
  122.                 nc++;

  123.             } else {
  124.                 nv++;
  125.             }
  126.         }
  127.     }

  128.     if ((v->len == 0 || v->data[0] != '$')
  129.         && (ccv->conf_prefix || ccv->root_prefix))
  130.     {
  131.         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
  132.             return NGX_ERROR;
  133.         }

  134.         ccv->conf_prefix = 0;
  135.         ccv->root_prefix = 0;
  136.     }

  137.     ccv->complex_value->value = *v;
  138.     ccv->complex_value->flushes = NULL;
  139.     ccv->complex_value->lengths = NULL;
  140.     ccv->complex_value->values = NULL;

  141.     if (nv == 0 && nc == 0) {
  142.         return NGX_OK;
  143.     }

  144.     n = nv + 1;

  145.     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
  146.         != NGX_OK)
  147.     {
  148.         return NGX_ERROR;
  149.     }

  150.     n = nv * (2 * sizeof(ngx_stream_script_copy_code_t)
  151.                   + sizeof(ngx_stream_script_var_code_t))
  152.         + sizeof(uintptr_t);

  153.     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
  154.         return NGX_ERROR;
  155.     }

  156.     n = (nv * (2 * sizeof(ngx_stream_script_copy_code_t)
  157.                    + sizeof(ngx_stream_script_var_code_t))
  158.                 + sizeof(uintptr_t)
  159.                 + v->len
  160.                 + sizeof(uintptr_t) - 1)
  161.             & ~(sizeof(uintptr_t) - 1);

  162.     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
  163.         return NGX_ERROR;
  164.     }

  165.     pf = &flushes;
  166.     pl = &lengths;
  167.     pv = &values;

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

  169.     sc.cf = ccv->cf;
  170.     sc.source = v;
  171.     sc.flushes = &pf;
  172.     sc.lengths = &pl;
  173.     sc.values = &pv;
  174.     sc.complete_lengths = 1;
  175.     sc.complete_values = 1;
  176.     sc.zero = ccv->zero;
  177.     sc.conf_prefix = ccv->conf_prefix;
  178.     sc.root_prefix = ccv->root_prefix;

  179.     if (ngx_stream_script_compile(&sc) != NGX_OK) {
  180.         return NGX_ERROR;
  181.     }

  182.     if (flushes.nelts) {
  183.         ccv->complex_value->flushes = flushes.elts;
  184.         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
  185.     }

  186.     ccv->complex_value->lengths = lengths.elts;
  187.     ccv->complex_value->values = values.elts;

  188.     return NGX_OK;
  189. }


  190. char *
  191. ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  192.     void *conf)
  193. {
  194.     char  *p = conf;

  195.     ngx_str_t                            *value;
  196.     ngx_stream_complex_value_t          **cv;
  197.     ngx_stream_compile_complex_value_t    ccv;

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

  199.     if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
  200.         return "is duplicate";
  201.     }

  202.     *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
  203.     if (*cv == NULL) {
  204.         return NGX_CONF_ERROR;
  205.     }

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

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

  208.     ccv.cf = cf;
  209.     ccv.value = &value[1];
  210.     ccv.complex_value = *cv;

  211.     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
  212.         return NGX_CONF_ERROR;
  213.     }

  214.     return NGX_CONF_OK;
  215. }


  216. char *
  217. ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  218.     void *conf)
  219. {
  220.     char  *p = conf;

  221.     ngx_str_t                            *value;
  222.     ngx_stream_complex_value_t          **cv;
  223.     ngx_stream_compile_complex_value_t    ccv;

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

  225.     if (*cv != NGX_CONF_UNSET_PTR) {
  226.         return "is duplicate";
  227.     }

  228.     *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
  229.     if (*cv == NULL) {
  230.         return NGX_CONF_ERROR;
  231.     }

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

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

  234.     ccv.cf = cf;
  235.     ccv.value = &value[1];
  236.     ccv.complex_value = *cv;
  237.     ccv.zero = 1;

  238.     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
  239.         return NGX_CONF_ERROR;
  240.     }

  241.     return NGX_CONF_OK;
  242. }


  243. char *
  244. ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  245.     void *conf)
  246. {
  247.     char  *p = conf;

  248.     char                        *rv;
  249.     ngx_stream_complex_value_t  *cv;

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

  251.     if (rv != NGX_CONF_OK) {
  252.         return rv;
  253.     }

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

  255.     if (cv->lengths) {
  256.         return NGX_CONF_OK;
  257.     }

  258.     cv->u.size = ngx_parse_size(&cv->value);
  259.     if (cv->u.size == (size_t) NGX_ERROR) {
  260.         return "invalid value";
  261.     }

  262.     return NGX_CONF_OK;
  263. }


  264. ngx_uint_t
  265. ngx_stream_script_variables_count(ngx_str_t *value)
  266. {
  267.     ngx_uint_t  i, n;

  268.     for (n = 0, i = 0; i < value->len; i++) {
  269.         if (value->data[i] == '$') {
  270.             n++;
  271.         }
  272.     }

  273.     return n;
  274. }


  275. ngx_int_t
  276. ngx_stream_script_compile(ngx_stream_script_compile_t *sc)
  277. {
  278.     u_char       ch;
  279.     ngx_str_t    name;
  280.     ngx_uint_t   i, bracket;

  281.     if (ngx_stream_script_init_arrays(sc) != NGX_OK) {
  282.         return NGX_ERROR;
  283.     }

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

  285.         name.len = 0;

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

  287.             if (++i == sc->source->len) {
  288.                 goto invalid_variable;
  289.             }

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

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

  294.                 if (ngx_stream_script_add_capture_code(sc, n) != NGX_OK) {
  295.                     return NGX_ERROR;
  296.                 }

  297.                 i++;

  298.                 continue;
  299. #else
  300.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  301.                                    "using variable \"$%c\" requires "
  302.                                    "PCRE library", sc->source->data[i]);
  303.                 return NGX_ERROR;
  304. #endif
  305.             }

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

  308.                 if (++i == sc->source->len) {
  309.                     goto invalid_variable;
  310.                 }

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

  312.             } else {
  313.                 bracket = 0;
  314.                 name.data = &sc->source->data[i];
  315.             }

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

  318.                 if (ch == '}' && bracket) {
  319.                     i++;
  320.                     bracket = 0;
  321.                     break;
  322.                 }

  323.                 if ((ch >= 'A' && ch <= 'Z')
  324.                     || (ch >= 'a' && ch <= 'z')
  325.                     || (ch >= '0' && ch <= '9')
  326.                     || ch == '_')
  327.                 {
  328.                     continue;
  329.                 }

  330.                 break;
  331.             }

  332.             if (bracket) {
  333.                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  334.                                    "the closing bracket in \"%V\" "
  335.                                    "variable is missing", &name);
  336.                 return NGX_ERROR;
  337.             }

  338.             if (name.len == 0) {
  339.                 goto invalid_variable;
  340.             }

  341.             sc->variables++;

  342.             if (ngx_stream_script_add_var_code(sc, &name) != NGX_OK) {
  343.                 return NGX_ERROR;
  344.             }

  345.             continue;
  346.         }

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

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

  349.             if (sc->source->data[i] == '$') {
  350.                 break;
  351.             }

  352.             i++;
  353.             name.len++;
  354.         }

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

  356.         if (ngx_stream_script_add_copy_code(sc, &name, (i == sc->source->len))
  357.             != NGX_OK)
  358.         {
  359.             return NGX_ERROR;
  360.         }
  361.     }

  362.     return ngx_stream_script_done(sc);

  363. invalid_variable:

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

  365.     return NGX_ERROR;
  366. }


  367. u_char *
  368. ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value,
  369.     void *code_lengths, size_t len, void *code_values)
  370. {
  371.     size_t                          n;
  372.     ngx_uint_t                      i;
  373.     ngx_stream_script_code_pt       code;
  374.     ngx_stream_script_engine_t      e;
  375.     ngx_stream_core_main_conf_t    *cmcf;
  376.     ngx_stream_script_len_code_pt   lcode;

  377.     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

  378.     for (i = 0; i < cmcf->variables.nelts; i++) {
  379.         if (s->variables[i].no_cacheable) {
  380.             s->variables[i].valid = 0;
  381.             s->variables[i].not_found = 0;
  382.         }
  383.     }

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

  385.     e.ip = code_lengths;
  386.     e.session = s;
  387.     e.flushed = 1;

  388.     n = len;

  389.     while (*(uintptr_t *) e.ip) {
  390.         lcode = *(ngx_stream_script_len_code_pt *) e.ip;
  391.         n += lcode(&e);
  392.     }


  393.     value->len = n;
  394.     value->data = ngx_pnalloc(s->connection->pool, n);
  395.     if (value->data == NULL) {
  396.         return NULL;
  397.     }

  398.     e.ip = code_values;
  399.     e.pos = value->data;
  400.     e.end = value->data + n;

  401.     while (*(uintptr_t *) e.ip) {
  402.         code = *(ngx_stream_script_code_pt *) e.ip;
  403.         code((ngx_stream_script_engine_t *) &e);
  404.     }

  405.     if (e.status) {
  406.         return NULL;
  407.     }

  408.     value->len = e.pos + len - value->data;

  409.     return e.pos;
  410. }


  411. void
  412. ngx_stream_script_flush_no_cacheable_variables(ngx_stream_session_t *s,
  413.     ngx_array_t *indices)
  414. {
  415.     ngx_uint_t  n, *index;

  416.     if (indices) {
  417.         index = indices->elts;
  418.         for (n = 0; n < indices->nelts; n++) {
  419.             if (s->variables[index[n]].no_cacheable) {
  420.                 s->variables[index[n]].valid = 0;
  421.                 s->variables[index[n]].not_found = 0;
  422.             }
  423.         }
  424.     }
  425. }


  426. static ngx_int_t
  427. ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc)
  428. {
  429.     ngx_uint_t   n;

  430.     if (sc->flushes && *sc->flushes == NULL) {
  431.         n = sc->variables ? sc->variables : 1;
  432.         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
  433.         if (*sc->flushes == NULL) {
  434.             return NGX_ERROR;
  435.         }
  436.     }

  437.     if (*sc->lengths == NULL) {
  438.         n = sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
  439.                              + sizeof(ngx_stream_script_var_code_t))
  440.             + sizeof(uintptr_t);

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

  446.     if (*sc->values == NULL) {
  447.         n = (sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
  448.                               + sizeof(ngx_stream_script_var_code_t))
  449.                 + sizeof(uintptr_t)
  450.                 + sc->source->len
  451.                 + sizeof(uintptr_t) - 1)
  452.             & ~(sizeof(uintptr_t) - 1);

  453.         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
  454.         if (*sc->values == NULL) {
  455.             return NGX_ERROR;
  456.         }
  457.     }

  458.     sc->variables = 0;

  459.     return NGX_OK;
  460. }


  461. static ngx_int_t
  462. ngx_stream_script_done(ngx_stream_script_compile_t *sc)
  463. {
  464.     ngx_str_t    zero;
  465.     uintptr_t   *code;

  466.     if (sc->zero) {

  467.         zero.len = 1;
  468.         zero.data = (u_char *) "\0";

  469.         if (ngx_stream_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
  470.             return NGX_ERROR;
  471.         }
  472.     }

  473.     if (sc->conf_prefix || sc->root_prefix) {
  474.         if (ngx_stream_script_add_full_name_code(sc) != NGX_OK) {
  475.             return NGX_ERROR;
  476.         }
  477.     }

  478.     if (sc->complete_lengths) {
  479.         code = ngx_stream_script_add_code(*sc->lengths, sizeof(uintptr_t),
  480.                                           NULL);
  481.         if (code == NULL) {
  482.             return NGX_ERROR;
  483.         }

  484.         *code = (uintptr_t) NULL;
  485.     }

  486.     if (sc->complete_values) {
  487.         code = ngx_stream_script_add_code(*sc->values, sizeof(uintptr_t),
  488.                                           &sc->main);
  489.         if (code == NULL) {
  490.             return NGX_ERROR;
  491.         }

  492.         *code = (uintptr_t) NULL;
  493.     }

  494.     return NGX_OK;
  495. }


  496. void *
  497. ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code)
  498. {
  499.     u_char  *elts, **p;
  500.     void    *new;

  501.     elts = codes->elts;

  502.     new = ngx_array_push_n(codes, size);
  503.     if (new == NULL) {
  504.         return NULL;
  505.     }

  506.     if (code) {
  507.         if (elts != codes->elts) {
  508.             p = code;
  509.             *p += (u_char *) codes->elts - elts;
  510.         }
  511.     }

  512.     return new;
  513. }


  514. ngx_int_t
  515. ngx_stream_script_check_length(ngx_stream_script_engine_t *e, size_t len)
  516. {
  517.     if (e->end == NULL) {
  518.         return NGX_OK;
  519.     }

  520.     if (e->end - e->pos < (ssize_t) len) {
  521.         ngx_log_error(NGX_LOG_ALERT, e->session->connection->log, 0,
  522.                       "no buffer space in script copy");
  523.         e->ip = ngx_stream_script_exit;
  524.         e->status = NGX_STREAM_INTERNAL_SERVER_ERROR;
  525.         return NGX_ERROR;
  526.     }

  527.     return NGX_OK;
  528. }


  529. static ngx_int_t
  530. ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc,
  531.     ngx_str_t *value, ngx_uint_t last)
  532. {
  533.     u_char                         *p;
  534.     size_t                          size, len, zero;
  535.     ngx_stream_script_copy_code_t  *code;

  536.     zero = (sc->zero && last);
  537.     len = value->len + zero;

  538.     code = ngx_stream_script_add_code(*sc->lengths,
  539.                                       sizeof(ngx_stream_script_copy_code_t),
  540.                                       NULL);
  541.     if (code == NULL) {
  542.         return NGX_ERROR;
  543.     }

  544.     code->code = (ngx_stream_script_code_pt) (void *)
  545.                                                ngx_stream_script_copy_len_code;
  546.     code->len = len;

  547.     size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  548.             & ~(sizeof(uintptr_t) - 1);

  549.     code = ngx_stream_script_add_code(*sc->values, size, &sc->main);
  550.     if (code == NULL) {
  551.         return NGX_ERROR;
  552.     }

  553.     code->code = ngx_stream_script_copy_code;
  554.     code->len = len;

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

  557.     if (zero) {
  558.         *p = '\0';
  559.         sc->zero = 0;
  560.     }

  561.     return NGX_OK;
  562. }


  563. size_t
  564. ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e)
  565. {
  566.     ngx_stream_script_copy_code_t  *code;

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

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

  569.     return code->len;
  570. }


  571. void
  572. ngx_stream_script_copy_code(ngx_stream_script_engine_t *e)
  573. {
  574.     u_char                         *p;
  575.     ngx_stream_script_copy_code_t  *code;

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

  577.     p = e->pos;

  578.     if (!e->skip) {

  579.         if (ngx_stream_script_check_length(e, code->len) != NGX_OK) {
  580.             return;
  581.         }

  582.         e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t),
  583.                           code->len);
  584.     }

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

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


  590. static ngx_int_t
  591. ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name)
  592. {
  593.     ngx_int_t                      index, *p;
  594.     ngx_stream_script_var_code_t  *code;

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

  596.     if (index == NGX_ERROR) {
  597.         return NGX_ERROR;
  598.     }

  599.     if (sc->flushes) {
  600.         p = ngx_array_push(*sc->flushes);
  601.         if (p == NULL) {
  602.             return NGX_ERROR;
  603.         }

  604.         *p = index;
  605.     }

  606.     code = ngx_stream_script_add_code(*sc->lengths,
  607.                                       sizeof(ngx_stream_script_var_code_t),
  608.                                       NULL);
  609.     if (code == NULL) {
  610.         return NGX_ERROR;
  611.     }

  612.     code->code = (ngx_stream_script_code_pt) (void *)
  613.                                            ngx_stream_script_copy_var_len_code;
  614.     code->index = (uintptr_t) index;

  615.     code = ngx_stream_script_add_code(*sc->values,
  616.                                       sizeof(ngx_stream_script_var_code_t),
  617.                                       &sc->main);
  618.     if (code == NULL) {
  619.         return NGX_ERROR;
  620.     }

  621.     code->code = ngx_stream_script_copy_var_code;
  622.     code->index = (uintptr_t) index;

  623.     return NGX_OK;
  624. }


  625. size_t
  626. ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e)
  627. {
  628.     ngx_stream_variable_value_t   *value;
  629.     ngx_stream_script_var_code_t  *code;

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

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

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

  634.     } else {
  635.         value = ngx_stream_get_flushed_variable(e->session, code->index);
  636.     }

  637.     if (value && !value->not_found) {
  638.         return value->len;
  639.     }

  640.     return 0;
  641. }


  642. void
  643. ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e)
  644. {
  645.     u_char                        *p;
  646.     ngx_stream_variable_value_t   *value;
  647.     ngx_stream_script_var_code_t  *code;

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

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

  650.     if (!e->skip) {

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

  653.         } else {
  654.             value = ngx_stream_get_flushed_variable(e->session, code->index);
  655.         }

  656.         if (value && !value->not_found) {

  657.             if (ngx_stream_script_check_length(e, value->len) != NGX_OK) {
  658.                 return;
  659.             }

  660.             p = e->pos;
  661.             e->pos = ngx_copy(p, value->data, value->len);

  662.             ngx_log_debug2(NGX_LOG_DEBUG_STREAM,
  663.                            e->session->connection->log, 0,
  664.                            "stream script var: \"%*s\"", e->pos - p, p);
  665.         }
  666.     }
  667. }


  668. #if (NGX_PCRE)

  669. static ngx_int_t
  670. ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc,
  671.     ngx_uint_t n)
  672. {
  673.     ngx_stream_script_copy_capture_code_t  *code;

  674.     code = ngx_stream_script_add_code(*sc->lengths,
  675.                                   sizeof(ngx_stream_script_copy_capture_code_t),
  676.                                   NULL);
  677.     if (code == NULL) {
  678.         return NGX_ERROR;
  679.     }

  680.     code->code = (ngx_stream_script_code_pt) (void *)
  681.                                        ngx_stream_script_copy_capture_len_code;
  682.     code->n = 2 * n;


  683.     code = ngx_stream_script_add_code(*sc->values,
  684.                                   sizeof(ngx_stream_script_copy_capture_code_t),
  685.                                   &sc->main);
  686.     if (code == NULL) {
  687.         return NGX_ERROR;
  688.     }

  689.     code->code = ngx_stream_script_copy_capture_code;
  690.     code->n = 2 * n;

  691.     if (sc->ncaptures < n) {
  692.         sc->ncaptures = n;
  693.     }

  694.     return NGX_OK;
  695. }


  696. size_t
  697. ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e)
  698. {
  699.     int                                    *cap;
  700.     size_t                                  len;
  701.     ngx_uint_t                              n;
  702.     ngx_stream_session_t                   *s;
  703.     ngx_stream_script_copy_capture_code_t  *code;

  704.     s = e->session;

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

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

  707.     n = code->n;

  708.     if (n < s->ncaptures) {
  709.         cap = s->captures;
  710.         len = cap[n + 1] - cap[n];
  711.         return len;
  712.     }

  713.     return 0;
  714. }


  715. void
  716. ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e)
  717. {
  718.     int                                    *cap;
  719.     u_char                                 *p, *pos;
  720.     size_t                                  len;
  721.     ngx_uint_t                              n;
  722.     ngx_stream_session_t                   *s;
  723.     ngx_stream_script_copy_capture_code_t  *code;

  724.     s = e->session;

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

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

  727.     n = code->n;

  728.     pos = e->pos;

  729.     if (n < s->ncaptures) {
  730.         cap = s->captures;
  731.         len = cap[n + 1] - cap[n];
  732.         p = s->captures_data + cap[n];

  733.         if (ngx_stream_script_check_length(e, len) != NGX_OK) {
  734.             return;
  735.         }

  736.         e->pos = ngx_copy(pos, p, len);
  737.     }

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

  741. #endif


  742. static ngx_int_t
  743. ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
  744. {
  745.     ngx_stream_script_full_name_code_t  *code;

  746.     code = ngx_stream_script_add_code(*sc->lengths,
  747.                                     sizeof(ngx_stream_script_full_name_code_t),
  748.                                     NULL);
  749.     if (code == NULL) {
  750.         return NGX_ERROR;
  751.     }

  752.     code->code = (ngx_stream_script_code_pt) (void *)
  753.                                           ngx_stream_script_full_name_len_code;
  754.     code->conf_prefix = sc->conf_prefix;

  755.     code = ngx_stream_script_add_code(*sc->values,
  756.                         sizeof(ngx_stream_script_full_name_code_t), &sc->main);
  757.     if (code == NULL) {
  758.         return NGX_ERROR;
  759.     }

  760.     code->code = ngx_stream_script_full_name_code;
  761.     code->conf_prefix = sc->conf_prefix;

  762.     return NGX_OK;
  763. }


  764. static size_t
  765. ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e)
  766. {
  767.     ngx_stream_script_full_name_code_t  *code;

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

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

  770.     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  771.                                ngx_cycle->prefix.len;
  772. }


  773. static void
  774. ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e)
  775. {
  776.     ngx_stream_script_full_name_code_t  *code;

  777.     ngx_str_t  value, *prefix;

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

  779.     value.data = e->buf.data;
  780.     value.len = e->pos - e->buf.data;

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

  783.     if (ngx_get_full_name(e->session->connection->pool, prefix, &value)
  784.         != NGX_OK)
  785.     {
  786.         e->ip = ngx_stream_script_exit;
  787.         e->status = NGX_STREAM_INTERNAL_SERVER_ERROR;
  788.         return;
  789.     }

  790.     e->buf = value;
  791.     e->pos = value.data + value.len;
  792.     e->end = e->pos;

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

  795.     e->ip += sizeof(ngx_stream_script_full_name_code_t);
  796. }