Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Roman Arutyunyan
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
0014 static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
0015 static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
0016 static void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf);
0017 static char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
0018     void *child);
0019 static char *ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
0020     void *conf);
0021 static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
0022     void *conf);
0023 static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
0024     void *conf);
0025 static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
0026     void *conf);
0027 
0028 
0029 static ngx_command_t  ngx_stream_core_commands[] = {
0030 
0031     { ngx_string("variables_hash_max_size"),
0032       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
0033       ngx_conf_set_num_slot,
0034       NGX_STREAM_MAIN_CONF_OFFSET,
0035       offsetof(ngx_stream_core_main_conf_t, variables_hash_max_size),
0036       NULL },
0037 
0038     { ngx_string("variables_hash_bucket_size"),
0039       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
0040       ngx_conf_set_num_slot,
0041       NGX_STREAM_MAIN_CONF_OFFSET,
0042       offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
0043       NULL },
0044 
0045     { ngx_string("server"),
0046       NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
0047       ngx_stream_core_server,
0048       0,
0049       0,
0050       NULL },
0051 
0052     { ngx_string("listen"),
0053       NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0054       ngx_stream_core_listen,
0055       NGX_STREAM_SRV_CONF_OFFSET,
0056       0,
0057       NULL },
0058 
0059     { ngx_string("error_log"),
0060       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0061       ngx_stream_core_error_log,
0062       NGX_STREAM_SRV_CONF_OFFSET,
0063       0,
0064       NULL },
0065 
0066     { ngx_string("resolver"),
0067       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0068       ngx_stream_core_resolver,
0069       NGX_STREAM_SRV_CONF_OFFSET,
0070       0,
0071       NULL },
0072 
0073     { ngx_string("resolver_timeout"),
0074       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0075       ngx_conf_set_msec_slot,
0076       NGX_STREAM_SRV_CONF_OFFSET,
0077       offsetof(ngx_stream_core_srv_conf_t, resolver_timeout),
0078       NULL },
0079 
0080     { ngx_string("proxy_protocol_timeout"),
0081       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0082       ngx_conf_set_msec_slot,
0083       NGX_STREAM_SRV_CONF_OFFSET,
0084       offsetof(ngx_stream_core_srv_conf_t, proxy_protocol_timeout),
0085       NULL },
0086 
0087     { ngx_string("tcp_nodelay"),
0088       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0089       ngx_conf_set_flag_slot,
0090       NGX_STREAM_SRV_CONF_OFFSET,
0091       offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay),
0092       NULL },
0093 
0094     { ngx_string("preread_buffer_size"),
0095       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0096       ngx_conf_set_size_slot,
0097       NGX_STREAM_SRV_CONF_OFFSET,
0098       offsetof(ngx_stream_core_srv_conf_t, preread_buffer_size),
0099       NULL },
0100 
0101     { ngx_string("preread_timeout"),
0102       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0103       ngx_conf_set_msec_slot,
0104       NGX_STREAM_SRV_CONF_OFFSET,
0105       offsetof(ngx_stream_core_srv_conf_t, preread_timeout),
0106       NULL },
0107 
0108       ngx_null_command
0109 };
0110 
0111 
0112 static ngx_stream_module_t  ngx_stream_core_module_ctx = {
0113     ngx_stream_core_preconfiguration,      /* preconfiguration */
0114     NULL,                                  /* postconfiguration */
0115 
0116     ngx_stream_core_create_main_conf,      /* create main configuration */
0117     ngx_stream_core_init_main_conf,        /* init main configuration */
0118 
0119     ngx_stream_core_create_srv_conf,       /* create server configuration */
0120     ngx_stream_core_merge_srv_conf         /* merge server configuration */
0121 };
0122 
0123 
0124 ngx_module_t  ngx_stream_core_module = {
0125     NGX_MODULE_V1,
0126     &ngx_stream_core_module_ctx,           /* module context */
0127     ngx_stream_core_commands,              /* module directives */
0128     NGX_STREAM_MODULE,                     /* module type */
0129     NULL,                                  /* init master */
0130     NULL,                                  /* init module */
0131     NULL,                                  /* init process */
0132     NULL,                                  /* init thread */
0133     NULL,                                  /* exit thread */
0134     NULL,                                  /* exit process */
0135     NULL,                                  /* exit master */
0136     NGX_MODULE_V1_PADDING
0137 };
0138 
0139 
0140 void
0141 ngx_stream_core_run_phases(ngx_stream_session_t *s)
0142 {
0143     ngx_int_t                     rc;
0144     ngx_stream_phase_handler_t   *ph;
0145     ngx_stream_core_main_conf_t  *cmcf;
0146 
0147     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
0148 
0149     ph = cmcf->phase_engine.handlers;
0150 
0151     while (ph[s->phase_handler].checker) {
0152 
0153         rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);
0154 
0155         if (rc == NGX_OK) {
0156             return;
0157         }
0158     }
0159 }
0160 
0161 
0162 ngx_int_t
0163 ngx_stream_core_generic_phase(ngx_stream_session_t *s,
0164     ngx_stream_phase_handler_t *ph)
0165 {
0166     ngx_int_t  rc;
0167 
0168     /*
0169      * generic phase checker,
0170      * used by all phases, except for preread and content
0171      */
0172 
0173     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
0174                    "generic phase: %ui", s->phase_handler);
0175 
0176     rc = ph->handler(s);
0177 
0178     if (rc == NGX_OK) {
0179         s->phase_handler = ph->next;
0180         return NGX_AGAIN;
0181     }
0182 
0183     if (rc == NGX_DECLINED) {
0184         s->phase_handler++;
0185         return NGX_AGAIN;
0186     }
0187 
0188     if (rc == NGX_AGAIN || rc == NGX_DONE) {
0189         return NGX_OK;
0190     }
0191 
0192     if (rc == NGX_ERROR) {
0193         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
0194     }
0195 
0196     ngx_stream_finalize_session(s, rc);
0197 
0198     return NGX_OK;
0199 }
0200 
0201 
0202 ngx_int_t
0203 ngx_stream_core_preread_phase(ngx_stream_session_t *s,
0204     ngx_stream_phase_handler_t *ph)
0205 {
0206     size_t                       size;
0207     ssize_t                      n;
0208     ngx_int_t                    rc;
0209     ngx_connection_t            *c;
0210     ngx_stream_core_srv_conf_t  *cscf;
0211 
0212     c = s->connection;
0213 
0214     c->log->action = "prereading client data";
0215 
0216     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0217 
0218     if (c->read->timedout) {
0219         rc = NGX_STREAM_OK;
0220 
0221     } else if (c->read->timer_set) {
0222         rc = NGX_AGAIN;
0223 
0224     } else {
0225         rc = ph->handler(s);
0226     }
0227 
0228     while (rc == NGX_AGAIN) {
0229 
0230         if (c->buffer == NULL) {
0231             c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
0232             if (c->buffer == NULL) {
0233                 rc = NGX_ERROR;
0234                 break;
0235             }
0236         }
0237 
0238         size = c->buffer->end - c->buffer->last;
0239 
0240         if (size == 0) {
0241             ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
0242             rc = NGX_STREAM_BAD_REQUEST;
0243             break;
0244         }
0245 
0246         if (c->read->eof) {
0247             rc = NGX_STREAM_OK;
0248             break;
0249         }
0250 
0251         if (!c->read->ready) {
0252             break;
0253         }
0254 
0255         n = c->recv(c, c->buffer->last, size);
0256 
0257         if (n == NGX_ERROR || n == 0) {
0258             rc = NGX_STREAM_OK;
0259             break;
0260         }
0261 
0262         if (n == NGX_AGAIN) {
0263             break;
0264         }
0265 
0266         c->buffer->last += n;
0267 
0268         rc = ph->handler(s);
0269     }
0270 
0271     if (rc == NGX_AGAIN) {
0272         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0273             ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0274             return NGX_OK;
0275         }
0276 
0277         if (!c->read->timer_set) {
0278             ngx_add_timer(c->read, cscf->preread_timeout);
0279         }
0280 
0281         c->read->handler = ngx_stream_session_handler;
0282 
0283         return NGX_OK;
0284     }
0285 
0286     if (c->read->timer_set) {
0287         ngx_del_timer(c->read);
0288     }
0289 
0290     if (rc == NGX_OK) {
0291         s->phase_handler = ph->next;
0292         return NGX_AGAIN;
0293     }
0294 
0295     if (rc == NGX_DECLINED) {
0296         s->phase_handler++;
0297         return NGX_AGAIN;
0298     }
0299 
0300     if (rc == NGX_DONE) {
0301         return NGX_OK;
0302     }
0303 
0304     if (rc == NGX_ERROR) {
0305         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
0306     }
0307 
0308     ngx_stream_finalize_session(s, rc);
0309 
0310     return NGX_OK;
0311 }
0312 
0313 
0314 ngx_int_t
0315 ngx_stream_core_content_phase(ngx_stream_session_t *s,
0316     ngx_stream_phase_handler_t *ph)
0317 {
0318     ngx_connection_t            *c;
0319     ngx_stream_core_srv_conf_t  *cscf;
0320 
0321     c = s->connection;
0322 
0323     c->log->action = NULL;
0324 
0325     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0326 
0327     if (c->type == SOCK_STREAM
0328         && cscf->tcp_nodelay
0329         && ngx_tcp_nodelay(c) != NGX_OK)
0330     {
0331         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0332         return NGX_OK;
0333     }
0334 
0335     cscf->handler(s);
0336 
0337     return NGX_OK;
0338 }
0339 
0340 
0341 static ngx_int_t
0342 ngx_stream_core_preconfiguration(ngx_conf_t *cf)
0343 {
0344     return ngx_stream_variables_add_core_vars(cf);
0345 }
0346 
0347 
0348 static void *
0349 ngx_stream_core_create_main_conf(ngx_conf_t *cf)
0350 {
0351     ngx_stream_core_main_conf_t  *cmcf;
0352 
0353     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t));
0354     if (cmcf == NULL) {
0355         return NULL;
0356     }
0357 
0358     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
0359                        sizeof(ngx_stream_core_srv_conf_t *))
0360         != NGX_OK)
0361     {
0362         return NULL;
0363     }
0364 
0365     if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
0366         != NGX_OK)
0367     {
0368         return NULL;
0369     }
0370 
0371     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
0372     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
0373 
0374     return cmcf;
0375 }
0376 
0377 
0378 static char *
0379 ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
0380 {
0381     ngx_stream_core_main_conf_t *cmcf = conf;
0382 
0383     ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
0384     ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
0385 
0386     cmcf->variables_hash_bucket_size =
0387                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
0388 
0389     if (cmcf->ncaptures) {
0390         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
0391     }
0392 
0393     return NGX_CONF_OK;
0394 }
0395 
0396 
0397 static void *
0398 ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
0399 {
0400     ngx_stream_core_srv_conf_t  *cscf;
0401 
0402     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t));
0403     if (cscf == NULL) {
0404         return NULL;
0405     }
0406 
0407     /*
0408      * set by ngx_pcalloc():
0409      *
0410      *     cscf->handler = NULL;
0411      *     cscf->error_log = NULL;
0412      */
0413 
0414     cscf->file_name = cf->conf_file->file.name.data;
0415     cscf->line = cf->conf_file->line;
0416     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
0417     cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC;
0418     cscf->tcp_nodelay = NGX_CONF_UNSET;
0419     cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
0420     cscf->preread_timeout = NGX_CONF_UNSET_MSEC;
0421 
0422     return cscf;
0423 }
0424 
0425 
0426 static char *
0427 ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
0428 {
0429     ngx_stream_core_srv_conf_t *prev = parent;
0430     ngx_stream_core_srv_conf_t *conf = child;
0431 
0432     ngx_conf_merge_msec_value(conf->resolver_timeout,
0433                               prev->resolver_timeout, 30000);
0434 
0435     if (conf->resolver == NULL) {
0436 
0437         if (prev->resolver == NULL) {
0438 
0439             /*
0440              * create dummy resolver in stream {} context
0441              * to inherit it in all servers
0442              */
0443 
0444             prev->resolver = ngx_resolver_create(cf, NULL, 0);
0445             if (prev->resolver == NULL) {
0446                 return NGX_CONF_ERROR;
0447             }
0448         }
0449 
0450         conf->resolver = prev->resolver;
0451     }
0452 
0453     if (conf->handler == NULL) {
0454         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0455                       "no handler for server in %s:%ui",
0456                       conf->file_name, conf->line);
0457         return NGX_CONF_ERROR;
0458     }
0459 
0460     if (conf->error_log == NULL) {
0461         if (prev->error_log) {
0462             conf->error_log = prev->error_log;
0463         } else {
0464             conf->error_log = &cf->cycle->new_log;
0465         }
0466     }
0467 
0468     ngx_conf_merge_msec_value(conf->proxy_protocol_timeout,
0469                               prev->proxy_protocol_timeout, 30000);
0470 
0471     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
0472 
0473     ngx_conf_merge_size_value(conf->preread_buffer_size,
0474                               prev->preread_buffer_size, 16384);
0475 
0476     ngx_conf_merge_msec_value(conf->preread_timeout,
0477                               prev->preread_timeout, 30000);
0478 
0479     return NGX_CONF_OK;
0480 }
0481 
0482 
0483 static char *
0484 ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0485 {
0486     ngx_stream_core_srv_conf_t  *cscf = conf;
0487 
0488     return ngx_log_set_log(cf, &cscf->error_log);
0489 }
0490 
0491 
0492 static char *
0493 ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0494 {
0495     char                         *rv;
0496     void                         *mconf;
0497     ngx_uint_t                    m;
0498     ngx_conf_t                    pcf;
0499     ngx_stream_module_t          *module;
0500     ngx_stream_conf_ctx_t        *ctx, *stream_ctx;
0501     ngx_stream_core_srv_conf_t   *cscf, **cscfp;
0502     ngx_stream_core_main_conf_t  *cmcf;
0503 
0504     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t));
0505     if (ctx == NULL) {
0506         return NGX_CONF_ERROR;
0507     }
0508 
0509     stream_ctx = cf->ctx;
0510     ctx->main_conf = stream_ctx->main_conf;
0511 
0512     /* the server{}'s srv_conf */
0513 
0514     ctx->srv_conf = ngx_pcalloc(cf->pool,
0515                                 sizeof(void *) * ngx_stream_max_module);
0516     if (ctx->srv_conf == NULL) {
0517         return NGX_CONF_ERROR;
0518     }
0519 
0520     for (m = 0; cf->cycle->modules[m]; m++) {
0521         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0522             continue;
0523         }
0524 
0525         module = cf->cycle->modules[m]->ctx;
0526 
0527         if (module->create_srv_conf) {
0528             mconf = module->create_srv_conf(cf);
0529             if (mconf == NULL) {
0530                 return NGX_CONF_ERROR;
0531             }
0532 
0533             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
0534         }
0535     }
0536 
0537     /* the server configuration context */
0538 
0539     cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index];
0540     cscf->ctx = ctx;
0541 
0542     cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index];
0543 
0544     cscfp = ngx_array_push(&cmcf->servers);
0545     if (cscfp == NULL) {
0546         return NGX_CONF_ERROR;
0547     }
0548 
0549     *cscfp = cscf;
0550 
0551 
0552     /* parse inside server{} */
0553 
0554     pcf = *cf;
0555     cf->ctx = ctx;
0556     cf->cmd_type = NGX_STREAM_SRV_CONF;
0557 
0558     rv = ngx_conf_parse(cf, NULL);
0559 
0560     *cf = pcf;
0561 
0562     if (rv == NGX_CONF_OK && !cscf->listen) {
0563         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0564                       "no \"listen\" is defined for server in %s:%ui",
0565                       cscf->file_name, cscf->line);
0566         return NGX_CONF_ERROR;
0567     }
0568 
0569     return rv;
0570 }
0571 
0572 
0573 static char *
0574 ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0575 {
0576     ngx_stream_core_srv_conf_t  *cscf = conf;
0577 
0578     ngx_str_t                    *value, size;
0579     ngx_url_t                     u;
0580     ngx_uint_t                    i, n, backlog;
0581     ngx_stream_listen_t          *ls, *als;
0582     ngx_stream_core_main_conf_t  *cmcf;
0583 
0584     cscf->listen = 1;
0585 
0586     value = cf->args->elts;
0587 
0588     ngx_memzero(&u, sizeof(ngx_url_t));
0589 
0590     u.url = value[1];
0591     u.listen = 1;
0592 
0593     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0594         if (u.err) {
0595             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0596                                "%s in \"%V\" of the \"listen\" directive",
0597                                u.err, &u.url);
0598         }
0599 
0600         return NGX_CONF_ERROR;
0601     }
0602 
0603     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
0604 
0605     ls = ngx_array_push_n(&cmcf->listen, u.naddrs);
0606     if (ls == NULL) {
0607         return NGX_CONF_ERROR;
0608     }
0609 
0610     ngx_memzero(ls, sizeof(ngx_stream_listen_t));
0611 
0612     ls->backlog = NGX_LISTEN_BACKLOG;
0613     ls->rcvbuf = -1;
0614     ls->sndbuf = -1;
0615     ls->type = SOCK_STREAM;
0616     ls->ctx = cf->ctx;
0617 
0618 #if (NGX_HAVE_INET6)
0619     ls->ipv6only = 1;
0620 #endif
0621 
0622     backlog = 0;
0623 
0624     for (i = 2; i < cf->args->nelts; i++) {
0625 
0626 #if !(NGX_WIN32)
0627         if (ngx_strcmp(value[i].data, "udp") == 0) {
0628             ls->type = SOCK_DGRAM;
0629             continue;
0630         }
0631 #endif
0632 
0633         if (ngx_strcmp(value[i].data, "bind") == 0) {
0634             ls->bind = 1;
0635             continue;
0636         }
0637 
0638         if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
0639             ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
0640             ls->bind = 1;
0641 
0642             if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
0643                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0644                                    "invalid backlog \"%V\"", &value[i]);
0645                 return NGX_CONF_ERROR;
0646             }
0647 
0648             backlog = 1;
0649 
0650             continue;
0651         }
0652 
0653         if (ngx_strncmp(value[i].data, "rcvbuf=", 7) == 0) {
0654             size.len = value[i].len - 7;
0655             size.data = value[i].data + 7;
0656 
0657             ls->rcvbuf = ngx_parse_size(&size);
0658             ls->bind = 1;
0659 
0660             if (ls->rcvbuf == NGX_ERROR) {
0661                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0662                                    "invalid rcvbuf \"%V\"", &value[i]);
0663                 return NGX_CONF_ERROR;
0664             }
0665 
0666             continue;
0667         }
0668 
0669         if (ngx_strncmp(value[i].data, "sndbuf=", 7) == 0) {
0670             size.len = value[i].len - 7;
0671             size.data = value[i].data + 7;
0672 
0673             ls->sndbuf = ngx_parse_size(&size);
0674             ls->bind = 1;
0675 
0676             if (ls->sndbuf == NGX_ERROR) {
0677                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0678                                    "invalid sndbuf \"%V\"", &value[i]);
0679                 return NGX_CONF_ERROR;
0680             }
0681 
0682             continue;
0683         }
0684 
0685         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
0686 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
0687             if (ngx_strcmp(&value[i].data[10], "n") == 0) {
0688                 ls->ipv6only = 1;
0689 
0690             } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
0691                 ls->ipv6only = 0;
0692 
0693             } else {
0694                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0695                                    "invalid ipv6only flags \"%s\"",
0696                                    &value[i].data[9]);
0697                 return NGX_CONF_ERROR;
0698             }
0699 
0700             ls->bind = 1;
0701             continue;
0702 #else
0703             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0704                                "bind ipv6only is not supported "
0705                                "on this platform");
0706             return NGX_CONF_ERROR;
0707 #endif
0708         }
0709 
0710         if (ngx_strcmp(value[i].data, "reuseport") == 0) {
0711 #if (NGX_HAVE_REUSEPORT)
0712             ls->reuseport = 1;
0713             ls->bind = 1;
0714 #else
0715             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0716                                "reuseport is not supported "
0717                                "on this platform, ignored");
0718 #endif
0719             continue;
0720         }
0721 
0722         if (ngx_strcmp(value[i].data, "ssl") == 0) {
0723 #if (NGX_STREAM_SSL)
0724             ngx_stream_ssl_conf_t  *sslcf;
0725 
0726             sslcf = ngx_stream_conf_get_module_srv_conf(cf,
0727                                                         ngx_stream_ssl_module);
0728 
0729             sslcf->listen = 1;
0730             sslcf->file = cf->conf_file->file.name.data;
0731             sslcf->line = cf->conf_file->line;
0732 
0733             ls->ssl = 1;
0734 
0735             continue;
0736 #else
0737             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0738                                "the \"ssl\" parameter requires "
0739                                "ngx_stream_ssl_module");
0740             return NGX_CONF_ERROR;
0741 #endif
0742         }
0743 
0744         if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
0745 
0746             if (ngx_strcmp(&value[i].data[13], "on") == 0) {
0747                 ls->so_keepalive = 1;
0748 
0749             } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
0750                 ls->so_keepalive = 2;
0751 
0752             } else {
0753 
0754 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0755                 u_char     *p, *end;
0756                 ngx_str_t   s;
0757 
0758                 end = value[i].data + value[i].len;
0759                 s.data = value[i].data + 13;
0760 
0761                 p = ngx_strlchr(s.data, end, ':');
0762                 if (p == NULL) {
0763                     p = end;
0764                 }
0765 
0766                 if (p > s.data) {
0767                     s.len = p - s.data;
0768 
0769                     ls->tcp_keepidle = ngx_parse_time(&s, 1);
0770                     if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
0771                         goto invalid_so_keepalive;
0772                     }
0773                 }
0774 
0775                 s.data = (p < end) ? (p + 1) : end;
0776 
0777                 p = ngx_strlchr(s.data, end, ':');
0778                 if (p == NULL) {
0779                     p = end;
0780                 }
0781 
0782                 if (p > s.data) {
0783                     s.len = p - s.data;
0784 
0785                     ls->tcp_keepintvl = ngx_parse_time(&s, 1);
0786                     if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
0787                         goto invalid_so_keepalive;
0788                     }
0789                 }
0790 
0791                 s.data = (p < end) ? (p + 1) : end;
0792 
0793                 if (s.data < end) {
0794                     s.len = end - s.data;
0795 
0796                     ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
0797                     if (ls->tcp_keepcnt == NGX_ERROR) {
0798                         goto invalid_so_keepalive;
0799                     }
0800                 }
0801 
0802                 if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
0803                     && ls->tcp_keepcnt == 0)
0804                 {
0805                     goto invalid_so_keepalive;
0806                 }
0807 
0808                 ls->so_keepalive = 1;
0809 
0810 #else
0811 
0812                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0813                                    "the \"so_keepalive\" parameter accepts "
0814                                    "only \"on\" or \"off\" on this platform");
0815                 return NGX_CONF_ERROR;
0816 
0817 #endif
0818             }
0819 
0820             ls->bind = 1;
0821 
0822             continue;
0823 
0824 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0825         invalid_so_keepalive:
0826 
0827             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0828                                "invalid so_keepalive value: \"%s\"",
0829                                &value[i].data[13]);
0830             return NGX_CONF_ERROR;
0831 #endif
0832         }
0833 
0834         if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
0835             ls->proxy_protocol = 1;
0836             continue;
0837         }
0838 
0839         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0840                            "the invalid \"%V\" parameter", &value[i]);
0841         return NGX_CONF_ERROR;
0842     }
0843 
0844     if (ls->type == SOCK_DGRAM) {
0845         if (backlog) {
0846             return "\"backlog\" parameter is incompatible with \"udp\"";
0847         }
0848 
0849 #if (NGX_STREAM_SSL)
0850         if (ls->ssl) {
0851             return "\"ssl\" parameter is incompatible with \"udp\"";
0852         }
0853 #endif
0854 
0855         if (ls->so_keepalive) {
0856             return "\"so_keepalive\" parameter is incompatible with \"udp\"";
0857         }
0858 
0859         if (ls->proxy_protocol) {
0860             return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
0861         }
0862     }
0863 
0864     als = cmcf->listen.elts;
0865 
0866     for (n = 0; n < u.naddrs; n++) {
0867         ls[n] = ls[0];
0868 
0869         ls[n].sockaddr = u.addrs[n].sockaddr;
0870         ls[n].socklen = u.addrs[n].socklen;
0871         ls[n].addr_text = u.addrs[n].name;
0872         ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr);
0873 
0874         for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) {
0875             if (ls[n].type != als[i].type) {
0876                 continue;
0877             }
0878 
0879             if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
0880                                  ls[n].sockaddr, ls[n].socklen, 1)
0881                 != NGX_OK)
0882             {
0883                 continue;
0884             }
0885 
0886             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0887                                "duplicate \"%V\" address and port pair",
0888                                &ls[n].addr_text);
0889             return NGX_CONF_ERROR;
0890         }
0891     }
0892 
0893     return NGX_CONF_OK;
0894 }
0895 
0896 
0897 static char *
0898 ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0899 {
0900     ngx_stream_core_srv_conf_t  *cscf = conf;
0901 
0902     ngx_str_t  *value;
0903 
0904     if (cscf->resolver) {
0905         return "is duplicate";
0906     }
0907 
0908     value = cf->args->elts;
0909 
0910     cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
0911     if (cscf->resolver == NULL) {
0912         return NGX_CONF_ERROR;
0913     }
0914 
0915     return NGX_CONF_OK;
0916 }