Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_limit_req_module.c @ 2883:d0cba58e5bfa
fix socket leak introduced in r2378
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 25 May 2009 09:56:01 +0000 |
parents | b3b8c66bd520 |
children | c7d57b539248 |
rev | line source |
---|---|
980 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
13 u_char color; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
14 u_char dummy; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
15 u_short len; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
16 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
17 ngx_msec_t last; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
18 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
19 ngx_uint_t excess; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
20 u_char data[1]; |
2294 | 21 } ngx_http_limit_req_node_t; |
980 | 22 |
23 | |
24 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
25 ngx_rbtree_t rbtree; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
26 ngx_rbtree_node_t sentinel; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
27 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
28 } ngx_http_limit_req_shctx_t; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
29 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
30 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
31 typedef struct { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
32 ngx_http_limit_req_shctx_t *sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
33 ngx_slab_pool_t *shpool; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
34 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
35 ngx_uint_t rate; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
36 ngx_int_t index; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
37 ngx_str_t var; |
2294 | 38 } ngx_http_limit_req_ctx_t; |
987 | 39 |
40 | |
41 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
42 ngx_shm_zone_t *shm_zone; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
43 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
44 ngx_uint_t burst; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
45 ngx_uint_t nodelay;/* unsigned nodelay:1 */ |
2294 | 46 } ngx_http_limit_req_conf_t; |
980 | 47 |
48 | |
2294 | 49 static void ngx_http_limit_req_delay(ngx_http_request_t *r); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
50 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
51 ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lrp); |
2294 | 52 static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, |
53 ngx_uint_t n); | |
980 | 54 |
2294 | 55 static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf); |
56 static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, | |
980 | 57 void *child); |
2294 | 58 static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 59 void *conf); |
2294 | 60 static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 61 void *conf); |
2294 | 62 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf); |
980 | 63 |
64 | |
2294 | 65 static ngx_command_t ngx_http_limit_req_commands[] = { |
980 | 66 |
2294 | 67 { ngx_string("limit_req_zone"), |
987 | 68 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3, |
2294 | 69 ngx_http_limit_req_zone, |
980 | 70 0, |
71 0, | |
72 NULL }, | |
73 | |
2294 | 74 { ngx_string("limit_req"), |
75 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, | |
76 ngx_http_limit_req, | |
980 | 77 NGX_HTTP_LOC_CONF_OFFSET, |
78 0, | |
79 NULL }, | |
80 | |
81 ngx_null_command | |
82 }; | |
83 | |
84 | |
2294 | 85 static ngx_http_module_t ngx_http_limit_req_module_ctx = { |
980 | 86 NULL, /* preconfiguration */ |
2294 | 87 ngx_http_limit_req_init, /* postconfiguration */ |
980 | 88 |
89 NULL, /* create main configuration */ | |
90 NULL, /* init main configuration */ | |
91 | |
92 NULL, /* create server configuration */ | |
93 NULL, /* merge server configuration */ | |
94 | |
2294 | 95 ngx_http_limit_req_create_conf, /* create location configration */ |
96 ngx_http_limit_req_merge_conf /* merge location configration */ | |
980 | 97 }; |
98 | |
99 | |
2294 | 100 ngx_module_t ngx_http_limit_req_module = { |
980 | 101 NGX_MODULE_V1, |
2294 | 102 &ngx_http_limit_req_module_ctx, /* module context */ |
103 ngx_http_limit_req_commands, /* module directives */ | |
980 | 104 NGX_HTTP_MODULE, /* module type */ |
105 NULL, /* init master */ | |
106 NULL, /* init module */ | |
107 NULL, /* init process */ | |
108 NULL, /* init thread */ | |
109 NULL, /* exit thread */ | |
110 NULL, /* exit process */ | |
111 NULL, /* exit master */ | |
112 NGX_MODULE_V1_PADDING | |
113 }; | |
114 | |
115 | |
116 static ngx_int_t | |
2294 | 117 ngx_http_limit_req_handler(ngx_http_request_t *r) |
980 | 118 { |
2294 | 119 size_t len, n; |
120 uint32_t hash; | |
121 ngx_int_t rc; | |
2313 | 122 ngx_uint_t excess; |
2294 | 123 ngx_time_t *tp; |
124 ngx_rbtree_node_t *node; | |
125 ngx_http_variable_value_t *vv; | |
126 ngx_http_limit_req_ctx_t *ctx; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
127 ngx_http_limit_req_node_t *lr; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
128 ngx_http_limit_req_conf_t *lrcf; |
980 | 129 |
2294 | 130 if (r->main->limit_req_set) { |
984
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
131 return NGX_DECLINED; |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
132 } |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
133 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
134 lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); |
980 | 135 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
136 if (lrcf->shm_zone == NULL) { |
980 | 137 return NGX_DECLINED; |
138 } | |
139 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
140 ctx = lrcf->shm_zone->data; |
987 | 141 |
142 vv = ngx_http_get_indexed_variable(r, ctx->index); | |
980 | 143 |
144 if (vv == NULL || vv->not_found) { | |
145 return NGX_DECLINED; | |
146 } | |
147 | |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
148 len = vv->len; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
149 |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
150 if (len == 0) { |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
151 return NGX_DECLINED; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
152 } |
984
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
153 |
2294 | 154 if (len > 65535) { |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
155 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
156 "the value of the \"%V\" variable " |
2294 | 157 "is more than 65535 bytes: \"%v\"", |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
158 &ctx->var, vv); |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
159 return NGX_DECLINED; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
160 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
161 |
2294 | 162 r->main->limit_req_set = 1; |
980 | 163 |
164 hash = ngx_crc32_short(vv->data, len); | |
165 | |
2294 | 166 ngx_shmtx_lock(&ctx->shpool->mutex); |
167 | |
168 ngx_http_limit_req_expire(ctx, 1); | |
169 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
170 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); |
2294 | 171 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
172 if (lr) { |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
173 ngx_queue_remove(&lr->queue); |
2294 | 174 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
175 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
2294 | 176 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
177 excess = lr->excess; |
2294 | 178 |
179 } else { | |
2313 | 180 excess = 0; |
980 | 181 } |
182 | |
2313 | 183 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
184 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); | |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
185 |
2294 | 186 if (rc == NGX_BUSY) { |
187 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
1012
11ffb8e4753f
stop rbtree search early if equal hash was found
Igor Sysoev <igor@sysoev.ru>
parents:
1011
diff
changeset
|
188 |
2294 | 189 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
2376
29d89920a749
*) add zone name while logging 503 error reason
Igor Sysoev <igor@sysoev.ru>
parents:
2375
diff
changeset
|
190 "limiting requests, excess: %ui.%03ui by zone \"%V\"", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
191 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
980 | 192 |
193 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
194 } | |
195 | |
2294 | 196 if (rc == NGX_AGAIN) { |
197 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
198 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
199 if (lrcf->nodelay) { |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
200 return NGX_DECLINED; |
2294 | 201 } |
202 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
203 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, |
2376
29d89920a749
*) add zone name while logging 503 error reason
Igor Sysoev <igor@sysoev.ru>
parents:
2375
diff
changeset
|
204 "delaying request, excess: %ui.%03ui, by zone \"%V\"", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
205 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
206 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
207 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
208 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
209 } |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
210 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
211 r->read_event_handler = ngx_http_test_reading; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
212 r->write_event_handler = ngx_http_limit_req_delay; |
2313 | 213 ngx_add_timer(r->connection->write, (ngx_msec_t) excess); |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
214 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
215 return NGX_AGAIN; |
2294 | 216 } |
217 | |
218 if (rc == NGX_OK) { | |
219 goto done; | |
220 } | |
221 | |
222 /* rc == NGX_DECLINED */ | |
223 | |
224 n = offsetof(ngx_rbtree_node_t, color) | |
225 + offsetof(ngx_http_limit_req_node_t, data) | |
226 + len; | |
227 | |
228 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
229 if (node == NULL) { | |
230 | |
231 ngx_http_limit_req_expire(ctx, 0); | |
232 | |
233 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
234 if (node == NULL) { | |
235 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
236 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
237 } | |
238 } | |
239 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
240 lr = (ngx_http_limit_req_node_t *) &node->color; |
980 | 241 |
242 node->key = hash; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
243 lr->len = (u_char) len; |
2294 | 244 |
245 tp = ngx_timeofday(); | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
246 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
2294 | 247 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
248 lr->excess = 0; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
249 ngx_memcpy(lr->data, vv->data, len); |
980 | 250 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
251 ngx_rbtree_insert(&ctx->sh->rbtree, node); |
980 | 252 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
253 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
2294 | 254 |
980 | 255 done: |
256 | |
2294 | 257 ngx_shmtx_unlock(&ctx->shpool->mutex); |
980 | 258 |
259 return NGX_DECLINED; | |
260 } | |
261 | |
262 | |
263 static void | |
2294 | 264 ngx_http_limit_req_delay(ngx_http_request_t *r) |
265 { | |
266 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
267 "limit_req delay"); | |
268 | |
269 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { | |
270 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
271 return; | |
272 } | |
273 | |
274 r->read_event_handler = ngx_http_block_reading; | |
275 r->write_event_handler = ngx_http_core_run_phases; | |
276 | |
277 ngx_http_core_run_phases(r); | |
278 } | |
279 | |
280 | |
281 static void | |
282 ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
283 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
284 { |
2294 | 285 ngx_rbtree_node_t **p; |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
286 ngx_http_limit_req_node_t *lrn, *lrnt; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
287 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
288 for ( ;; ) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
289 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
290 if (node->key < temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
291 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
292 p = &temp->left; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
293 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
294 } else if (node->key > temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
295 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
296 p = &temp->right; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
297 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
298 } else { /* node->key == temp->key */ |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
299 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
300 lrn = (ngx_http_limit_req_node_t *) &node->color; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
301 lrnt = (ngx_http_limit_req_node_t *) &temp->color; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
302 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
303 p = (ngx_memn2cmp(lrn->data, lrnt->data, lrn->len, lrnt->len) < 0) |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
304 ? &temp->left : &temp->right; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
305 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
306 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
307 if (*p == sentinel) { |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
308 break; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
309 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
310 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
311 temp = *p; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
312 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
313 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
314 *p = node; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
315 node->parent = temp; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
316 node->left = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
317 node->right = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
318 ngx_rbt_red(node); |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
319 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
320 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
321 |
2294 | 322 static ngx_int_t |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
323 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
324 u_char *data, size_t len, ngx_http_limit_req_node_t **lrp) |
980 | 325 { |
2313 | 326 ngx_int_t rc, excess; |
2294 | 327 ngx_time_t *tp; |
328 ngx_msec_t now; | |
329 ngx_msec_int_t ms; | |
330 ngx_rbtree_node_t *node, *sentinel; | |
331 ngx_http_limit_req_ctx_t *ctx; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
332 ngx_http_limit_req_node_t *lr; |
2294 | 333 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
334 ctx = lrcf->shm_zone->data; |
2294 | 335 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
336 node = ctx->sh->rbtree.root; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
337 sentinel = ctx->sh->rbtree.sentinel; |
980 | 338 |
2294 | 339 while (node != sentinel) { |
340 | |
341 if (hash < node->key) { | |
342 node = node->left; | |
343 continue; | |
344 } | |
345 | |
346 if (hash > node->key) { | |
347 node = node->right; | |
348 continue; | |
349 } | |
350 | |
351 /* hash == node->key */ | |
352 | |
353 do { | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
354 lr = (ngx_http_limit_req_node_t *) &node->color; |
980 | 355 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
356 rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); |
2294 | 357 |
358 if (rc == 0) { | |
359 | |
360 tp = ngx_timeofday(); | |
980 | 361 |
2294 | 362 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
363 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 364 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
365 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; |
2294 | 366 |
2313 | 367 if (excess < 0) { |
368 excess = 0; | |
2294 | 369 } |
370 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
371 lr->excess = excess; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
372 lr->last = now; |
980 | 373 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
374 *lrp = lr; |
2294 | 375 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
376 if ((ngx_uint_t) excess > lrcf->burst) { |
2294 | 377 return NGX_BUSY; |
378 } | |
980 | 379 |
2313 | 380 if (excess) { |
2294 | 381 return NGX_AGAIN; |
382 } | |
980 | 383 |
2294 | 384 return NGX_OK; |
385 } | |
386 | |
387 node = (rc < 0) ? node->left : node->right; | |
388 | |
389 } while (node != sentinel && hash == node->key); | |
390 | |
391 break; | |
980 | 392 } |
393 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
394 *lrp = NULL; |
2294 | 395 |
396 return NGX_DECLINED; | |
397 } | |
398 | |
399 | |
400 static void | |
401 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) | |
402 { | |
2313 | 403 ngx_int_t excess; |
2294 | 404 ngx_time_t *tp; |
405 ngx_msec_t now; | |
406 ngx_queue_t *q; | |
407 ngx_msec_int_t ms; | |
408 ngx_rbtree_node_t *node; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
409 ngx_http_limit_req_node_t *lr; |
2294 | 410 |
411 tp = ngx_timeofday(); | |
412 | |
413 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
414 | |
415 /* | |
416 * n == 1 deletes one or two zero rate entries | |
417 * n == 0 deletes oldest entry by force | |
418 * and one or two zero rate entries | |
419 */ | |
420 | |
421 while (n < 3) { | |
422 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
423 if (ngx_queue_empty(&ctx->sh->queue)) { |
2294 | 424 return; |
425 } | |
426 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
427 q = ngx_queue_last(&ctx->sh->queue); |
2294 | 428 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
429 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); |
2294 | 430 |
431 if (n++ != 0) { | |
432 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
433 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 434 ms = ngx_abs(ms); |
435 | |
436 if (ms < 60000) { | |
437 return; | |
438 } | |
439 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
440 excess = lr->excess - ctx->rate * ms / 1000; |
2294 | 441 |
2313 | 442 if (excess > 0) { |
2294 | 443 return; |
444 } | |
445 } | |
446 | |
447 ngx_queue_remove(q); | |
448 | |
449 node = (ngx_rbtree_node_t *) | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
450 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); |
2294 | 451 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
452 ngx_rbtree_delete(&ctx->sh->rbtree, node); |
2294 | 453 |
454 ngx_slab_free_locked(ctx->shpool, node); | |
455 } | |
980 | 456 } |
457 | |
458 | |
459 static ngx_int_t | |
2294 | 460 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) |
980 | 461 { |
2294 | 462 ngx_http_limit_req_ctx_t *octx = data; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
463 |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
464 size_t len; |
2294 | 465 ngx_http_limit_req_ctx_t *ctx; |
980 | 466 |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
467 ctx = shm_zone->data; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
468 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
469 if (octx) { |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
470 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
471 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
2294 | 472 "limit_req \"%V\" uses the \"%V\" variable " |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
473 "while previously it used the \"%V\" variable", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
474 &shm_zone->shm.name, &ctx->var, &octx->var); |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
475 return NGX_ERROR; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
476 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
477 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
478 ctx->sh = octx->sh; |
2294 | 479 ctx->shpool = octx->shpool; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
480 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
481 return NGX_OK; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
482 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
483 |
2294 | 484 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
980 | 485 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
486 if (shm_zone->shm.exists) { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
487 ctx->sh = ctx->shpool->data; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
488 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
489 return NGX_OK; |
980 | 490 } |
491 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
492 ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t)); |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
493 if (ctx->sh == NULL) { |
980 | 494 return NGX_ERROR; |
495 } | |
496 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
497 ctx->shpool->data = ctx->sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
498 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
499 ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, |
2294 | 500 ngx_http_limit_req_rbtree_insert_value); |
501 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
502 ngx_queue_init(&ctx->sh->queue); |
980 | 503 |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
504 len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len; |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
505 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
506 ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len); |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
507 if (ctx->shpool->log_ctx == NULL) { |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
508 return NGX_ERROR; |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
509 } |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
510 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
511 ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
512 &shm_zone->shm.name); |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
513 |
980 | 514 return NGX_OK; |
515 } | |
516 | |
517 | |
518 static void * | |
2294 | 519 ngx_http_limit_req_create_conf(ngx_conf_t *cf) |
980 | 520 { |
2294 | 521 ngx_http_limit_req_conf_t *conf; |
980 | 522 |
2294 | 523 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_conf_t)); |
980 | 524 if (conf == NULL) { |
525 return NGX_CONF_ERROR; | |
526 } | |
527 | |
528 /* | |
529 * set by ngx_pcalloc(): | |
530 * | |
531 * conf->shm_zone = NULL; | |
2375 | 532 * conf->burst = 0; |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
533 * conf->nodelay = 0; |
980 | 534 */ |
535 | |
536 return conf; | |
537 } | |
538 | |
539 | |
540 static char * | |
2294 | 541 ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
980 | 542 { |
2294 | 543 ngx_http_limit_req_conf_t *prev = parent; |
544 ngx_http_limit_req_conf_t *conf = child; | |
980 | 545 |
546 if (conf->shm_zone == NULL) { | |
547 *conf = *prev; | |
548 } | |
549 | |
550 return NGX_CONF_OK; | |
551 } | |
552 | |
553 | |
554 static char * | |
2294 | 555 ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 556 { |
2294 | 557 u_char *p; |
558 size_t size, len; | |
559 ngx_str_t *value, name, s; | |
560 ngx_int_t rate, scale; | |
561 ngx_uint_t i; | |
562 ngx_shm_zone_t *shm_zone; | |
563 ngx_http_limit_req_ctx_t *ctx; | |
980 | 564 |
565 value = cf->args->elts; | |
566 | |
2294 | 567 ctx = NULL; |
568 size = 0; | |
569 rate = 1; | |
570 scale = 1; | |
571 name.len = 0; | |
572 | |
573 for (i = 1; i < cf->args->nelts; i++) { | |
574 | |
575 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
576 | |
577 name.data = value[i].data + 5; | |
578 | |
579 p = (u_char *) ngx_strchr(name.data, ':'); | |
580 | |
581 if (p) { | |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
582 *p = '\0'; |
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
583 |
2294 | 584 name.len = p - name.data; |
585 | |
586 p++; | |
587 | |
588 s.len = value[i].data + value[i].len - p; | |
589 s.data = p; | |
590 | |
591 size = ngx_parse_size(&s); | |
592 if (size > 8191) { | |
593 continue; | |
594 } | |
595 } | |
596 | |
597 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
598 "invalid zone size \"%V\"", &value[i]); | |
599 return NGX_CONF_ERROR; | |
600 } | |
601 | |
602 if (ngx_strncmp(value[i].data, "rate=", 5) == 0) { | |
603 | |
604 len = value[i].len; | |
605 p = value[i].data + len - 3; | |
987 | 606 |
2294 | 607 if (ngx_strncmp(p, "r/s", 3) == 0) { |
608 scale = 1; | |
609 len -= 3; | |
610 | |
611 } else if (ngx_strncmp(p, "r/m", 3) == 0) { | |
612 scale = 60; | |
613 len -= 3; | |
614 } | |
615 | |
616 rate = ngx_atoi(value[i].data + 5, len - 5); | |
617 if (rate <= NGX_ERROR) { | |
618 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
619 "invalid rate \"%V\"", &value[i]); | |
620 return NGX_CONF_ERROR; | |
621 } | |
622 | |
623 continue; | |
624 } | |
625 | |
626 if (value[i].data[0] == '$') { | |
987 | 627 |
2294 | 628 value[i].len--; |
629 value[i].data++; | |
630 | |
631 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); | |
632 if (ctx == NULL) { | |
633 return NGX_CONF_ERROR; | |
634 } | |
635 | |
636 ctx->index = ngx_http_get_variable_index(cf, &value[i]); | |
637 if (ctx->index == NGX_ERROR) { | |
638 return NGX_CONF_ERROR; | |
639 } | |
640 | |
641 ctx->var = value[i]; | |
642 | |
643 continue; | |
644 } | |
645 | |
646 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
647 "invalid parameter \"%V\"", &value[i]); | |
987 | 648 return NGX_CONF_ERROR; |
649 } | |
650 | |
2294 | 651 if (name.len == 0 || size == 0) { |
652 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
653 "\"%V\" must have \"zone\" parameter", | |
654 &cmd->name); | |
987 | 655 return NGX_CONF_ERROR; |
656 } | |
657 | |
2294 | 658 if (ctx == NULL) { |
980 | 659 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 660 "no variable is defined for limit_req_zone \"%V\"", |
661 &cmd->name); | |
980 | 662 return NGX_CONF_ERROR; |
663 } | |
664 | |
2313 | 665 ctx->rate = rate * 1000 / scale; |
980 | 666 |
2294 | 667 shm_zone = ngx_shared_memory_add(cf, &name, size, |
668 &ngx_http_limit_req_module); | |
980 | 669 if (shm_zone == NULL) { |
670 return NGX_CONF_ERROR; | |
671 } | |
672 | |
987 | 673 if (shm_zone->data) { |
674 ctx = shm_zone->data; | |
675 | |
676 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2294 | 677 "limit_req_zone \"%V\" is already bound to variable \"%V\"", |
678 &value[1], &ctx->var); | |
987 | 679 return NGX_CONF_ERROR; |
680 } | |
681 | |
2294 | 682 shm_zone->init = ngx_http_limit_req_init_zone; |
987 | 683 shm_zone->data = ctx; |
980 | 684 |
685 return NGX_CONF_OK; | |
686 } | |
687 | |
688 | |
689 static char * | |
2294 | 690 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 691 { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
692 ngx_http_limit_req_conf_t *lrcf = conf; |
980 | 693 |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
694 ngx_int_t burst; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
695 ngx_str_t *value, s; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
696 ngx_uint_t i; |
2294 | 697 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
698 if (lrcf->shm_zone) { |
2294 | 699 return "is duplicate"; |
700 } | |
980 | 701 |
702 value = cf->args->elts; | |
703 | |
2294 | 704 burst = 0; |
705 | |
706 for (i = 1; i < cf->args->nelts; i++) { | |
707 | |
708 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
709 | |
710 s.len = value[i].len - 5; | |
711 s.data = value[i].data + 5; | |
712 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
713 lrcf->shm_zone = ngx_shared_memory_add(cf, &s, 0, |
2294 | 714 &ngx_http_limit_req_module); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
715 if (lrcf->shm_zone == NULL) { |
2294 | 716 return NGX_CONF_ERROR; |
717 } | |
718 | |
719 continue; | |
720 } | |
721 | |
722 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { | |
723 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
724 burst = ngx_atoi(value[i].data + 6, value[i].len - 6); |
2294 | 725 if (burst <= 0) { |
726 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
727 "invalid burst rate \"%V\"", &value[i]); | |
728 return NGX_CONF_ERROR; | |
729 } | |
730 | |
731 continue; | |
732 } | |
733 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
734 if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
735 lrcf->nodelay = 1; |
2294 | 736 continue; |
737 } | |
738 | |
739 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
740 "invalid parameter \"%V\"", &value[i]); | |
980 | 741 return NGX_CONF_ERROR; |
742 } | |
743 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
744 if (lrcf->shm_zone == NULL) { |
980 | 745 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 746 "\"%V\" must have \"zone\" parameter", |
747 &cmd->name); | |
980 | 748 return NGX_CONF_ERROR; |
749 } | |
750 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
751 if (lrcf->shm_zone->data == NULL) { |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
752 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 753 "unknown limit_req_zone \"%V\"", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
754 &lrcf->shm_zone->shm.name); |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
755 return NGX_CONF_ERROR; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
756 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
757 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
758 lrcf->burst = burst * 1000; |
980 | 759 |
760 return NGX_CONF_OK; | |
761 } | |
762 | |
763 | |
764 static ngx_int_t | |
2294 | 765 ngx_http_limit_req_init(ngx_conf_t *cf) |
980 | 766 { |
767 ngx_http_handler_pt *h; | |
768 ngx_http_core_main_conf_t *cmcf; | |
769 | |
770 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
771 | |
772 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); | |
773 if (h == NULL) { | |
774 return NGX_ERROR; | |
775 } | |
776 | |
2294 | 777 *h = ngx_http_limit_req_handler; |
980 | 778 |
779 return NGX_OK; | |
780 } |