Mercurial > hg > nginx
comparison src/stream/ngx_stream_limit_conn_module.c @ 7595:9606d93aa586
Limit conn: $limit_conn_status variable.
The variable takes one of the values: PASSED, REJECTED or REJECTED_DRY_RUN.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 18 Nov 2019 17:48:32 +0300 |
parents | 359b0ea2b067 |
children | b45f052483b8 |
comparison
equal
deleted
inserted
replaced
7594:359b0ea2b067 | 7595:9606d93aa586 |
---|---|
6 | 6 |
7 | 7 |
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_stream.h> | 10 #include <ngx_stream.h> |
11 | |
12 | |
13 #define NGX_STREAM_LIMIT_CONN_PASSED 1 | |
14 #define NGX_STREAM_LIMIT_CONN_REJECTED 2 | |
15 #define NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN 3 | |
11 | 16 |
12 | 17 |
13 typedef struct { | 18 typedef struct { |
14 u_char color; | 19 u_char color; |
15 u_char len; | 20 u_char len; |
46 static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, | 51 static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, |
47 ngx_str_t *key, uint32_t hash); | 52 ngx_str_t *key, uint32_t hash); |
48 static void ngx_stream_limit_conn_cleanup(void *data); | 53 static void ngx_stream_limit_conn_cleanup(void *data); |
49 static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool); | 54 static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool); |
50 | 55 |
56 static ngx_int_t ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s, | |
57 ngx_stream_variable_value_t *v, uintptr_t data); | |
51 static void *ngx_stream_limit_conn_create_conf(ngx_conf_t *cf); | 58 static void *ngx_stream_limit_conn_create_conf(ngx_conf_t *cf); |
52 static char *ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, | 59 static char *ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, |
53 void *child); | 60 void *child); |
54 static char *ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, | 61 static char *ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
55 void *conf); | 62 void *conf); |
56 static char *ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, | 63 static char *ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, |
57 void *conf); | 64 void *conf); |
65 static ngx_int_t ngx_stream_limit_conn_add_variables(ngx_conf_t *cf); | |
58 static ngx_int_t ngx_stream_limit_conn_init(ngx_conf_t *cf); | 66 static ngx_int_t ngx_stream_limit_conn_init(ngx_conf_t *cf); |
59 | 67 |
60 | 68 |
61 static ngx_conf_enum_t ngx_stream_limit_conn_log_levels[] = { | 69 static ngx_conf_enum_t ngx_stream_limit_conn_log_levels[] = { |
62 { ngx_string("info"), NGX_LOG_INFO }, | 70 { ngx_string("info"), NGX_LOG_INFO }, |
100 ngx_null_command | 108 ngx_null_command |
101 }; | 109 }; |
102 | 110 |
103 | 111 |
104 static ngx_stream_module_t ngx_stream_limit_conn_module_ctx = { | 112 static ngx_stream_module_t ngx_stream_limit_conn_module_ctx = { |
105 NULL, /* preconfiguration */ | 113 ngx_stream_limit_conn_add_variables, /* preconfiguration */ |
106 ngx_stream_limit_conn_init, /* postconfiguration */ | 114 ngx_stream_limit_conn_init, /* postconfiguration */ |
107 | 115 |
108 NULL, /* create main configuration */ | 116 NULL, /* create main configuration */ |
109 NULL, /* init main configuration */ | 117 NULL, /* init main configuration */ |
110 | 118 |
127 NULL, /* exit master */ | 135 NULL, /* exit master */ |
128 NGX_MODULE_V1_PADDING | 136 NGX_MODULE_V1_PADDING |
129 }; | 137 }; |
130 | 138 |
131 | 139 |
140 static ngx_stream_variable_t ngx_stream_limit_conn_vars[] = { | |
141 | |
142 { ngx_string("limit_conn_status"), NULL, | |
143 ngx_stream_limit_conn_status_variable, 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, | |
144 | |
145 ngx_stream_null_variable | |
146 }; | |
147 | |
148 | |
149 static ngx_str_t ngx_stream_limit_conn_status[] = { | |
150 ngx_string("PASSED"), | |
151 ngx_string("REJECTED"), | |
152 ngx_string("REJECTED_DRY_RUN") | |
153 }; | |
154 | |
155 | |
132 static ngx_int_t | 156 static ngx_int_t |
133 ngx_stream_limit_conn_handler(ngx_stream_session_t *s) | 157 ngx_stream_limit_conn_handler(ngx_stream_session_t *s) |
134 { | 158 { |
135 size_t n; | 159 size_t n; |
136 uint32_t hash; | 160 uint32_t hash; |
165 "is more than 255 bytes: \"%V\"", | 189 "is more than 255 bytes: \"%V\"", |
166 &ctx->key.value, &key); | 190 &ctx->key.value, &key); |
167 continue; | 191 continue; |
168 } | 192 } |
169 | 193 |
194 s->limit_conn_status = NGX_STREAM_LIMIT_CONN_PASSED; | |
195 | |
170 hash = ngx_crc32_short(key.data, key.len); | 196 hash = ngx_crc32_short(key.data, key.len); |
171 | 197 |
172 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; | 198 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; |
173 | 199 |
174 ngx_shmtx_lock(&shpool->mutex); | 200 ngx_shmtx_lock(&shpool->mutex); |
186 if (node == NULL) { | 212 if (node == NULL) { |
187 ngx_shmtx_unlock(&shpool->mutex); | 213 ngx_shmtx_unlock(&shpool->mutex); |
188 ngx_stream_limit_conn_cleanup_all(s->connection->pool); | 214 ngx_stream_limit_conn_cleanup_all(s->connection->pool); |
189 | 215 |
190 if (lccf->dry_run) { | 216 if (lccf->dry_run) { |
217 s->limit_conn_status = | |
218 NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN; | |
191 return NGX_DECLINED; | 219 return NGX_DECLINED; |
192 } | 220 } |
221 | |
222 s->limit_conn_status = NGX_STREAM_LIMIT_CONN_REJECTED; | |
193 | 223 |
194 return NGX_STREAM_SERVICE_UNAVAILABLE; | 224 return NGX_STREAM_SERVICE_UNAVAILABLE; |
195 } | 225 } |
196 | 226 |
197 lc = (ngx_stream_limit_conn_node_t *) &node->color; | 227 lc = (ngx_stream_limit_conn_node_t *) &node->color; |
217 &limits[i].shm_zone->shm.name); | 247 &limits[i].shm_zone->shm.name); |
218 | 248 |
219 ngx_stream_limit_conn_cleanup_all(s->connection->pool); | 249 ngx_stream_limit_conn_cleanup_all(s->connection->pool); |
220 | 250 |
221 if (lccf->dry_run) { | 251 if (lccf->dry_run) { |
252 s->limit_conn_status = | |
253 NGX_STREAM_LIMIT_CONN_REJECTED_DRY_RUN; | |
222 return NGX_DECLINED; | 254 return NGX_DECLINED; |
223 } | 255 } |
256 | |
257 s->limit_conn_status = NGX_STREAM_LIMIT_CONN_REJECTED; | |
224 | 258 |
225 return NGX_STREAM_SERVICE_UNAVAILABLE; | 259 return NGX_STREAM_SERVICE_UNAVAILABLE; |
226 } | 260 } |
227 | 261 |
228 lc->conn++; | 262 lc->conn++; |
444 | 478 |
445 return NGX_OK; | 479 return NGX_OK; |
446 } | 480 } |
447 | 481 |
448 | 482 |
483 static ngx_int_t | |
484 ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s, | |
485 ngx_stream_variable_value_t *v, uintptr_t data) | |
486 { | |
487 if (s->limit_conn_status == 0) { | |
488 v->not_found = 1; | |
489 return NGX_OK; | |
490 } | |
491 | |
492 v->valid = 1; | |
493 v->no_cacheable = 0; | |
494 v->not_found = 0; | |
495 v->len = ngx_stream_limit_conn_status[s->limit_conn_status - 1].len; | |
496 v->data = ngx_stream_limit_conn_status[s->limit_conn_status - 1].data; | |
497 | |
498 return NGX_OK; | |
499 } | |
500 | |
501 | |
449 static void * | 502 static void * |
450 ngx_stream_limit_conn_create_conf(ngx_conf_t *cf) | 503 ngx_stream_limit_conn_create_conf(ngx_conf_t *cf) |
451 { | 504 { |
452 ngx_stream_limit_conn_conf_t *conf; | 505 ngx_stream_limit_conn_conf_t *conf; |
453 | 506 |
648 return NGX_CONF_OK; | 701 return NGX_CONF_OK; |
649 } | 702 } |
650 | 703 |
651 | 704 |
652 static ngx_int_t | 705 static ngx_int_t |
706 ngx_stream_limit_conn_add_variables(ngx_conf_t *cf) | |
707 { | |
708 ngx_stream_variable_t *var, *v; | |
709 | |
710 for (v = ngx_stream_limit_conn_vars; v->name.len; v++) { | |
711 var = ngx_stream_add_variable(cf, &v->name, v->flags); | |
712 if (var == NULL) { | |
713 return NGX_ERROR; | |
714 } | |
715 | |
716 var->get_handler = v->get_handler; | |
717 var->data = v->data; | |
718 } | |
719 | |
720 return NGX_OK; | |
721 } | |
722 | |
723 | |
724 static ngx_int_t | |
653 ngx_stream_limit_conn_init(ngx_conf_t *cf) | 725 ngx_stream_limit_conn_init(ngx_conf_t *cf) |
654 { | 726 { |
655 ngx_stream_handler_pt *h; | 727 ngx_stream_handler_pt *h; |
656 ngx_stream_core_main_conf_t *cmcf; | 728 ngx_stream_core_main_conf_t *cmcf; |
657 | 729 |