Mercurial > hg > nginx-ranges
diff src/http/modules/ngx_http_limit_zone_module.c @ 274:052a7b1d40e5 NGINX_0_5_7
nginx 0.5.7
*) Feature: the ssl_session_cache storage optimization.
*) Bugfixes in the "ssl_session_cache" and "limit_zone" directives.
*) Bugfix: the segmentation fault was occurred on start or while
reconfiguration if the "ssl_session_cache" or "limit_zone"
directives were used on 64-bit platforms.
*) Bugfix: a segmentation fault occurred if the "add_before_body" or
"add_after_body" directives were used and there was no
"Content-Type" header line in response.
*) Bugfix: the OpenSSL library was always built with the threads
support.
Thanks to Den Ivanov.
*) Bugfix: the PCRE-6.5+ library and the icc compiler compatibility.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 15 Jan 2007 00:00:00 +0300 |
parents | 29a6403156b0 |
children | c5c2b2883984 |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_limit_zone_module.c +++ b/src/http/modules/ngx_http_limit_zone_module.c @@ -104,6 +104,7 @@ ngx_http_limit_zone_handler(ngx_http_req { size_t len, n; uint32_t hash; + ngx_int_t rc; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node, *sentinel; ngx_pool_cleanup_t *cln; @@ -131,9 +132,21 @@ ngx_http_limit_zone_handler(ngx_http_req return NGX_DECLINED; } - r->limit_zone_set = 1; + len = vv->len; + + if (len == 0) { + return NGX_DECLINED; + } - len = vv->len; + if (len > 255) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the value of the \"%V\" variable " + "is more than 255 bytes: \"%V\"", + &ctx->var, vv); + return NGX_DECLINED; + } + + r->main->limit_zone_set = 1; hash = ngx_crc32_short(vv->data, len); @@ -161,12 +174,14 @@ ngx_http_limit_zone_handler(ngx_http_req continue; } - if (hash == node->key ){ + /* hash == node->key */ + + do { lz = (ngx_http_limit_zone_node_t *) &node->color; - if (len == (size_t) lz->len - && ngx_strncmp(lz->data, vv->data, len) == 0) - { + rc = ngx_memn2cmp(lz->data, vv->data, (size_t) lz->len, len); + + if (rc == 0) { if ((ngx_uint_t) lz->conn < lzcf->conn) { lz->conn++; goto done; @@ -176,7 +191,12 @@ ngx_http_limit_zone_handler(ngx_http_req return NGX_HTTP_SERVICE_UNAVAILABLE; } - } + + node = (rc < 0) ? node->left : node->right; + + } while (node != sentinel && hash == node->key); + + break; } n = offsetof(ngx_rbtree_node_t, color) @@ -216,6 +236,65 @@ done: static void +ngx_http_limit_zone_rbtree_insert_value(ngx_rbtree_node_t *temp, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) +{ + ngx_http_limit_zone_node_t *lzn, *lznt; + + for ( ;; ) { + + if (node->key < temp->key) { + + if (temp->left == sentinel) { + temp->left = node; + break; + } + + temp = temp->left; + + } else if (node->key > temp->key) { + + if (temp->right == sentinel) { + temp->right = node; + break; + } + + temp = temp->right; + + } else { /* node->key == temp->key */ + + lzn = (ngx_http_limit_zone_node_t *) &node->color; + lznt = (ngx_http_limit_zone_node_t *) &temp->color; + + if (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) { + + if (temp->left == sentinel) { + temp->left = node; + break; + } + + temp = temp->left; + + } else { + + if (temp->right == sentinel) { + temp->right = node; + break; + } + + temp = temp->right; + } + } + } + + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + ngx_rbt_red(node); +} + + +static void ngx_http_limit_zone_cleanup(void *data) { ngx_http_limit_zone_cleanup_t *lzcln = data; @@ -260,7 +339,7 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo if (octx) { if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, - "limit_zone \"%V\" use the \"%V\" variable " + "limit_zone \"%V\" uses the \"%V\" variable " "while previously it used the \"%V\" variable", &shm_zone->name, &ctx->var, &octx->var); return NGX_ERROR; @@ -287,7 +366,7 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo ctx->rbtree->root = sentinel; ctx->rbtree->sentinel = sentinel; - ctx->rbtree->insert = ngx_rbtree_insert_value; + ctx->rbtree->insert = ngx_http_limit_zone_rbtree_insert_value; return NGX_OK; } @@ -419,6 +498,12 @@ ngx_http_limit_conn(ngx_conf_t *cf, ngx_ return NGX_CONF_ERROR; } + if (n > 65535) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "connection limit must be less 65536"); + return NGX_CONF_ERROR; + } + lzcf->conn = n; return NGX_CONF_OK;