Mercurial > hg > nginx
comparison src/stream/ngx_stream_limit_conn_module.c @ 6610:d5b5866c06c4
Stream: got rid of pseudo variables.
Stream limit_conn, upstream_hash and proxy modules now use complex values.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Wed, 29 Jun 2016 12:46:12 +0300 |
parents | 2f41d383c9c7 |
children | 8ed51b02f655 |
comparison
equal
deleted
inserted
replaced
6609:73543af69f14 | 6610:d5b5866c06c4 |
---|---|
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_stream.h> | 10 #include <ngx_stream.h> |
11 | 11 |
12 | 12 |
13 typedef struct { | 13 typedef struct { |
14 u_char color; | 14 u_char color; |
15 u_char len; | 15 u_char len; |
16 u_short conn; | 16 u_short conn; |
17 u_char data[1]; | 17 u_char data[1]; |
18 } ngx_stream_limit_conn_node_t; | 18 } ngx_stream_limit_conn_node_t; |
19 | 19 |
20 | 20 |
21 typedef struct { | 21 typedef struct { |
22 ngx_shm_zone_t *shm_zone; | 22 ngx_shm_zone_t *shm_zone; |
23 ngx_rbtree_node_t *node; | 23 ngx_rbtree_node_t *node; |
24 } ngx_stream_limit_conn_cleanup_t; | 24 } ngx_stream_limit_conn_cleanup_t; |
25 | 25 |
26 | 26 |
27 typedef struct { | 27 typedef struct { |
28 ngx_rbtree_t *rbtree; | 28 ngx_rbtree_t *rbtree; |
29 ngx_stream_complex_value_t key; | |
29 } ngx_stream_limit_conn_ctx_t; | 30 } ngx_stream_limit_conn_ctx_t; |
30 | 31 |
31 | 32 |
32 typedef struct { | 33 typedef struct { |
33 ngx_shm_zone_t *shm_zone; | 34 ngx_shm_zone_t *shm_zone; |
34 ngx_uint_t conn; | 35 ngx_uint_t conn; |
35 } ngx_stream_limit_conn_limit_t; | 36 } ngx_stream_limit_conn_limit_t; |
36 | 37 |
37 | 38 |
38 typedef struct { | 39 typedef struct { |
39 ngx_array_t limits; | 40 ngx_array_t limits; |
40 ngx_uint_t log_level; | 41 ngx_uint_t log_level; |
41 } ngx_stream_limit_conn_conf_t; | 42 } ngx_stream_limit_conn_conf_t; |
42 | 43 |
43 | 44 |
44 static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, | 45 static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, |
45 ngx_str_t *key, uint32_t hash); | 46 ngx_str_t *key, uint32_t hash); |
128 ngx_str_t key; | 129 ngx_str_t key; |
129 ngx_uint_t i; | 130 ngx_uint_t i; |
130 ngx_slab_pool_t *shpool; | 131 ngx_slab_pool_t *shpool; |
131 ngx_rbtree_node_t *node; | 132 ngx_rbtree_node_t *node; |
132 ngx_pool_cleanup_t *cln; | 133 ngx_pool_cleanup_t *cln; |
133 struct sockaddr_in *sin; | |
134 #if (NGX_HAVE_INET6) | |
135 struct sockaddr_in6 *sin6; | |
136 #endif | |
137 ngx_stream_limit_conn_ctx_t *ctx; | 134 ngx_stream_limit_conn_ctx_t *ctx; |
138 ngx_stream_limit_conn_node_t *lc; | 135 ngx_stream_limit_conn_node_t *lc; |
139 ngx_stream_limit_conn_conf_t *lccf; | 136 ngx_stream_limit_conn_conf_t *lccf; |
140 ngx_stream_limit_conn_limit_t *limits; | 137 ngx_stream_limit_conn_limit_t *limits; |
141 ngx_stream_limit_conn_cleanup_t *lccln; | 138 ngx_stream_limit_conn_cleanup_t *lccln; |
142 | 139 |
143 switch (s->connection->sockaddr->sa_family) { | |
144 | |
145 case AF_INET: | |
146 sin = (struct sockaddr_in *) s->connection->sockaddr; | |
147 | |
148 key.len = sizeof(in_addr_t); | |
149 key.data = (u_char *) &sin->sin_addr; | |
150 | |
151 break; | |
152 | |
153 #if (NGX_HAVE_INET6) | |
154 case AF_INET6: | |
155 sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; | |
156 | |
157 key.len = sizeof(struct in6_addr); | |
158 key.data = sin6->sin6_addr.s6_addr; | |
159 | |
160 break; | |
161 #endif | |
162 | |
163 default: | |
164 return NGX_DECLINED; | |
165 } | |
166 | |
167 hash = ngx_crc32_short(key.data, key.len); | |
168 | |
169 lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module); | 140 lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module); |
170 limits = lccf->limits.elts; | 141 limits = lccf->limits.elts; |
171 | 142 |
172 for (i = 0; i < lccf->limits.nelts; i++) { | 143 for (i = 0; i < lccf->limits.nelts; i++) { |
173 ctx = limits[i].shm_zone->data; | 144 ctx = limits[i].shm_zone->data; |
145 | |
146 if (ngx_stream_complex_value(s, &ctx->key, &key) != NGX_OK) { | |
147 return NGX_ERROR; | |
148 } | |
149 | |
150 if (key.len == 0) { | |
151 continue; | |
152 } | |
153 | |
154 if (key.len > 255) { | |
155 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, | |
156 "the value of the \"%V\" key " | |
157 "is more than 255 bytes: \"%V\"", | |
158 &ctx->key.value, &key); | |
159 continue; | |
160 } | |
161 | |
162 hash = ngx_crc32_short(key.data, key.len); | |
174 | 163 |
175 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; | 164 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; |
176 | 165 |
177 ngx_shmtx_lock(&shpool->mutex); | 166 ngx_shmtx_lock(&shpool->mutex); |
178 | 167 |
381 ngx_stream_limit_conn_ctx_t *ctx; | 370 ngx_stream_limit_conn_ctx_t *ctx; |
382 | 371 |
383 ctx = shm_zone->data; | 372 ctx = shm_zone->data; |
384 | 373 |
385 if (octx) { | 374 if (octx) { |
375 if (ctx->key.value.len != octx->key.value.len | |
376 || ngx_strncmp(ctx->key.value.data, octx->key.value.data, | |
377 ctx->key.value.len) | |
378 != 0) | |
379 { | |
380 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, | |
381 "limit_conn_zone \"%V\" uses the \"%V\" key " | |
382 "while previously it used the \"%V\" key", | |
383 &shm_zone->shm.name, &ctx->key.value, | |
384 &octx->key.value); | |
385 return NGX_ERROR; | |
386 } | |
387 | |
386 ctx->rbtree = octx->rbtree; | 388 ctx->rbtree = octx->rbtree; |
387 | 389 |
388 return NGX_OK; | 390 return NGX_OK; |
389 } | 391 } |
390 | 392 |
464 | 466 |
465 | 467 |
466 static char * | 468 static char * |
467 ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 469 ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
468 { | 470 { |
469 u_char *p; | 471 u_char *p; |
470 ssize_t size; | 472 ssize_t size; |
471 ngx_str_t *value, name, s; | 473 ngx_str_t *value, name, s; |
472 ngx_uint_t i; | 474 ngx_uint_t i; |
473 ngx_shm_zone_t *shm_zone; | 475 ngx_shm_zone_t *shm_zone; |
474 ngx_stream_limit_conn_ctx_t *ctx; | 476 ngx_stream_limit_conn_ctx_t *ctx; |
477 ngx_stream_compile_complex_value_t ccv; | |
475 | 478 |
476 value = cf->args->elts; | 479 value = cf->args->elts; |
477 | 480 |
478 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_limit_conn_ctx_t)); | 481 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_limit_conn_ctx_t)); |
479 if (ctx == NULL) { | 482 if (ctx == NULL) { |
483 return NGX_CONF_ERROR; | |
484 } | |
485 | |
486 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); | |
487 | |
488 ccv.cf = cf; | |
489 ccv.value = &value[1]; | |
490 ccv.complex_value = &ctx->key; | |
491 | |
492 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { | |
480 return NGX_CONF_ERROR; | 493 return NGX_CONF_ERROR; |
481 } | 494 } |
482 | 495 |
483 size = 0; | 496 size = 0; |
484 name.len = 0; | 497 name.len = 0; |
536 if (shm_zone == NULL) { | 549 if (shm_zone == NULL) { |
537 return NGX_CONF_ERROR; | 550 return NGX_CONF_ERROR; |
538 } | 551 } |
539 | 552 |
540 if (shm_zone->data) { | 553 if (shm_zone->data) { |
554 ctx = shm_zone->data; | |
555 | |
541 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 556 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
542 "%V \"%V\" is already bound to key " | 557 "%V \"%V\" is already bound to key \"%V\"", |
543 "\"$binary_remote_addr\"", | 558 &cmd->name, &name, &ctx->key.value); |
544 &cmd->name, &name); | |
545 return NGX_CONF_ERROR; | |
546 } | |
547 | |
548 if (ngx_strcmp(value[1].data, "$binary_remote_addr") != 0) { | |
549 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
550 "unsupported key \"%V\", use " | |
551 "$binary_remote_addr", &value[1]); | |
552 return NGX_CONF_ERROR; | 559 return NGX_CONF_ERROR; |
553 } | 560 } |
554 | 561 |
555 shm_zone->init = ngx_stream_limit_conn_init_zone; | 562 shm_zone->init = ngx_stream_limit_conn_init_zone; |
556 shm_zone->data = ctx; | 563 shm_zone->data = ctx; |