Mercurial > hg > nginx-vendor-0-7
comparison 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 |
comparison
equal
deleted
inserted
replaced
273:60df8db42ffb | 274:052a7b1d40e5 |
---|---|
102 static ngx_int_t | 102 static ngx_int_t |
103 ngx_http_limit_zone_handler(ngx_http_request_t *r) | 103 ngx_http_limit_zone_handler(ngx_http_request_t *r) |
104 { | 104 { |
105 size_t len, n; | 105 size_t len, n; |
106 uint32_t hash; | 106 uint32_t hash; |
107 ngx_int_t rc; | |
107 ngx_slab_pool_t *shpool; | 108 ngx_slab_pool_t *shpool; |
108 ngx_rbtree_node_t *node, *sentinel; | 109 ngx_rbtree_node_t *node, *sentinel; |
109 ngx_pool_cleanup_t *cln; | 110 ngx_pool_cleanup_t *cln; |
110 ngx_http_variable_value_t *vv; | 111 ngx_http_variable_value_t *vv; |
111 ngx_http_limit_zone_ctx_t *ctx; | 112 ngx_http_limit_zone_ctx_t *ctx; |
129 | 130 |
130 if (vv == NULL || vv->not_found) { | 131 if (vv == NULL || vv->not_found) { |
131 return NGX_DECLINED; | 132 return NGX_DECLINED; |
132 } | 133 } |
133 | 134 |
134 r->limit_zone_set = 1; | |
135 | |
136 len = vv->len; | 135 len = vv->len; |
136 | |
137 if (len == 0) { | |
138 return NGX_DECLINED; | |
139 } | |
140 | |
141 if (len > 255) { | |
142 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
143 "the value of the \"%V\" variable " | |
144 "is more than 255 bytes: \"%V\"", | |
145 &ctx->var, vv); | |
146 return NGX_DECLINED; | |
147 } | |
148 | |
149 r->main->limit_zone_set = 1; | |
137 | 150 |
138 hash = ngx_crc32_short(vv->data, len); | 151 hash = ngx_crc32_short(vv->data, len); |
139 | 152 |
140 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_zone_cleanup_t)); | 153 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_zone_cleanup_t)); |
141 if (cln == NULL) { | 154 if (cln == NULL) { |
159 if (hash > node->key) { | 172 if (hash > node->key) { |
160 node = node->right; | 173 node = node->right; |
161 continue; | 174 continue; |
162 } | 175 } |
163 | 176 |
164 if (hash == node->key ){ | 177 /* hash == node->key */ |
178 | |
179 do { | |
165 lz = (ngx_http_limit_zone_node_t *) &node->color; | 180 lz = (ngx_http_limit_zone_node_t *) &node->color; |
166 | 181 |
167 if (len == (size_t) lz->len | 182 rc = ngx_memn2cmp(lz->data, vv->data, (size_t) lz->len, len); |
168 && ngx_strncmp(lz->data, vv->data, len) == 0) | 183 |
169 { | 184 if (rc == 0) { |
170 if ((ngx_uint_t) lz->conn < lzcf->conn) { | 185 if ((ngx_uint_t) lz->conn < lzcf->conn) { |
171 lz->conn++; | 186 lz->conn++; |
172 goto done; | 187 goto done; |
173 } | 188 } |
174 | 189 |
175 ngx_shmtx_unlock(&shpool->mutex); | 190 ngx_shmtx_unlock(&shpool->mutex); |
176 | 191 |
177 return NGX_HTTP_SERVICE_UNAVAILABLE; | 192 return NGX_HTTP_SERVICE_UNAVAILABLE; |
178 } | 193 } |
179 } | 194 |
195 node = (rc < 0) ? node->left : node->right; | |
196 | |
197 } while (node != sentinel && hash == node->key); | |
198 | |
199 break; | |
180 } | 200 } |
181 | 201 |
182 n = offsetof(ngx_rbtree_node_t, color) | 202 n = offsetof(ngx_rbtree_node_t, color) |
183 + offsetof(ngx_http_limit_zone_node_t, data) | 203 + offsetof(ngx_http_limit_zone_node_t, data) |
184 + len; | 204 + len; |
214 return NGX_DECLINED; | 234 return NGX_DECLINED; |
215 } | 235 } |
216 | 236 |
217 | 237 |
218 static void | 238 static void |
239 ngx_http_limit_zone_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
240 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
241 { | |
242 ngx_http_limit_zone_node_t *lzn, *lznt; | |
243 | |
244 for ( ;; ) { | |
245 | |
246 if (node->key < temp->key) { | |
247 | |
248 if (temp->left == sentinel) { | |
249 temp->left = node; | |
250 break; | |
251 } | |
252 | |
253 temp = temp->left; | |
254 | |
255 } else if (node->key > temp->key) { | |
256 | |
257 if (temp->right == sentinel) { | |
258 temp->right = node; | |
259 break; | |
260 } | |
261 | |
262 temp = temp->right; | |
263 | |
264 } else { /* node->key == temp->key */ | |
265 | |
266 lzn = (ngx_http_limit_zone_node_t *) &node->color; | |
267 lznt = (ngx_http_limit_zone_node_t *) &temp->color; | |
268 | |
269 if (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) { | |
270 | |
271 if (temp->left == sentinel) { | |
272 temp->left = node; | |
273 break; | |
274 } | |
275 | |
276 temp = temp->left; | |
277 | |
278 } else { | |
279 | |
280 if (temp->right == sentinel) { | |
281 temp->right = node; | |
282 break; | |
283 } | |
284 | |
285 temp = temp->right; | |
286 } | |
287 } | |
288 } | |
289 | |
290 node->parent = temp; | |
291 node->left = sentinel; | |
292 node->right = sentinel; | |
293 ngx_rbt_red(node); | |
294 } | |
295 | |
296 | |
297 static void | |
219 ngx_http_limit_zone_cleanup(void *data) | 298 ngx_http_limit_zone_cleanup(void *data) |
220 { | 299 { |
221 ngx_http_limit_zone_cleanup_t *lzcln = data; | 300 ngx_http_limit_zone_cleanup_t *lzcln = data; |
222 | 301 |
223 ngx_slab_pool_t *shpool; | 302 ngx_slab_pool_t *shpool; |
258 ctx = shm_zone->data; | 337 ctx = shm_zone->data; |
259 | 338 |
260 if (octx) { | 339 if (octx) { |
261 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { | 340 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { |
262 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, | 341 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
263 "limit_zone \"%V\" use the \"%V\" variable " | 342 "limit_zone \"%V\" uses the \"%V\" variable " |
264 "while previously it used the \"%V\" variable", | 343 "while previously it used the \"%V\" variable", |
265 &shm_zone->name, &ctx->var, &octx->var); | 344 &shm_zone->name, &ctx->var, &octx->var); |
266 return NGX_ERROR; | 345 return NGX_ERROR; |
267 } | 346 } |
268 | 347 |
285 | 364 |
286 ngx_rbtree_sentinel_init(sentinel); | 365 ngx_rbtree_sentinel_init(sentinel); |
287 | 366 |
288 ctx->rbtree->root = sentinel; | 367 ctx->rbtree->root = sentinel; |
289 ctx->rbtree->sentinel = sentinel; | 368 ctx->rbtree->sentinel = sentinel; |
290 ctx->rbtree->insert = ngx_rbtree_insert_value; | 369 ctx->rbtree->insert = ngx_http_limit_zone_rbtree_insert_value; |
291 | 370 |
292 return NGX_OK; | 371 return NGX_OK; |
293 } | 372 } |
294 | 373 |
295 | 374 |
417 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 496 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
418 "invalid number of connections \"%V\"", &value[2]); | 497 "invalid number of connections \"%V\"", &value[2]); |
419 return NGX_CONF_ERROR; | 498 return NGX_CONF_ERROR; |
420 } | 499 } |
421 | 500 |
501 if (n > 65535) { | |
502 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
503 "connection limit must be less 65536"); | |
504 return NGX_CONF_ERROR; | |
505 } | |
506 | |
422 lzcf->conn = n; | 507 lzcf->conn = n; |
423 | 508 |
424 return NGX_CONF_OK; | 509 return NGX_CONF_OK; |
425 } | 510 } |
426 | 511 |