Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 static ngx_int_t ngx_stream_script_init_arrays(
0014     ngx_stream_script_compile_t *sc);
0015 static ngx_int_t ngx_stream_script_done(ngx_stream_script_compile_t *sc);
0016 static ngx_int_t ngx_stream_script_add_copy_code(
0017     ngx_stream_script_compile_t *sc, ngx_str_t *value, ngx_uint_t last);
0018 static ngx_int_t ngx_stream_script_add_var_code(
0019     ngx_stream_script_compile_t *sc, ngx_str_t *name);
0020 #if (NGX_PCRE)
0021 static ngx_int_t ngx_stream_script_add_capture_code(
0022     ngx_stream_script_compile_t *sc, ngx_uint_t n);
0023 #endif
0024 static ngx_int_t ngx_stream_script_add_full_name_code(
0025     ngx_stream_script_compile_t *sc);
0026 static size_t ngx_stream_script_full_name_len_code(
0027     ngx_stream_script_engine_t *e);
0028 static void ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e);
0029 
0030 
0031 #define ngx_stream_script_exit  (u_char *) &ngx_stream_script_exit_code
0032 
0033 static uintptr_t ngx_stream_script_exit_code = (uintptr_t) NULL;
0034 
0035 
0036 void
0037 ngx_stream_script_flush_complex_value(ngx_stream_session_t *s,
0038     ngx_stream_complex_value_t *val)
0039 {
0040     ngx_uint_t *index;
0041 
0042     index = val->flushes;
0043 
0044     if (index) {
0045         while (*index != (ngx_uint_t) -1) {
0046 
0047             if (s->variables[*index].no_cacheable) {
0048                 s->variables[*index].valid = 0;
0049                 s->variables[*index].not_found = 0;
0050             }
0051 
0052             index++;
0053         }
0054     }
0055 }
0056 
0057 
0058 ngx_int_t
0059 ngx_stream_complex_value(ngx_stream_session_t *s,
0060     ngx_stream_complex_value_t *val, ngx_str_t *value)
0061 {
0062     size_t                         len;
0063     ngx_stream_script_code_pt      code;
0064     ngx_stream_script_engine_t     e;
0065     ngx_stream_script_len_code_pt  lcode;
0066 
0067     if (val->lengths == NULL) {
0068         *value = val->value;
0069         return NGX_OK;
0070     }
0071 
0072     ngx_stream_script_flush_complex_value(s, val);
0073 
0074     ngx_memzero(&e, sizeof(ngx_stream_script_engine_t));
0075 
0076     e.ip = val->lengths;
0077     e.session = s;
0078     e.flushed = 1;
0079 
0080     len = 0;
0081 
0082     while (*(uintptr_t *) e.ip) {
0083         lcode = *(ngx_stream_script_len_code_pt *) e.ip;
0084         len += lcode(&e);
0085     }
0086 
0087     value->len = len;
0088     value->data = ngx_pnalloc(s->connection->pool, len);
0089     if (value->data == NULL) {
0090         return NGX_ERROR;
0091     }
0092 
0093     e.ip = val->values;
0094     e.pos = value->data;
0095     e.buf = *value;
0096 
0097     while (*(uintptr_t *) e.ip) {
0098         code = *(ngx_stream_script_code_pt *) e.ip;
0099         code((ngx_stream_script_engine_t *) &e);
0100     }
0101 
0102     *value = e.buf;
0103 
0104     return NGX_OK;
0105 }
0106 
0107 
0108 ngx_int_t
0109 ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv)
0110 {
0111     ngx_str_t                    *v;
0112     ngx_uint_t                    i, n, nv, nc;
0113     ngx_array_t                   flushes, lengths, values, *pf, *pl, *pv;
0114     ngx_stream_script_compile_t   sc;
0115 
0116     v = ccv->value;
0117 
0118     nv = 0;
0119     nc = 0;
0120 
0121     for (i = 0; i < v->len; i++) {
0122         if (v->data[i] == '$') {
0123             if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
0124                 nc++;
0125 
0126             } else {
0127                 nv++;
0128             }
0129         }
0130     }
0131 
0132     if ((v->len == 0 || v->data[0] != '$')
0133         && (ccv->conf_prefix || ccv->root_prefix))
0134     {
0135         if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
0136             return NGX_ERROR;
0137         }
0138 
0139         ccv->conf_prefix = 0;
0140         ccv->root_prefix = 0;
0141     }
0142 
0143     ccv->complex_value->value = *v;
0144     ccv->complex_value->flushes = NULL;
0145     ccv->complex_value->lengths = NULL;
0146     ccv->complex_value->values = NULL;
0147 
0148     if (nv == 0 && nc == 0) {
0149         return NGX_OK;
0150     }
0151 
0152     n = nv + 1;
0153 
0154     if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
0155         != NGX_OK)
0156     {
0157         return NGX_ERROR;
0158     }
0159 
0160     n = nv * (2 * sizeof(ngx_stream_script_copy_code_t)
0161                   + sizeof(ngx_stream_script_var_code_t))
0162         + sizeof(uintptr_t);
0163 
0164     if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
0165         return NGX_ERROR;
0166     }
0167 
0168     n = (nv * (2 * sizeof(ngx_stream_script_copy_code_t)
0169                    + sizeof(ngx_stream_script_var_code_t))
0170                 + sizeof(uintptr_t)
0171                 + v->len
0172                 + sizeof(uintptr_t) - 1)
0173             & ~(sizeof(uintptr_t) - 1);
0174 
0175     if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
0176         return NGX_ERROR;
0177     }
0178 
0179     pf = &flushes;
0180     pl = &lengths;
0181     pv = &values;
0182 
0183     ngx_memzero(&sc, sizeof(ngx_stream_script_compile_t));
0184 
0185     sc.cf = ccv->cf;
0186     sc.source = v;
0187     sc.flushes = &pf;
0188     sc.lengths = &pl;
0189     sc.values = &pv;
0190     sc.complete_lengths = 1;
0191     sc.complete_values = 1;
0192     sc.zero = ccv->zero;
0193     sc.conf_prefix = ccv->conf_prefix;
0194     sc.root_prefix = ccv->root_prefix;
0195 
0196     if (ngx_stream_script_compile(&sc) != NGX_OK) {
0197         return NGX_ERROR;
0198     }
0199 
0200     if (flushes.nelts) {
0201         ccv->complex_value->flushes = flushes.elts;
0202         ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
0203     }
0204 
0205     ccv->complex_value->lengths = lengths.elts;
0206     ccv->complex_value->values = values.elts;
0207 
0208     return NGX_OK;
0209 }
0210 
0211 
0212 char *
0213 ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
0214     void *conf)
0215 {
0216     char  *p = conf;
0217 
0218     ngx_str_t                            *value;
0219     ngx_stream_complex_value_t          **cv;
0220     ngx_stream_compile_complex_value_t    ccv;
0221 
0222     cv = (ngx_stream_complex_value_t **) (p + cmd->offset);
0223 
0224     if (*cv != NULL) {
0225         return "is duplicate";
0226     }
0227 
0228     *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
0229     if (*cv == NULL) {
0230         return NGX_CONF_ERROR;
0231     }
0232 
0233     value = cf->args->elts;
0234 
0235     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
0236 
0237     ccv.cf = cf;
0238     ccv.value = &value[1];
0239     ccv.complex_value = *cv;
0240 
0241     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
0242         return NGX_CONF_ERROR;
0243     }
0244 
0245     return NGX_CONF_OK;
0246 }
0247 
0248 
0249 ngx_uint_t
0250 ngx_stream_script_variables_count(ngx_str_t *value)
0251 {
0252     ngx_uint_t  i, n;
0253 
0254     for (n = 0, i = 0; i < value->len; i++) {
0255         if (value->data[i] == '$') {
0256             n++;
0257         }
0258     }
0259 
0260     return n;
0261 }
0262 
0263 
0264 ngx_int_t
0265 ngx_stream_script_compile(ngx_stream_script_compile_t *sc)
0266 {
0267     u_char       ch;
0268     ngx_str_t    name;
0269     ngx_uint_t   i, bracket;
0270 
0271     if (ngx_stream_script_init_arrays(sc) != NGX_OK) {
0272         return NGX_ERROR;
0273     }
0274 
0275     for (i = 0; i < sc->source->len; /* void */ ) {
0276 
0277         name.len = 0;
0278 
0279         if (sc->source->data[i] == '$') {
0280 
0281             if (++i == sc->source->len) {
0282                 goto invalid_variable;
0283             }
0284 
0285             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
0286 #if (NGX_PCRE)
0287                 ngx_uint_t  n;
0288 
0289                 n = sc->source->data[i] - '0';
0290 
0291                 if (ngx_stream_script_add_capture_code(sc, n) != NGX_OK) {
0292                     return NGX_ERROR;
0293                 }
0294 
0295                 i++;
0296 
0297                 continue;
0298 #else
0299                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
0300                                    "using variable \"$%c\" requires "
0301                                    "PCRE library", sc->source->data[i]);
0302                 return NGX_ERROR;
0303 #endif
0304             }
0305 
0306             if (sc->source->data[i] == '{') {
0307                 bracket = 1;
0308 
0309                 if (++i == sc->source->len) {
0310                     goto invalid_variable;
0311                 }
0312 
0313                 name.data = &sc->source->data[i];
0314 
0315             } else {
0316                 bracket = 0;
0317                 name.data = &sc->source->data[i];
0318             }
0319 
0320             for ( /* void */ ; i < sc->source->len; i++, name.len++) {
0321                 ch = sc->source->data[i];
0322 
0323                 if (ch == '}' && bracket) {
0324                     i++;
0325                     bracket = 0;
0326                     break;
0327                 }
0328 
0329                 if ((ch >= 'A' && ch <= 'Z')
0330                     || (ch >= 'a' && ch <= 'z')
0331                     || (ch >= '0' && ch <= '9')
0332                     || ch == '_')
0333                 {
0334                     continue;
0335                 }
0336 
0337                 break;
0338             }
0339 
0340             if (bracket) {
0341                 ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
0342                                    "the closing bracket in \"%V\" "
0343                                    "variable is missing", &name);
0344                 return NGX_ERROR;
0345             }
0346 
0347             if (name.len == 0) {
0348                 goto invalid_variable;
0349             }
0350 
0351             sc->variables++;
0352 
0353             if (ngx_stream_script_add_var_code(sc, &name) != NGX_OK) {
0354                 return NGX_ERROR;
0355             }
0356 
0357             continue;
0358         }
0359 
0360         name.data = &sc->source->data[i];
0361 
0362         while (i < sc->source->len) {
0363 
0364             if (sc->source->data[i] == '$') {
0365                 break;
0366             }
0367 
0368             i++;
0369             name.len++;
0370         }
0371 
0372         sc->size += name.len;
0373 
0374         if (ngx_stream_script_add_copy_code(sc, &name, (i == sc->source->len))
0375             != NGX_OK)
0376         {
0377             return NGX_ERROR;
0378         }
0379     }
0380 
0381     return ngx_stream_script_done(sc);
0382 
0383 invalid_variable:
0384 
0385     ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
0386 
0387     return NGX_ERROR;
0388 }
0389 
0390 
0391 u_char *
0392 ngx_stream_script_run(ngx_stream_session_t *s, ngx_str_t *value,
0393     void *code_lengths, size_t len, void *code_values)
0394 {
0395     ngx_uint_t                      i;
0396     ngx_stream_script_code_pt       code;
0397     ngx_stream_script_engine_t      e;
0398     ngx_stream_core_main_conf_t    *cmcf;
0399     ngx_stream_script_len_code_pt   lcode;
0400 
0401     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
0402 
0403     for (i = 0; i < cmcf->variables.nelts; i++) {
0404         if (s->variables[i].no_cacheable) {
0405             s->variables[i].valid = 0;
0406             s->variables[i].not_found = 0;
0407         }
0408     }
0409 
0410     ngx_memzero(&e, sizeof(ngx_stream_script_engine_t));
0411 
0412     e.ip = code_lengths;
0413     e.session = s;
0414     e.flushed = 1;
0415 
0416     while (*(uintptr_t *) e.ip) {
0417         lcode = *(ngx_stream_script_len_code_pt *) e.ip;
0418         len += lcode(&e);
0419     }
0420 
0421 
0422     value->len = len;
0423     value->data = ngx_pnalloc(s->connection->pool, len);
0424     if (value->data == NULL) {
0425         return NULL;
0426     }
0427 
0428     e.ip = code_values;
0429     e.pos = value->data;
0430 
0431     while (*(uintptr_t *) e.ip) {
0432         code = *(ngx_stream_script_code_pt *) e.ip;
0433         code((ngx_stream_script_engine_t *) &e);
0434     }
0435 
0436     return e.pos;
0437 }
0438 
0439 
0440 void
0441 ngx_stream_script_flush_no_cacheable_variables(ngx_stream_session_t *s,
0442     ngx_array_t *indices)
0443 {
0444     ngx_uint_t  n, *index;
0445 
0446     if (indices) {
0447         index = indices->elts;
0448         for (n = 0; n < indices->nelts; n++) {
0449             if (s->variables[index[n]].no_cacheable) {
0450                 s->variables[index[n]].valid = 0;
0451                 s->variables[index[n]].not_found = 0;
0452             }
0453         }
0454     }
0455 }
0456 
0457 
0458 static ngx_int_t
0459 ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc)
0460 {
0461     ngx_uint_t   n;
0462 
0463     if (sc->flushes && *sc->flushes == NULL) {
0464         n = sc->variables ? sc->variables : 1;
0465         *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
0466         if (*sc->flushes == NULL) {
0467             return NGX_ERROR;
0468         }
0469     }
0470 
0471     if (*sc->lengths == NULL) {
0472         n = sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
0473                              + sizeof(ngx_stream_script_var_code_t))
0474             + sizeof(uintptr_t);
0475 
0476         *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
0477         if (*sc->lengths == NULL) {
0478             return NGX_ERROR;
0479         }
0480     }
0481 
0482     if (*sc->values == NULL) {
0483         n = (sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t)
0484                               + sizeof(ngx_stream_script_var_code_t))
0485                 + sizeof(uintptr_t)
0486                 + sc->source->len
0487                 + sizeof(uintptr_t) - 1)
0488             & ~(sizeof(uintptr_t) - 1);
0489 
0490         *sc->values = ngx_array_create(sc->cf->pool, n, 1);
0491         if (*sc->values == NULL) {
0492             return NGX_ERROR;
0493         }
0494     }
0495 
0496     sc->variables = 0;
0497 
0498     return NGX_OK;
0499 }
0500 
0501 
0502 static ngx_int_t
0503 ngx_stream_script_done(ngx_stream_script_compile_t *sc)
0504 {
0505     ngx_str_t    zero;
0506     uintptr_t   *code;
0507 
0508     if (sc->zero) {
0509 
0510         zero.len = 1;
0511         zero.data = (u_char *) "\0";
0512 
0513         if (ngx_stream_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
0514             return NGX_ERROR;
0515         }
0516     }
0517 
0518     if (sc->conf_prefix || sc->root_prefix) {
0519         if (ngx_stream_script_add_full_name_code(sc) != NGX_OK) {
0520             return NGX_ERROR;
0521         }
0522     }
0523 
0524     if (sc->complete_lengths) {
0525         code = ngx_stream_script_add_code(*sc->lengths, sizeof(uintptr_t),
0526                                           NULL);
0527         if (code == NULL) {
0528             return NGX_ERROR;
0529         }
0530 
0531         *code = (uintptr_t) NULL;
0532     }
0533 
0534     if (sc->complete_values) {
0535         code = ngx_stream_script_add_code(*sc->values, sizeof(uintptr_t),
0536                                           &sc->main);
0537         if (code == NULL) {
0538             return NGX_ERROR;
0539         }
0540 
0541         *code = (uintptr_t) NULL;
0542     }
0543 
0544     return NGX_OK;
0545 }
0546 
0547 
0548 void *
0549 ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code)
0550 {
0551     u_char  *elts, **p;
0552     void    *new;
0553 
0554     elts = codes->elts;
0555 
0556     new = ngx_array_push_n(codes, size);
0557     if (new == NULL) {
0558         return NULL;
0559     }
0560 
0561     if (code) {
0562         if (elts != codes->elts) {
0563             p = code;
0564             *p += (u_char *) codes->elts - elts;
0565         }
0566     }
0567 
0568     return new;
0569 }
0570 
0571 
0572 static ngx_int_t
0573 ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc,
0574     ngx_str_t *value, ngx_uint_t last)
0575 {
0576     u_char                         *p;
0577     size_t                          size, len, zero;
0578     ngx_stream_script_copy_code_t  *code;
0579 
0580     zero = (sc->zero && last);
0581     len = value->len + zero;
0582 
0583     code = ngx_stream_script_add_code(*sc->lengths,
0584                                       sizeof(ngx_stream_script_copy_code_t),
0585                                       NULL);
0586     if (code == NULL) {
0587         return NGX_ERROR;
0588     }
0589 
0590     code->code = (ngx_stream_script_code_pt) ngx_stream_script_copy_len_code;
0591     code->len = len;
0592 
0593     size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
0594             & ~(sizeof(uintptr_t) - 1);
0595 
0596     code = ngx_stream_script_add_code(*sc->values, size, &sc->main);
0597     if (code == NULL) {
0598         return NGX_ERROR;
0599     }
0600 
0601     code->code = ngx_stream_script_copy_code;
0602     code->len = len;
0603 
0604     p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t),
0605                    value->data, value->len);
0606 
0607     if (zero) {
0608         *p = '\0';
0609         sc->zero = 0;
0610     }
0611 
0612     return NGX_OK;
0613 }
0614 
0615 
0616 size_t
0617 ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e)
0618 {
0619     ngx_stream_script_copy_code_t  *code;
0620 
0621     code = (ngx_stream_script_copy_code_t *) e->ip;
0622 
0623     e->ip += sizeof(ngx_stream_script_copy_code_t);
0624 
0625     return code->len;
0626 }
0627 
0628 
0629 void
0630 ngx_stream_script_copy_code(ngx_stream_script_engine_t *e)
0631 {
0632     u_char                         *p;
0633     ngx_stream_script_copy_code_t  *code;
0634 
0635     code = (ngx_stream_script_copy_code_t *) e->ip;
0636 
0637     p = e->pos;
0638 
0639     if (!e->skip) {
0640         e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t),
0641                           code->len);
0642     }
0643 
0644     e->ip += sizeof(ngx_stream_script_copy_code_t)
0645           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
0646 
0647     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0648                    "stream script copy: \"%*s\"", e->pos - p, p);
0649 }
0650 
0651 
0652 static ngx_int_t
0653 ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name)
0654 {
0655     ngx_int_t                      index, *p;
0656     ngx_stream_script_var_code_t  *code;
0657 
0658     index = ngx_stream_get_variable_index(sc->cf, name);
0659 
0660     if (index == NGX_ERROR) {
0661         return NGX_ERROR;
0662     }
0663 
0664     if (sc->flushes) {
0665         p = ngx_array_push(*sc->flushes);
0666         if (p == NULL) {
0667             return NGX_ERROR;
0668         }
0669 
0670         *p = index;
0671     }
0672 
0673     code = ngx_stream_script_add_code(*sc->lengths,
0674                                       sizeof(ngx_stream_script_var_code_t),
0675                                       NULL);
0676     if (code == NULL) {
0677         return NGX_ERROR;
0678     }
0679 
0680     code->code = (ngx_stream_script_code_pt)
0681                       ngx_stream_script_copy_var_len_code;
0682     code->index = (uintptr_t) index;
0683 
0684     code = ngx_stream_script_add_code(*sc->values,
0685                                       sizeof(ngx_stream_script_var_code_t),
0686                                       &sc->main);
0687     if (code == NULL) {
0688         return NGX_ERROR;
0689     }
0690 
0691     code->code = ngx_stream_script_copy_var_code;
0692     code->index = (uintptr_t) index;
0693 
0694     return NGX_OK;
0695 }
0696 
0697 
0698 size_t
0699 ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e)
0700 {
0701     ngx_stream_variable_value_t   *value;
0702     ngx_stream_script_var_code_t  *code;
0703 
0704     code = (ngx_stream_script_var_code_t *) e->ip;
0705 
0706     e->ip += sizeof(ngx_stream_script_var_code_t);
0707 
0708     if (e->flushed) {
0709         value = ngx_stream_get_indexed_variable(e->session, code->index);
0710 
0711     } else {
0712         value = ngx_stream_get_flushed_variable(e->session, code->index);
0713     }
0714 
0715     if (value && !value->not_found) {
0716         return value->len;
0717     }
0718 
0719     return 0;
0720 }
0721 
0722 
0723 void
0724 ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e)
0725 {
0726     u_char                        *p;
0727     ngx_stream_variable_value_t   *value;
0728     ngx_stream_script_var_code_t  *code;
0729 
0730     code = (ngx_stream_script_var_code_t *) e->ip;
0731 
0732     e->ip += sizeof(ngx_stream_script_var_code_t);
0733 
0734     if (!e->skip) {
0735 
0736         if (e->flushed) {
0737             value = ngx_stream_get_indexed_variable(e->session, code->index);
0738 
0739         } else {
0740             value = ngx_stream_get_flushed_variable(e->session, code->index);
0741         }
0742 
0743         if (value && !value->not_found) {
0744             p = e->pos;
0745             e->pos = ngx_copy(p, value->data, value->len);
0746 
0747             ngx_log_debug2(NGX_LOG_DEBUG_STREAM,
0748                            e->session->connection->log, 0,
0749                            "stream script var: \"%*s\"", e->pos - p, p);
0750         }
0751     }
0752 }
0753 
0754 
0755 #if (NGX_PCRE)
0756 
0757 static ngx_int_t
0758 ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc,
0759     ngx_uint_t n)
0760 {
0761     ngx_stream_script_copy_capture_code_t  *code;
0762 
0763     code = ngx_stream_script_add_code(*sc->lengths,
0764                                   sizeof(ngx_stream_script_copy_capture_code_t),
0765                                   NULL);
0766     if (code == NULL) {
0767         return NGX_ERROR;
0768     }
0769 
0770     code->code = (ngx_stream_script_code_pt)
0771                       ngx_stream_script_copy_capture_len_code;
0772     code->n = 2 * n;
0773 
0774 
0775     code = ngx_stream_script_add_code(*sc->values,
0776                                   sizeof(ngx_stream_script_copy_capture_code_t),
0777                                   &sc->main);
0778     if (code == NULL) {
0779         return NGX_ERROR;
0780     }
0781 
0782     code->code = ngx_stream_script_copy_capture_code;
0783     code->n = 2 * n;
0784 
0785     if (sc->ncaptures < n) {
0786         sc->ncaptures = n;
0787     }
0788 
0789     return NGX_OK;
0790 }
0791 
0792 
0793 size_t
0794 ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e)
0795 {
0796     int                                    *cap;
0797     ngx_uint_t                              n;
0798     ngx_stream_session_t                   *s;
0799     ngx_stream_script_copy_capture_code_t  *code;
0800 
0801     s = e->session;
0802 
0803     code = (ngx_stream_script_copy_capture_code_t *) e->ip;
0804 
0805     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);
0806 
0807     n = code->n;
0808 
0809     if (n < s->ncaptures) {
0810         cap = s->captures;
0811         return cap[n + 1] - cap[n];
0812     }
0813 
0814     return 0;
0815 }
0816 
0817 
0818 void
0819 ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e)
0820 {
0821     int                                    *cap;
0822     u_char                                 *p, *pos;
0823     ngx_uint_t                              n;
0824     ngx_stream_session_t                   *s;
0825     ngx_stream_script_copy_capture_code_t  *code;
0826 
0827     s = e->session;
0828 
0829     code = (ngx_stream_script_copy_capture_code_t *) e->ip;
0830 
0831     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);
0832 
0833     n = code->n;
0834 
0835     pos = e->pos;
0836 
0837     if (n < s->ncaptures) {
0838         cap = s->captures;
0839         p = s->captures_data;
0840         e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
0841     }
0842 
0843     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0844                    "stream script capture: \"%*s\"", e->pos - pos, pos);
0845 }
0846 
0847 #endif
0848 
0849 
0850 static ngx_int_t
0851 ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
0852 {
0853     ngx_stream_script_full_name_code_t  *code;
0854 
0855     code = ngx_stream_script_add_code(*sc->lengths,
0856                                     sizeof(ngx_stream_script_full_name_code_t),
0857                                     NULL);
0858     if (code == NULL) {
0859         return NGX_ERROR;
0860     }
0861 
0862     code->code = (ngx_stream_script_code_pt)
0863                                           ngx_stream_script_full_name_len_code;
0864     code->conf_prefix = sc->conf_prefix;
0865 
0866     code = ngx_stream_script_add_code(*sc->values,
0867                         sizeof(ngx_stream_script_full_name_code_t), &sc->main);
0868     if (code == NULL) {
0869         return NGX_ERROR;
0870     }
0871 
0872     code->code = ngx_stream_script_full_name_code;
0873     code->conf_prefix = sc->conf_prefix;
0874 
0875     return NGX_OK;
0876 }
0877 
0878 
0879 static size_t
0880 ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e)
0881 {
0882     ngx_stream_script_full_name_code_t  *code;
0883 
0884     code = (ngx_stream_script_full_name_code_t *) e->ip;
0885 
0886     e->ip += sizeof(ngx_stream_script_full_name_code_t);
0887 
0888     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
0889                                ngx_cycle->prefix.len;
0890 }
0891 
0892 
0893 static void
0894 ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e)
0895 {
0896     ngx_stream_script_full_name_code_t  *code;
0897 
0898     ngx_str_t  value, *prefix;
0899 
0900     code = (ngx_stream_script_full_name_code_t *) e->ip;
0901 
0902     value.data = e->buf.data;
0903     value.len = e->pos - e->buf.data;
0904 
0905     prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
0906                                  (ngx_str_t *) &ngx_cycle->prefix;
0907 
0908     if (ngx_get_full_name(e->session->connection->pool, prefix, &value)
0909         != NGX_OK)
0910     {
0911         e->ip = ngx_stream_script_exit;
0912         return;
0913     }
0914 
0915     e->buf = value;
0916 
0917     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0918                    "stream script fullname: \"%V\"", &value);
0919 
0920     e->ip += sizeof(ngx_stream_script_full_name_code_t);
0921 }