Latest update - 9224
This commit is contained in:
+602
-163
@@ -10,6 +10,11 @@
|
||||
#include <ngx_stream.h>
|
||||
|
||||
|
||||
static ngx_uint_t ngx_stream_preread_can_peek(ngx_connection_t *c);
|
||||
static ngx_int_t ngx_stream_preread_peek(ngx_stream_session_t *s,
|
||||
ngx_stream_phase_handler_t *ph);
|
||||
static ngx_int_t ngx_stream_preread(ngx_stream_session_t *s,
|
||||
ngx_stream_phase_handler_t *ph);
|
||||
static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
|
||||
static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
|
||||
static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
|
||||
@@ -22,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);
|
||||
|
||||
@@ -42,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,
|
||||
@@ -56,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,
|
||||
@@ -203,8 +231,6 @@ ngx_int_t
|
||||
ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
||||
ngx_stream_phase_handler_t *ph)
|
||||
{
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *c;
|
||||
ngx_stream_core_srv_conf_t *cscf;
|
||||
@@ -217,56 +243,33 @@ ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
||||
|
||||
if (c->read->timedout) {
|
||||
rc = NGX_STREAM_OK;
|
||||
goto done;
|
||||
}
|
||||
|
||||
} else if (c->read->timer_set) {
|
||||
rc = NGX_AGAIN;
|
||||
if (!c->read->timer_set) {
|
||||
rc = ph->handler(s);
|
||||
|
||||
if (rc != NGX_AGAIN) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->buffer == NULL) {
|
||||
c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
|
||||
if (c->buffer == NULL) {
|
||||
rc = NGX_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_stream_preread_can_peek(c)) {
|
||||
rc = ngx_stream_preread_peek(s, ph);
|
||||
|
||||
} else {
|
||||
rc = ph->handler(s);
|
||||
rc = ngx_stream_preread(s, ph);
|
||||
}
|
||||
|
||||
while (rc == NGX_AGAIN) {
|
||||
|
||||
if (c->buffer == NULL) {
|
||||
c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
|
||||
if (c->buffer == NULL) {
|
||||
rc = NGX_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size = c->buffer->end - c->buffer->last;
|
||||
|
||||
if (size == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
||||
rc = NGX_STREAM_BAD_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c->read->eof) {
|
||||
rc = NGX_STREAM_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c->read->ready) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = c->recv(c, c->buffer->last, size);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
rc = NGX_STREAM_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
break;
|
||||
}
|
||||
|
||||
c->buffer->last += n;
|
||||
|
||||
rc = ph->handler(s);
|
||||
}
|
||||
done:
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
@@ -311,6 +314,129 @@ ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
||||
}
|
||||
|
||||
|
||||
static ngx_uint_t
|
||||
ngx_stream_preread_can_peek(ngx_connection_t *c)
|
||||
{
|
||||
#if (NGX_STREAM_SSL)
|
||||
if (c->ssl) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ngx_event_flags & NGX_USE_CLEAR_EVENT) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_KQUEUE)
|
||||
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_EPOLLRDHUP)
|
||||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_preread_peek(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_err_t err;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = s->connection;
|
||||
|
||||
n = recv(c->fd, (char *) c->buffer->last,
|
||||
c->buffer->end - c->buffer->last, MSG_PEEK);
|
||||
|
||||
err = ngx_socket_errno;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream recv(): %z", n);
|
||||
|
||||
if (n == -1) {
|
||||
if (err == NGX_EAGAIN) {
|
||||
c->read->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ngx_connection_error(c, err, "recv() failed");
|
||||
return NGX_STREAM_OK;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
return NGX_STREAM_OK;
|
||||
}
|
||||
|
||||
c->buffer->last += n;
|
||||
|
||||
rc = ph->handler(s);
|
||||
|
||||
if (rc != NGX_AGAIN) {
|
||||
c->buffer->last = c->buffer->pos;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (c->buffer->last == c->buffer->end) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
||||
return NGX_STREAM_BAD_REQUEST;
|
||||
}
|
||||
|
||||
if (c->read->pending_eof) {
|
||||
return NGX_STREAM_OK;
|
||||
}
|
||||
|
||||
c->buffer->last = c->buffer->pos;
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_preread(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = s->connection;
|
||||
|
||||
while (c->read->ready) {
|
||||
|
||||
n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
return NGX_STREAM_OK;
|
||||
}
|
||||
|
||||
c->buffer->last += n;
|
||||
|
||||
rc = ph->handler(s);
|
||||
|
||||
if (rc != NGX_AGAIN) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (c->buffer->last == c->buffer->end) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
||||
return NGX_STREAM_BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
||||
ngx_stream_phase_handler_t *ph)
|
||||
@@ -338,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)
|
||||
{
|
||||
@@ -362,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;
|
||||
@@ -380,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);
|
||||
|
||||
@@ -411,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;
|
||||
@@ -429,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);
|
||||
|
||||
@@ -476,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;
|
||||
}
|
||||
|
||||
@@ -575,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;
|
||||
|
||||
@@ -600,51 +914,67 @@ 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);
|
||||
ngx_memzero(&lsopt, sizeof(ngx_stream_listen_opt_t));
|
||||
|
||||
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;
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
ls->fastopen = -1;
|
||||
lsopt.backlog = NGX_LISTEN_BACKLOG;
|
||||
lsopt.type = SOCK_STREAM;
|
||||
lsopt.rcvbuf = -1;
|
||||
lsopt.sndbuf = -1;
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
lsopt.setfib = -1;
|
||||
#endif
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
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_SETFIB)
|
||||
if (ngx_strncmp(value[i].data, "setfib=", 7) == 0) {
|
||||
lsopt.setfib = ngx_atoi(value[i].data + 7, value[i].len - 7);
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
|
||||
if (lsopt.setfib == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid setfib \"%V\"", &value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#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;
|
||||
@@ -655,10 +985,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;
|
||||
@@ -673,10 +1004,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;
|
||||
@@ -689,10 +1021,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;
|
||||
@@ -701,13 +1034,40 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(value[i].data, "accept_filter=", 14) == 0) {
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
lsopt.accept_filter = (char *) &value[i].data[14];
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"accept filters \"%V\" are not supported "
|
||||
"on this platform, ignored",
|
||||
&value[i]);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[i].data, "deferred") == 0) {
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||
lsopt.deferred_accept = 1;
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"the deferred accept is not supported "
|
||||
"on this platform, ignored");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -716,11 +1076,13 @@ 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,
|
||||
"bind ipv6only is not supported "
|
||||
"ipv6only is not supported "
|
||||
"on this platform");
|
||||
return NGX_CONF_ERROR;
|
||||
#endif
|
||||
@@ -728,8 +1090,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 "
|
||||
@@ -740,17 +1103,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,
|
||||
@@ -763,10 +1116,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 {
|
||||
|
||||
@@ -785,8 +1138,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;
|
||||
}
|
||||
}
|
||||
@@ -801,8 +1154,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;
|
||||
}
|
||||
}
|
||||
@@ -812,19 +1165,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
|
||||
|
||||
@@ -836,7 +1189,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;
|
||||
|
||||
@@ -851,39 +1205,51 @@ 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;
|
||||
}
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"the invalid \"%V\" parameter", &value[i]);
|
||||
"invalid parameter \"%V\"", &value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ls->type == SOCK_DGRAM) {
|
||||
if (lsopt.type == SOCK_DGRAM) {
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
if (lsopt.fastopen != -1) {
|
||||
return "\"fastopen\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (backlog) {
|
||||
return "\"backlog\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
if (lsopt.accept_filter) {
|
||||
return "\"accept_filter\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||
if (lsopt.deferred_accept) {
|
||||
return "\"deferred\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
#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) {
|
||||
return "\"fastopen\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (n = 0; n < u.naddrs; n++) {
|
||||
@@ -897,40 +1263,12 @@ 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);
|
||||
|
||||
*nls = *ls;
|
||||
|
||||
} else {
|
||||
nls = ls;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
als = cmcf->listen.elts;
|
||||
|
||||
for (i = 0; i < cmcf->listen.nelts - 1; i++) {
|
||||
if (nls->type != als[i].type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
|
||||
nls->sockaddr, nls->socklen, 1)
|
||||
!= NGX_OK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate \"%V\" address and port pair",
|
||||
&nls->addr_text);
|
||||
if (ngx_stream_add_listen(cf, cscf, &lsopt) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
@@ -942,6 +1280,107 @@ 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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
|
||||
sn->name = cf->cycle->hostname;
|
||||
|
||||
} else {
|
||||
sn->name = value[i];
|
||||
}
|
||||
|
||||
if (value[i].data[0] != '~') {
|
||||
ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if (NGX_PCRE)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_regex_compile_t rc;
|
||||
u_char errstr[NGX_MAX_CONF_ERRSTR];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
sn->regex = ngx_stream_regex_compile(cf, &rc);
|
||||
if (sn->regex == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user