Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_upstream_keepalive_module.c @ 6986:0cdee26605f3
Cleaned up r->headers_out.headers allocation error handling.
If initialization of a header failed for some reason after ngx_list_push(),
leaving the header as is can result in uninitialized memory access by
the header filter or the log module. The fix is to clear partially
initialized headers in case of errors.
For the Cache-Control header, the fix is to postpone pushing
r->headers_out.cache_control until its value is completed.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 20 Apr 2017 18:26:37 +0300 |
parents | adf25b8d0431 |
children | 1cb92a2d672e |
rev | line source |
---|---|
4127 | 1 |
2 /* | |
3 * Copyright (C) Maxim Dounin | |
4412 | 4 * Copyright (C) Nginx, Inc. |
4127 | 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_uint_t max_cached; | |
15 | |
16 ngx_queue_t cache; | |
17 ngx_queue_t free; | |
18 | |
19 ngx_http_upstream_init_pt original_init_upstream; | |
20 ngx_http_upstream_init_peer_pt original_init_peer; | |
21 | |
22 } ngx_http_upstream_keepalive_srv_conf_t; | |
23 | |
24 | |
25 typedef struct { | |
26 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
27 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
28 ngx_queue_t queue; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
29 ngx_connection_t *connection; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
30 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
31 socklen_t socklen; |
6559
adf25b8d0431
Introduced the ngx_sockaddr_t type.
Ruslan Ermilov <ru@nginx.com>
parents:
6332
diff
changeset
|
32 ngx_sockaddr_t sockaddr; |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
33 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
34 } ngx_http_upstream_keepalive_cache_t; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
35 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
36 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
37 typedef struct { |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
38 ngx_http_upstream_keepalive_srv_conf_t *conf; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
39 |
4127 | 40 ngx_http_upstream_t *upstream; |
41 | |
42 void *data; | |
43 | |
44 ngx_event_get_peer_pt original_get_peer; | |
45 ngx_event_free_peer_pt original_free_peer; | |
46 | |
47 #if (NGX_HTTP_SSL) | |
48 ngx_event_set_peer_session_pt original_set_session; | |
49 ngx_event_save_peer_session_pt original_save_session; | |
50 #endif | |
51 | |
52 } ngx_http_upstream_keepalive_peer_data_t; | |
53 | |
54 | |
55 static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, | |
56 ngx_http_upstream_srv_conf_t *us); | |
57 static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, | |
58 void *data); | |
59 static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, | |
60 void *data, ngx_uint_t state); | |
61 | |
62 static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev); | |
63 static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev); | |
64 static void ngx_http_upstream_keepalive_close(ngx_connection_t *c); | |
65 | |
66 #if (NGX_HTTP_SSL) | |
67 static ngx_int_t ngx_http_upstream_keepalive_set_session( | |
68 ngx_peer_connection_t *pc, void *data); | |
69 static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, | |
70 void *data); | |
71 #endif | |
72 | |
73 static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf); | |
74 static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, | |
75 void *conf); | |
76 | |
77 | |
78 static ngx_command_t ngx_http_upstream_keepalive_commands[] = { | |
79 | |
80 { ngx_string("keepalive"), | |
5830
3e5b630e0ec9
Upstream keepalive: removed "single" parameter remnants.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5213
diff
changeset
|
81 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, |
4127 | 82 ngx_http_upstream_keepalive, |
5213
822b82191940
Upstream keepalive: slightly simplified code.
Ruslan Ermilov <ru@nginx.com>
parents:
5133
diff
changeset
|
83 NGX_HTTP_SRV_CONF_OFFSET, |
4127 | 84 0, |
85 NULL }, | |
86 | |
87 ngx_null_command | |
88 }; | |
89 | |
90 | |
91 static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = { | |
92 NULL, /* preconfiguration */ | |
93 NULL, /* postconfiguration */ | |
94 | |
95 NULL, /* create main configuration */ | |
96 NULL, /* init main configuration */ | |
97 | |
98 ngx_http_upstream_keepalive_create_conf, /* create server configuration */ | |
99 NULL, /* merge server configuration */ | |
100 | |
101 NULL, /* create location configuration */ | |
102 NULL /* merge location configuration */ | |
103 }; | |
104 | |
105 | |
106 ngx_module_t ngx_http_upstream_keepalive_module = { | |
107 NGX_MODULE_V1, | |
108 &ngx_http_upstream_keepalive_module_ctx, /* module context */ | |
109 ngx_http_upstream_keepalive_commands, /* module directives */ | |
110 NGX_HTTP_MODULE, /* module type */ | |
111 NULL, /* init master */ | |
112 NULL, /* init module */ | |
113 NULL, /* init process */ | |
114 NULL, /* init thread */ | |
115 NULL, /* exit thread */ | |
116 NULL, /* exit process */ | |
117 NULL, /* exit master */ | |
118 NGX_MODULE_V1_PADDING | |
119 }; | |
120 | |
121 | |
122 static ngx_int_t | |
123 ngx_http_upstream_init_keepalive(ngx_conf_t *cf, | |
124 ngx_http_upstream_srv_conf_t *us) | |
125 { | |
126 ngx_uint_t i; | |
127 ngx_http_upstream_keepalive_srv_conf_t *kcf; | |
128 ngx_http_upstream_keepalive_cache_t *cached; | |
129 | |
130 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, | |
131 "init keepalive"); | |
132 | |
133 kcf = ngx_http_conf_upstream_srv_conf(us, | |
134 ngx_http_upstream_keepalive_module); | |
135 | |
136 if (kcf->original_init_upstream(cf, us) != NGX_OK) { | |
137 return NGX_ERROR; | |
138 } | |
139 | |
140 kcf->original_init_peer = us->peer.init; | |
141 | |
142 us->peer.init = ngx_http_upstream_init_keepalive_peer; | |
143 | |
144 /* allocate cache items and add to free queue */ | |
145 | |
146 cached = ngx_pcalloc(cf->pool, | |
147 sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached); | |
148 if (cached == NULL) { | |
149 return NGX_ERROR; | |
150 } | |
151 | |
152 ngx_queue_init(&kcf->cache); | |
153 ngx_queue_init(&kcf->free); | |
154 | |
155 for (i = 0; i < kcf->max_cached; i++) { | |
156 ngx_queue_insert_head(&kcf->free, &cached[i].queue); | |
157 cached[i].conf = kcf; | |
158 } | |
159 | |
160 return NGX_OK; | |
161 } | |
162 | |
163 | |
164 static ngx_int_t | |
165 ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, | |
166 ngx_http_upstream_srv_conf_t *us) | |
167 { | |
168 ngx_http_upstream_keepalive_peer_data_t *kp; | |
169 ngx_http_upstream_keepalive_srv_conf_t *kcf; | |
170 | |
171 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
172 "init keepalive peer"); | |
173 | |
174 kcf = ngx_http_conf_upstream_srv_conf(us, | |
175 ngx_http_upstream_keepalive_module); | |
176 | |
177 kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t)); | |
178 if (kp == NULL) { | |
179 return NGX_ERROR; | |
180 } | |
181 | |
182 if (kcf->original_init_peer(r, us) != NGX_OK) { | |
183 return NGX_ERROR; | |
184 } | |
185 | |
186 kp->conf = kcf; | |
187 kp->upstream = r->upstream; | |
188 kp->data = r->upstream->peer.data; | |
189 kp->original_get_peer = r->upstream->peer.get; | |
190 kp->original_free_peer = r->upstream->peer.free; | |
191 | |
192 r->upstream->peer.data = kp; | |
193 r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer; | |
194 r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer; | |
195 | |
196 #if (NGX_HTTP_SSL) | |
197 kp->original_set_session = r->upstream->peer.set_session; | |
198 kp->original_save_session = r->upstream->peer.save_session; | |
199 r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session; | |
200 r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session; | |
201 #endif | |
202 | |
203 return NGX_OK; | |
204 } | |
205 | |
206 | |
207 static ngx_int_t | |
208 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) | |
209 { | |
210 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
211 ngx_http_upstream_keepalive_cache_t *item; | |
212 | |
213 ngx_int_t rc; | |
214 ngx_queue_t *q, *cache; | |
215 ngx_connection_t *c; | |
216 | |
217 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
218 "get keepalive peer"); | |
219 | |
4694
5b5c07dee156
Upstream keepalive: "single" parameter deprecated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
220 /* ask balancer */ |
4127 | 221 |
222 rc = kp->original_get_peer(pc, kp->data); | |
223 | |
4694
5b5c07dee156
Upstream keepalive: "single" parameter deprecated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
224 if (rc != NGX_OK) { |
4127 | 225 return rc; |
226 } | |
227 | |
228 /* search cache for suitable connection */ | |
229 | |
230 cache = &kp->conf->cache; | |
231 | |
232 for (q = ngx_queue_head(cache); | |
233 q != ngx_queue_sentinel(cache); | |
234 q = ngx_queue_next(q)) | |
235 { | |
236 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
237 c = item->connection; | |
238 | |
239 if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, | |
240 item->socklen, pc->socklen) | |
241 == 0) | |
242 { | |
243 ngx_queue_remove(q); | |
244 ngx_queue_insert_head(&kp->conf->free, q); | |
245 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
246 goto found; |
4127 | 247 } |
248 } | |
249 | |
250 return NGX_OK; | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
251 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
252 found: |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
253 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
254 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
255 "get keepalive peer: using connection %p", c); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
256 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
257 c->idle = 0; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
258 c->sent = 0; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
259 c->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
260 c->read->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
261 c->write->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
262 c->pool->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
263 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
264 pc->connection = c; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
265 pc->cached = 1; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
266 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
267 return NGX_DONE; |
4127 | 268 } |
269 | |
270 | |
271 static void | |
272 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, | |
273 ngx_uint_t state) | |
274 { | |
275 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
276 ngx_http_upstream_keepalive_cache_t *item; | |
277 | |
278 ngx_queue_t *q; | |
279 ngx_connection_t *c; | |
280 ngx_http_upstream_t *u; | |
281 | |
282 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
283 "free keepalive peer"); | |
284 | |
285 /* cache valid connections */ | |
286 | |
287 u = kp->upstream; | |
288 c = pc->connection; | |
289 | |
5133
089a662c17d1
Upstream: removed double-free workarounds in peer.free() methods.
Ruslan Ermilov <ru@nginx.com>
parents:
4998
diff
changeset
|
290 if (state & NGX_PEER_FAILED |
4127 | 291 || c == NULL |
292 || c->read->eof | |
293 || c->read->error | |
294 || c->read->timedout | |
295 || c->write->error | |
296 || c->write->timedout) | |
297 { | |
298 goto invalid; | |
299 } | |
300 | |
301 if (!u->keepalive) { | |
302 goto invalid; | |
303 } | |
304 | |
6332
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
305 if (!u->request_body_sent) { |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
306 goto invalid; |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
307 } |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
308 |
6220
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
309 if (ngx_terminate || ngx_exiting) { |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
310 goto invalid; |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
311 } |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
312 |
4127 | 313 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { |
314 goto invalid; | |
315 } | |
316 | |
317 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
318 "free keepalive peer: saving connection %p", c); | |
319 | |
320 if (ngx_queue_empty(&kp->conf->free)) { | |
321 | |
322 q = ngx_queue_last(&kp->conf->cache); | |
323 ngx_queue_remove(q); | |
324 | |
325 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
326 | |
327 ngx_http_upstream_keepalive_close(item->connection); | |
328 | |
329 } else { | |
330 q = ngx_queue_head(&kp->conf->free); | |
331 ngx_queue_remove(q); | |
332 | |
333 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
334 } | |
335 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
336 ngx_queue_insert_head(&kp->conf->cache, q); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
337 |
4127 | 338 item->connection = c; |
339 | |
340 pc->connection = NULL; | |
341 | |
342 if (c->read->timer_set) { | |
343 ngx_del_timer(c->read); | |
344 } | |
345 if (c->write->timer_set) { | |
346 ngx_del_timer(c->write); | |
347 } | |
348 | |
349 c->write->handler = ngx_http_upstream_keepalive_dummy_handler; | |
350 c->read->handler = ngx_http_upstream_keepalive_close_handler; | |
351 | |
352 c->data = item; | |
353 c->idle = 1; | |
354 c->log = ngx_cycle->log; | |
355 c->read->log = ngx_cycle->log; | |
356 c->write->log = ngx_cycle->log; | |
357 c->pool->log = ngx_cycle->log; | |
358 | |
359 item->socklen = pc->socklen; | |
360 ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); | |
361 | |
362 if (c->read->ready) { | |
363 ngx_http_upstream_keepalive_close_handler(c->read); | |
364 } | |
365 | |
366 invalid: | |
367 | |
368 kp->original_free_peer(pc, kp->data, state); | |
369 } | |
370 | |
371 | |
372 static void | |
373 ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev) | |
374 { | |
375 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, | |
376 "keepalive dummy handler"); | |
377 } | |
378 | |
379 | |
380 static void | |
381 ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev) | |
382 { | |
383 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
384 ngx_http_upstream_keepalive_cache_t *item; | |
385 | |
386 int n; | |
387 char buf[1]; | |
388 ngx_connection_t *c; | |
389 | |
390 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, | |
391 "keepalive close handler"); | |
392 | |
393 c = ev->data; | |
394 | |
395 if (c->close) { | |
396 goto close; | |
397 } | |
398 | |
399 n = recv(c->fd, buf, 1, MSG_PEEK); | |
400 | |
401 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { | |
5999
4d8936b1fc32
Upstream keepalive: drop ready flag on EAGAIN from recv(MSG_PEEK).
Valentin Bartenev <vbart@nginx.com>
parents:
5864
diff
changeset
|
402 ev->ready = 0; |
4127 | 403 |
404 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | |
405 goto close; | |
406 } | |
407 | |
408 return; | |
409 } | |
410 | |
411 close: | |
412 | |
413 item = c->data; | |
414 conf = item->conf; | |
415 | |
416 ngx_http_upstream_keepalive_close(c); | |
417 | |
418 ngx_queue_remove(&item->queue); | |
419 ngx_queue_insert_head(&conf->free, &item->queue); | |
420 } | |
421 | |
422 | |
423 static void | |
424 ngx_http_upstream_keepalive_close(ngx_connection_t *c) | |
425 { | |
426 | |
427 #if (NGX_HTTP_SSL) | |
428 | |
429 if (c->ssl) { | |
430 c->ssl->no_wait_shutdown = 1; | |
431 c->ssl->no_send_shutdown = 1; | |
432 | |
433 if (ngx_ssl_shutdown(c) == NGX_AGAIN) { | |
434 c->ssl->handler = ngx_http_upstream_keepalive_close; | |
435 return; | |
436 } | |
437 } | |
438 | |
439 #endif | |
440 | |
441 ngx_destroy_pool(c->pool); | |
442 ngx_close_connection(c); | |
443 } | |
444 | |
445 | |
446 #if (NGX_HTTP_SSL) | |
447 | |
448 static ngx_int_t | |
449 ngx_http_upstream_keepalive_set_session(ngx_peer_connection_t *pc, void *data) | |
450 { | |
451 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
452 | |
453 return kp->original_set_session(pc, kp->data); | |
454 } | |
455 | |
456 | |
457 static void | |
458 ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data) | |
459 { | |
460 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
461 | |
462 kp->original_save_session(pc, kp->data); | |
463 return; | |
464 } | |
465 | |
466 #endif | |
467 | |
468 | |
469 static void * | |
470 ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf) | |
471 { | |
472 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
473 | |
474 conf = ngx_pcalloc(cf->pool, | |
475 sizeof(ngx_http_upstream_keepalive_srv_conf_t)); | |
476 if (conf == NULL) { | |
477 return NULL; | |
478 } | |
479 | |
480 /* | |
481 * set by ngx_pcalloc(): | |
482 * | |
483 * conf->original_init_upstream = NULL; | |
484 * conf->original_init_peer = NULL; | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
485 * conf->max_cached = 0; |
4127 | 486 */ |
487 | |
488 return conf; | |
489 } | |
490 | |
491 | |
492 static char * | |
493 ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
494 { | |
495 ngx_http_upstream_srv_conf_t *uscf; | |
5213
822b82191940
Upstream keepalive: slightly simplified code.
Ruslan Ermilov <ru@nginx.com>
parents:
5133
diff
changeset
|
496 ngx_http_upstream_keepalive_srv_conf_t *kcf = conf; |
4127 | 497 |
498 ngx_int_t n; | |
499 ngx_str_t *value; | |
500 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
501 if (kcf->max_cached) { |
4998
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
502 return "is duplicate"; |
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
503 } |
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
504 |
4127 | 505 /* read options */ |
506 | |
507 value = cf->args->elts; | |
508 | |
509 n = ngx_atoi(value[1].data, value[1].len); | |
510 | |
511 if (n == NGX_ERROR || n == 0) { | |
512 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
513 "invalid value \"%V\" in \"%V\" directive", | |
514 &value[1], &cmd->name); | |
515 return NGX_CONF_ERROR; | |
516 } | |
517 | |
518 kcf->max_cached = n; | |
519 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
520 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
521 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
522 kcf->original_init_upstream = uscf->peer.init_upstream |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
523 ? uscf->peer.init_upstream |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
524 : ngx_http_upstream_init_round_robin; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
525 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
526 uscf->peer.init_upstream = ngx_http_upstream_init_keepalive; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
527 |
4127 | 528 return NGX_CONF_OK; |
529 } |