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