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