ngx_hash.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 956 行 · 第 1/2 页

C
956
字号
#endif        dot = 0;        for (len = 0; len < names[n].key.len; len++) {            if (names[n].key.data[len] == '.') {                dot = 1;                break;            }        }        name = ngx_array_push(&curr_names);        if (name == NULL) {            return NGX_ERROR;        }        name->key.len = len;        name->key.data = names[n].key.data;        name->key_hash = hinit->key(name->key.data, name->key.len);        name->value = names[n].value;#if 0        ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,                      "wc1: \"%V\" %ui", &name->key, dot);#endif        dot_len = len + 1;        if (dot) {            len++;        }        next_names.nelts = 0;        if (names[n].key.len != len) {            next_name = ngx_array_push(&next_names);            if (next_name == NULL) {                return NGX_ERROR;            }            next_name->key.len = names[n].key.len - len;            next_name->key.data = names[n].key.data + len;            next_name->key_hash= 0;            next_name->value = names[n].value;#if 0            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,                          "wc2: \"%V\"", &next_name->key);#endif        }        for (i = n + 1; i < nelts; i++) {            if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) {                break;            }            if (!dot                && names[i].key.len > len                && names[i].key.data[len] != '.')            {                break;            }            next_name = ngx_array_push(&next_names);            if (next_name == NULL) {                return NGX_ERROR;            }            next_name->key.len = names[i].key.len - dot_len;            next_name->key.data = names[i].key.data + dot_len;            next_name->key_hash= 0;            next_name->value = names[i].value;#if 0            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,                          "wc3: \"%V\"", &next_name->key);#endif        }        if (next_names.nelts) {            h = *hinit;            h.hash = NULL;            if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts,                                       next_names.nelts)                != NGX_OK)            {                return NGX_ERROR;            }            wdc = (ngx_hash_wildcard_t *) h.hash;            if (names[n].key.len == len) {                wdc->value = names[n].value;#if 0                ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,                              "wdc: \"%V\"", wdc->value);#endif            }            name->value = (void *) ((uintptr_t) wdc | (dot ? 1 : 3));        }    }    if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts,                      curr_names.nelts)        != NGX_OK)    {        return NGX_ERROR;    }    return NGX_OK;}ngx_uint_tngx_hash_key(u_char *data, size_t len){    ngx_uint_t  i, key;    key = 0;    for (i = 0; i < len; i++) {        key = ngx_hash(key, data[i]);    }    return key;}ngx_uint_tngx_hash_key_lc(u_char *data, size_t len){    ngx_uint_t  i, key;    key = 0;    for (i = 0; i < len; i++) {        key = ngx_hash(key, ngx_tolower(data[i]));    }    return key;}ngx_int_tngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type){    ngx_uint_t  asize;    if (type == NGX_HASH_SMALL) {        asize = 4;        ha->hsize = 107;    } else {        asize = NGX_HASH_LARGE_ASIZE;        ha->hsize = NGX_HASH_LARGE_HSIZE;    }    if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t))        != NGX_OK)    {        return NGX_ERROR;    }    if (ngx_array_init(&ha->dns_wc_head, ha->temp_pool, asize,                       sizeof(ngx_hash_key_t))        != NGX_OK)    {        return NGX_ERROR;    }    if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize,                       sizeof(ngx_hash_key_t))        != NGX_OK)    {        return NGX_ERROR;    }    ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);    if (ha->keys_hash == NULL) {        return NGX_ERROR;    }    ha->dns_wc_head_hash = ngx_pcalloc(ha->temp_pool,                                       sizeof(ngx_array_t) * ha->hsize);    if (ha->dns_wc_head_hash == NULL) {        return NGX_ERROR;    }    ha->dns_wc_tail_hash = ngx_pcalloc(ha->temp_pool,                                       sizeof(ngx_array_t) * ha->hsize);    if (ha->dns_wc_tail_hash == NULL) {        return NGX_ERROR;    }    return NGX_OK;}ngx_int_tngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,    ngx_uint_t flags){    size_t           len;    u_char          *p;    ngx_str_t       *name;    ngx_uint_t       i, k, n, skip, last;    ngx_array_t     *keys, *hwc;    ngx_hash_key_t  *hk;    last = key->len;    if (flags & NGX_HASH_WILDCARD_KEY) {        /*         * supported wildcards:         *     "*.example.com", ".example.com", and "www.example.*"         */        n = 0;        for (i = 0; i < key->len; i++) {            if (key->data[i] == '*') {                if (++n > 1) {                    return NGX_DECLINED;                }            }            if (key->data[i] == '.' && key->data[i + 1] == '.') {                return NGX_DECLINED;            }        }        if (key->len > 1 && key->data[0] == '.') {            skip = 1;            goto wildcard;        }        if (key->len > 2) {            if (key->data[0] == '*' && key->data[1] == '.') {                skip = 2;                goto wildcard;            }            if (key->data[i - 2] == '.' && key->data[i - 1] == '*') {                skip = 0;                last -= 2;                goto wildcard;            }        }        if (n) {            return NGX_DECLINED;        }    }    /* exact hash */    k = 0;    for (i = 0; i < last; i++) {        if (!(flags & NGX_HASH_READONLY_KEY)) {            key->data[i] = ngx_tolower(key->data[i]);        }        k = ngx_hash(k, key->data[i]);    }    k %= ha->hsize;    /* check conflicts in exact hash */    name = ha->keys_hash[k].elts;    if (name) {        for (i = 0; i < ha->keys_hash[k].nelts; i++) {            if (last != name[i].len) {                continue;            }            if (ngx_strncmp(key->data, name[i].data, last) == 0) {                return NGX_BUSY;            }        }    } else {        if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,                           sizeof(ngx_str_t))            != NGX_OK)        {            return NGX_ERROR;        }    }    name = ngx_array_push(&ha->keys_hash[k]);    if (name == NULL) {        return NGX_ERROR;    }    *name = *key;    hk = ngx_array_push(&ha->keys);    if (hk == NULL) {        return NGX_ERROR;    }    hk->key = *key;    hk->key_hash = ngx_hash_key(key->data, last);    hk->value = value;    return NGX_OK;wildcard:    /* wildcard hash */    k = 0;    for (i = skip; i < last; i++) {        key->data[i] = ngx_tolower(key->data[i]);        k = ngx_hash(k, key->data[i]);    }    k %= ha->hsize;    if (skip == 1) {        /* check conflicts in exact hash for ".example.com" */        name = ha->keys_hash[k].elts;        if (name) {            len = last - skip;            for (i = 0; i < ha->keys_hash[k].nelts; i++) {                if (len != name[i].len) {                    continue;                }                if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {                    return NGX_BUSY;                }            }        } else {            if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,                               sizeof(ngx_str_t))                != NGX_OK)            {                return NGX_ERROR;            }        }        name = ngx_array_push(&ha->keys_hash[k]);        if (name == NULL) {            return NGX_ERROR;        }        name->len = last - 1;        name->data = ngx_palloc(ha->temp_pool, name->len);        if (name->data == NULL) {            return NGX_ERROR;        }        ngx_memcpy(name->data, &key->data[1], name->len);    }    if (skip) {        /*         * convert "*.example.com" to "com.example.\0"         *      and ".example.com" to "com.example\0"         */        p = ngx_palloc(ha->temp_pool, last);        if (p == NULL) {            return NGX_ERROR;        }        len = 0;        n = 0;        for (i = last - 1; i; i--) {            if (key->data[i] == '.') {                ngx_memcpy(&p[n], &key->data[i + 1], len);                n += len;                p[n++] = '.';                len = 0;                continue;            }            len++;        }        if (len) {            ngx_memcpy(&p[n], &key->data[1], len);            n += len;        }        p[n] = '\0';        hwc = &ha->dns_wc_head;        keys = &ha->dns_wc_head_hash[k];    } else {        /* convert "www.example.*" to "www.example\0" */        last++;        p = ngx_palloc(ha->temp_pool, last);        if (p == NULL) {            return NGX_ERROR;        }        ngx_cpystrn(p, key->data, last);        hwc = &ha->dns_wc_tail;        keys = &ha->dns_wc_tail_hash[k];    }    hk = ngx_array_push(hwc);    if (hk == NULL) {        return NGX_ERROR;    }    hk->key.len = last - 1;    hk->key.data = p;    hk->key_hash = 0;    hk->value = value;    /* check conflicts in wildcard hash */    name = keys->elts;    if (name) {        len = last - skip;        for (i = 0; i < keys->nelts; i++) {            if (len != name[i].len) {                continue;            }            if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {                return NGX_BUSY;            }        }    } else {        if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)        {            return NGX_ERROR;        }    }    name = ngx_array_push(keys);    if (name == NULL) {        return NGX_ERROR;    }    name->len = last - skip;    name->data = ngx_palloc(ha->temp_pool, name->len);    if (name->data == NULL) {        return NGX_ERROR;    }    ngx_memcpy(name->data, key->data + skip, name->len);    return NGX_OK;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?