Mercurial > hg > nginx-quic
annotate src/stream/ngx_stream_split_clients_module.c @ 8456:c72d8839f427
Mail: fixed SMTP pipelining to send the response immediately.
Previously, if there were some pipelined SMTP data in the buffer when
a proxied connection with the backend was established, nginx called
ngx_mail_proxy_handler() to send these data, and not tried to send the
response to the last command. In most cases, this response was later sent
along with the response to the pipelined command, but if for some reason
client decides to wait for the response before finishing the next command
this might result in a connection hang.
Fix is to always call ngx_mail_proxy_handler() to send the response, and
additionally post an event to send the pipelined data if needed.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 19 May 2021 03:13:12 +0300 |
parents | 787dcc15b802 |
children |
rev | line source |
---|---|
3513 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
3513 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
10 #include <ngx_stream.h> |
3513 | 11 |
12 | |
13 typedef struct { | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
14 uint32_t percent; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
15 ngx_stream_variable_value_t value; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
16 } ngx_stream_split_clients_part_t; |
3513 | 17 |
18 | |
19 typedef struct { | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
20 ngx_stream_complex_value_t value; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
21 ngx_array_t parts; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
22 } ngx_stream_split_clients_ctx_t; |
3513 | 23 |
24 | |
25 static char *ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, | |
26 void *conf); | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
27 static char *ngx_stream_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, |
3513 | 28 void *conf); |
29 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
30 static ngx_command_t ngx_stream_split_clients_commands[] = { |
3513 | 31 |
32 { ngx_string("split_clients"), | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
33 NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, |
3513 | 34 ngx_conf_split_clients_block, |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
35 NGX_STREAM_MAIN_CONF_OFFSET, |
3513 | 36 0, |
37 NULL }, | |
38 | |
39 ngx_null_command | |
40 }; | |
41 | |
42 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
43 static ngx_stream_module_t ngx_stream_split_clients_module_ctx = { |
3513 | 44 NULL, /* preconfiguration */ |
45 NULL, /* postconfiguration */ | |
46 | |
47 NULL, /* create main configuration */ | |
48 NULL, /* init main configuration */ | |
49 | |
50 NULL, /* create server configuration */ | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
51 NULL /* merge server configuration */ |
3513 | 52 }; |
53 | |
54 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
55 ngx_module_t ngx_stream_split_clients_module = { |
3513 | 56 NGX_MODULE_V1, |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
57 &ngx_stream_split_clients_module_ctx, /* module context */ |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
58 ngx_stream_split_clients_commands, /* module directives */ |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
59 NGX_STREAM_MODULE, /* module type */ |
3513 | 60 NULL, /* init master */ |
61 NULL, /* init module */ | |
62 NULL, /* init process */ | |
63 NULL, /* init thread */ | |
64 NULL, /* exit thread */ | |
65 NULL, /* exit process */ | |
66 NULL, /* exit master */ | |
67 NGX_MODULE_V1_PADDING | |
68 }; | |
69 | |
70 | |
71 static ngx_int_t | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
72 ngx_stream_split_clients_variable(ngx_stream_session_t *s, |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
73 ngx_stream_variable_value_t *v, uintptr_t data) |
3513 | 74 { |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
75 ngx_stream_split_clients_ctx_t *ctx = |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
76 (ngx_stream_split_clients_ctx_t *) data; |
3513 | 77 |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
78 uint32_t hash; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
79 ngx_str_t val; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
80 ngx_uint_t i; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
81 ngx_stream_split_clients_part_t *part; |
3513 | 82 |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
83 *v = ngx_stream_variable_null_value; |
3513 | 84 |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
85 if (ngx_stream_complex_value(s, &ctx->value, &val) != NGX_OK) { |
3513 | 86 return NGX_OK; |
87 } | |
88 | |
3892
12d8d2f30205
use MurmurHash2 for split_clients, because
Igor Sysoev <igor@sysoev.ru>
parents:
3607
diff
changeset
|
89 hash = ngx_murmur_hash2(val.data, val.len); |
3513 | 90 |
91 part = ctx->parts.elts; | |
92 | |
93 for (i = 0; i < ctx->parts.nelts; i++) { | |
94 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
95 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
96 "stream split: %uD %uD", hash, part[i].percent); |
3513 | 97 |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
98 if (hash < part[i].percent || part[i].percent == 0) { |
3513 | 99 *v = part[i].value; |
100 return NGX_OK; | |
101 } | |
102 } | |
103 | |
104 return NGX_OK; | |
105 } | |
106 | |
107 | |
108 static char * | |
109 ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
110 { | |
111 char *rv; | |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
112 uint32_t sum, last; |
3513 | 113 ngx_str_t *value, name; |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
114 ngx_uint_t i; |
3513 | 115 ngx_conf_t save; |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
116 ngx_stream_variable_t *var; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
117 ngx_stream_split_clients_ctx_t *ctx; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
118 ngx_stream_split_clients_part_t *part; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
119 ngx_stream_compile_complex_value_t ccv; |
3513 | 120 |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
121 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_split_clients_ctx_t)); |
3513 | 122 if (ctx == NULL) { |
123 return NGX_CONF_ERROR; | |
124 } | |
125 | |
126 value = cf->args->elts; | |
127 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
128 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); |
3513 | 129 |
130 ccv.cf = cf; | |
131 ccv.value = &value[1]; | |
132 ccv.complex_value = &ctx->value; | |
133 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
134 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { |
3513 | 135 return NGX_CONF_ERROR; |
136 } | |
137 | |
138 name = value[2]; | |
4635
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
139 |
4972
8b635cf36ccc
Added checks that disallow adding a variable with an empty name.
Ruslan Ermilov <ru@nginx.com>
parents:
4635
diff
changeset
|
140 if (name.data[0] != '$') { |
4635
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
141 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
142 "invalid variable name \"%V\"", &name); |
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
143 return NGX_CONF_ERROR; |
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
144 } |
9c9fbdbe9383
Added syntax checking of the second parameter of the "split_clients" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4593
diff
changeset
|
145 |
3513 | 146 name.len--; |
147 name.data++; | |
148 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
149 var = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE); |
3513 | 150 if (var == NULL) { |
151 return NGX_CONF_ERROR; | |
152 } | |
153 | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
154 var->get_handler = ngx_stream_split_clients_variable; |
3513 | 155 var->data = (uintptr_t) ctx; |
156 | |
157 if (ngx_array_init(&ctx->parts, cf->pool, 2, | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
158 sizeof(ngx_stream_split_clients_part_t)) |
3513 | 159 != NGX_OK) |
160 { | |
161 return NGX_CONF_ERROR; | |
162 } | |
163 | |
164 save = *cf; | |
165 cf->ctx = ctx; | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
166 cf->handler = ngx_stream_split_clients; |
3513 | 167 cf->handler_conf = conf; |
168 | |
169 rv = ngx_conf_parse(cf, NULL); | |
170 | |
171 *cf = save; | |
172 | |
3607
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
173 if (rv != NGX_CONF_OK) { |
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
174 return rv; |
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
175 } |
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
176 |
3513 | 177 sum = 0; |
178 last = 0; | |
179 part = ctx->parts.elts; | |
180 | |
181 for (i = 0; i < ctx->parts.nelts; i++) { | |
182 sum = part[i].percent ? sum + part[i].percent : 10000; | |
183 if (sum > 10000) { | |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
184 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
4593
834049edae24
Fixed grammar in error messages.
Ruslan Ermilov <ru@nginx.com>
parents:
4561
diff
changeset
|
185 "percent total is greater than 100%%"); |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
186 return NGX_CONF_ERROR; |
3513 | 187 } |
188 | |
189 if (part[i].percent) { | |
4561
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
190 last += part[i].percent * (uint64_t) 0xffffffff / 10000; |
ae63013cbffa
Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
191 part[i].percent = last; |
3513 | 192 } |
193 } | |
194 | |
195 return rv; | |
196 } | |
197 | |
198 | |
199 static char * | |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
200 ngx_stream_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
3513 | 201 { |
6632
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
202 ngx_int_t n; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
203 ngx_str_t *value; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
204 ngx_stream_split_clients_ctx_t *ctx; |
787dcc15b802
Stream: split_clients module.
Vladimir Homutov <vl@nginx.com>
parents:
5128
diff
changeset
|
205 ngx_stream_split_clients_part_t *part; |
3513 | 206 |
207 ctx = cf->ctx; | |
208 value = cf->args->elts; | |
209 | |
210 part = ngx_array_push(&ctx->parts); | |
211 if (part == NULL) { | |
212 return NGX_CONF_ERROR; | |
213 } | |
214 | |
215 if (value[0].len == 1 && value[0].data[0] == '*') { | |
216 part->percent = 0; | |
217 | |
218 } else { | |
5128
b78cf2414fda
Split clients: check length when parsing configuration.
Ruslan Ermilov <ru@nginx.com>
parents:
4972
diff
changeset
|
219 if (value[0].len == 0 || value[0].data[value[0].len - 1] != '%') { |
3513 | 220 goto invalid; |
221 } | |
222 | |
223 n = ngx_atofp(value[0].data, value[0].len - 1, 2); | |
224 if (n == NGX_ERROR || n == 0) { | |
225 goto invalid; | |
226 } | |
227 | |
228 part->percent = (uint32_t) n; | |
229 } | |
230 | |
231 part->value.len = value[1].len; | |
232 part->value.valid = 1; | |
233 part->value.no_cacheable = 0; | |
234 part->value.not_found = 0; | |
235 part->value.data = value[1].data; | |
236 | |
237 return NGX_CONF_OK; | |
238 | |
239 invalid: | |
240 | |
241 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
242 "invalid percent value \"%V\"", &value[0]); | |
243 return NGX_CONF_ERROR; | |
244 } |