Mercurial > hg > nginx
annotate src/stream/ngx_stream_core_module.c @ 6230:2a621245f4cf
Win32: MSVC 2015 compatibility.
Resolved warnings about declarations that hide previous local declarations.
Warnings about WSASocketA() being deprecated resolved by explicit use of
WSASocketW() instead of WSASocket(). When compiling without IPv6 support,
WinSock deprecated warnings are disabled to allow use of gethostbyname().
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 17 Aug 2015 18:09:17 +0300 |
parents | 7565e056fad6 |
children | cf5e822cf470 |
rev | line source |
---|---|
6115 | 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_stream.h> | |
11 | |
12 | |
13 static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf); | |
14 static void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf); | |
15 static char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, | |
16 void *child); | |
17 static char *ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, | |
18 void *conf); | |
19 static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, | |
20 void *conf); | |
21 static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, | |
22 void *conf); | |
23 | |
24 | |
25 static ngx_command_t ngx_stream_core_commands[] = { | |
26 | |
27 { ngx_string("server"), | |
28 NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, | |
29 ngx_stream_core_server, | |
30 0, | |
31 0, | |
32 NULL }, | |
33 | |
34 { ngx_string("listen"), | |
35 NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, | |
36 ngx_stream_core_listen, | |
37 NGX_STREAM_SRV_CONF_OFFSET, | |
38 0, | |
39 NULL }, | |
40 | |
41 { ngx_string("error_log"), | |
42 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, | |
43 ngx_stream_core_error_log, | |
44 NGX_STREAM_SRV_CONF_OFFSET, | |
45 0, | |
46 NULL }, | |
47 | |
6221
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
48 { ngx_string("tcp_nodelay"), |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
49 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
50 ngx_conf_set_flag_slot, |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
51 NGX_STREAM_SRV_CONF_OFFSET, |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
52 offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay), |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
53 NULL }, |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
54 |
6115 | 55 ngx_null_command |
56 }; | |
57 | |
58 | |
59 static ngx_stream_module_t ngx_stream_core_module_ctx = { | |
6174
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
60 NULL, /* postconfiguration */ |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
61 |
6115 | 62 ngx_stream_core_create_main_conf, /* create main configuration */ |
63 NULL, /* init main configuration */ | |
64 | |
65 ngx_stream_core_create_srv_conf, /* create server configuration */ | |
66 ngx_stream_core_merge_srv_conf /* merge server configuration */ | |
67 }; | |
68 | |
69 | |
70 ngx_module_t ngx_stream_core_module = { | |
71 NGX_MODULE_V1, | |
72 &ngx_stream_core_module_ctx, /* module context */ | |
73 ngx_stream_core_commands, /* module directives */ | |
74 NGX_STREAM_MODULE, /* module type */ | |
75 NULL, /* init master */ | |
76 NULL, /* init module */ | |
77 NULL, /* init process */ | |
78 NULL, /* init thread */ | |
79 NULL, /* exit thread */ | |
80 NULL, /* exit process */ | |
81 NULL, /* exit master */ | |
82 NGX_MODULE_V1_PADDING | |
83 }; | |
84 | |
85 | |
86 static void * | |
87 ngx_stream_core_create_main_conf(ngx_conf_t *cf) | |
88 { | |
89 ngx_stream_core_main_conf_t *cmcf; | |
90 | |
91 cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t)); | |
92 if (cmcf == NULL) { | |
93 return NULL; | |
94 } | |
95 | |
96 if (ngx_array_init(&cmcf->servers, cf->pool, 4, | |
97 sizeof(ngx_stream_core_srv_conf_t *)) | |
98 != NGX_OK) | |
99 { | |
100 return NULL; | |
101 } | |
102 | |
103 if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t)) | |
104 != NGX_OK) | |
105 { | |
106 return NULL; | |
107 } | |
108 | |
109 return cmcf; | |
110 } | |
111 | |
112 | |
113 static void * | |
114 ngx_stream_core_create_srv_conf(ngx_conf_t *cf) | |
115 { | |
116 ngx_stream_core_srv_conf_t *cscf; | |
117 | |
118 cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t)); | |
119 if (cscf == NULL) { | |
120 return NULL; | |
121 } | |
122 | |
123 /* | |
124 * set by ngx_pcalloc(): | |
125 * | |
126 * cscf->handler = NULL; | |
127 * cscf->error_log = NULL; | |
128 */ | |
129 | |
130 cscf->file_name = cf->conf_file->file.name.data; | |
131 cscf->line = cf->conf_file->line; | |
6221
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
132 cscf->tcp_nodelay = NGX_CONF_UNSET; |
6115 | 133 |
134 return cscf; | |
135 } | |
136 | |
137 | |
138 static char * | |
139 ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
140 { | |
141 ngx_stream_core_srv_conf_t *prev = parent; | |
142 ngx_stream_core_srv_conf_t *conf = child; | |
143 | |
144 if (conf->handler == NULL) { | |
145 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
146 "no handler for server in %s:%ui", | |
147 conf->file_name, conf->line); | |
148 return NGX_CONF_ERROR; | |
149 } | |
150 | |
151 if (conf->error_log == NULL) { | |
152 if (prev->error_log) { | |
153 conf->error_log = prev->error_log; | |
154 } else { | |
155 conf->error_log = &cf->cycle->new_log; | |
156 } | |
157 } | |
158 | |
6221
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
159 ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); |
7565e056fad6
Stream: the "tcp_nodelay" directive.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
160 |
6115 | 161 return NGX_CONF_OK; |
162 } | |
163 | |
164 | |
165 static char * | |
166 ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
167 { | |
168 ngx_stream_core_srv_conf_t *cscf = conf; | |
169 | |
170 return ngx_log_set_log(cf, &cscf->error_log); | |
171 } | |
172 | |
173 | |
174 static char * | |
175 ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
176 { | |
177 char *rv; | |
178 void *mconf; | |
179 ngx_uint_t m; | |
180 ngx_conf_t pcf; | |
181 ngx_stream_module_t *module; | |
182 ngx_stream_conf_ctx_t *ctx, *stream_ctx; | |
183 ngx_stream_core_srv_conf_t *cscf, **cscfp; | |
184 ngx_stream_core_main_conf_t *cmcf; | |
185 | |
186 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); | |
187 if (ctx == NULL) { | |
188 return NGX_CONF_ERROR; | |
189 } | |
190 | |
191 stream_ctx = cf->ctx; | |
192 ctx->main_conf = stream_ctx->main_conf; | |
193 | |
194 /* the server{}'s srv_conf */ | |
195 | |
196 ctx->srv_conf = ngx_pcalloc(cf->pool, | |
197 sizeof(void *) * ngx_stream_max_module); | |
198 if (ctx->srv_conf == NULL) { | |
199 return NGX_CONF_ERROR; | |
200 } | |
201 | |
202 for (m = 0; ngx_modules[m]; m++) { | |
203 if (ngx_modules[m]->type != NGX_STREAM_MODULE) { | |
204 continue; | |
205 } | |
206 | |
207 module = ngx_modules[m]->ctx; | |
208 | |
209 if (module->create_srv_conf) { | |
210 mconf = module->create_srv_conf(cf); | |
211 if (mconf == NULL) { | |
212 return NGX_CONF_ERROR; | |
213 } | |
214 | |
215 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; | |
216 } | |
217 } | |
218 | |
219 /* the server configuration context */ | |
220 | |
221 cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index]; | |
222 cscf->ctx = ctx; | |
223 | |
224 cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; | |
225 | |
226 cscfp = ngx_array_push(&cmcf->servers); | |
227 if (cscfp == NULL) { | |
228 return NGX_CONF_ERROR; | |
229 } | |
230 | |
231 *cscfp = cscf; | |
232 | |
233 | |
234 /* parse inside server{} */ | |
235 | |
236 pcf = *cf; | |
237 cf->ctx = ctx; | |
238 cf->cmd_type = NGX_STREAM_SRV_CONF; | |
239 | |
240 rv = ngx_conf_parse(cf, NULL); | |
241 | |
242 *cf = pcf; | |
243 | |
244 return rv; | |
245 } | |
246 | |
247 | |
248 static char * | |
249 ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
250 { | |
251 size_t len, off; | |
252 in_port_t port; | |
253 ngx_str_t *value; | |
254 ngx_url_t u; | |
255 ngx_uint_t i; | |
256 struct sockaddr *sa; | |
257 struct sockaddr_in *sin; | |
258 ngx_stream_listen_t *ls; | |
259 ngx_stream_core_main_conf_t *cmcf; | |
260 #if (NGX_HAVE_INET6) | |
261 struct sockaddr_in6 *sin6; | |
262 #endif | |
263 | |
264 value = cf->args->elts; | |
265 | |
266 ngx_memzero(&u, sizeof(ngx_url_t)); | |
267 | |
268 u.url = value[1]; | |
269 u.listen = 1; | |
270 | |
271 if (ngx_parse_url(cf->pool, &u) != NGX_OK) { | |
272 if (u.err) { | |
273 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
274 "%s in \"%V\" of the \"listen\" directive", | |
275 u.err, &u.url); | |
276 } | |
277 | |
278 return NGX_CONF_ERROR; | |
279 } | |
280 | |
281 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); | |
282 | |
283 ls = cmcf->listen.elts; | |
284 | |
285 for (i = 0; i < cmcf->listen.nelts; i++) { | |
286 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
287 sa = &ls[i].u.sockaddr; |
6115 | 288 |
289 if (sa->sa_family != u.family) { | |
290 continue; | |
291 } | |
292 | |
293 switch (sa->sa_family) { | |
294 | |
295 #if (NGX_HAVE_INET6) | |
296 case AF_INET6: | |
297 off = offsetof(struct sockaddr_in6, sin6_addr); | |
298 len = 16; | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
299 sin6 = &ls[i].u.sockaddr_in6; |
6115 | 300 port = sin6->sin6_port; |
301 break; | |
302 #endif | |
303 | |
304 #if (NGX_HAVE_UNIX_DOMAIN) | |
305 case AF_UNIX: | |
306 off = offsetof(struct sockaddr_un, sun_path); | |
307 len = sizeof(((struct sockaddr_un *) sa)->sun_path); | |
308 port = 0; | |
309 break; | |
310 #endif | |
311 | |
312 default: /* AF_INET */ | |
313 off = offsetof(struct sockaddr_in, sin_addr); | |
314 len = 4; | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
315 sin = &ls[i].u.sockaddr_in; |
6115 | 316 port = sin->sin_port; |
317 break; | |
318 } | |
319 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
320 if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
321 != 0) |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
322 { |
6115 | 323 continue; |
324 } | |
325 | |
326 if (port != u.port) { | |
327 continue; | |
328 } | |
329 | |
330 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
331 "duplicate \"%V\" address and port pair", &u.url); | |
332 return NGX_CONF_ERROR; | |
333 } | |
334 | |
335 ls = ngx_array_push(&cmcf->listen); | |
336 if (ls == NULL) { | |
337 return NGX_CONF_ERROR; | |
338 } | |
339 | |
340 ngx_memzero(ls, sizeof(ngx_stream_listen_t)); | |
341 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
342 ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); |
6115 | 343 |
344 ls->socklen = u.socklen; | |
6172 | 345 ls->backlog = NGX_LISTEN_BACKLOG; |
6115 | 346 ls->wildcard = u.wildcard; |
347 ls->ctx = cf->ctx; | |
348 | |
349 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) | |
350 ls->ipv6only = 1; | |
351 #endif | |
352 | |
353 for (i = 2; i < cf->args->nelts; i++) { | |
354 | |
355 if (ngx_strcmp(value[i].data, "bind") == 0) { | |
356 ls->bind = 1; | |
357 continue; | |
358 } | |
359 | |
6172 | 360 if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { |
361 ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); | |
362 ls->bind = 1; | |
363 | |
364 if (ls->backlog == NGX_ERROR || ls->backlog == 0) { | |
365 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
366 "invalid backlog \"%V\"", &value[i]); | |
367 return NGX_CONF_ERROR; | |
368 } | |
369 | |
370 continue; | |
371 } | |
372 | |
6115 | 373 if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { |
374 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) | |
6230
2a621245f4cf
Win32: MSVC 2015 compatibility.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6221
diff
changeset
|
375 u_char buf[NGX_SOCKADDR_STRLEN]; |
6115 | 376 |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
377 sa = &ls->u.sockaddr; |
6115 | 378 |
379 if (sa->sa_family == AF_INET6) { | |
380 | |
381 if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
382 ls->ipv6only = 1; | |
383 | |
384 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
385 ls->ipv6only = 0; | |
386 | |
387 } else { | |
388 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
389 "invalid ipv6only flags \"%s\"", | |
390 &value[i].data[9]); | |
391 return NGX_CONF_ERROR; | |
392 } | |
393 | |
394 ls->bind = 1; | |
395 | |
396 } else { | |
397 len = ngx_sock_ntop(sa, ls->socklen, buf, | |
398 NGX_SOCKADDR_STRLEN, 1); | |
399 | |
400 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
401 "ipv6only is not supported " | |
402 "on addr \"%*s\", ignored", len, buf); | |
403 } | |
404 | |
405 continue; | |
406 #else | |
407 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
408 "bind ipv6only is not supported " | |
409 "on this platform"); | |
410 return NGX_CONF_ERROR; | |
411 #endif | |
412 } | |
413 | |
6153
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
414 if (ngx_strcmp(value[i].data, "reuseport") == 0) { |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
415 #if (NGX_HAVE_REUSEPORT) |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
416 ls->reuseport = 1; |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
417 ls->bind = 1; |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
418 #else |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
419 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
420 "reuseport is not supported " |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
421 "on this platform, ignored"); |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
422 #endif |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
423 continue; |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
424 } |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6115
diff
changeset
|
425 |
6115 | 426 if (ngx_strcmp(value[i].data, "ssl") == 0) { |
427 #if (NGX_STREAM_SSL) | |
428 ls->ssl = 1; | |
429 continue; | |
430 #else | |
431 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
432 "the \"ssl\" parameter requires " | |
433 "ngx_stream_ssl_module"); | |
434 return NGX_CONF_ERROR; | |
435 #endif | |
436 } | |
437 | |
438 if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { | |
439 | |
440 if (ngx_strcmp(&value[i].data[13], "on") == 0) { | |
441 ls->so_keepalive = 1; | |
442 | |
443 } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { | |
444 ls->so_keepalive = 2; | |
445 | |
446 } else { | |
447 | |
448 #if (NGX_HAVE_KEEPALIVE_TUNABLE) | |
449 u_char *p, *end; | |
450 ngx_str_t s; | |
451 | |
452 end = value[i].data + value[i].len; | |
453 s.data = value[i].data + 13; | |
454 | |
455 p = ngx_strlchr(s.data, end, ':'); | |
456 if (p == NULL) { | |
457 p = end; | |
458 } | |
459 | |
460 if (p > s.data) { | |
461 s.len = p - s.data; | |
462 | |
463 ls->tcp_keepidle = ngx_parse_time(&s, 1); | |
464 if (ls->tcp_keepidle == (time_t) NGX_ERROR) { | |
465 goto invalid_so_keepalive; | |
466 } | |
467 } | |
468 | |
469 s.data = (p < end) ? (p + 1) : end; | |
470 | |
471 p = ngx_strlchr(s.data, end, ':'); | |
472 if (p == NULL) { | |
473 p = end; | |
474 } | |
475 | |
476 if (p > s.data) { | |
477 s.len = p - s.data; | |
478 | |
479 ls->tcp_keepintvl = ngx_parse_time(&s, 1); | |
480 if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { | |
481 goto invalid_so_keepalive; | |
482 } | |
483 } | |
484 | |
485 s.data = (p < end) ? (p + 1) : end; | |
486 | |
487 if (s.data < end) { | |
488 s.len = end - s.data; | |
489 | |
490 ls->tcp_keepcnt = ngx_atoi(s.data, s.len); | |
491 if (ls->tcp_keepcnt == NGX_ERROR) { | |
492 goto invalid_so_keepalive; | |
493 } | |
494 } | |
495 | |
496 if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 | |
497 && ls->tcp_keepcnt == 0) | |
498 { | |
499 goto invalid_so_keepalive; | |
500 } | |
501 | |
502 ls->so_keepalive = 1; | |
503 | |
504 #else | |
505 | |
506 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
507 "the \"so_keepalive\" parameter accepts " | |
508 "only \"on\" or \"off\" on this platform"); | |
509 return NGX_CONF_ERROR; | |
510 | |
511 #endif | |
512 } | |
513 | |
514 ls->bind = 1; | |
515 | |
516 continue; | |
517 | |
518 #if (NGX_HAVE_KEEPALIVE_TUNABLE) | |
519 invalid_so_keepalive: | |
520 | |
521 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
522 "invalid so_keepalive value: \"%s\"", | |
523 &value[i].data[13]); | |
524 return NGX_CONF_ERROR; | |
525 #endif | |
526 } | |
527 | |
528 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
529 "the invalid \"%V\" parameter", &value[i]); | |
530 return NGX_CONF_ERROR; | |
531 } | |
532 | |
533 return NGX_CONF_OK; | |
534 } |