Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.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) (void *)
0591                                                ngx_stream_script_copy_len_code;
0592     code->len = len;
0593 
0594     size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
0595             & ~(sizeof(uintptr_t) - 1);
0596 
0597     code = ngx_stream_script_add_code(*sc->values, size, &sc->main);
0598     if (code == NULL) {
0599         return NGX_ERROR;
0600     }
0601 
0602     code->code = ngx_stream_script_copy_code;
0603     code->len = len;
0604 
0605     p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t),
0606                    value->data, value->len);
0607 
0608     if (zero) {
0609         *p = '\0';
0610         sc->zero = 0;
0611     }
0612 
0613     return NGX_OK;
0614 }
0615 
0616 
0617 size_t
0618 ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e)
0619 {
0620     ngx_stream_script_copy_code_t  *code;
0621 
0622     code = (ngx_stream_script_copy_code_t *) e->ip;
0623 
0624     e->ip += sizeof(ngx_stream_script_copy_code_t);
0625 
0626     return code->len;
0627 }
0628 
0629 
0630 void
0631 ngx_stream_script_copy_code(ngx_stream_script_engine_t *e)
0632 {
0633     u_char                         *p;
0634     ngx_stream_script_copy_code_t  *code;
0635 
0636     code = (ngx_stream_script_copy_code_t *) e->ip;
0637 
0638     p = e->pos;
0639 
0640     if (!e->skip) {
0641         e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t),
0642                           code->len);
0643     }
0644 
0645     e->ip += sizeof(ngx_stream_script_copy_code_t)
0646           + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
0647 
0648     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0649                    "stream script copy: \"%*s\"", e->pos - p, p);
0650 }
0651 
0652 
0653 static ngx_int_t
0654 ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name)
0655 {
0656     ngx_int_t                      index, *p;
0657     ngx_stream_script_var_code_t  *code;
0658 
0659     index = ngx_stream_get_variable_index(sc->cf, name);
0660 
0661     if (index == NGX_ERROR) {
0662         return NGX_ERROR;
0663     }
0664 
0665     if (sc->flushes) {
0666         p = ngx_array_push(*sc->flushes);
0667         if (p == NULL) {
0668             return NGX_ERROR;
0669         }
0670 
0671         *p = index;
0672     }
0673 
0674     code = ngx_stream_script_add_code(*sc->lengths,
0675                                       sizeof(ngx_stream_script_var_code_t),
0676                                       NULL);
0677     if (code == NULL) {
0678         return NGX_ERROR;
0679     }
0680 
0681     code->code = (ngx_stream_script_code_pt) (void *)
0682                                            ngx_stream_script_copy_var_len_code;
0683     code->index = (uintptr_t) index;
0684 
0685     code = ngx_stream_script_add_code(*sc->values,
0686                                       sizeof(ngx_stream_script_var_code_t),
0687                                       &sc->main);
0688     if (code == NULL) {
0689         return NGX_ERROR;
0690     }
0691 
0692     code->code = ngx_stream_script_copy_var_code;
0693     code->index = (uintptr_t) index;
0694 
0695     return NGX_OK;
0696 }
0697 
0698 
0699 size_t
0700 ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e)
0701 {
0702     ngx_stream_variable_value_t   *value;
0703     ngx_stream_script_var_code_t  *code;
0704 
0705     code = (ngx_stream_script_var_code_t *) e->ip;
0706 
0707     e->ip += sizeof(ngx_stream_script_var_code_t);
0708 
0709     if (e->flushed) {
0710         value = ngx_stream_get_indexed_variable(e->session, code->index);
0711 
0712     } else {
0713         value = ngx_stream_get_flushed_variable(e->session, code->index);
0714     }
0715 
0716     if (value && !value->not_found) {
0717         return value->len;
0718     }
0719 
0720     return 0;
0721 }
0722 
0723 
0724 void
0725 ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e)
0726 {
0727     u_char                        *p;
0728     ngx_stream_variable_value_t   *value;
0729     ngx_stream_script_var_code_t  *code;
0730 
0731     code = (ngx_stream_script_var_code_t *) e->ip;
0732 
0733     e->ip += sizeof(ngx_stream_script_var_code_t);
0734 
0735     if (!e->skip) {
0736 
0737         if (e->flushed) {
0738             value = ngx_stream_get_indexed_variable(e->session, code->index);
0739 
0740         } else {
0741             value = ngx_stream_get_flushed_variable(e->session, code->index);
0742         }
0743 
0744         if (value && !value->not_found) {
0745             p = e->pos;
0746             e->pos = ngx_copy(p, value->data, value->len);
0747 
0748             ngx_log_debug2(NGX_LOG_DEBUG_STREAM,
0749                            e->session->connection->log, 0,
0750                            "stream script var: \"%*s\"", e->pos - p, p);
0751         }
0752     }
0753 }
0754 
0755 
0756 #if (NGX_PCRE)
0757 
0758 static ngx_int_t
0759 ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc,
0760     ngx_uint_t n)
0761 {
0762     ngx_stream_script_copy_capture_code_t  *code;
0763 
0764     code = ngx_stream_script_add_code(*sc->lengths,
0765                                   sizeof(ngx_stream_script_copy_capture_code_t),
0766                                   NULL);
0767     if (code == NULL) {
0768         return NGX_ERROR;
0769     }
0770 
0771     code->code = (ngx_stream_script_code_pt) (void *)
0772                                        ngx_stream_script_copy_capture_len_code;
0773     code->n = 2 * n;
0774 
0775 
0776     code = ngx_stream_script_add_code(*sc->values,
0777                                   sizeof(ngx_stream_script_copy_capture_code_t),
0778                                   &sc->main);
0779     if (code == NULL) {
0780         return NGX_ERROR;
0781     }
0782 
0783     code->code = ngx_stream_script_copy_capture_code;
0784     code->n = 2 * n;
0785 
0786     if (sc->ncaptures < n) {
0787         sc->ncaptures = n;
0788     }
0789 
0790     return NGX_OK;
0791 }
0792 
0793 
0794 size_t
0795 ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e)
0796 {
0797     int                                    *cap;
0798     ngx_uint_t                              n;
0799     ngx_stream_session_t                   *s;
0800     ngx_stream_script_copy_capture_code_t  *code;
0801 
0802     s = e->session;
0803 
0804     code = (ngx_stream_script_copy_capture_code_t *) e->ip;
0805 
0806     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);
0807 
0808     n = code->n;
0809 
0810     if (n < s->ncaptures) {
0811         cap = s->captures;
0812         return cap[n + 1] - cap[n];
0813     }
0814 
0815     return 0;
0816 }
0817 
0818 
0819 void
0820 ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e)
0821 {
0822     int                                    *cap;
0823     u_char                                 *p, *pos;
0824     ngx_uint_t                              n;
0825     ngx_stream_session_t                   *s;
0826     ngx_stream_script_copy_capture_code_t  *code;
0827 
0828     s = e->session;
0829 
0830     code = (ngx_stream_script_copy_capture_code_t *) e->ip;
0831 
0832     e->ip += sizeof(ngx_stream_script_copy_capture_code_t);
0833 
0834     n = code->n;
0835 
0836     pos = e->pos;
0837 
0838     if (n < s->ncaptures) {
0839         cap = s->captures;
0840         p = s->captures_data;
0841         e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
0842     }
0843 
0844     ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0845                    "stream script capture: \"%*s\"", e->pos - pos, pos);
0846 }
0847 
0848 #endif
0849 
0850 
0851 static ngx_int_t
0852 ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
0853 {
0854     ngx_stream_script_full_name_code_t  *code;
0855 
0856     code = ngx_stream_script_add_code(*sc->lengths,
0857                                     sizeof(ngx_stream_script_full_name_code_t),
0858                                     NULL);
0859     if (code == NULL) {
0860         return NGX_ERROR;
0861     }
0862 
0863     code->code = (ngx_stream_script_code_pt) (void *)
0864                                           ngx_stream_script_full_name_len_code;
0865     code->conf_prefix = sc->conf_prefix;
0866 
0867     code = ngx_stream_script_add_code(*sc->values,
0868                         sizeof(ngx_stream_script_full_name_code_t), &sc->main);
0869     if (code == NULL) {
0870         return NGX_ERROR;
0871     }
0872 
0873     code->code = ngx_stream_script_full_name_code;
0874     code->conf_prefix = sc->conf_prefix;
0875 
0876     return NGX_OK;
0877 }
0878 
0879 
0880 static size_t
0881 ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e)
0882 {
0883     ngx_stream_script_full_name_code_t  *code;
0884 
0885     code = (ngx_stream_script_full_name_code_t *) e->ip;
0886 
0887     e->ip += sizeof(ngx_stream_script_full_name_code_t);
0888 
0889     return code->conf_prefix ? ngx_cycle->conf_prefix.len:
0890                                ngx_cycle->prefix.len;
0891 }
0892 
0893 
0894 static void
0895 ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e)
0896 {
0897     ngx_stream_script_full_name_code_t  *code;
0898 
0899     ngx_str_t  value, *prefix;
0900 
0901     code = (ngx_stream_script_full_name_code_t *) e->ip;
0902 
0903     value.data = e->buf.data;
0904     value.len = e->pos - e->buf.data;
0905 
0906     prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
0907                                  (ngx_str_t *) &ngx_cycle->prefix;
0908 
0909     if (ngx_get_full_name(e->session->connection->pool, prefix, &value)
0910         != NGX_OK)
0911     {
0912         e->ip = ngx_stream_script_exit;
0913         return;
0914     }
0915 
0916     e->buf = value;
0917 
0918     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0,
0919                    "stream script fullname: \"%V\"", &value);
0920 
0921     e->ip += sizeof(ngx_stream_script_full_name_code_t);
0922 }