static char *ngx_http_small_light_pattern_define(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_small_light_conf_t *srv_conf; ngx_uint_t rc; ngx_str_t *ptn_name; ngx_str_t *ptn_str; ngx_str_t *value; ngx_hash_init_t hash; srv_conf = conf; value = cf->args->elts; ptn_name = &value[1]; ptn_str = &value[2]; rc = ngx_hash_add_key(&srv_conf->patterns, ptn_name, ptn_str->data, NGX_HASH_READONLY_KEY); if (rc != NGX_OK) { return NGX_CONF_ERROR; } hash.hash = &srv_conf->hash; hash.key = ngx_hash_key_lc; hash.max_size = 128; hash.bucket_size = ngx_cacheline_size; hash.name = "small_light_pattern_define"; hash.pool = srv_conf->patterns.keys.pool; hash.temp_pool = NULL; if (ngx_hash_init(&hash, srv_conf->patterns.keys.elts, srv_conf->patterns.keys.nelts) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) {//ngx_http_core_preconfiguration函数在程序解析配置之前就调用这里 //将ngx_http_core_variables 的变量全部导入到variables_keys里面,其里面会有各个handler来帮助存取变量值。 ngx_int_t rc; ngx_http_variable_t *v; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); if (cmcf->variables_keys == NULL) { return NGX_ERROR; } cmcf->variables_keys->pool = cf->pool; cmcf->variables_keys->temp_pool = cf->pool; if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) != NGX_OK) { return NGX_ERROR; } //循环将这些变量加入到哈希表中。用户自定义的是不会存在这里面的,因为太多了。 for (v = ngx_http_core_variables; v->name.len; v++) { //将著名的头部字段加入variables_keys,注意没有加入variables。为了效率。 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, NGX_HASH_READONLY_KEY); if (rc == NGX_OK) { continue; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", &v->name); } return NGX_ERROR; } return NGX_OK; }
static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf) { #if (NGX_HTTP_SSI) ngx_int_t rc; ngx_http_ssi_main_conf_t *smcf; smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module); rc = ngx_hash_add_key(&smcf->commands, &ngx_http_perl_ssi_command.name, &ngx_http_perl_ssi_command, NGX_HASH_READONLY_KEY); if (rc != NGX_OK) { if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting SSI command \"%V\"", &ngx_http_perl_ssi_command.name); } return NGX_ERROR; } #endif return NGX_OK; }
int main(){ //数字对齐方法ngx_align用到了/os/unix/ngx_alloc.c中ngx_cacheline_size的值 //如果不启动nginx则该值为0,这时ngx_align就一直返回为0,所以我们这给他一个默认值 ngx_cacheline_size = 32; //用于构造带通配符的散列表 ngx_hash_keys_arrays_t ha; ngx_pool_t *pool = ngx_create_pool(2024, NULL); ha.temp_pool = pool; ha.pool = pool; if(ngx_hash_keys_array_init(&ha,NGX_HASH_LARGE) != NGX_OK){ printf("初始化失败\n"); return 0; } //添加元素 *.jd.com ngx_str_t *key = ngx_pcalloc(pool, sizeof(ngx_str_t)); key->len = ngx_strlen("*.com"); key->data = ngx_pcalloc(pool, ngx_strlen("*.com")); ngx_memcpy(key->data, "*.com", ngx_strlen("*.com")); int *value = ngx_pcalloc(pool, sizeof(int)); *value = 1234; ngx_int_t rc; rc = ngx_hash_add_key(&ha, key, value, NGX_HASH_WILDCARD_KEY); if(rc != NGX_OK){ printf("添加key错误\n"); } //构造通配符散列表 ngx_hash_init_t hash; hash.hash = NULL; hash.key = ngx_hash_key; hash.max_size = 10; hash.bucket_size = 100; hash.pool = pool; hash.temp_pool = pool; //初始化前置通配符散列表 rc = ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, ha.dns_wc_head.nelts); if(rc != NGX_OK){ printf("初始化通配符散列表错误\n"); } // *.com和 as.dd.com a.b.c.com都匹配 void *result = ngx_hash_find_wc_head((ngx_hash_wildcard_t *)hash.hash, "as.dd.com",ngx_strlen("as.dd.com")); int *bb = (int *)result; printf("%d\n",*bb); }
static ngx_int_t ngx_http_extravars_add_variables(ngx_conf_t *cf) { ngx_int_t rc; ngx_http_variable_t *v; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); for (v = ngx_http_extra_variables; v->name.len; v++) { rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, NGX_HASH_READONLY_KEY); if (rc == NGX_OK) { continue; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", &v->name); } return NGX_ERROR; } return NGX_OK; }
void* add_urls_to_array(ngx_pool_t *pool, ngx_hash_keys_arrays_t *ha, ngx_array_t *url, ngx_array_t *value) { ngx_uint_t loop; ngx_int_t rc; ngx_str_t *strUrl, *strValue; memset(ha, 0, sizeof(ngx_hash_keys_arrays_t)); ha->temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, &ngx_log); ha->pool = pool; if (ngx_hash_keys_array_init(ha, NGX_HASH_LARGE) != NGX_OK) { goto failed; } strUrl = url->elts; strValue = value->elts; for (loop = 0; loop < url->nelts; loop++) { rc = ngx_hash_add_key(ha, &strUrl[loop], &strValue[loop], NGX_HASH_WILDCARD_KEY); if (rc == NGX_ERROR) { goto failed; } } return ha; failed: ngx_destroy_pool(ha->temp_pool); return NULL; }
ngx_int_t ngx_http_small_light_parse_params(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx, ngx_str_t *define_pattern, char *pv) { char *tk, *tv, *sp1, *sp2; char *k, *kk, *v, *vv; ngx_str_t ks; char p[BUFSIZ]; if (define_pattern->len > BUFSIZ - 1) { return NGX_ERROR; } ngx_cpystrn((u_char *)p, define_pattern->data, define_pattern->len + 1); tk = strtok_r(p, ",", &sp1); while (tk != NULL) { tv = strtok_r(tk, "=", &sp2); k = tv; v = strtok_r(NULL, "=", &sp2); if (k == NULL || v == NULL) { return NGX_OK; } kk = ngx_palloc(r->pool, ngx_strlen(k) + 1); ngx_cpystrn((u_char *)kk, (u_char *)k, ngx_strlen(k) + 1); ks.data = (u_char *)kk; ks.len = ngx_strlen(kk); if (ngx_strcmp(k, "p") == 0) { ngx_cpystrn((u_char *)pv, (u_char *)v, ngx_strlen(v) + 1); } else { vv = ngx_palloc(r->pool, ngx_strlen(v) + 1); ngx_cpystrn((u_char *)vv, (u_char *)v, ngx_strlen(v) + 1); ngx_hash_add_key(&ctx->params, &ks, vv, NGX_HASH_READONLY_KEY); } tk = strtok_r(NULL, ",", &sp1); } return NGX_OK; }
ngx_http_variable_t * ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) {//在cmcf->variables_keys里面查找有没有key相同的,如果有就返回,否则申请一个新的槽位。 //变量的get/set回调还没有设置,需要上层设置的。 ngx_int_t rc; ngx_uint_t i; ngx_hash_key_t *key; ngx_http_variable_t *v; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { if (name->len != key[i].key.len || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) { continue; } v = key[i].value; if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the duplicate \"%V\" variable", name); return NULL; } return v; } //没有找到已有的,下面申请一个 v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); if (v == NULL) { return NULL; } v->name.len = name->len; v->name.data = ngx_pnalloc(cf->pool, name->len); if (v->name.data == NULL) { return NULL; } ngx_strlow(v->name.data, name->data, name->len); v->set_handler = NULL;//回调需要上层设置。 v->get_handler = NULL; v->data = 0; v->flags = flags; v->index = 0;// rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); if (rc == NGX_ERROR) { return NULL; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", name); return NULL; } return v; }
ngx_int_t ngx_stream_variables_add_core_vars(ngx_conf_t *cf) { ngx_int_t rc; ngx_stream_variable_t *cv, *v; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); if (cmcf->variables_keys == NULL) { return NGX_ERROR; } cmcf->variables_keys->pool = cf->pool; cmcf->variables_keys->temp_pool = cf->pool; if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) != NGX_OK) { return NGX_ERROR; } for (cv = ngx_stream_core_variables; cv->name.len; cv++) { v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); if (v == NULL) { return NGX_ERROR; } *v = *cv; rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, NGX_HASH_READONLY_KEY); if (rc == NGX_OK) { continue; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", &v->name); } return NGX_ERROR; } return NGX_OK; }
static char * ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri) { ngx_int_t rc; ngx_str_t *u; if (uri->len == 0) { u = NGX_HTTP_REFERER_NO_URI_PART; } else { u = ngx_palloc(cf->pool, sizeof(ngx_str_t)); if (u == NULL) { return NGX_CONF_ERROR; } *u = *uri; } rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY); if (rc == NGX_OK) { return NGX_CONF_OK; } if (rc == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", value); } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", value); } return NGX_CONF_ERROR; }
static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ngx_int_t rc; ngx_str_t *value, file; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_variable_value_t *var, **vp; ctx = cf->ctx; value = cf->args->elts; if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "hostnames") == 0) { ctx->hostnames = 1; return NGX_CONF_OK; } else if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; } else if (value[0].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid first parameter"); return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } key = 0; for (i = 0; i < value[1].len; i++) { key = ngx_hash(key, value[1].data[i]); } key %= ctx->keys.hsize; vp = ctx->values_hash[key].elts; if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { if (value[1].len != (size_t) vp[i]->len) { continue; } if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { var = vp[i]; goto found; } } } else { if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, sizeof(ngx_http_variable_value_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } var->len = value[1].len; var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); if (var->data == NULL) { return NGX_CONF_ERROR; } var->valid = 1; var->no_cacheable = 0; var->not_found = 0; vp = ngx_array_push(&ctx->values_hash[key]); if (vp == NULL) { return NGX_CONF_ERROR; } *vp = var; found: if (ngx_strcmp(value[0].data, "default") == 0) { if (ctx->default_value) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate default map parameter"); return NGX_CONF_ERROR; } ctx->default_value = var; return NGX_CONF_OK; } if (value[0].len && value[0].data[0] == '!') { value[0].len--; value[0].data++; } rc = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); if (rc == NGX_OK) { return NGX_CONF_OK; } if (rc == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } return NGX_CONF_ERROR; }
static void ngx_http_small_light_init_params_default(ngx_http_small_light_ctx_t *ctx) { ngx_str_t p = ngx_string("p"); ngx_str_t sx = ngx_string("sx"); ngx_str_t sy = ngx_string("sy"); ngx_str_t sw = ngx_string("sw"); ngx_str_t sh = ngx_string("sh"); ngx_str_t dx = ngx_string("dx"); ngx_str_t dy = ngx_string("dy"); ngx_str_t dw = ngx_string("dw"); ngx_str_t dh = ngx_string("dh"); ngx_str_t da = ngx_string("da"); ngx_str_t ds = ngx_string("ds"); ngx_str_t cw = ngx_string("cw"); ngx_str_t ch = ngx_string("ch"); ngx_str_t cc = ngx_string("cc"); ngx_str_t bw = ngx_string("bw"); ngx_str_t bh = ngx_string("bh"); ngx_str_t bc = ngx_string("bc"); ngx_str_t pt = ngx_string("pt"); ngx_str_t q = ngx_string("q"); ngx_str_t of = ngx_string("of"); ngx_str_t info = ngx_string("info"); ngx_str_t inhexif = ngx_string("inhexif"); ngx_str_t jpeghint = ngx_string("jpeghint"); ngx_str_t rmprof = ngx_string("rmprof"); ngx_str_t embedicon = ngx_string("embedicon"); ngx_str_t ix = ngx_string("ix"); ngx_str_t iy = ngx_string("iy"); ngx_str_t e = ngx_string("e"); ngx_hash_add_key(&ctx->params, &p, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &sx, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &sy, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &sw, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &sh, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &dx, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &dy, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &dw, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &dh, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &da, "l", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &ds, "n", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &cw, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &ch, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &cc, "000000", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &bw, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &bh, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &bc, "000000", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &pt, "n", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &q, "0", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &of, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &info, "0", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &inhexif, "n", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &jpeghint, "n", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &rmprof, "n", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &embedicon, "", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &ix, "0", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &iy, "0", NGX_HASH_READONLY_KEY); ngx_hash_add_key(&ctx->params, &e, NGX_HTTP_SMALL_LIGHT_CONVERTER_IMAGEMAGICK, NGX_HASH_READONLY_KEY); }
static ngx_int_t ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr) { ngx_int_t rc; ngx_uint_t n, s; ngx_hash_init_t hash; ngx_hash_keys_arrays_t ha; ngx_http_server_name_t *name; ngx_http_core_srv_conf_t **cscfp; #if (NGX_PCRE) ngx_uint_t regex, i; regex = 0; #endif ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); ha.temp_pool = ngx_create_pool(16384, cf->log); if (ha.temp_pool == NULL) { return NGX_ERROR; } ha.pool = cf->pool; if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { goto failed; } cscfp = addr->servers.elts; for (s = 0; s < addr->servers.nelts; s++) { name = cscfp[s]->server_names.elts; for (n = 0; n < cscfp[s]->server_names.nelts; n++) { #if (NGX_PCRE) if (name[n].regex) { regex++; continue; } #endif rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, NGX_HASH_WILDCARD_KEY); if (rc == NGX_ERROR) { return NGX_ERROR; } if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "invalid server name or wildcard \"%V\" on %s", &name[n].name, addr->opt.addr); return NGX_ERROR; } if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "conflicting server name \"%V\" on %s, ignored", &name[n].name, addr->opt.addr); } } } hash.key = ngx_hash_key_lc; hash.max_size = cmcf->server_names_hash_max_size; hash.bucket_size = cmcf->server_names_hash_bucket_size; hash.name = "server_names_hash"; hash.pool = cf->pool; if (ha.keys.nelts) { hash.hash = &addr->hash; hash.temp_pool = NULL; if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) { goto failed; } } if (ha.dns_wc_head.nelts) { ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts, sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards); hash.hash = NULL; hash.temp_pool = ha.temp_pool; if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, ha.dns_wc_head.nelts) != NGX_OK) { goto failed; } addr->wc_head = (ngx_hash_wildcard_t *) hash.hash; } if (ha.dns_wc_tail.nelts) { ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts, sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards); hash.hash = NULL; hash.temp_pool = ha.temp_pool; if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, ha.dns_wc_tail.nelts) != NGX_OK) { goto failed; } addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash; } ngx_destroy_pool(ha.temp_pool); #if (NGX_PCRE) if (regex == 0) { return NGX_OK; } addr->nregex = regex; addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t)); if (addr->regex == NULL) { return NGX_ERROR; } i = 0; for (s = 0; s < addr->servers.nelts; s++) { name = cscfp[s]->server_names.elts; for (n = 0; n < cscfp[s]->server_names.nelts; n++) { if (name[n].regex) { addr->regex[i++] = name[n]; } } } #endif return NGX_OK; failed: ngx_destroy_pool(ha.temp_pool); return NGX_ERROR; }
ngx_stream_variable_t * ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) { ngx_int_t rc; ngx_uint_t i; ngx_hash_key_t *key; ngx_stream_variable_t *v; ngx_stream_core_main_conf_t *cmcf; if (name->len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid variable name \"$\""); return NULL; } cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { if (name->len != key[i].key.len || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) { continue; } v = key[i].value; if (!(v->flags & NGX_STREAM_VAR_CHANGEABLE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the duplicate \"%V\" variable", name); return NULL; } return v; } v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); if (v == NULL) { return NULL; } v->name.len = name->len; v->name.data = ngx_pnalloc(cf->pool, name->len); if (v->name.data == NULL) { return NULL; } ngx_strlow(v->name.data, name->data, name->len); v->set_handler = NULL; v->get_handler = NULL; v->data = 0; v->flags = flags; v->index = 0; rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); if (rc == NGX_ERROR) { return NULL; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", name); return NULL; } return v; }
static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { u_char *data; size_t len; ngx_int_t rv; ngx_str_t *value, v; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_complex_value_t cv, *cvp; ngx_http_variable_value_t *var, **vp; ngx_http_compile_complex_value_t ccv; ctx = cf->ctx; value = cf->args->elts; if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "hostnames") == 0) { ctx->hostnames = 1; return NGX_CONF_OK; } if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "volatile") == 0) { ctx->no_cacheable = 1; return NGX_CONF_OK; } if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { return ngx_conf_include(cf, dummy, conf); } key = 0; for (i = 0; i < value[1].len; i++) { key = ngx_hash(key, value[1].data[i]); } key %= ctx->keys.hsize; vp = ctx->values_hash[key].elts; if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { if (vp[i]->valid) { data = vp[i]->data; len = vp[i]->len; } else { cvp = (ngx_http_complex_value_t *) vp[i]->data; data = cvp->value.data; len = cvp->value.len; } if (value[1].len != len) { continue; } if (ngx_strncmp(value[1].data, data, len) == 0) { var = vp[i]; goto found; } } } else { if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, sizeof(ngx_http_variable_value_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } v.len = value[1].len; v.data = ngx_pstrdup(ctx->keys.pool, &value[1]); if (v.data == NULL) { return NGX_CONF_ERROR; } ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = ctx->cf; ccv.value = &v; ccv.complex_value = &cv; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } if (cv.lengths != NULL) { cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_complex_value_t)); if (cvp == NULL) { return NGX_CONF_ERROR; } *cvp = cv; var->len = 0; var->data = (u_char *) cvp; var->valid = 0; } else { var->len = v.len; var->data = v.data; var->valid = 1; } var->no_cacheable = 0; var->not_found = 0; vp = ngx_array_push(&ctx->values_hash[key]); if (vp == NULL) { return NGX_CONF_ERROR; } *vp = var; found: if (ngx_strcmp(value[0].data, "default") == 0) { if (ctx->default_value) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate default map parameter"); return NGX_CONF_ERROR; } ctx->default_value = var; return NGX_CONF_OK; } #if (NGX_PCRE) if (value[0].len && value[0].data[0] == '~') { ngx_regex_compile_t rc; ngx_http_map_regex_t *regex; u_char errstr[NGX_MAX_CONF_ERRSTR]; regex = ngx_array_push(&ctx->regexes); if (regex == NULL) { return NGX_CONF_ERROR; } value[0].len--; value[0].data++; ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); if (value[0].data[0] == '*') { value[0].len--; value[0].data++; rc.options = NGX_REGEX_CASELESS; } rc.pattern = value[0]; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.err.data = errstr; regex->regex = ngx_http_regex_compile(ctx->cf, &rc); if (regex->regex == NULL) { return NGX_CONF_ERROR; } regex->value = var; return NGX_CONF_OK; } #endif if (value[0].len && value[0].data[0] == '\\') { value[0].len--; value[0].data++; } rv = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); if (rv == NGX_OK) { return NGX_CONF_OK; } if (rv == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } if (rv == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } return NGX_CONF_ERROR; }