aboutsummaryrefslogtreecommitdiff
path: root/src/stream/ngx_stream_core_module.c
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2023-12-14 21:58:39 +0400
committerRoman Arutyunyan <arut@nginx.com>2023-12-14 21:58:39 +0400
commitd21675228a0ba8d4331e05c60660228a5d3326de (patch)
tree5218a1fcffa6998931d6d55e24255208635ddc7f /src/stream/ngx_stream_core_module.c
parent72e5d6ac19a93c9fb64678dd33ea185757a6021a (diff)
downloadnginx-d21675228a0ba8d4331e05c60660228a5d3326de.tar.gz
nginx-d21675228a0ba8d4331e05c60660228a5d3326de.zip
Stream: virtual servers.
Server name is taken either from ngx_stream_ssl_module or ngx_stream_ssl_preread_module. The change adds "default_server" parameter to the "listen" directive, as well as the following directives: "server_names_hash_max_size", "server_names_hash_bucket_size", "server_name" and "ssl_reject_handshake".
Diffstat (limited to 'src/stream/ngx_stream_core_module.c')
-rw-r--r--src/stream/ngx_stream_core_module.c480
1 files changed, 379 insertions, 101 deletions
diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c
index 2ef39af24..31a34aee5 100644
--- a/src/stream/ngx_stream_core_module.c
+++ b/src/stream/ngx_stream_core_module.c
@@ -27,6 +27,8 @@ static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -47,6 +49,20 @@ static ngx_command_t ngx_stream_core_commands[] = {
offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
NULL },
+ { ngx_string("server_names_hash_max_size"),
+ NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_STREAM_MAIN_CONF_OFFSET,
+ offsetof(ngx_stream_core_main_conf_t, server_names_hash_max_size),
+ NULL },
+
+ { ngx_string("server_names_hash_bucket_size"),
+ NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_STREAM_MAIN_CONF_OFFSET,
+ offsetof(ngx_stream_core_main_conf_t, server_names_hash_bucket_size),
+ NULL },
+
{ ngx_string("server"),
NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_stream_core_server,
@@ -61,6 +77,13 @@ static ngx_command_t ngx_stream_core_commands[] = {
0,
NULL },
+ { ngx_string("server_name"),
+ NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
+ ngx_stream_core_server_name,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("error_log"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
ngx_stream_core_error_log,
@@ -441,6 +464,149 @@ ngx_stream_core_content_phase(ngx_stream_session_t *s,
}
+ngx_int_t
+ngx_stream_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
+{
+ u_char *h, ch;
+ size_t i, dot_pos, host_len;
+
+ enum {
+ sw_usual = 0,
+ sw_literal,
+ sw_rest
+ } state;
+
+ dot_pos = host->len;
+ host_len = host->len;
+
+ h = host->data;
+
+ state = sw_usual;
+
+ for (i = 0; i < host->len; i++) {
+ ch = h[i];
+
+ switch (ch) {
+
+ case '.':
+ if (dot_pos == i - 1) {
+ return NGX_DECLINED;
+ }
+ dot_pos = i;
+ break;
+
+ case ':':
+ if (state == sw_usual) {
+ host_len = i;
+ state = sw_rest;
+ }
+ break;
+
+ case '[':
+ if (i == 0) {
+ state = sw_literal;
+ }
+ break;
+
+ case ']':
+ if (state == sw_literal) {
+ host_len = i + 1;
+ state = sw_rest;
+ }
+ break;
+
+ default:
+
+ if (ngx_path_separator(ch)) {
+ return NGX_DECLINED;
+ }
+
+ if (ch <= 0x20 || ch == 0x7f) {
+ return NGX_DECLINED;
+ }
+
+ if (ch >= 'A' && ch <= 'Z') {
+ alloc = 1;
+ }
+
+ break;
+ }
+ }
+
+ if (dot_pos == host_len - 1) {
+ host_len--;
+ }
+
+ if (host_len == 0) {
+ return NGX_DECLINED;
+ }
+
+ if (alloc) {
+ host->data = ngx_pnalloc(pool, host_len);
+ if (host->data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_strlow(host->data, h, host_len);
+ }
+
+ host->len = host_len;
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_stream_find_virtual_server(ngx_stream_session_t *s,
+ ngx_str_t *host, ngx_stream_core_srv_conf_t **cscfp)
+{
+ ngx_stream_core_srv_conf_t *cscf;
+
+ if (s->virtual_names == NULL) {
+ return NGX_DECLINED;
+ }
+
+ cscf = ngx_hash_find_combined(&s->virtual_names->names,
+ ngx_hash_key(host->data, host->len),
+ host->data, host->len);
+
+ if (cscf) {
+ *cscfp = cscf;
+ return NGX_OK;
+ }
+
+#if (NGX_PCRE)
+
+ if (host->len && s->virtual_names->nregex) {
+ ngx_int_t n;
+ ngx_uint_t i;
+ ngx_stream_server_name_t *sn;
+
+ sn = s->virtual_names->regex;
+
+ for (i = 0; i < s->virtual_names->nregex; i++) {
+
+ n = ngx_stream_regex_exec(s, sn[i].regex, host);
+
+ if (n == NGX_DECLINED) {
+ continue;
+ }
+
+ if (n == NGX_OK) {
+ *cscfp = sn[i].server;
+ return NGX_OK;
+ }
+
+ return NGX_ERROR;
+ }
+ }
+
+#endif /* NGX_PCRE */
+
+ return NGX_DECLINED;
+}
+
+
static ngx_int_t
ngx_stream_core_preconfiguration(ngx_conf_t *cf)
{
@@ -465,11 +631,8 @@ ngx_stream_core_create_main_conf(ngx_conf_t *cf)
return NULL;
}
- if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
- != NGX_OK)
- {
- return NULL;
- }
+ cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
+ cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
@@ -483,6 +646,14 @@ ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_stream_core_main_conf_t *cmcf = conf;
+ ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
+ ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
+ ngx_cacheline_size);
+
+ cmcf->server_names_hash_bucket_size =
+ ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
+
+
ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
@@ -514,6 +685,13 @@ ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
* cscf->error_log = NULL;
*/
+ if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
+ sizeof(ngx_stream_server_name_t))
+ != NGX_OK)
+ {
+ return NULL;
+ }
+
cscf->file_name = cf->conf_file->file.name.data;
cscf->line = cf->conf_file->line;
cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
@@ -532,6 +710,9 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_stream_core_srv_conf_t *prev = parent;
ngx_stream_core_srv_conf_t *conf = child;
+ ngx_str_t name;
+ ngx_stream_server_name_t *sn;
+
ngx_conf_merge_msec_value(conf->resolver_timeout,
prev->resolver_timeout, 30000);
@@ -579,6 +760,37 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->preread_timeout,
prev->preread_timeout, 30000);
+ if (conf->server_names.nelts == 0) {
+ /* the array has 4 empty preallocated elements, so push cannot fail */
+ sn = ngx_array_push(&conf->server_names);
+#if (NGX_PCRE)
+ sn->regex = NULL;
+#endif
+ sn->server = conf;
+ ngx_str_set(&sn->name, "");
+ }
+
+ sn = conf->server_names.elts;
+ name = sn[0].name;
+
+#if (NGX_PCRE)
+ if (sn->regex) {
+ name.len++;
+ name.data--;
+ } else
+#endif
+
+ if (name.data[0] == '.') {
+ name.len--;
+ name.data++;
+ }
+
+ conf->server_name.len = name.len;
+ conf->server_name.data = ngx_pstrdup(cf->pool, &name);
+ if (conf->server_name.data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
return NGX_CONF_OK;
}
@@ -678,11 +890,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_stream_core_srv_conf_t *cscf = conf;
- ngx_str_t *value, size;
- ngx_url_t u;
- ngx_uint_t i, n, backlog;
- ngx_stream_listen_t *ls, *als, *nls;
- ngx_stream_core_main_conf_t *cmcf;
+ ngx_str_t *value, size;
+ ngx_url_t u;
+ ngx_uint_t n, i, backlog;
+ ngx_stream_listen_opt_t lsopt;
cscf->listen = 1;
@@ -703,51 +914,48 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
-
- ls = ngx_array_push(&cmcf->listen);
- if (ls == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(ls, sizeof(ngx_stream_listen_t));
-
- ls->backlog = NGX_LISTEN_BACKLOG;
- ls->rcvbuf = -1;
- ls->sndbuf = -1;
- ls->type = SOCK_STREAM;
- ls->ctx = cf->ctx;
+ ngx_memzero(&lsopt, sizeof(ngx_stream_listen_opt_t));
+ lsopt.backlog = NGX_LISTEN_BACKLOG;
+ lsopt.type = SOCK_STREAM;
+ lsopt.rcvbuf = -1;
+ lsopt.sndbuf = -1;
#if (NGX_HAVE_TCP_FASTOPEN)
- ls->fastopen = -1;
+ lsopt.fastopen = -1;
#endif
-
#if (NGX_HAVE_INET6)
- ls->ipv6only = 1;
+ lsopt.ipv6only = 1;
#endif
backlog = 0;
for (i = 2; i < cf->args->nelts; i++) {
+ if (ngx_strcmp(value[i].data, "default_server") == 0) {
+ lsopt.default_server = 1;
+ continue;
+ }
+
#if !(NGX_WIN32)
if (ngx_strcmp(value[i].data, "udp") == 0) {
- ls->type = SOCK_DGRAM;
+ lsopt.type = SOCK_DGRAM;
continue;
}
#endif
if (ngx_strcmp(value[i].data, "bind") == 0) {
- ls->bind = 1;
+ lsopt.set = 1;
+ lsopt.bind = 1;
continue;
}
#if (NGX_HAVE_TCP_FASTOPEN)
if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) {
- ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
- ls->bind = 1;
+ lsopt.fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
+ lsopt.set = 1;
+ lsopt.bind = 1;
- if (ls->fastopen == NGX_ERROR) {
+ if (lsopt.fastopen == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid fastopen \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -758,10 +966,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
- ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
- ls->bind = 1;
+ lsopt.backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
+ lsopt.set = 1;
+ lsopt.bind = 1;
- if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
+ if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid backlog \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -776,10 +985,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size.len = value[i].len - 7;
size.data = value[i].data + 7;
- ls->rcvbuf = ngx_parse_size(&size);
- ls->bind = 1;
+ lsopt.rcvbuf = ngx_parse_size(&size);
+ lsopt.set = 1;
+ lsopt.bind = 1;
- if (ls->rcvbuf == NGX_ERROR) {
+ if (lsopt.rcvbuf == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid rcvbuf \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -792,10 +1002,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size.len = value[i].len - 7;
size.data = value[i].data + 7;
- ls->sndbuf = ngx_parse_size(&size);
- ls->bind = 1;
+ lsopt.sndbuf = ngx_parse_size(&size);
+ lsopt.set = 1;
+ lsopt.bind = 1;
- if (ls->sndbuf == NGX_ERROR) {
+ if (lsopt.sndbuf == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid sndbuf \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -807,10 +1018,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
if (ngx_strcmp(&value[i].data[10], "n") == 0) {
- ls->ipv6only = 1;
+ lsopt.ipv6only = 1;
} else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
- ls->ipv6only = 0;
+ lsopt.ipv6only = 0;
} else {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -819,7 +1030,9 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- ls->bind = 1;
+ lsopt.set = 1;
+ lsopt.bind = 1;
+
continue;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -831,8 +1044,9 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strcmp(value[i].data, "reuseport") == 0) {
#if (NGX_HAVE_REUSEPORT)
- ls->reuseport = 1;
- ls->bind = 1;
+ lsopt.reuseport = 1;
+ lsopt.set = 1;
+ lsopt.bind = 1;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"reuseport is not supported "
@@ -843,17 +1057,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strcmp(value[i].data, "ssl") == 0) {
#if (NGX_STREAM_SSL)
- ngx_stream_ssl_conf_t *sslcf;
-
- sslcf = ngx_stream_conf_get_module_srv_conf(cf,
- ngx_stream_ssl_module);
-
- sslcf->listen = 1;
- sslcf->file = cf->conf_file->file.name.data;
- sslcf->line = cf->conf_file->line;
-
- ls->ssl = 1;
-
+ lsopt.ssl = 1;
continue;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -866,10 +1070,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
if (ngx_strcmp(&value[i].data[13], "on") == 0) {
- ls->so_keepalive = 1;
+ lsopt.so_keepalive = 1;
} else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
- ls->so_keepalive = 2;
+ lsopt.so_keepalive = 2;
} else {
@@ -888,8 +1092,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (p > s.data) {
s.len = p - s.data;
- ls->tcp_keepidle = ngx_parse_time(&s, 1);
- if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
+ lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
+ if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
@@ -904,8 +1108,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (p > s.data) {
s.len = p - s.data;
- ls->tcp_keepintvl = ngx_parse_time(&s, 1);
- if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
+ lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
+ if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
@@ -915,19 +1119,19 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (s.data < end) {
s.len = end - s.data;
- ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
- if (ls->tcp_keepcnt == NGX_ERROR) {
+ lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
+ if (lsopt.tcp_keepcnt == NGX_ERROR) {
goto invalid_so_keepalive;
}
}
- if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
- && ls->tcp_keepcnt == 0)
+ if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
+ && lsopt.tcp_keepcnt == 0)
{
goto invalid_so_keepalive;
}
- ls->so_keepalive = 1;
+ lsopt.so_keepalive = 1;
#else
@@ -939,7 +1143,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
- ls->bind = 1;
+ lsopt.set = 1;
+ lsopt.bind = 1;
continue;
@@ -954,7 +1159,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
- ls->proxy_protocol = 1;
+ lsopt.proxy_protocol = 1;
continue;
}
@@ -963,27 +1168,27 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ls->type == SOCK_DGRAM) {
+ if (lsopt.type == SOCK_DGRAM) {
if (backlog) {
return "\"backlog\" parameter is incompatible with \"udp\"";
}
#if (NGX_STREAM_SSL)
- if (ls->ssl) {
+ if (lsopt.ssl) {
return "\"ssl\" parameter is incompatible with \"udp\"";
}
#endif
- if (ls->so_keepalive) {
+ if (lsopt.so_keepalive) {
return "\"so_keepalive\" parameter is incompatible with \"udp\"";
}
- if (ls->proxy_protocol) {
+ if (lsopt.proxy_protocol) {
return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
}
#if (NGX_HAVE_TCP_FASTOPEN)
- if (ls->fastopen != -1) {
+ if (lsopt.fastopen != -1) {
return "\"fastopen\" parameter is incompatible with \"udp\"";
}
#endif
@@ -1000,45 +1205,118 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
- if (n != 0) {
- nls = ngx_array_push(&cmcf->listen);
- if (nls == NULL) {
- return NGX_CONF_ERROR;
- }
+ lsopt.sockaddr = u.addrs[n].sockaddr;
+ lsopt.socklen = u.addrs[n].socklen;
+ lsopt.addr_text = u.addrs[n].name;
+ lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr);
+
+ if (ngx_stream_add_listen(cf, cscf, &lsopt) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ next:
+ continue;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_stream_core_srv_conf_t *cscf = conf;
+
+ u_char ch;
+ ngx_str_t *value;
+ ngx_uint_t i;
+ ngx_stream_server_name_t *sn;
+
+ value = cf->args->elts;
+
+ for (i = 1; i < cf->args->nelts; i++) {
+
+ ch = value[i].data[0];
+
+ if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
+ || (ch == '.' && value[i].len < 2))
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "server name \"%V\" is invalid", &value[i]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_strchr(value[i].data, '/')) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "server name \"%V\" has suspicious symbols",
+ &value[i]);
+ }
+
+ sn = ngx_array_push(&cscf->server_names);
+ if (sn == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+#if (NGX_PCRE)
+ sn->regex = NULL;
+#endif
+ sn->server = cscf;
- *nls = *ls;
+ if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
+ sn->name = cf->cycle->hostname;
} else {
- nls = ls;
+ sn->name = value[i];
}
- nls->sockaddr = u.addrs[n].sockaddr;
- nls->socklen = u.addrs[n].socklen;
- nls->addr_text = u.addrs[n].name;
- nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
+ if (value[i].data[0] != '~') {
+ ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
+ continue;
+ }
- als = cmcf->listen.elts;
+#if (NGX_PCRE)
+ {
+ u_char *p;
+ ngx_regex_compile_t rc;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
- for (i = 0; i < cmcf->listen.nelts - 1; i++) {
- if (nls->type != als[i].type) {
- continue;
- }
+ if (value[i].len == 1) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "empty regex in server name \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+ }
- if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
- nls->sockaddr, nls->socklen, 1)
- != NGX_OK)
- {
- continue;
+ value[i].len--;
+ value[i].data++;
+
+ ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+ rc.pattern = value[i];
+ rc.err.len = NGX_MAX_CONF_ERRSTR;
+ rc.err.data = errstr;
+
+ for (p = value[i].data; p < value[i].data + value[i].len; p++) {
+ if (*p >= 'A' && *p <= 'Z') {
+ rc.options = NGX_REGEX_CASELESS;
+ break;
}
+ }
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "duplicate \"%V\" address and port pair",
- &nls->addr_text);
+ sn->regex = ngx_stream_regex_compile(cf, &rc);
+ if (sn->regex == NULL) {
return NGX_CONF_ERROR;
}
- next:
- continue;
+ sn->name = value[i];
+ cscf->captures = (rc.captures > 0);
+ }
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "using regex \"%V\" "
+ "requires PCRE library", &value[i]);
+
+ return NGX_CONF_ERROR;
+#endif
}
return NGX_CONF_OK;