Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_mirror_module.c @ 8084:eece8e35e64d quic
QUIC: allowed old DCID for initial packets until first ACK.
If a packet sent in response to an initial client packet was lost, then
successive client initial packets were dropped by nginx with the unexpected
dcid message logged. This was because the new DCID generated by the server was
not available to the client.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 09 Sep 2020 16:35:29 +0300 |
parents | 230d16d35ebc |
children |
rev | line source |
---|---|
7072 | 1 |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_array_t *mirror; | |
15 ngx_flag_t request_body; | |
16 } ngx_http_mirror_loc_conf_t; | |
17 | |
18 | |
19 typedef struct { | |
20 ngx_int_t status; | |
21 } ngx_http_mirror_ctx_t; | |
22 | |
23 | |
24 static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r); | |
25 static void ngx_http_mirror_body_handler(ngx_http_request_t *r); | |
26 static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r); | |
27 static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf); | |
28 static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, | |
29 void *child); | |
7073
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
30 static char *ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
7072 | 31 static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf); |
32 | |
33 | |
34 static ngx_command_t ngx_http_mirror_commands[] = { | |
35 | |
36 { ngx_string("mirror"), | |
37 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
7073
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
38 ngx_http_mirror, |
7072 | 39 NGX_HTTP_LOC_CONF_OFFSET, |
7073
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
40 0, |
7072 | 41 NULL }, |
42 | |
43 { ngx_string("mirror_request_body"), | |
44 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
45 ngx_conf_set_flag_slot, | |
46 NGX_HTTP_LOC_CONF_OFFSET, | |
47 offsetof(ngx_http_mirror_loc_conf_t, request_body), | |
48 NULL }, | |
49 | |
50 ngx_null_command | |
51 }; | |
52 | |
53 | |
54 static ngx_http_module_t ngx_http_mirror_module_ctx = { | |
55 NULL, /* preconfiguration */ | |
56 ngx_http_mirror_init, /* postconfiguration */ | |
57 | |
58 NULL, /* create main configuration */ | |
59 NULL, /* init main configuration */ | |
60 | |
61 NULL, /* create server configuration */ | |
62 NULL, /* merge server configuration */ | |
63 | |
64 ngx_http_mirror_create_loc_conf, /* create location configuration */ | |
65 ngx_http_mirror_merge_loc_conf /* merge location configuration */ | |
66 }; | |
67 | |
68 | |
69 ngx_module_t ngx_http_mirror_module = { | |
70 NGX_MODULE_V1, | |
71 &ngx_http_mirror_module_ctx, /* module context */ | |
72 ngx_http_mirror_commands, /* module directives */ | |
73 NGX_HTTP_MODULE, /* module type */ | |
74 NULL, /* init master */ | |
75 NULL, /* init module */ | |
76 NULL, /* init process */ | |
77 NULL, /* init thread */ | |
78 NULL, /* exit thread */ | |
79 NULL, /* exit process */ | |
80 NULL, /* exit master */ | |
81 NGX_MODULE_V1_PADDING | |
82 }; | |
83 | |
84 | |
85 static ngx_int_t | |
86 ngx_http_mirror_handler(ngx_http_request_t *r) | |
87 { | |
88 ngx_int_t rc; | |
89 ngx_http_mirror_ctx_t *ctx; | |
90 ngx_http_mirror_loc_conf_t *mlcf; | |
91 | |
92 if (r != r->main) { | |
93 return NGX_DECLINED; | |
94 } | |
95 | |
96 mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); | |
97 | |
98 if (mlcf->mirror == NULL) { | |
99 return NGX_DECLINED; | |
100 } | |
101 | |
102 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler"); | |
103 | |
104 if (mlcf->request_body) { | |
105 ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); | |
106 | |
107 if (ctx) { | |
108 return ctx->status; | |
109 } | |
110 | |
111 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t)); | |
112 if (ctx == NULL) { | |
113 return NGX_ERROR; | |
114 } | |
115 | |
116 ctx->status = NGX_DONE; | |
117 | |
118 ngx_http_set_ctx(r, ctx, ngx_http_mirror_module); | |
119 | |
120 rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler); | |
121 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
122 return rc; | |
123 } | |
124 | |
125 ngx_http_finalize_request(r, NGX_DONE); | |
126 return NGX_DONE; | |
127 } | |
128 | |
129 return ngx_http_mirror_handler_internal(r); | |
130 } | |
131 | |
132 | |
133 static void | |
134 ngx_http_mirror_body_handler(ngx_http_request_t *r) | |
135 { | |
136 ngx_http_mirror_ctx_t *ctx; | |
137 | |
138 ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); | |
139 | |
140 ctx->status = ngx_http_mirror_handler_internal(r); | |
141 | |
142 r->preserve_body = 1; | |
143 | |
144 r->write_event_handler = ngx_http_core_run_phases; | |
145 ngx_http_core_run_phases(r); | |
146 } | |
147 | |
148 | |
149 static ngx_int_t | |
150 ngx_http_mirror_handler_internal(ngx_http_request_t *r) | |
151 { | |
152 ngx_str_t *name; | |
153 ngx_uint_t i; | |
154 ngx_http_request_t *sr; | |
155 ngx_http_mirror_loc_conf_t *mlcf; | |
156 | |
157 mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); | |
158 | |
159 name = mlcf->mirror->elts; | |
160 | |
161 for (i = 0; i < mlcf->mirror->nelts; i++) { | |
162 if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, | |
163 NGX_HTTP_SUBREQUEST_BACKGROUND) | |
164 != NGX_OK) | |
165 { | |
166 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
167 } | |
168 | |
169 sr->header_only = 1; | |
170 sr->method = r->method; | |
171 sr->method_name = r->method_name; | |
172 } | |
173 | |
174 return NGX_DECLINED; | |
175 } | |
176 | |
177 | |
178 static void * | |
179 ngx_http_mirror_create_loc_conf(ngx_conf_t *cf) | |
180 { | |
181 ngx_http_mirror_loc_conf_t *mlcf; | |
182 | |
183 mlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mirror_loc_conf_t)); | |
184 if (mlcf == NULL) { | |
185 return NULL; | |
186 } | |
187 | |
188 mlcf->mirror = NGX_CONF_UNSET_PTR; | |
189 mlcf->request_body = NGX_CONF_UNSET; | |
190 | |
191 return mlcf; | |
192 } | |
193 | |
194 | |
195 static char * | |
196 ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
197 { | |
198 ngx_http_mirror_loc_conf_t *prev = parent; | |
199 ngx_http_mirror_loc_conf_t *conf = child; | |
200 | |
201 ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL); | |
202 ngx_conf_merge_value(conf->request_body, prev->request_body, 1); | |
203 | |
204 return NGX_CONF_OK; | |
205 } | |
206 | |
207 | |
7073
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
208 static char * |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
209 ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
210 { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
211 ngx_http_mirror_loc_conf_t *mlcf = conf; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
212 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
213 ngx_str_t *value, *s; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
214 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
215 value = cf->args->elts; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
216 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
217 if (ngx_strcmp(value[1].data, "off") == 0) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
218 if (mlcf->mirror != NGX_CONF_UNSET_PTR) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
219 return "is duplicate"; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
220 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
221 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
222 mlcf->mirror = NULL; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
223 return NGX_CONF_OK; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
224 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
225 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
226 if (mlcf->mirror == NULL) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
227 return "is duplicate"; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
228 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
229 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
230 if (mlcf->mirror == NGX_CONF_UNSET_PTR) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
231 mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
232 if (mlcf->mirror == NULL) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
233 return NGX_CONF_ERROR; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
234 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
235 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
236 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
237 s = ngx_array_push(mlcf->mirror); |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
238 if (s == NULL) { |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
239 return NGX_CONF_ERROR; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
240 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
241 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
242 *s = value[1]; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
243 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
244 return NGX_CONF_OK; |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
245 } |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
246 |
230d16d35ebc
Mirror: "off" paramater of the "mirror" directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7072
diff
changeset
|
247 |
7072 | 248 static ngx_int_t |
249 ngx_http_mirror_init(ngx_conf_t *cf) | |
250 { | |
251 ngx_http_handler_pt *h; | |
252 ngx_http_core_main_conf_t *cmcf; | |
253 | |
254 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
255 | |
256 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers); | |
257 if (h == NULL) { | |
258 return NGX_ERROR; | |
259 } | |
260 | |
261 *h = ngx_http_mirror_handler; | |
262 | |
263 return NGX_OK; | |
264 } |