summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nxt_application.c75
-rw-r--r--src/nxt_clone.c4
-rw-r--r--src/nxt_conf.c24
-rw-r--r--src/nxt_conf.h9
-rw-r--r--src/nxt_conf_validation.c150
-rw-r--r--src/nxt_conn.h23
-rw-r--r--src/nxt_conn_accept.c9
-rw-r--r--src/nxt_conn_close.c14
-rw-r--r--src/nxt_controller.c171
-rw-r--r--src/nxt_event_engine.h5
-rw-r--r--src/nxt_h1proto.c15
-rw-r--r--src/nxt_http.h34
-rw-r--r--src/nxt_http_parse.c26
-rw-r--r--src/nxt_http_parse.h2
-rw-r--r--src/nxt_http_request.c317
-rw-r--r--src/nxt_http_return.c7
-rw-r--r--src/nxt_http_route.c162
-rw-r--r--src/nxt_http_route_addr.c12
-rw-r--r--src/nxt_http_route_addr.h1
-rw-r--r--src/nxt_http_static.c26
-rw-r--r--src/nxt_http_variables.c446
-rw-r--r--src/nxt_isolation.c10
-rw-r--r--src/nxt_isolation.h6
-rw-r--r--src/nxt_job_resolve.c132
-rw-r--r--src/nxt_job_resolve.h29
-rw-r--r--src/nxt_main.h1
-rw-r--r--src/nxt_main_process.c4
-rw-r--r--src/nxt_mp.c4
-rw-r--r--src/nxt_nncq.h6
-rw-r--r--src/nxt_nvbcq.h6
-rw-r--r--src/nxt_port.h9
-rw-r--r--src/nxt_port_memory.c131
-rw-r--r--src/nxt_port_memory.h21
-rw-r--r--src/nxt_port_memory_int.h9
-rw-r--r--src/nxt_port_rpc.c1
-rw-r--r--src/nxt_port_socket.c4
-rw-r--r--src/nxt_process.c82
-rw-r--r--src/nxt_process.h4
-rw-r--r--src/nxt_router.c717
-rw-r--r--src/nxt_router.h26
-rw-r--r--src/nxt_router_access_log.c442
-rw-r--r--src/nxt_runtime.c13
-rw-r--r--src/nxt_sockaddr.c423
-rw-r--r--src/nxt_sockaddr.h12
-rw-r--r--src/nxt_status.c105
-rw-r--r--src/nxt_status.h33
-rw-r--r--src/nxt_string.c2
-rw-r--r--src/nxt_string.h2
-rw-r--r--src/nxt_time_parse.c2
-rw-r--r--src/nxt_unit.c38
-rw-r--r--src/nxt_unix.h2
-rw-r--r--src/nxt_var.c418
-rw-r--r--src/nxt_var.h39
-rw-r--r--src/nxt_websocket_accept.c4
-rw-r--r--src/python/nxt_python_asgi.c44
-rw-r--r--src/ruby/nxt_ruby.c52
-rw-r--r--src/ruby/nxt_ruby.h1
57 files changed, 2476 insertions, 1890 deletions
diff --git a/src/nxt_application.c b/src/nxt_application.c
index 594574b1..556f1ffb 100644
--- a/src/nxt_application.c
+++ b/src/nxt_application.c
@@ -23,6 +23,13 @@
#endif
+#ifdef WCOREDUMP
+#define NXT_WCOREDUMP(s) WCOREDUMP(s)
+#else
+#define NXT_WCOREDUMP(s) 0
+#endif
+
+
typedef struct {
nxt_app_type_t type;
nxt_str_t version;
@@ -636,6 +643,8 @@ nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
process->data.app = nxt_app_conf;
process->stream = msg->port_msg.stream;
+ init->siblings = &nxt_proto_children;
+
ret = nxt_process_start(task, process);
if (nxt_slow_path(ret == NXT_ERROR)) {
nxt_process_use(task, process, -1);
@@ -711,15 +720,19 @@ nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid,
pid);
- nxt_runtime_process_remove(task->thread->runtime, process);
-
process->pid = pid;
- nxt_runtime_process_add(task, process);
-
} else {
nxt_debug(task, "app process %PI is created", isolated_pid);
}
+
+ if (!process->registered) {
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ nxt_runtime_process_add(task, process);
+
+ nxt_port_use(task, nxt_process_port_first(process), -1);
+ }
}
@@ -753,7 +766,11 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data)
int status;
nxt_err_t err;
nxt_pid_t pid;
+ nxt_port_t *port;
nxt_process_t *process;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
nxt_debug(task, "proto sigchld handler signo:%d (%s)",
(int) (uintptr_t) obj, data);
@@ -783,32 +800,58 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data)
return;
}
+ process = nxt_proto_process_remove(task, pid);
+
if (WTERMSIG(status)) {
-#ifdef WCOREDUMP
- nxt_alert(task, "app process (isolated %PI) exited on signal %d%s",
- pid, WTERMSIG(status),
- WCOREDUMP(status) ? " (core dumped)" : "");
-#else
- nxt_alert(task, "app process (isolated %PI) exited on signal %d",
- pid, WTERMSIG(status));
-#endif
+ if (rt->is_pid_isolated) {
+ nxt_alert(task, "app process %PI (isolated %PI) "
+ "exited on signal %d%s",
+ process != NULL ? process->pid : 0,
+ pid, WTERMSIG(status),
+ NXT_WCOREDUMP(status) ? " (core dumped)" : "");
+
+ } else {
+ nxt_alert(task, "app process %PI exited on signal %d%s",
+ pid, WTERMSIG(status),
+ NXT_WCOREDUMP(status) ? " (core dumped)" : "");
+ }
} else {
- nxt_trace(task, "app process (isolated %PI) exited with code %d",
- pid, WEXITSTATUS(status));
+ if (rt->is_pid_isolated) {
+ nxt_trace(task, "app process %PI (isolated %PI) "
+ "exited with code %d",
+ process != NULL ? process->pid : 0,
+ pid, WEXITSTATUS(status));
+
+ } else {
+ nxt_trace(task, "app process %PI exited with code %d",
+ pid, WEXITSTATUS(status));
+ }
}
- process = nxt_proto_process_remove(task, pid);
if (process == NULL) {
continue;
}
+ if (process->registered) {
+ port = NULL;
+
+ } else {
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ port = nxt_process_port_first(process);
+ }
+
if (process->state != NXT_PROCESS_STATE_CREATING) {
nxt_port_remove_notify_others(task, process);
}
nxt_process_close_ports(task, process);
+ if (port != NULL) {
+ nxt_port_use(task, port, -1);
+ }
+
if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) {
nxt_process_quit(task, 0);
return;
@@ -1122,7 +1165,7 @@ nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process)
break;
default:
- nxt_debug(task, "process (isolated %PI) failed to add",
+ nxt_alert(task, "process (isolated %PI) failed to add",
process->isolated_pid);
break;
}
diff --git a/src/nxt_clone.c b/src/nxt_clone.c
index aa952a54..a9b39ac1 100644
--- a/src/nxt_clone.c
+++ b/src/nxt_clone.c
@@ -14,9 +14,9 @@ pid_t
nxt_clone(nxt_int_t flags)
{
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
- return syscall(__NR_clone, NULL, flags);
+ return syscall(SYS_clone, NULL, flags);
#else
- return syscall(__NR_clone, flags, NULL);
+ return syscall(SYS_clone, flags, NULL);
#endif
}
diff --git a/src/nxt_conf.c b/src/nxt_conf.c
index 79e776a0..c6312f3d 100644
--- a/src/nxt_conf.c
+++ b/src/nxt_conf.c
@@ -102,7 +102,7 @@ typedef struct {
static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse,
nxt_str_t *token);
-static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end);
+static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end);
static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value,
u_char *start, u_char *end, nxt_conf_json_error_t *error);
static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value,
@@ -266,7 +266,7 @@ nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count)
void
nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
- nxt_conf_value_t *value, uint32_t index)
+ const nxt_conf_value_t *value, uint32_t index)
{
nxt_conf_object_member_t *member;
@@ -278,6 +278,20 @@ nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
}
+nxt_int_t
+nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, nxt_str_t *name,
+ nxt_conf_value_t *value, uint32_t index)
+{
+ nxt_conf_object_member_t *member;
+
+ member = &object->u.object->members[index];
+
+ member->value = *value;
+
+ return nxt_conf_set_string_dup(&member->name, mp, name);
+}
+
+
void
nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
nxt_str_t *value, uint32_t index)
@@ -367,7 +381,7 @@ nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count)
void
nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
- nxt_conf_value_t *value)
+ const nxt_conf_value_t *value)
{
array->u.array->elements[index] = *value;
}
@@ -1271,7 +1285,7 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end,
static u_char *
-nxt_conf_json_skip_space(u_char *start, u_char *end)
+nxt_conf_json_skip_space(u_char *start, const u_char *end)
{
u_char *p, ch;
@@ -2605,7 +2619,7 @@ nxt_conf_json_escape(u_char *dst, u_char *src, size_t size)
void
-nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
+nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line,
nxt_uint_t *column)
{
u_char *p;
diff --git a/src/nxt_conf.h b/src/nxt_conf.h
index cfbc5991..c8a276c0 100644
--- a/src/nxt_conf.h
+++ b/src/nxt_conf.h
@@ -72,6 +72,7 @@ typedef struct {
nxt_mp_t *pool;
nxt_str_t error;
void *ctx;
+ nxt_array_t *var_fields; /* of nxt_var_field_t */
nxt_mp_t *conf_pool;
nxt_uint_t ver;
} nxt_conf_validation_t;
@@ -109,7 +110,7 @@ size_t nxt_conf_json_length(nxt_conf_value_t *value,
nxt_conf_json_pretty_t *pretty);
u_char *nxt_conf_json_print(u_char *p, nxt_conf_value_t *value,
nxt_conf_json_pretty_t *pretty);
-void nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
+void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line,
nxt_uint_t *column);
nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt);
@@ -125,7 +126,9 @@ NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value);
NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value);
nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count);
void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
- nxt_conf_value_t *value, uint32_t index);
+ const nxt_conf_value_t *value, uint32_t index);
+nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp,
+ nxt_str_t *name, nxt_conf_value_t *value, uint32_t index);
void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
nxt_str_t *value, uint32_t index);
nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp,
@@ -137,7 +140,7 @@ void nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name,
nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count);
void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
- nxt_conf_value_t *value);
+ const nxt_conf_value_t *value);
nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp,
nxt_uint_t index, nxt_str_t *value);
NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value);
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index ee7ebe44..fe6c22e5 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -166,6 +166,8 @@ static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
+static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
nxt_str_t *name, nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
@@ -200,6 +202,8 @@ static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
nxt_str_t *name, nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
+static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
@@ -220,6 +224,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[];
+static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[];
#if (NXT_TLS)
static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[];
@@ -238,6 +243,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[];
#if (NXT_HAVE_ISOLATION_ROOTFS)
static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[];
#endif
+static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
@@ -267,7 +273,8 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
.u.object = nxt_conf_vldt_upstream,
}, {
.name = nxt_string("access_log"),
- .type = NXT_CONF_VLDT_STRING,
+ .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT,
+ .validator = nxt_conf_vldt_access_log,
},
NXT_CONF_VLDT_END
@@ -366,6 +373,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
.type = NXT_CONF_VLDT_STRING,
.validator = nxt_conf_vldt_app_name,
}, {
+ .name = nxt_string("forwarded"),
+ .type = NXT_CONF_VLDT_OBJECT,
+ .validator = nxt_conf_vldt_forwarded,
+ }, {
.name = nxt_string("client_ip"),
.type = NXT_CONF_VLDT_OBJECT,
.validator = nxt_conf_vldt_object,
@@ -385,6 +396,27 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
};
+static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = {
+ {
+ .name = nxt_string("client_ip"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("protocol"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("source"),
+ .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
+ .validator = nxt_conf_vldt_match_addrs,
+ .flags = NXT_CONF_VLDT_REQUIRED
+ }, {
+ .name = nxt_string("recursive"),
+ .type = NXT_CONF_VLDT_BOOLEAN,
+ },
+
+ NXT_CONF_VLDT_END
+};
+
+
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = {
{
.name = nxt_string("source"),
@@ -1177,11 +1209,29 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
};
+static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = {
+ {
+ .name = nxt_string("path"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("format"),
+ .type = NXT_CONF_VLDT_STRING,
+ },
+
+ NXT_CONF_VLDT_END
+};
+
+
nxt_int_t
nxt_conf_validate(nxt_conf_validation_t *vldt)
{
nxt_int_t ret;
+ vldt->var_fields = nxt_array_create(vldt->pool, 4, sizeof(nxt_var_field_t));
+ if (nxt_slow_path(vldt->var_fields == NULL)) {
+ return NXT_ERROR;
+ }
+
ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
if (ret != NXT_OK) {
return ret;
@@ -1314,7 +1364,7 @@ nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
{
u_char error[NXT_MAX_ERROR_STR];
- if (nxt_var_test(value, error) != NXT_OK) {
+ if (nxt_var_test(value, vldt->var_fields, error) != NXT_OK) {
return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.",
error, name);
}
@@ -1430,9 +1480,14 @@ nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
nxt_conf_value_t *value)
{
nxt_int_t ret;
+ nxt_str_t str;
nxt_sockaddr_t *sa;
- sa = nxt_sockaddr_parse(vldt->pool, name);
+ if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) {
+ return NXT_ERROR;
+ }
+
+ sa = nxt_sockaddr_parse(vldt->pool, &str);
if (nxt_slow_path(sa == NULL)) {
return nxt_conf_vldt_error(vldt,
"The listener address \"%V\" is invalid.",
@@ -2124,6 +2179,11 @@ nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
"IPv6 with your configuration.");
+ case NXT_ADDR_PATTERN_NO_UNIX_ERROR:
+ return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
+ "UNIX domain sockets with your "
+ "configuration.");
+
default:
return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
"format.");
@@ -2318,6 +2378,28 @@ error:
static nxt_int_t
+nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
+ void *data)
+{
+ nxt_conf_value_t *client_ip, *protocol;
+
+ static nxt_str_t client_ip_str = nxt_string("client_ip");
+ static nxt_str_t protocol_str = nxt_string("protocol");
+
+ client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL);
+ protocol = nxt_conf_get_object_member(value, &protocol_str, NULL);
+
+ if (client_ip == NULL && protocol == NULL) {
+ return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have "
+ "either \"client_ip\" or \"protocol\" "
+ "option set.");
+ }
+
+ return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members);
+}
+
+
+static nxt_int_t
nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
nxt_conf_value_t *value)
{
@@ -3030,3 +3112,65 @@ nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
return NXT_OK;
}
+
+
+typedef struct {
+ nxt_str_t path;
+ nxt_str_t format;
+} nxt_conf_vldt_access_log_conf_t;
+
+
+static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = {
+ {
+ nxt_string("path"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_conf_vldt_access_log_conf_t, path),
+ },
+
+ {
+ nxt_string("format"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_conf_vldt_access_log_conf_t, format),
+ },
+};
+
+
+static nxt_int_t
+nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
+ void *data)
+{
+ nxt_int_t ret;
+ nxt_conf_vldt_access_log_conf_t conf;
+
+ static nxt_str_t format_str = nxt_string("format");
+
+ if (nxt_conf_type(value) == NXT_CONF_STRING) {
+ return NXT_OK;
+ }
+
+ ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t));
+
+ ret = nxt_conf_map_object(vldt->pool, value,
+ nxt_conf_vldt_access_log_map,
+ nxt_nitems(nxt_conf_vldt_access_log_map),
+ &conf);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ if (conf.path.length == 0) {
+ return nxt_conf_vldt_error(vldt,
+ "The \"path\" string must not be empty.");
+ }
+
+ if (nxt_is_var(&conf.format)) {
+ return nxt_conf_vldt_var(vldt, &format_str, &conf.format);
+ }
+
+ return NXT_OK;
+}
diff --git a/src/nxt_conn.h b/src/nxt_conn.h
index a443601f..8a703e9a 100644
--- a/src/nxt_conn.h
+++ b/src/nxt_conn.h
@@ -160,6 +160,7 @@ struct nxt_conn_s {
uint8_t block_read; /* 1 bit */
uint8_t block_write; /* 1 bit */
uint8_t delayed; /* 1 bit */
+ uint8_t idle; /* 1 bit */
#define NXT_CONN_SENDFILE_OFF 0
#define NXT_CONN_SENDFILE_ON 1
@@ -294,6 +295,28 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task,
} while (0)
+#define nxt_conn_idle(engine, c) \
+ do { \
+ nxt_event_engine_t *e = engine; \
+ \
+ nxt_queue_insert_head(&e->idle_connections, &c->link); \
+ \
+ c->idle = 1; \
+ e->idle_conns_cnt++; \
+ } while (0)
+
+
+#define nxt_conn_active(engine, c) \
+ do { \
+ nxt_event_engine_t *e = engine; \
+ \
+ nxt_queue_remove(&c->link); \
+ \
+ c->idle = 0; \
+ e->idle_conns_cnt--; \
+ } while (0)
+
+
extern nxt_conn_io_t nxt_unix_conn_io;
diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c
index 77c44c58..720c7b64 100644
--- a/src/nxt_conn_accept.c
+++ b/src/nxt_conn_accept.c
@@ -187,7 +187,8 @@ nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data)
void
nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c)
{
- nxt_conn_t *next;
+ nxt_conn_t *next;
+ nxt_event_engine_t *engine;
nxt_sockaddr_text(c->remote);
@@ -195,7 +196,11 @@ nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c)
(size_t) c->remote->address_length,
nxt_sockaddr_address(c->remote));
- nxt_queue_insert_head(&task->thread->engine->idle_connections, &c->link);
+ engine = task->thread->engine;
+
+ engine->accepted_conns_cnt++;
+
+ nxt_conn_idle(engine, c);
c->listen = lev;
lev->count++;
diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c
index 7c130309..92bd8d1b 100644
--- a/src/nxt_conn_close.c
+++ b/src/nxt_conn_close.c
@@ -119,6 +119,8 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data)
nxt_socket_close(task, c->socket.fd);
c->socket.fd = -1;
+ engine->closed_conns_cnt++;
+
if (timers_pending == 0) {
nxt_work_queue_add(&engine->fast_work_queue,
c->write_state->ready_handler,
@@ -137,8 +139,9 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data)
static void
nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data)
{
- nxt_conn_t *c;
- nxt_timer_t *timer;
+ nxt_conn_t *c;
+ nxt_timer_t *timer;
+ nxt_event_engine_t *engine;
timer = obj;
@@ -146,13 +149,16 @@ nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd);
+ engine = task->thread->engine;
+
if (c->socket.fd != -1) {
nxt_socket_close(task, c->socket.fd);
c->socket.fd = -1;
+
+ engine->closed_conns_cnt++;
}
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- c->write_state->ready_handler,
+ nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler,
task, c, c->socket.data);
}
diff --git a/src/nxt_controller.c b/src/nxt_controller.c
index 7510d6f0..09168821 100644
--- a/src/nxt_controller.c
+++ b/src/nxt_controller.c
@@ -9,6 +9,7 @@
#include <nxt_runtime.h>
#include <nxt_main_process.h>
#include <nxt_conf.h>
+#include <nxt_status.h>
#include <nxt_cert.h>
@@ -85,6 +86,12 @@ static void nxt_controller_process_request(nxt_task_t *task,
static void nxt_controller_process_config(nxt_task_t *task,
nxt_controller_request_t *req, nxt_str_t *path);
static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task);
+static void nxt_controller_process_status(nxt_task_t *task,
+ nxt_controller_request_t *req);
+static void nxt_controller_status_handler(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_controller_status_response(nxt_task_t *task,
+ nxt_controller_request_t *req, nxt_str_t *path);
#if (NXT_TLS)
static void nxt_controller_process_cert(nxt_task_t *task,
nxt_controller_request_t *req, nxt_str_t *path);
@@ -120,6 +127,7 @@ static nxt_uint_t nxt_controller_router_ready;
static nxt_controller_conf_t nxt_controller_conf;
static nxt_queue_t nxt_controller_waiting_requests;
static nxt_bool_t nxt_controller_waiting_init_conf;
+static nxt_conf_value_t *nxt_controller_status;
static const nxt_event_conn_state_t nxt_controller_conn_read_state;
@@ -725,7 +733,7 @@ static const nxt_event_conn_state_t nxt_controller_conn_read_state
.timer_handler = nxt_controller_conn_read_timeout,
.timer_value = nxt_controller_conn_timeout_value,
- .timer_data = 60 * 1000,
+ .timer_data = 300 * 1000,
};
@@ -1035,6 +1043,7 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
static nxt_str_t certificates = nxt_string("certificates");
#endif
static nxt_str_t config = nxt_string("config");
+ static nxt_str_t status = nxt_string("status");
c = req->conn;
path = req->parser.path;
@@ -1058,6 +1067,32 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
return;
}
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ if (nxt_str_start(&path, "/status", 7)
+ && (path.length == 7 || path.start[7] == '/'))
+ {
+ if (!nxt_str_eq(&req->parser.method, "GET", 3)) {
+ goto invalid_method;
+ }
+
+ if (nxt_controller_status == NULL) {
+ nxt_controller_process_status(task, req);
+ return;
+ }
+
+ if (path.length == 7) {
+ path.length = 1;
+
+ } else {
+ path.length -= 7;
+ path.start += 7;
+ }
+
+ nxt_controller_status_response(task, req, &path);
+ return;
+ }
+
#if (NXT_TLS)
if (nxt_str_start(&path, "/certificates", 13)
@@ -1085,15 +1120,18 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
return;
}
- nxt_memzero(&resp, sizeof(nxt_controller_response_t));
-
if (path.length == 1 && path.start[0] == '/') {
if (!nxt_str_eq(&req->parser.method, "GET", 3)) {
goto invalid_method;
}
- count = 1;
+ if (nxt_controller_status == NULL) {
+ nxt_controller_process_status(task, req);
+ return;
+ }
+
+ count = 2;
#if (NXT_TLS)
count++;
#endif
@@ -1114,7 +1152,8 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
nxt_conf_set_member(value, &certificates, certs, i++);
#endif
- nxt_conf_set_member(value, &config, nxt_controller_conf.root, i);
+ nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++);
+ nxt_conf_set_member(value, &status, nxt_controller_status, i);
resp.status = 200;
resp.conf = value;
@@ -1451,6 +1490,128 @@ nxt_controller_check_postpone_request(nxt_task_t *task)
}
+static void
+nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req)
+{
+ uint32_t stream;
+ nxt_int_t rc;
+ nxt_port_t *router_port, *controller_port;
+ nxt_runtime_t *rt;
+ nxt_controller_response_t resp;
+
+ if (nxt_controller_check_postpone_request(task)) {
+ nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link);
+ return;
+ }
+
+ rt = task->thread->runtime;
+
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ nxt_assert(router_port != NULL);
+ nxt_assert(nxt_controller_router_ready);
+
+ controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
+
+ stream = nxt_port_rpc_register_handler(task, controller_port,
+ nxt_controller_status_handler,
+ nxt_controller_status_handler,
+ router_port->pid, req);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS,
+ -1, stream, controller_port->id, NULL);
+
+ if (nxt_slow_path(rc != NXT_OK)) {
+ nxt_port_rpc_cancel(task, controller_port, stream);
+
+ goto fail;
+ }
+
+ nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link);
+ return;
+
+fail:
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ resp.status = 500;
+ resp.title = (u_char *) "Failed to get status.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ return;
+}
+
+
+static void
+nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_conf_value_t *status;
+ nxt_controller_request_t *req;
+ nxt_controller_response_t resp;
+
+ nxt_debug(task, "controller status handler");
+
+ req = data;
+
+ if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) {
+ status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos,
+ req->conn->mem_pool);
+ } else {
+ status = NULL;
+ }
+
+ if (status == NULL) {
+ nxt_queue_remove(&req->link);
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ resp.status = 500;
+ resp.title = (u_char *) "Failed to get status.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ }
+
+ nxt_controller_status = status;
+
+ nxt_controller_flush_requests(task);
+
+ nxt_controller_status = NULL;
+}
+
+
+static void
+nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req,
+ nxt_str_t *path)
+{
+ nxt_conf_value_t *status;
+ nxt_controller_response_t resp;
+
+ status = nxt_conf_get_path(nxt_controller_status, path);
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ if (status == NULL) {
+ resp.status = 404;
+ resp.title = (u_char *) "Invalid path.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ return;
+ }
+
+ resp.status = 200;
+ resp.conf = status;
+
+ nxt_controller_response(task, req, &resp);
+}
+
+
#if (NXT_TLS)
static void
diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h
index 91cfc0aa..291ea749 100644
--- a/src/nxt_event_engine.h
+++ b/src/nxt_event_engine.h
@@ -483,6 +483,11 @@ struct nxt_event_engine_s {
nxt_queue_t idle_connections;
nxt_array_t *mem_cache;
+ nxt_atomic_uint_t accepted_conns_cnt;
+ nxt_atomic_uint_t idle_conns_cnt;
+ nxt_atomic_uint_t closed_conns_cnt;
+ nxt_atomic_uint_t requests_cnt;
+
nxt_queue_link_t link;
// STUB: router link
nxt_queue_link_t link0;
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c
index d3340774..852b4866 100644
--- a/src/nxt_h1proto.c
+++ b/src/nxt_h1proto.c
@@ -478,7 +478,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn request init");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
r = nxt_http_request_create(task);
@@ -490,7 +490,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
r->remote = c->remote;
#if (NXT_TLS)
- r->tls = c->u.tls;
+ r->tls = (c->u.tls != NULL);
#endif
r->task = c->task;
@@ -1739,7 +1739,7 @@ nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn close");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_shutdown(task, c);
}
@@ -1754,7 +1754,7 @@ nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn error");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_shutdown(task, c);
}
@@ -1801,7 +1801,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
c->sent = 0;
engine = task->thread->engine;
- nxt_queue_insert_head(&engine->idle_connections, &c->link);
+
+ nxt_conn_idle(engine, c);
if (in == NULL) {
c->read_state = &nxt_h1p_keepalive_state;
@@ -1855,7 +1856,7 @@ nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p idle close");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_idle_response(task, c);
}
@@ -1874,7 +1875,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
c = nxt_read_timer_conn(timer);
c->block_read = 1;
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_idle_response(task, c);
}
diff --git a/src/nxt_http.h b/src/nxt_http.h
index d299fdd4..c2e85840 100644
--- a/src/nxt_http.h
+++ b/src/nxt_http.h
@@ -162,7 +162,6 @@ struct nxt_http_request_s {
nxt_sockaddr_t *remote;
nxt_sockaddr_t *local;
- void *tls;
nxt_task_t task;
nxt_timer_t timer;
@@ -190,6 +189,7 @@ struct nxt_http_request_s {
uint8_t pass_count; /* 8 bits */
uint8_t app_target;
nxt_http_protocol_t protocol:8; /* 2 bits */
+ uint8_t tls; /* 1 bit */
uint8_t logged; /* 1 bit */
uint8_t header_sent; /* 1 bit */
uint8_t inconsistent; /* 1 bit */
@@ -207,6 +207,13 @@ typedef struct {
} nxt_http_name_value_t;
+typedef enum {
+ NXT_HTTP_URI_ENCODING_NONE = 0,
+ NXT_HTTP_URI_ENCODING,
+ NXT_HTTP_URI_ENCODING_PLUS
+} nxt_http_uri_encoding_t;
+
+
typedef struct nxt_http_route_s nxt_http_route_t;
typedef struct nxt_http_route_rule_s nxt_http_route_rule_t;
typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t;
@@ -266,10 +273,16 @@ typedef struct {
} nxt_http_proto_table_t;
-struct nxt_http_client_ip_s {
- nxt_http_route_addr_rule_t *source;
+typedef struct {
nxt_str_t *header;
uint32_t header_hash;
+} nxt_http_forward_header_t;
+
+
+struct nxt_http_forward_s {
+ nxt_http_forward_header_t client_ip;
+ nxt_http_forward_header_t protocol;
+ nxt_http_route_addr_rule_t *source;
uint8_t recursive; /* 1 bit */
};
@@ -324,6 +337,12 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field,
nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r);
nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r);
+int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name,
+ nxt_bool_t case_sensitive, uint8_t encoding);
+int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name);
+int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name);
+int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name);
+
nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf);
nxt_http_action_t *nxt_http_action_create(nxt_task_t *task,
@@ -353,15 +372,16 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
nxt_upstream_t ***upstream_joint);
-nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
- nxt_http_action_conf_t *acf);
+nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf,
+ nxt_http_action_t *action, nxt_http_action_conf_t *acf);
nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_http_action_t *action, nxt_http_action_conf_t *acf);
nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash);
nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
- nxt_str_t *exten, nxt_str_t *type);
-nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten);
+ const nxt_str_t *exten, nxt_str_t *type);
+nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash,
+ const nxt_str_t *exten);
nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task,
nxt_http_request_t *r, nxt_http_action_t *action);
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c
index 1ab6cc90..1bb4291f 100644
--- a/src/nxt_http_parse.c
+++ b/src/nxt_http_parse.c
@@ -8,16 +8,16 @@
static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
-static u_char *nxt_http_lookup_field_end(u_char *p, u_char *end);
+ u_char **pos, const u_char *end);
+static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end);
static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
@@ -62,7 +62,7 @@ static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = {
nxt_inline nxt_http_target_traps_e
-nxt_http_parse_target(u_char **pos, u_char *end)
+nxt_http_parse_target(u_char **pos, const u_char *end)
{
u_char *p;
nxt_uint_t trap;
@@ -158,7 +158,7 @@ nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b)
static nxt_int_t
nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, ch, *after_slash, *args;
nxt_int_t rc;
@@ -479,7 +479,7 @@ space_after_target:
static nxt_int_t
nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, ch;
@@ -517,7 +517,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos,
static nxt_int_t
nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, c;
size_t len;
@@ -624,7 +624,7 @@ name_end:
static nxt_int_t
nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, *start, ch;
size_t len;
@@ -704,7 +704,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
static u_char *
-nxt_http_lookup_field_end(u_char *p, u_char *end)
+nxt_http_lookup_field_end(u_char *p, const u_char *end)
{
while (nxt_fast_path(end - p >= 16)) {
@@ -771,7 +771,7 @@ nxt_http_lookup_field_end(u_char *p, u_char *end)
static nxt_int_t
nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p;
nxt_http_field_t *field;
diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h
index 3cd9bd15..2b714464 100644
--- a/src/nxt_http_parse.h
+++ b/src/nxt_http_parse.h
@@ -35,7 +35,7 @@ typedef union {
struct nxt_http_request_parse_s {
nxt_int_t (*handler)(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
nxt_str_t method;
diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c
index 04a6f7f3..943ad82d 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -10,10 +10,14 @@
static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp);
static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data);
-static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task,
- nxt_http_request_t *r);
+static nxt_int_t nxt_http_request_forward(nxt_task_t *task,
+ nxt_http_request_t *r, nxt_http_forward_t *forward);
+static void nxt_http_request_forward_client_ip(nxt_http_request_t *r,
+ nxt_http_forward_t *forward, nxt_array_t *fields);
static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr(
nxt_http_request_t *r, u_char *start, size_t len);
+static void nxt_http_request_forward_protocol(nxt_http_request_t *r,
+ nxt_http_field_t *field);
static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data);
static void nxt_http_request_proto_info(nxt_task_t *task,
nxt_http_request_t *r);
@@ -26,11 +30,11 @@ static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now,
static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array,
u_char *name, size_t name_length, uint32_t hash, u_char *start,
- u_char *end);
+ const u_char *end);
static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start,
- u_char *end);
+ const u_char *end);
static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name,
- size_t name_length, u_char *start, u_char *end);
+ size_t name_length, u_char *start, const u_char *end);
#define NXT_HTTP_COOKIE_HASH \
@@ -274,6 +278,8 @@ nxt_http_request_create(nxt_task_t *task)
r->resp.content_length_n = -1;
r->state = &nxt_http_request_init_state;
+ task->thread->engine->requests_cnt++;
+
return r;
fail:
@@ -296,74 +302,125 @@ static void
nxt_http_request_start(nxt_task_t *task, void *obj, void *data)
{
nxt_int_t ret;
+ nxt_socket_conf_t *skcf;
nxt_http_request_t *r;
r = obj;
r->state = &nxt_http_request_body_state;
- ret = nxt_http_request_client_ip(task, r);
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
+ skcf = r->conf->socket_conf;
+
+ if (skcf->forwarded != NULL) {
+ ret = nxt_http_request_forward(task, r, skcf->forwarded);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+ }
+
+ if (skcf->client_ip != NULL) {
+ ret = nxt_http_request_forward(task, r, skcf->client_ip);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
}
nxt_http_request_read_body(task, r);
+
+ return;
+
+fail:
+ nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
}
static nxt_int_t
-nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
+nxt_http_request_forward(nxt_task_t *task, nxt_http_request_t *r,
+ nxt_http_forward_t *forward)
{
- u_char *start, *p;
- nxt_int_t ret, i, len;
- nxt_str_t *header;
- nxt_array_t *fields_arr; /* of nxt_http_field_t * */
- nxt_sockaddr_t *sa, *prev_sa;
- nxt_http_field_t *f, **fields;
- nxt_http_client_ip_t *client_ip;
+ nxt_int_t ret;
+ nxt_array_t *client_ip_fields;
+ nxt_http_field_t *f, **fields, *protocol_field;
+ nxt_http_forward_header_t *client_ip, *protocol;
- client_ip = r->conf->socket_conf->client_ip;
-
- if (client_ip == NULL) {
- return NXT_OK;
- }
-
- ret = nxt_http_route_addr_rule(r, client_ip->source, r->remote);
+ ret = nxt_http_route_addr_rule(r, forward->source, r->remote);
if (ret <= 0) {
return NXT_OK;
}
- header = client_ip->header;
+ client_ip = &forward->client_ip;
+ protocol = &forward->protocol;
+
+ if (client_ip->header != NULL) {
+ client_ip_fields = nxt_array_create(r->mem_pool, 1,
+ sizeof(nxt_http_field_t *));
+ if (nxt_slow_path(client_ip_fields == NULL)) {
+ return NXT_ERROR;
+ }
- fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *));
- if (nxt_slow_path(fields_arr == NULL)) {
- return NXT_ERROR;
+ } else {
+ client_ip_fields = NULL;
}
+ protocol_field = NULL;
+
nxt_list_each(f, r->fields) {
- if (f->hash == client_ip->header_hash
- && f->name_length == client_ip->header->length
+ if (client_ip_fields != NULL
+ && f->hash == client_ip->header_hash
&& f->value_length > 0
- && nxt_memcasecmp(f->name, header->start, header->length) == 0)
+ && f->name_length == client_ip->header->length
+ && nxt_memcasecmp(f->name, client_ip->header->start,
+ client_ip->header->length) == 0)
{
- fields = nxt_array_add(fields_arr);
+ fields = nxt_array_add(client_ip_fields);
if (nxt_slow_path(fields == NULL)) {
return NXT_ERROR;
}
*fields = f;
}
+
+ if (protocol->header != NULL
+ && protocol_field == NULL
+ && f->hash == protocol->header_hash
+ && f->value_length > 0
+ && f->name_length == protocol->header->length
+ && nxt_memcasecmp(f->name, protocol->header->start,
+ protocol->header->length) == 0)
+ {
+ protocol_field = f;
+ }
} nxt_list_loop;
+ if (client_ip_fields != NULL) {
+ nxt_http_request_forward_client_ip(r, forward, client_ip_fields);
+ }
+
+ if (protocol_field != NULL) {
+ nxt_http_request_forward_protocol(r, protocol_field);
+ }
+
+ return NXT_OK;
+}
+
+
+static void
+nxt_http_request_forward_client_ip(nxt_http_request_t *r,
+ nxt_http_forward_t *forward, nxt_array_t *fields)
+{
+ u_char *start, *p;
+ nxt_int_t ret, i, len;
+ nxt_sockaddr_t *sa, *prev_sa;
+ nxt_http_field_t **f;
+
prev_sa = r->remote;
- fields = (nxt_http_field_t **) fields_arr->elts;
+ f = (nxt_http_field_t **) fields->elts;
- i = fields_arr->nelts;
+ i = fields->nelts;
while (i-- > 0) {
- f = fields[i];
- start = f->value;
- len = f->value_length;
+ start = f[i]->value;
+ len = f[i]->value_length;
do {
for (p = start + len - 1; p > start; p--, len--) {
@@ -385,20 +442,18 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
r->remote = prev_sa;
}
- return NXT_OK;
+ return;
}
- if (!client_ip->recursive) {
+ if (!forward->recursive) {
r->remote = sa;
-
- return NXT_OK;
+ return;
}
- ret = nxt_http_route_addr_rule(r, client_ip->source, sa);
+ ret = nxt_http_route_addr_rule(r, forward->source, sa);
if (ret <= 0 || (i == 0 && p == start)) {
r->remote = sa;
-
- return NXT_OK;
+ return;
}
prev_sa = sa;
@@ -406,8 +461,6 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
} while (len > 0);
}
-
- return NXT_OK;
}
@@ -451,6 +504,28 @@ nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start,
}
+static void
+nxt_http_request_forward_protocol(nxt_http_request_t *r,
+ nxt_http_field_t *field)
+{
+ if (field->value_length == 4) {
+ if (nxt_memcasecmp(field->value, "http", 4) == 0) {
+ r->tls = 0;
+ }
+
+ } else if (field->value_length == 5) {
+ if (nxt_memcasecmp(field->value, "https", 5) == 0) {
+ r->tls = 1;
+ }
+
+ } else if (field->value_length == 2) {
+ if (nxt_memcasecmp(field->value, "on", 2) == 0) {
+ r->tls = 1;
+ }
+ }
+}
+
+
static const nxt_http_request_state_t nxt_http_request_body_state
nxt_aligned(64) =
{
@@ -718,6 +793,7 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data)
void
nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
{
+ nxt_var_t *log_format;
nxt_http_proto_t proto;
nxt_http_request_t *r;
nxt_http_protocol_t protocol;
@@ -727,20 +803,22 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
r = obj;
proto.any = data;
- nxt_debug(task, "http request close handler");
-
conf = r->conf;
if (!r->logged) {
r->logged = 1;
access_log = conf->socket_conf->router_conf->access_log;
+ log_format = conf->socket_conf->router_conf->log_format;
if (access_log != NULL) {
- access_log->handler(task, r, access_log);
+ access_log->handler(task, r, access_log, log_format);
+ return;
}
}
+ nxt_debug(task, "http request close handler");
+
r->proto.any = NULL;
if (r->body != NULL && nxt_buf_is_file(r->body)
@@ -876,7 +954,7 @@ nxt_http_arguments_parse(nxt_http_request_t *r)
static nxt_http_name_value_t *
nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length,
- uint32_t hash, u_char *start, u_char *end)
+ uint32_t hash, u_char *start, const u_char *end)
{
size_t length;
nxt_http_name_value_t *nv;
@@ -945,7 +1023,7 @@ nxt_http_cookies_parse(nxt_http_request_t *r)
static nxt_int_t
-nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end)
+nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end)
{
size_t name_length;
u_char c, *p, *name;
@@ -994,7 +1072,7 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end)
static nxt_http_name_value_t *
nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length,
- u_char *start, u_char *end)
+ u_char *start, const u_char *end)
{
u_char c, *p;
uint32_t hash;
@@ -1024,3 +1102,140 @@ nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length,
return nv;
}
+
+
+int64_t
+nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive,
+ uint8_t encoding)
+{
+ u_char c, *p, *src, *start, *end, plus;
+ uint8_t d0, d1;
+ uint32_t hash;
+ nxt_str_t str;
+ nxt_uint_t i;
+
+ str.length = name->length;
+
+ str.start = nxt_mp_nget(mp, str.length);
+ if (nxt_slow_path(str.start == NULL)) {
+ return -1;
+ }
+
+ p = str.start;
+
+ hash = NXT_HTTP_FIELD_HASH_INIT;
+
+ if (encoding == NXT_HTTP_URI_ENCODING_NONE) {
+ for (i = 0; i < name->length; i++) {
+ c = name->start[i];
+ *p++ = c;
+
+ c = case_sensitive ? c : nxt_lowcase(c);
+ hash = nxt_http_field_hash_char(hash, c);
+ }
+
+ goto end;
+ }
+
+ plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+';
+
+ start = name->start;
+ end = start + name->length;
+
+ for (src = start; src < end; src++) {
+ c = *src;
+
+ switch (c) {
+ case '%':
+ if (nxt_slow_path(end - src <= 2)) {
+ return -1;
+ }
+
+ d0 = nxt_hex2int[src[1]];
+ d1 = nxt_hex2int[src[2]];
+ src += 2;
+
+ if (nxt_slow_path((d0 | d1) >= 16)) {
+ return -1;
+ }
+
+ c = (d0 << 4) + d1;
+ *p++ = c;
+ break;
+
+ case '+':
+ c = plus;
+ *p++ = c;
+ break;
+
+ default:
+ *p++ = c;
+ break;
+ }
+
+ c = case_sensitive ? c : nxt_lowcase(c);
+ hash = nxt_http_field_hash_char(hash, c);
+ }
+
+ str.length = p - str.start;
+
+end:
+
+ *name = str;
+
+ return nxt_http_field_hash_end(hash) & 0xFFFF;
+}
+
+
+int64_t
+nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS);
+}
+
+
+int64_t
+nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ u_char c, *p;
+ uint32_t i, hash;
+ nxt_str_t str;
+
+ str.length = name->length;
+
+ str.start = nxt_mp_nget(mp, str.length);
+ if (nxt_slow_path(str.start == NULL)) {
+ return -1;
+ }
+
+ p = str.start;
+ hash = NXT_HTTP_FIELD_HASH_INIT;
+
+ for (i = 0; i < name->length; i++) {
+ c = name->start[i];
+
+ if (c >= 'A' && c <= 'Z') {
+ *p = c | 0x20;
+
+ } else if (c == '_') {
+ *p = '-';
+
+ } else {
+ *p = c;
+ }
+
+ hash = nxt_http_field_hash_char(hash, *p);
+ p++;
+ }
+
+ *name = str;
+
+ return nxt_http_field_hash_end(hash) & 0xFFFF;
+}
+
+
+int64_t
+nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE);
+}
diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c
index 82c91568..9f3c4fc5 100644
--- a/src/nxt_http_return.c
+++ b/src/nxt_http_return.c
@@ -32,12 +32,15 @@ static const nxt_http_request_state_t nxt_http_return_send_state;
nxt_int_t
-nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
+nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action,
nxt_http_action_conf_t *acf)
{
+ nxt_mp_t *mp;
nxt_str_t str;
nxt_http_return_conf_t *conf;
+ mp = rtcf->mem_pool;
+
conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t));
if (nxt_slow_path(conf == NULL)) {
return NXT_ERROR;
@@ -54,7 +57,7 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
nxt_conf_get_string(acf->location, &str);
- conf->location = nxt_var_compile(&str, mp, 0);
+ conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0);
if (nxt_slow_path(conf->location == NULL)) {
return NXT_ERROR;
}
diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c
index 9200dc52..cdc9077f 100644
--- a/src/nxt_http_route.c
+++ b/src/nxt_http_route.c
@@ -40,13 +40,6 @@ typedef enum {
} nxt_http_route_pattern_case_t;
-typedef enum {
- NXT_HTTP_ROUTE_ENCODING_NONE = 0,
- NXT_HTTP_ROUTE_ENCODING_URI,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS
-} nxt_http_route_encoding_t;
-
-
typedef struct {
nxt_conf_value_t *host;
nxt_conf_value_t *uri;
@@ -169,29 +162,29 @@ static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static int nxt_http_pattern_compare(const void *one, const void *two);
static int nxt_http_addr_pattern_compare(const void *one, const void *two);
static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices,
nxt_str_t *test,
nxt_http_route_pattern_type_t type,
- nxt_http_route_encoding_t encoding,
+ nxt_http_uri_encoding_t encoding,
nxt_http_route_pattern_case_t pattern_case);
static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
@@ -457,7 +450,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.scheme != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -470,7 +463,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.host != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1,
NXT_HTTP_ROUTE_PATTERN_LOWCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -484,7 +477,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.uri != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_URI);
+ NXT_HTTP_URI_ENCODING);
if (rule == NULL) {
return NULL;
}
@@ -498,7 +491,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.method != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1,
NXT_HTTP_ROUTE_PATTERN_UPCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -512,7 +505,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.headers != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.headers,
NXT_HTTP_ROUTE_HEADER, 0,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (table == NULL) {
return NULL;
}
@@ -524,7 +517,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.arguments != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.arguments,
NXT_HTTP_ROUTE_ARGUMENT, 1,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS);
+ NXT_HTTP_URI_ENCODING_PLUS);
if (table == NULL) {
return NULL;
}
@@ -536,7 +529,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.cookies != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.cookies,
NXT_HTTP_ROUTE_COOKIE, 1,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (table == NULL) {
return NULL;
}
@@ -548,7 +541,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.query != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS);
+ NXT_HTTP_URI_ENCODING_PLUS);
if (rule == NULL) {
return NULL;
}
@@ -650,6 +643,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_mp_t *mp;
nxt_int_t ret;
nxt_str_t pass;
+ nxt_router_conf_t *rtcf;
nxt_http_action_conf_t acf;
nxt_memzero(&acf, sizeof(acf));
@@ -662,10 +656,11 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_memzero(action, sizeof(nxt_http_action_t));
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
if (acf.ret != NULL) {
- return nxt_http_return_init(mp, action, &acf);
+ return nxt_http_return_init(rtcf, action, &acf);
}
if (acf.share != NULL) {
@@ -678,7 +673,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_conf_get_string(acf.pass, &pass);
- action->u.var = nxt_var_compile(&pass, mp, 0);
+ action->u.var = nxt_var_compile(&pass, mp, rtcf->var_fields, 0);
if (nxt_slow_path(action->u.var == NULL)) {
return NXT_ERROR;
}
@@ -690,7 +685,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
static nxt_http_route_table_t *
nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n;
@@ -729,7 +724,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_http_route_ruleset_t *
nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n, next;
@@ -777,12 +772,9 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_http_route_rule_t *
nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
- u_char c, *p, *src, *start, *end, plus;
- uint8_t d0, d1;
- uint32_t hash;
- nxt_uint_t i;
+ int64_t hash;
nxt_http_route_rule_t *rule;
rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
@@ -792,73 +784,14 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
return NULL;
}
- rule->u.name.length = name->length;
-
- p = nxt_mp_nget(mp, name->length);
- if (nxt_slow_path(p == NULL)) {
+ hash = nxt_http_field_hash(mp, name, case_sensitive, encoding);
+ if (nxt_slow_path(hash == -1)) {
return NULL;
}
- hash = NXT_HTTP_FIELD_HASH_INIT;
- rule->u.name.start = p;
-
- if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) {
- for (i = 0; i < name->length; i++) {
- c = name->start[i];
- *p++ = c;
-
- c = case_sensitive ? c : nxt_lowcase(c);
- hash = nxt_http_field_hash_char(hash, c);
- }
-
- goto end;
- }
-
- plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+';
-
- start = name->start;
- end = start + name->length;
-
- for (src = start; src < end; src++) {
- c = *src;
-
- switch (c) {
- case '%':
- if (nxt_slow_path(end - src <= 2)) {
- return NULL;
- }
-
- d0 = nxt_hex2int[src[1]];
- d1 = nxt_hex2int[src[2]];
- src += 2;
-
- if (nxt_slow_path((d0 | d1) >= 16)) {
- return NULL;
- }
-
- c = (d0 << 4) + d1;
- *p++ = c;
- break;
-
- case '+':
- c = plus;
- *p++ = c;
- break;
-
- default:
- *p++ = c;
- break;
- }
-
- c = case_sensitive ? c : nxt_lowcase(c);
- hash = nxt_http_field_hash_char(hash, c);
- }
-
- rule->u.name.length = p - rule->u.name.start;
-
-end:
-
- rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF;
+ rule->u.name.hash = hash;
+ rule->u.name.start = name->start;
+ rule->u.name.length = name->length;
return rule;
}
@@ -868,7 +801,7 @@ static nxt_http_route_rule_t *
nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n;
@@ -953,7 +886,7 @@ nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp,
{
return nxt_http_route_rule_create(task, mp, types, 0,
NXT_HTTP_ROUTE_PATTERN_LOWCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
}
@@ -992,7 +925,7 @@ static nxt_int_t
nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
u_char c, *p, *end;
nxt_str_t test, tmp;
@@ -1188,15 +1121,15 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_int_t
-nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
+nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding)
{
u_char *start, *end;
switch (encoding) {
- case NXT_HTTP_ROUTE_ENCODING_NONE:
+ case NXT_HTTP_URI_ENCODING_NONE:
break;
- case NXT_HTTP_ROUTE_ENCODING_URI:
+ case NXT_HTTP_URI_ENCODING:
start = str->start;
end = nxt_decode_uri(start, start, str->length);
@@ -1207,7 +1140,7 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
str->length = end - start;
break;
- case NXT_HTTP_ROUTE_ENCODING_URI_PLUS:
+ case NXT_HTTP_URI_ENCODING_PLUS:
start = str->start;
end = nxt_decode_uri_plus(start, start, str->length);
@@ -1228,9 +1161,8 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
static nxt_int_t
nxt_http_route_pattern_slice(nxt_array_t *slices,
- nxt_str_t *test,
- nxt_http_route_pattern_type_t type,
- nxt_http_route_encoding_t encoding,
+ nxt_str_t *test, nxt_http_route_pattern_type_t type,
+ nxt_http_uri_encoding_t encoding,
nxt_http_route_pattern_case_t pattern_case)
{
u_char *start;
@@ -1554,16 +1486,18 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
{
nxt_mp_t *mp;
nxt_int_t ret;
+ nxt_router_conf_t *rtcf;
nxt_http_action_t *action;
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t));
if (nxt_slow_path(action == NULL)) {
return NULL;
}
- action->u.var = nxt_var_compile(pass, mp, 0);
+ action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0);
if (nxt_slow_path(action->u.var == NULL)) {
return NULL;
}
@@ -1884,6 +1818,13 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p,
break;
#endif
+#if (NXT_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+
+ match = (base->addr_family == AF_UNIX);
+ break;
+#endif
+
default:
match = 0;
break;
@@ -2019,14 +1960,13 @@ nxt_http_route_test_argument(nxt_http_request_t *r,
static nxt_int_t
nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
{
- nxt_bool_t tls, https;
+ nxt_bool_t https;
nxt_http_route_pattern_slice_t *pattern_slice;
pattern_slice = rule->pattern[0].u.pattern_slices->elts;
https = (pattern_slice->length == nxt_length("https"));
- tls = (r->tls != NULL);
- return (tls == https);
+ return (r->tls == https);
}
diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c
index 2907a902..34455af4 100644
--- a/src/nxt_http_route_addr.c
+++ b/src/nxt_http_route_addr.c
@@ -41,6 +41,16 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp,
base->negative = 0;
}
+ if (nxt_str_eq(&addr, "unix", 4)) {
+#if (NXT_HAVE_UNIX_DOMAIN)
+ base->addr_family = AF_UNIX;
+
+ return NXT_OK;
+#else
+ return NXT_ADDR_PATTERN_NO_UNIX_ERROR;
+#endif
+ }
+
if (nxt_slow_path(addr.length < 2)) {
return NXT_ADDR_PATTERN_LENGTH_ERROR;
}
@@ -233,7 +243,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp,
}
addr.length = delim - addr.start;
- inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - cidr_prefix)));
+ inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix)));
inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end;
if (nxt_slow_path(inet->start == INADDR_NONE)) {
diff --git a/src/nxt_http_route_addr.h b/src/nxt_http_route_addr.h
index 3b1e1da3..2deda6f8 100644
--- a/src/nxt_http_route_addr.h
+++ b/src/nxt_http_route_addr.h
@@ -26,6 +26,7 @@ enum {
NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR,
NXT_ADDR_PATTERN_CIDR_ERROR,
NXT_ADDR_PATTERN_NO_IPv6_ERROR,
+ NXT_ADDR_PATTERN_NO_UNIX_ERROR,
};
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index 61dd0cb3..0507e038 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -79,9 +79,11 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_str_t str, *ret;
nxt_var_t *var;
nxt_conf_value_t *cv;
+ nxt_router_conf_t *rtcf;
nxt_http_static_conf_t *conf;
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t));
if (nxt_slow_path(conf == NULL)) {
@@ -102,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
cv = nxt_conf_get_array_element_or_itself(acf->share, i);
nxt_conf_get_string(cv, &str);
- var = nxt_var_compile(&str, mp, 1);
+ var = nxt_var_compile(&str, mp, rtcf->var_fields, NXT_VAR_STRZ);
if (nxt_slow_path(var == NULL)) {
return NXT_ERROR;
}
@@ -128,7 +130,8 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_str_t chr, shr;
nxt_bool_t is_const;
- conf->chroot = nxt_var_compile(&acf->chroot, mp, 1);
+ conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields,
+ NXT_VAR_STRZ);
if (nxt_slow_path(conf->chroot == NULL)) {
return NXT_ERROR;
}
@@ -756,9 +759,7 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten)
end = path->start + path->length;
p = end;
- for ( ;; ) {
- /* There's always '/' in the beginning of the request path. */
-
+ while (p > path->start) {
p--;
ch = *p;
@@ -767,11 +768,14 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten)
p++;
/* Fall through. */
case '.':
- exten->length = end - p;
- exten->start = p;
- return;
+ goto extension;
}
}
+
+extension:
+
+ exten->length = end - p;
+ exten->start = p;
}
@@ -1023,7 +1027,7 @@ typedef struct {
nxt_int_t
nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
- nxt_str_t *exten, nxt_str_t *type)
+ const nxt_str_t *exten, nxt_str_t *type)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
@@ -1048,7 +1052,7 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
nxt_str_t *
-nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten)
+nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, const nxt_str_t *exten)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c
index b765e177..5a632b24 100644
--- a/src/nxt_http_variables.c
+++ b/src/nxt_http_variables.c
@@ -7,32 +7,90 @@
#include <nxt_http.h>
-static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task,
- nxt_var_query_t *query, nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
+static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now,
+ struct tm *tm, size_t size, const char *format);
+static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
static nxt_var_decl_t nxt_http_vars[] = {
- { nxt_string("method"),
- &nxt_http_var_method,
- 0 },
-
- { nxt_string("request_uri"),
- &nxt_http_var_request_uri,
- 0 },
-
- { nxt_string("uri"),
- &nxt_http_var_uri,
- 0 },
-
- { nxt_string("host"),
- &nxt_http_var_host,
- 0 },
+ {
+ .name = nxt_string("dollar"),
+ .handler = nxt_http_var_dollar,
+ }, {
+ .name = nxt_string("method"),
+ .handler = nxt_http_var_method,
+ }, {
+ .name = nxt_string("request_uri"),
+ .handler = nxt_http_var_request_uri,
+ }, {
+ .name = nxt_string("uri"),
+ .handler = nxt_http_var_uri,
+ }, {
+ .name = nxt_string("host"),
+ .handler = nxt_http_var_host,
+ }, {
+ .name = nxt_string("remote_addr"),
+ .handler = nxt_http_var_remote_addr,
+ }, {
+ .name = nxt_string("time_local"),
+ .handler = nxt_http_var_time_local,
+ }, {
+ .name = nxt_string("request_line"),
+ .handler = nxt_http_var_request_line,
+ }, {
+ .name = nxt_string("status"),
+ .handler = nxt_http_var_status,
+ }, {
+ .name = nxt_string("body_bytes_sent"),
+ .handler = nxt_http_var_body_bytes_sent,
+ }, {
+ .name = nxt_string("header_referer"),
+ .handler = nxt_http_var_referer,
+ }, {
+ .name = nxt_string("header_user_agent"),
+ .handler = nxt_http_var_user_agent,
+ }, {
+ .name = nxt_string("arg"),
+ .handler = nxt_http_var_arg,
+ .field_hash = nxt_http_argument_hash,
+ }, {
+ .name = nxt_string("header"),
+ .handler = nxt_http_var_header,
+ .field_hash = nxt_http_header_hash,
+ }, {
+ .name = nxt_string("cookie"),
+ .handler = nxt_http_var_cookie,
+ .field_hash = nxt_http_cookie_hash,
+ },
};
@@ -44,8 +102,16 @@ nxt_http_register_variables(void)
static nxt_int_t
-nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_str_set(str, "$");
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -58,8 +124,8 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
static nxt_int_t
-nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx)
+nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
{
nxt_http_request_t *r;
@@ -72,8 +138,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query,
static nxt_int_t
-nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -86,8 +151,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
static nxt_int_t
-nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -97,3 +161,323 @@ nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
return NXT_OK;
}
+
+
+static nxt_int_t
+nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->length = r->remote->address_length;
+ str->start = nxt_sockaddr_address(r->remote);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ static nxt_time_string_t date_cache = {
+ (nxt_atomic_uint_t) -1,
+ nxt_http_log_date,
+ "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d",
+ nxt_length("31/Dec/1986:19:40:00 +0300"),
+ NXT_THREAD_TIME_LOCAL,
+ NXT_THREAD_TIME_SEC,
+ };
+
+ r = ctx;
+
+ str->length = date_cache.size;
+
+ str->start = nxt_mp_nget(r->mem_pool, str->length);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ str->length = nxt_thread_time_string(task->thread, &date_cache, str->start)
+ - str->start;
+
+ return NXT_OK;
+}
+
+
+static u_char *
+nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
+ size_t size, const char *format)
+{
+ u_char sign;
+ time_t gmtoff;
+
+ static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ gmtoff = nxt_timezone(tm) / 60;
+
+ if (gmtoff < 0) {
+ gmtoff = -gmtoff;
+ sign = '-';
+
+ } else {
+ sign = '+';
+ }
+
+ return nxt_sprintf(buf, buf + size, format,
+ tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ sign, gmtoff / 60, gmtoff % 60);
+}
+
+
+static nxt_int_t
+nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ size_t length;
+ u_char *p, *start;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ length = r->method->length + 1 + r->target.length + 1 + r->version.length;
+
+ start = nxt_mp_nget(r->mem_pool, length);
+ if (nxt_slow_path(start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ p = start;
+
+ if (r->method->length != 0) {
+ p = nxt_cpymem(p, r->method->start, r->method->length);
+
+ if (r->target.length != 0) {
+ *p++ = ' ';
+ p = nxt_cpymem(p, r->target.start, r->target.length);
+
+ if (r->version.length != 0) {
+ *p++ = ' ';
+ p = nxt_cpymem(p, r->version.start, r->version.length);
+ }
+ }
+
+ } else {
+ *p++ = '-';
+ }
+
+ str->start = start;
+ str->length = p - start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_off_t bytes;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto);
+
+ str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O",
+ bytes) - str->start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->start = nxt_mp_nget(r->mem_pool, 3);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status)
+ - str->start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ if (r->referer != NULL) {
+ str->start = r->referer->value;
+ str->length = r->referer->value_length;
+
+ } else {
+ nxt_str_null(str);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ if (r->user_agent != NULL) {
+ str->start = r->user_agent->value;
+ str->length = r->user_agent->value_length;
+
+ } else {
+ nxt_str_null(str);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_array_t *args;
+ nxt_var_field_t *vf;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+ nxt_http_name_value_t *nv, *start;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ args = nxt_http_arguments_parse(r);
+ if (nxt_slow_path(args == NULL)) {
+ return NXT_ERROR;
+ }
+
+ start = args->elts;
+ nv = start + args->nelts - 1;
+
+ while (nv >= start) {
+
+ if (vf->hash == nv->hash
+ && vf->name.length == nv->name_length
+ && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0)
+ {
+ str->start = nv->value;
+ str->length = nv->value_length;
+
+ return NXT_OK;
+ }
+
+ nv--;
+ }
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_var_field_t *vf;
+ nxt_http_field_t *f;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ nxt_list_each(f, r->fields) {
+
+ if (vf->hash == f->hash
+ && vf->name.length == f->name_length
+ && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0)
+ {
+ str->start = f->value;
+ str->length = f->value_length;
+
+ return NXT_OK;
+ }
+
+ } nxt_list_loop;
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_array_t *cookies;
+ nxt_var_field_t *vf;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+ nxt_http_name_value_t *nv, *end;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ cookies = nxt_http_cookies_parse(r);
+ if (nxt_slow_path(cookies == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nv = cookies->elts;
+ end = nv + cookies->nelts;
+
+ while (nv < end) {
+
+ if (vf->hash == nv->hash
+ && vf->name.length == nv->name_length
+ && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0)
+ {
+ str->start = nv->value;
+ str->length = nv->value_length;
+
+ return NXT_OK;
+ }
+
+ nv++;
+ }
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c
index e3cb1f22..796da4c6 100644
--- a/src/nxt_isolation.c
+++ b/src/nxt_isolation.c
@@ -7,7 +7,7 @@
#include <nxt_process.h>
#include <nxt_isolation.h>
-#if (NXT_HAVE_PIVOT_ROOT)
+#if (NXT_HAVE_MNTENT_H)
#include <mntent.h>
#endif
@@ -45,7 +45,7 @@ static int nxt_cdecl nxt_isolation_mount_compare(const void *v1,
const void *v2);
static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process);
-#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
+#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs);
static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task,
const char *rootfs);
@@ -752,7 +752,7 @@ undo:
}
-#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
+#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
nxt_int_t
nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process)
@@ -1003,11 +1003,11 @@ fail:
nxt_inline int
nxt_pivot_root(const char *new_root, const char *old_root)
{
- return syscall(__NR_pivot_root, new_root, old_root);
+ return syscall(SYS_pivot_root, new_root, old_root);
}
-#else /* !(NXT_HAVE_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */
+#else /* !(NXT_HAVE_LINUX_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */
nxt_int_t
diff --git a/src/nxt_isolation.h b/src/nxt_isolation.h
index 88a5f9e1..b1bfc33c 100644
--- a/src/nxt_isolation.h
+++ b/src/nxt_isolation.h
@@ -2,8 +2,8 @@
* Copyright (C) NGINX, Inc.
*/
-#ifndef _NXT_ISOLATION_H_
-#define _NXT_ISOLATION_H_
+#ifndef _NXT_ISOLATION_H_INCLUDED_
+#define _NXT_ISOLATION_H_INCLUDED_
nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process,
@@ -15,4 +15,4 @@ nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task,
nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process);
#endif
-#endif /* _NXT_ISOLATION_H_ */
+#endif /* _NXT_ISOLATION_H_INCLUDED_ */
diff --git a/src/nxt_job_resolve.c b/src/nxt_job_resolve.c
deleted file mode 100644
index 0f1fb9aa..00000000
--- a/src/nxt_job_resolve.c
+++ /dev/null
@@ -1,132 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_main.h>
-
-
-void
-nxt_job_resolve(nxt_job_resolve_t *jbr)
-{
- int err;
- u_char *host;
- size_t length;
- nxt_mp_t *mp;
- nxt_uint_t n;
- nxt_sockaddr_t *sa;
- struct addrinfo hint, *res, *r;
- nxt_work_handler_t handler;
-
- #define NXT_BUFSIZE 64
- u_char buf[NXT_BUFSIZE];
-
- handler = jbr->error_handler;
- res = NULL;
-
- length = jbr->name.length + 1;
-
- if (nxt_fast_path(length <= NXT_BUFSIZE)) {
- host = buf;
-
- } else {
- host = nxt_mp_alloc(jbr->job.mem_pool, length);
- if (nxt_slow_path(host == NULL)) {
- goto fail;
- }
- }
-
- nxt_cpystrn(host, jbr->name.start, length);
-
- nxt_memzero(&hint, sizeof(struct addrinfo));
- hint.ai_socktype = SOCK_STREAM;
-
- err = getaddrinfo((char *) host, NULL, &hint, &res);
-
- if (err != 0) {
- nxt_thread_log_error(jbr->log_level,
- "getaddrinfo(\"%s\") failed (%d: %s)",
- host, err, gai_strerror(err));
- goto fail;
- }
-
- n = 0;
- for (r = res; r != NULL; r = r->ai_next) {
-
- switch (r->ai_addr->sa_family) {
-#if (NXT_INET6)
- case AF_INET6:
-#endif
- case AF_INET:
- n++;
- break;
-
- default:
- break;
- }
- }
-
- jbr->count = n;
- mp = jbr->job.mem_pool;
-
- jbr->sockaddrs = nxt_mp_alloc(mp, n * sizeof(nxt_sockaddr_t *));
- if (nxt_slow_path(jbr->sockaddrs == NULL)) {
- goto fail;
- }
-
- n = 0;
- for (r = res; r != NULL; r = r->ai_next) {
-
- switch (r->ai_addr->sa_family) {
-#if (NXT_INET6)
- case AF_INET6:
- length = NXT_INET6_ADDR_STR_LEN;
- break;
-#endif
- case AF_INET:
- length = NXT_INET_ADDR_STR_LEN;
- break;
-
- default:
- continue;
- }
-
- sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen, length);
- if (nxt_slow_path(sa == NULL)) {
- goto fail;
- }
-
- jbr->sockaddrs[n++] = sa;
-
- if (jbr->port != 0) {
-
- switch (sa->u.sockaddr.sa_family) {
- case AF_INET:
- sa->u.sockaddr_in.sin_port = jbr->port;
- break;
-#if (NXT_INET6)
- case AF_INET6:
- sa->u.sockaddr_in6.sin6_port = jbr->port;
- break;
-#endif
- default:
- break;
- }
- }
- }
-
- handler = jbr->ready_handler;
-
-fail:
-
- if (nxt_fast_path(res != NULL)) {
- freeaddrinfo(res);
- }
-
- if (host != buf) {
- nxt_mp_free(jbr->job.mem_pool, host);
- }
-
- nxt_job_return(jbr->job.task, &jbr->job, handler);
-}
diff --git a/src/nxt_job_resolve.h b/src/nxt_job_resolve.h
deleted file mode 100644
index fef55b99..00000000
--- a/src/nxt_job_resolve.h
+++ /dev/null
@@ -1,29 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#ifndef _NXT_JOB_RESOLVE_H_INCLUDED_
-#define _NXT_JOB_RESOLVE_H_INCLUDED_
-
-
-typedef struct {
- nxt_job_t job;
- nxt_str_t name;
-
- uint32_t log_level; /* 4 bits */
- in_port_t port;
- uint16_t count;
-
- nxt_sockaddr_t **sockaddrs;
-
- nxt_work_handler_t ready_handler;
- nxt_work_handler_t error_handler;
-} nxt_job_resolve_t;
-
-
-void nxt_job_resolve(nxt_job_resolve_t *jbr);
-
-
-#endif /* _NXT_JOB_RESOLVE_H_INCLUDED_ */
diff --git a/src/nxt_main.h b/src/nxt_main.h
index 7f812568..dca4b6dc 100644
--- a/src/nxt_main.h
+++ b/src/nxt_main.h
@@ -146,7 +146,6 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c);
#include <nxt_job_file.h>
#include <nxt_buf_filter.h>
-#include <nxt_job_resolve.h>
#include <nxt_sockaddr.h>
#include <nxt_cache.h>
diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c
index 03761a10..39a8e112 100644
--- a/src/nxt_main_process.c
+++ b/src/nxt_main_process.c
@@ -1187,7 +1187,9 @@ nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
#if (NXT_HAVE_UNIX_DOMAIN)
- if (sa->u.sockaddr.sa_family == AF_UNIX) {
+ if (sa->u.sockaddr.sa_family == AF_UNIX
+ && sa->u.sockaddr_un.sun_path[0] != '\0')
+ {
char *filename;
mode_t access;
diff --git a/src/nxt_mp.c b/src/nxt_mp.c
index d0de2c0e..2bd8cdee 100644
--- a/src/nxt_mp.c
+++ b/src/nxt_mp.c
@@ -155,7 +155,7 @@ static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size,
nxt_bool_t freeable);
static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1,
nxt_rbtree_node_t *node2);
-static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p);
+static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p);
static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster,
u_char *p);
@@ -830,7 +830,7 @@ nxt_mp_free(nxt_mp_t *mp, void *p)
static nxt_mp_block_t *
-nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p)
+nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p)
{
nxt_mp_block_t *block;
nxt_rbtree_node_t *node, *sentinel;
diff --git a/src/nxt_nncq.h b/src/nxt_nncq.h
index 20e7ecff..6c9ab326 100644
--- a/src/nxt_nncq.h
+++ b/src/nxt_nncq.h
@@ -85,7 +85,7 @@ nxt_nncq_empty(nxt_nncq_t const volatile *q)
}
-static void
+static inline void
nxt_nncq_init(nxt_nncq_t volatile *q)
{
q->head = NXT_NNCQ_SIZE;
@@ -94,7 +94,7 @@ nxt_nncq_init(nxt_nncq_t volatile *q)
}
-static void
+static inline void
nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val)
{
nxt_nncq_cycle_t e_cycle, t_cycle;
@@ -128,7 +128,7 @@ nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val)
}
-static nxt_nncq_atomic_t
+static inline nxt_nncq_atomic_t
nxt_nncq_dequeue(nxt_nncq_t volatile *q)
{
nxt_nncq_cycle_t e_cycle, h_cycle;
diff --git a/src/nxt_nvbcq.h b/src/nxt_nvbcq.h
index 2b019dcc..e164615b 100644
--- a/src/nxt_nvbcq.h
+++ b/src/nxt_nvbcq.h
@@ -64,7 +64,7 @@ nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q)
}
-static void
+static inline void
nxt_nvbcq_init(nxt_nvbcq_t volatile *q)
{
nxt_nvbcq_atomic_t i;
@@ -79,7 +79,7 @@ nxt_nvbcq_init(nxt_nvbcq_t volatile *q)
}
-static void
+static inline void
nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val)
{
nxt_nvbcq_atomic_t t, h, i;
@@ -110,7 +110,7 @@ nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val)
}
-static nxt_nvbcq_atomic_t
+static inline nxt_nvbcq_atomic_t
nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q)
{
nxt_nvbcq_atomic_t h, t, i, e;
diff --git a/src/nxt_port.h b/src/nxt_port.h
index 3b66edfd..3a8da5ad 100644
--- a/src/nxt_port.h
+++ b/src/nxt_port.h
@@ -53,6 +53,9 @@ struct nxt_port_handlers_s {
nxt_port_handler_t data;
nxt_port_handler_t app_restart;
+ /* Status report. */
+ nxt_port_handler_t status;
+
nxt_port_handler_t oosm;
nxt_port_handler_t shm_ack;
nxt_port_handler_t read_queue;
@@ -104,6 +107,7 @@ typedef enum {
_NXT_PORT_MSG_DATA = nxt_port_handler_idx(data),
_NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart),
+ _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status),
_NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm),
_NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack),
@@ -145,6 +149,7 @@ typedef enum {
NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA,
NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA),
NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART),
+ NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS),
NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM),
NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK),
@@ -174,9 +179,6 @@ typedef struct {
/* More Fragments followed. */
uint8_t mf; /* 1 bit */
-
- /* Message delivery tracking enabled, next chunk is tracking msg. */
- uint8_t tracking; /* 1 bit */
} nxt_port_msg_t;
@@ -186,7 +188,6 @@ typedef struct {
size_t share;
nxt_fd_t fd[2];
nxt_port_msg_t port_msg;
- uint32_t tracking_msg[2];
uint8_t close_fd; /* 1 bit */
uint8_t allocated; /* 1 bit */
} nxt_port_send_msg_t;
diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c
index e799f860..0a4a6c53 100644
--- a/src/nxt_port_memory.c
+++ b/src/nxt_port_memory.c
@@ -539,137 +539,6 @@ nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id)
}
-nxt_int_t
-nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream)
-{
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
-
- nxt_debug(task, "request tracking for stream #%uD", stream);
-
- mmap_handler = nxt_port_mmap_get(task, mmaps, &c, 1, 1);
- if (nxt_slow_path(mmap_handler == NULL)) {
- return NXT_ERROR;
- }
-
- nxt_port_mmap_handler_use(mmap_handler, 1);
-
- hdr = mmap_handler->hdr;
-
- tracking->mmap_handler = mmap_handler;
- tracking->tracking = hdr->tracking + c;
-
- *tracking->tracking = stream;
-
- nxt_debug(task, "outgoing tracking allocation: %PI->%PI,%d,%d",
- hdr->src_pid, hdr->dst_pid, hdr->id, c);
-
- return NXT_OK;
-}
-
-
-nxt_bool_t
-nxt_port_mmap_tracking_cancel(nxt_task_t *task,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream)
-{
- nxt_bool_t res;
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
-
- mmap_handler = tracking->mmap_handler;
-
- if (nxt_slow_path(mmap_handler == NULL)) {
- return 0;
- }
-
- hdr = mmap_handler->hdr;
-
- res = nxt_atomic_cmp_set(tracking->tracking, stream, 0);
-
- nxt_debug(task, "%s tracking for stream #%uD",
- (res ? "cancelled" : "failed to cancel"), stream);
-
- if (!res) {
- c = tracking->tracking - hdr->tracking;
- nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c);
- }
-
- nxt_port_mmap_handler_use(mmap_handler, -1);
-
- return res;
-}
-
-
-nxt_int_t
-nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t)
-{
- nxt_port_mmap_handler_t *mmap_handler;
-
- mmap_handler = t->mmap_handler;
-
-#if (NXT_DEBUG)
- {
- nxt_atomic_t *tracking;
-
- tracking = mmap_handler->hdr->tracking;
-
- nxt_assert(t->tracking >= tracking);
- nxt_assert(t->tracking < tracking + PORT_MMAP_CHUNK_COUNT);
- }
-#endif
-
- buf[0] = mmap_handler->hdr->id;
- buf[1] = t->tracking - mmap_handler->hdr->tracking;
-
- return NXT_OK;
-}
-
-nxt_bool_t
-nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg)
-{
- nxt_buf_t *b;
- nxt_bool_t res;
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
- nxt_port_mmap_tracking_msg_t *tracking_msg;
-
- b = msg->buf;
-
- if (nxt_buf_used_size(b) < (int) sizeof(nxt_port_mmap_tracking_msg_t)) {
- nxt_debug(task, "too small message %O", nxt_buf_used_size(b));
- return 0;
- }
-
- tracking_msg = (nxt_port_mmap_tracking_msg_t *) b->mem.pos;
-
- b->mem.pos += sizeof(nxt_port_mmap_tracking_msg_t);
- mmap_handler = nxt_port_get_port_incoming_mmap(task, msg->port_msg.pid,
- tracking_msg->mmap_id);
-
- if (nxt_slow_path(mmap_handler == NULL)) {
- return 0;
- }
-
- hdr = mmap_handler->hdr;
-
- c = tracking_msg->tracking_id;
- res = nxt_atomic_cmp_set(hdr->tracking + c, msg->port_msg.stream, 0);
-
- nxt_debug(task, "tracking for stream #%uD %s", msg->port_msg.stream,
- (res ? "received" : "already cancelled"));
-
- if (!res) {
- nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c);
- }
-
- return res;
-}
-
-
nxt_buf_t *
nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size)
{
diff --git a/src/nxt_port_memory.h b/src/nxt_port_memory.h
index a2cdf5dd..f1e70964 100644
--- a/src/nxt_port_memory.h
+++ b/src/nxt_port_memory.h
@@ -15,27 +15,6 @@ typedef struct nxt_port_mmap_handler_s nxt_port_mmap_handler_t;
void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts);
-typedef struct nxt_port_mmap_tracking_s nxt_port_mmap_tracking_t;
-
-struct nxt_port_mmap_tracking_s {
- void *mmap_handler;
- nxt_atomic_t *tracking;
-};
-
-nxt_int_t
-nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream);
-
-nxt_bool_t
-nxt_port_mmap_tracking_cancel(nxt_task_t *task,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream);
-
-nxt_int_t
-nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t);
-
-nxt_bool_t
-nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg);
-
/*
* Allocates nxt_but_t structure from task's thread engine mem_pool, assigns
* this buf 'mem' pointers to first available shared mem bucket(s). 'size'
diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h
index d2524ee4..21a05b10 100644
--- a/src/nxt_port_memory_int.h
+++ b/src/nxt_port_memory_int.h
@@ -84,13 +84,6 @@ struct nxt_port_mmap_msg_s {
};
-typedef struct nxt_port_mmap_tracking_msg_s nxt_port_mmap_tracking_msg_t;
-
-struct nxt_port_mmap_tracking_msg_s {
- uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */
- nxt_chunk_id_t tracking_id; /* Tracking index. */
-};
-
nxt_inline nxt_bool_t
nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c);
@@ -107,7 +100,7 @@ nxt_inline void
nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c);
nxt_inline nxt_chunk_id_t
-nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, u_char *p)
+nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p)
{
u_char *mm_start;
diff --git a/src/nxt_port_rpc.c b/src/nxt_port_rpc.c
index 0cac5cbb..28590933 100644
--- a/src/nxt_port_rpc.c
+++ b/src/nxt_port_rpc.c
@@ -512,7 +512,6 @@ nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port)
msg.port_msg.mmap = 0;
msg.port_msg.nf = 0;
msg.port_msg.mf = 0;
- msg.port_msg.tracking = 0;
msg.size = 0;
msg.cancelled = 0;
msg.u.data = NULL;
diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c
index 2a51dfb6..5752d5ab 100644
--- a/src/nxt_port_socket.c
+++ b/src/nxt_port_socket.c
@@ -19,7 +19,7 @@ static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm,
void *qbuf, nxt_buf_t *b);
static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port,
nxt_port_send_msg_t *msg);
-static nxt_port_send_msg_t *nxt_port_msg_alloc(nxt_port_send_msg_t *m);
+static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m);
static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data);
static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port);
nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg);
@@ -332,7 +332,7 @@ nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port,
static nxt_port_send_msg_t *
-nxt_port_msg_alloc(nxt_port_send_msg_t *m)
+nxt_port_msg_alloc(const nxt_port_send_msg_t *m)
{
nxt_port_send_msg_t *msg;
diff --git a/src/nxt_process.c b/src/nxt_process.c
index 82e66a99..738a03bf 100644
--- a/src/nxt_process.c
+++ b/src/nxt_process.c
@@ -296,6 +296,16 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
} nxt_runtime_process_loop;
+ if (init->siblings != NULL) {
+ nxt_queue_each(p, init->siblings, nxt_process_t, link) {
+
+ nxt_debug(task, "remove sibling process %PI", p->pid);
+
+ nxt_process_close_ports(task, p);
+
+ } nxt_queue_loop;
+ }
+
return NXT_OK;
}
@@ -303,8 +313,9 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
static nxt_pid_t
nxt_process_create(nxt_task_t *task, nxt_process_t *process)
{
- nxt_int_t ret;
- nxt_pid_t pid;
+ nxt_int_t ret;
+ nxt_pid_t pid;
+ nxt_runtime_t *rt;
#if (NXT_HAVE_CLONE)
pid = nxt_clone(SIGCHLD | process->isolation.clone.flags);
@@ -352,7 +363,20 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
process->pid = pid;
process->isolated_pid = pid;
- nxt_runtime_process_add(task, process);
+ rt = task->thread->runtime;
+
+ if (rt->is_pid_isolated) {
+ /*
+ * Do not register process in runtime with isolated pid.
+ * Only global pid can be the key to avoid clash.
+ */
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ nxt_port_use(task, nxt_process_port_first(process), 1);
+
+ } else {
+ nxt_runtime_process_add(task, process);
+ }
return pid;
}
@@ -798,8 +822,6 @@ nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
}
-#if (NXT_HAVE_POSIX_SPAWN)
-
/*
* Linux glibc 2.2 posix_spawn() is implemented via fork()/execve().
* Linux glibc 2.4 posix_spawn() without file actions and spawn
@@ -834,52 +856,6 @@ nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp)
return pid;
}
-#else
-
-nxt_pid_t
-nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp)
-{
- nxt_pid_t pid;
-
- /*
- * vfork() is better than fork() because:
- * it is faster several times;
- * its execution time does not depend on private memory mapping size;
- * it has lesser chances to fail due to the ENOMEM error.
- */
-
- pid = vfork();
-
- switch (pid) {
-
- case -1:
- nxt_alert(task, "vfork() failed while executing \"%s\" %E",
- name, nxt_errno);
- break;
-
- case 0:
- /* A child. */
- nxt_debug(task, "execve(\"%s\")", name);
-
- (void) execve(name, argv, envp);
-
- nxt_alert(task, "execve(\"%s\") failed %E", name, nxt_errno);
-
- exit(1);
- nxt_unreachable();
- break;
-
- default:
- /* A parent. */
- nxt_debug(task, "vfork(): %PI", pid);
- break;
- }
-
- return pid;
-}
-
-#endif
-
nxt_int_t
nxt_process_daemon(nxt_task_t *task)
@@ -1008,6 +984,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process)
{
nxt_port_t *port;
+ nxt_process_use(task, process, 1);
+
nxt_process_port_each(process, port) {
nxt_port_close(task, port);
@@ -1015,6 +993,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process)
nxt_runtime_port_remove(task, port);
} nxt_process_port_loop;
+
+ nxt_process_use(task, process, -1);
}
diff --git a/src/nxt_process.h b/src/nxt_process.h
index 694f457e..15fd4e7f 100644
--- a/src/nxt_process.h
+++ b/src/nxt_process.h
@@ -19,7 +19,7 @@
* fork(2) calls. As we use clone(2) for container, it returns the wrong pid.
*/
#define nxt_getpid() \
- syscall(__NR_getpid)
+ syscall(SYS_getpid)
#else
#define nxt_getpid() \
getpid()
@@ -148,6 +148,8 @@ typedef struct {
const nxt_port_handlers_t *port_handlers;
const nxt_sig_event_t *signals;
+
+ nxt_queue_t *siblings;
} nxt_process_init_t;
diff --git a/src/nxt_router.c b/src/nxt_router.c
index 3a32a363..f02bf3f2 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -7,6 +7,7 @@
#include <nxt_router.h>
#include <nxt_conf.h>
+#include <nxt_status.h>
#if (NXT_TLS)
#include <nxt_cert.h>
#endif
@@ -90,17 +91,14 @@ static void nxt_router_conf_data_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static void nxt_router_app_restart_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
-static void nxt_router_remove_pid_handler(nxt_task_t *task,
+static void nxt_router_status_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
-static void nxt_router_access_log_reopen_handler(nxt_task_t *task,
+static void nxt_router_remove_pid_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
-static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
static void nxt_router_conf_ready(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf);
-static void nxt_router_conf_error(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf);
static void nxt_router_conf_send(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
@@ -108,9 +106,10 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task,
nxt_router_conf_t *rtcf, nxt_conf_value_t *conf);
-static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf,
- nxt_conf_value_t *conf);
+static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task,
+ nxt_mp_t *mp, nxt_conf_value_t *conf);
+static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp,
+ nxt_conf_value_t *conf, nxt_http_forward_header_t *fh);
static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
@@ -200,27 +199,6 @@ static void nxt_router_req_headers_ack_handler(nxt_task_t *task,
static void nxt_router_listen_socket_release(nxt_task_t *task,
nxt_socket_conf_t *skcf);
-static void nxt_router_access_log_writer(nxt_task_t *task,
- nxt_http_request_t *r, nxt_router_access_log_t *access_log);
-static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now,
- struct tm *tm, size_t size, const char *format);
-static void nxt_router_access_log_open(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf);
-static void nxt_router_access_log_ready(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_error(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log);
-static void nxt_router_access_log_release(nxt_task_t *task,
- nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log);
-static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj,
- void *data);
-static void nxt_router_access_log_reopen_ready(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_reopen_error(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-
static void nxt_router_app_port_ready(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
static void nxt_router_app_port_error(nxt_task_t *task,
@@ -270,7 +248,7 @@ static void nxt_router_get_mmap_handler(nxt_task_t *task,
extern const nxt_http_request_state_t nxt_http_websocket;
-static nxt_router_t *nxt_router;
+nxt_router_t *nxt_router;
static const nxt_str_t http_prefix = nxt_string("HTTP_");
static const nxt_str_t empty_prefix = nxt_string("");
@@ -294,6 +272,7 @@ static const nxt_port_handlers_t nxt_router_process_port_handlers = {
.get_mmap = nxt_router_get_mmap_handler,
.data = nxt_router_conf_data_handler,
.app_restart = nxt_router_app_restart_handler,
+ .status = nxt_router_status_handler,
.remove_pid = nxt_router_remove_pid_handler,
.access_log = nxt_router_access_log_reopen_handler,
.rpc_ready = nxt_port_rpc_handler,
@@ -944,6 +923,84 @@ fail:
static void
+nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ u_char *p;
+ size_t alloc;
+ nxt_app_t *app;
+ nxt_buf_t *b;
+ nxt_uint_t type;
+ nxt_port_t *port;
+ nxt_status_app_t *app_stat;
+ nxt_event_engine_t *engine;
+ nxt_status_report_t *report;
+
+ port = nxt_runtime_port_find(task->thread->runtime,
+ msg->port_msg.pid,
+ msg->port_msg.reply_port);
+ if (nxt_slow_path(port == NULL)) {
+ nxt_alert(task, "nxt_router_status_handler(): reply port not found");
+ return;
+ }
+
+ alloc = sizeof(nxt_status_report_t);
+
+ nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
+
+ alloc += sizeof(nxt_status_app_t) + app->name.length;
+
+ } nxt_queue_loop;
+
+ b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0);
+ if (nxt_slow_path(b == NULL)) {
+ type = NXT_PORT_MSG_RPC_ERROR;
+ goto fail;
+ }
+
+ report = (nxt_status_report_t *) b->mem.free;
+ b->mem.free = b->mem.end;
+
+ nxt_memzero(report, sizeof(nxt_status_report_t));
+
+ nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) {
+
+ report->accepted_conns += engine->accepted_conns_cnt;
+ report->idle_conns += engine->idle_conns_cnt;
+ report->closed_conns += engine->closed_conns_cnt;
+ report->requests += engine->requests_cnt;
+
+ } nxt_queue_loop;
+
+ report->apps_count = 0;
+ app_stat = report->apps;
+ p = b->mem.end;
+
+ nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
+ p -= app->name.length;
+
+ nxt_memcpy(p, app->name.start, app->name.length);
+
+ app_stat->name.length = app->name.length;
+ app_stat->name.start = (u_char *) (p - b->mem.pos);
+
+ app_stat->active_requests = app->active_requests;
+ app_stat->pending_processes = app->pending_processes;
+ app_stat->processes = app->processes;
+ app_stat->idle_processes = app->idle_processes;
+
+ report->apps_count++;
+ app_stat++;
+ } nxt_queue_loop;
+
+ type = NXT_PORT_MSG_RPC_READY_LAST;
+
+fail:
+
+ nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b);
+}
+
+
+static void
nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port,
void *data)
{
@@ -1003,6 +1060,11 @@ nxt_router_temp_conf(nxt_task_t *task)
rtcf->mem_pool = mp;
+ rtcf->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t));
+ if (nxt_slow_path(rtcf->var_fields == NULL)) {
+ goto fail;
+ }
+
tmp = nxt_mp_create(1024, 128, 256, 32);
if (nxt_slow_path(tmp == NULL)) {
goto fail;
@@ -1069,7 +1131,7 @@ nxt_router_app_need_start(nxt_app_t *app)
}
-static void
+void
nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
{
nxt_int_t ret;
@@ -1225,11 +1287,10 @@ nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
}
-static void
+void
nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
{
nxt_app_t *app;
- nxt_queue_t new_socket_confs;
nxt_socket_t s;
nxt_router_t *router;
nxt_queue_link_t *qlk;
@@ -1252,11 +1313,6 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
nxt_free(skcf->listen);
}
- nxt_queue_init(&new_socket_confs);
- nxt_queue_add(&new_socket_confs, &updating_sockets);
- nxt_queue_add(&new_socket_confs, &pending_sockets);
- nxt_queue_add(&new_socket_confs, &creating_sockets);
-
rtcf = tmcf->router_conf;
nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
@@ -1483,7 +1539,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_mp_t *mp, *app_mp;
uint32_t next, next_target;
nxt_int_t ret;
- nxt_str_t name, path, target;
+ nxt_str_t name, target;
nxt_app_t *app, *prev;
nxt_str_t *t, *s, *targets;
nxt_uint_t n, i;
@@ -1494,16 +1550,15 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_tls_init_t *tls_init;
nxt_conf_value_t *certificate;
#endif
- nxt_conf_value_t *conf, *http, *value, *websocket;
+ nxt_conf_value_t *root, *conf, *http, *value, *websocket;
nxt_conf_value_t *applications, *application;
nxt_conf_value_t *listeners, *listener;
- nxt_conf_value_t *routes_conf, *static_conf, *client_ip_conf;
nxt_socket_conf_t *skcf;
+ nxt_router_conf_t *rtcf;
nxt_http_routes_t *routes;
nxt_event_engine_t *engine;
nxt_app_lang_module_t *lang;
nxt_router_app_conf_t apcf;
- nxt_router_access_log_t *access_log;
nxt_router_listener_conf_t lscf;
static nxt_str_t http_path = nxt_string("/settings/http");
@@ -1520,37 +1575,39 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
#endif
static nxt_str_t static_path = nxt_string("/settings/http/static");
static nxt_str_t websocket_path = nxt_string("/settings/http/websocket");
+ static nxt_str_t forwarded_path = nxt_string("/forwarded");
static nxt_str_t client_ip_path = nxt_string("/client_ip");
- conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
- if (conf == NULL) {
+ root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
+ if (root == NULL) {
nxt_alert(task, "configuration parsing error");
return NXT_ERROR;
}
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
- ret = nxt_conf_map_object(mp, conf, nxt_router_conf,
- nxt_nitems(nxt_router_conf), tmcf->router_conf);
+ ret = nxt_conf_map_object(mp, root, nxt_router_conf,
+ nxt_nitems(nxt_router_conf), rtcf);
if (ret != NXT_OK) {
nxt_alert(task, "root map error");
return NXT_ERROR;
}
- if (tmcf->router_conf->threads == 0) {
- tmcf->router_conf->threads = nxt_ncpu;
+ if (rtcf->threads == 0) {
+ rtcf->threads = nxt_ncpu;
}
- static_conf = nxt_conf_get_path(conf, &static_path);
+ conf = nxt_conf_get_path(root, &static_path);
- ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf);
+ ret = nxt_router_conf_process_static(task, rtcf, conf);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
- router = tmcf->router_conf->router;
+ router = rtcf->router;
- applications = nxt_conf_get_path(conf, &applications_path);
+ applications = nxt_conf_get_path(root, &applications_path);
if (applications != NULL) {
next = 0;
@@ -1599,7 +1656,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_queue_remove(&prev->link);
nxt_queue_insert_tail(&tmcf->previous, &prev->link);
- ret = nxt_router_apps_hash_add(tmcf->router_conf, prev);
+ ret = nxt_router_apps_hash_add(rtcf, prev);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
@@ -1734,7 +1791,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_queue_insert_tail(&tmcf->apps, &app->link);
- ret = nxt_router_apps_hash_add(tmcf->router_conf, app);
+ ret = nxt_router_apps_hash_add(rtcf, app);
if (nxt_slow_path(ret != NXT_OK)) {
goto app_fail;
}
@@ -1785,21 +1842,22 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
}
- routes_conf = nxt_conf_get_path(conf, &routes_path);
- if (nxt_fast_path(routes_conf != NULL)) {
- routes = nxt_http_routes_create(task, tmcf, routes_conf);
+ conf = nxt_conf_get_path(root, &routes_path);
+ if (nxt_fast_path(conf != NULL)) {
+ routes = nxt_http_routes_create(task, tmcf, conf);
if (nxt_slow_path(routes == NULL)) {
return NXT_ERROR;
}
- tmcf->router_conf->routes = routes;
+
+ rtcf->routes = routes;
}
- ret = nxt_upstreams_create(task, tmcf, conf);
+ ret = nxt_upstreams_create(task, tmcf, root);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
- http = nxt_conf_get_path(conf, &http_path);
+ http = nxt_conf_get_path(root, &http_path);
#if 0
if (http == NULL) {
nxt_alert(task, "no \"http\" block");
@@ -1807,9 +1865,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
#endif
- websocket = nxt_conf_get_path(conf, &websocket_path);
+ websocket = nxt_conf_get_path(root, &websocket_path);
- listeners = nxt_conf_get_path(conf, &listeners_path);
+ listeners = nxt_conf_get_path(root, &listeners_path);
if (listeners != NULL) {
next = 0;
@@ -1889,11 +1947,22 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
t->length = nxt_strlen(t->start);
}
- client_ip_conf = nxt_conf_get_path(listener, &client_ip_path);
- ret = nxt_router_conf_process_client_ip(task, tmcf, skcf,
- client_ip_conf);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
+ conf = nxt_conf_get_path(listener, &forwarded_path);
+
+ if (conf != NULL) {
+ skcf->forwarded = nxt_router_conf_forward(task, mp, conf);
+ if (nxt_slow_path(skcf->forwarded == NULL)) {
+ return NXT_ERROR;
+ }
+ }
+
+ conf = nxt_conf_get_path(listener, &client_ip_path);
+
+ if (conf != NULL) {
+ skcf->client_ip = nxt_router_conf_forward(task, mp, conf);
+ if (nxt_slow_path(skcf->client_ip == NULL)) {
+ return NXT_ERROR;
+ }
}
#if (NXT_TLS)
@@ -1941,7 +2010,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
#endif
skcf->listen->handler = nxt_http_conn_init;
- skcf->router_conf = tmcf->router_conf;
+ skcf->router_conf = rtcf;
skcf->router_conf->count++;
if (lscf.pass.length != 0) {
@@ -1949,8 +2018,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
/* COMPATIBILITY: listener application. */
} else if (lscf.application.length > 0) {
- skcf->action = nxt_http_pass_application(task,
- tmcf->router_conf,
+ skcf->action = nxt_http_pass_application(task, rtcf,
&lscf.application);
}
@@ -1965,36 +2033,13 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
goto fail;
}
- value = nxt_conf_get_path(conf, &access_log_path);
+ value = nxt_conf_get_path(root, &access_log_path);
if (value != NULL) {
- nxt_conf_get_string(value, &path);
-
- access_log = router->access_log;
-
- if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) {
- nxt_router_access_log_use(&router->lock, access_log);
-
- } else {
- access_log = nxt_malloc(sizeof(nxt_router_access_log_t)
- + path.length);
- if (access_log == NULL) {
- nxt_alert(task, "failed to allocate access log structure");
- goto fail;
- }
-
- access_log->fd = -1;
- access_log->handler = &nxt_router_access_log_writer;
- access_log->count = 1;
-
- access_log->path.length = path.length;
- access_log->path.start = (u_char *) access_log
- + sizeof(nxt_router_access_log_t);
-
- nxt_memcpy(access_log->path.start, path.start, path.length);
+ ret = nxt_router_access_log_create(task, rtcf, value);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
}
-
- tmcf->router_conf->access_log = access_log;
}
nxt_queue_add(&deleting_sockets, &router->sockets);
@@ -2129,74 +2174,103 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf,
}
-static nxt_int_t
-nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
- nxt_socket_conf_t *skcf, nxt_conf_value_t *conf)
+static nxt_http_forward_t *
+nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf)
{
- char c;
- size_t i;
- nxt_mp_t *mp;
- uint32_t hash;
- nxt_str_t header;
- nxt_conf_value_t *source_conf, *header_conf, *recursive_conf;
- nxt_http_client_ip_t *client_ip;
+ nxt_int_t ret;
+ nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf;
+ nxt_conf_value_t *source_conf, *recursive_conf;
+ nxt_http_forward_t *forward;
nxt_http_route_addr_rule_t *source;
static nxt_str_t header_path = nxt_string("/header");
+ static nxt_str_t client_ip_path = nxt_string("/client_ip");
+ static nxt_str_t protocol_path = nxt_string("/protocol");
static nxt_str_t source_path = nxt_string("/source");
static nxt_str_t recursive_path = nxt_string("/recursive");
- if (conf == NULL) {
- skcf->client_ip = NULL;
+ header_conf = nxt_conf_get_path(conf, &header_path);
- return NXT_OK;
- }
+ if (header_conf != NULL) {
+ client_ip_conf = nxt_conf_get_path(conf, &header_path);
+ protocol_conf = NULL;
- mp = tmcf->router_conf->mem_pool;
+ } else {
+ client_ip_conf = nxt_conf_get_path(conf, &client_ip_path);
+ protocol_conf = nxt_conf_get_path(conf, &protocol_path);
+ }
source_conf = nxt_conf_get_path(conf, &source_path);
- header_conf = nxt_conf_get_path(conf, &header_path);
recursive_conf = nxt_conf_get_path(conf, &recursive_path);
- if (source_conf == NULL || header_conf == NULL) {
- return NXT_ERROR;
+ if (source_conf == NULL
+ || (protocol_conf == NULL && client_ip_conf == NULL))
+ {
+ return NULL;
}
- client_ip = nxt_mp_zget(mp, sizeof(nxt_http_client_ip_t));
- if (nxt_slow_path(client_ip == NULL)) {
- return NXT_ERROR;
+ forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t));
+ if (nxt_slow_path(forward == NULL)) {
+ return NULL;
}
source = nxt_http_route_addr_rule_create(task, mp, source_conf);
if (nxt_slow_path(source == NULL)) {
- return NXT_ERROR;
+ return NULL;
}
- client_ip->source = source;
-
- nxt_conf_get_string(header_conf, &header);
+ forward->source = source;
if (recursive_conf != NULL) {
- client_ip->recursive = nxt_conf_get_boolean(recursive_conf);
+ forward->recursive = nxt_conf_get_boolean(recursive_conf);
}
- client_ip->header = nxt_str_dup(mp, NULL, &header);
- if (nxt_slow_path(client_ip->header == NULL)) {
+ if (client_ip_conf != NULL) {
+ ret = nxt_router_conf_forward_header(mp, client_ip_conf,
+ &forward->client_ip);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+ }
+
+ if (protocol_conf != NULL) {
+ ret = nxt_router_conf_forward_header(mp, protocol_conf,
+ &forward->protocol);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+ }
+
+ return forward;
+}
+
+
+static nxt_int_t
+nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf,
+ nxt_http_forward_header_t *fh)
+{
+ char c;
+ size_t i;
+ uint32_t hash;
+ nxt_str_t header;
+
+ nxt_conf_get_string(conf, &header);
+
+ fh->header = nxt_str_dup(mp, NULL, &header);
+ if (nxt_slow_path(fh->header == NULL)) {
return NXT_ERROR;
}
hash = NXT_HTTP_FIELD_HASH_INIT;
- for (i = 0; i < client_ip->header->length; i++) {
- c = client_ip->header->start[i];
+ for (i = 0; i < fh->header->length; i++) {
+ c = fh->header->start[i];
hash = nxt_http_field_hash_char(hash, nxt_lowcase(c));
}
hash = nxt_http_field_hash_end(hash) & 0xFFFF;
- client_ip->header_hash = hash;
-
- skcf->client_ip = client_ip;
+ fh->header_hash = hash;
return NXT_OK;
}
@@ -3719,384 +3793,6 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint)
static void
-nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r,
- nxt_router_access_log_t *access_log)
-{
- size_t size;
- u_char *buf, *p;
- nxt_off_t bytes;
-
- static nxt_time_string_t date_cache = {
- (nxt_atomic_uint_t) -1,
- nxt_router_access_log_date,
- "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d",
- nxt_length("31/Dec/1986:19:40:00 +0300"),
- NXT_THREAD_TIME_LOCAL,
- NXT_THREAD_TIME_SEC,
- };
-
- size = r->remote->address_length
- + 6 /* ' - - [' */
- + date_cache.size
- + 3 /* '] "' */
- + r->method->length
- + 1 /* space */
- + r->target.length
- + 1 /* space */
- + r->version.length
- + 2 /* '" ' */
- + 3 /* status */
- + 1 /* space */
- + NXT_OFF_T_LEN
- + 2 /* ' "' */
- + (r->referer != NULL ? r->referer->value_length : 1)
- + 3 /* '" "' */
- + (r->user_agent != NULL ? r->user_agent->value_length : 1)
- + 2 /* '"\n' */
- ;
-
- buf = nxt_mp_nget(r->mem_pool, size);
- if (nxt_slow_path(buf == NULL)) {
- return;
- }
-
- p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote),
- r->remote->address_length);
-
- p = nxt_cpymem(p, " - - [", 6);
-
- p = nxt_thread_time_string(task->thread, &date_cache, p);
-
- p = nxt_cpymem(p, "] \"", 3);
-
- if (r->method->length != 0) {
- p = nxt_cpymem(p, r->method->start, r->method->length);
-
- if (r->target.length != 0) {
- *p++ = ' ';
- p = nxt_cpymem(p, r->target.start, r->target.length);
-
- if (r->version.length != 0) {
- *p++ = ' ';
- p = nxt_cpymem(p, r->version.start, r->version.length);
- }
- }
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\" ", 2);
-
- p = nxt_sprintf(p, p + 3, "%03d", r->status);
-
- *p++ = ' ';
-
- bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto);
-
- p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes);
-
- p = nxt_cpymem(p, " \"", 2);
-
- if (r->referer != NULL) {
- p = nxt_cpymem(p, r->referer->value, r->referer->value_length);
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\" \"", 3);
-
- if (r->user_agent != NULL) {
- p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length);
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\"\n", 2);
-
- nxt_fd_write(access_log->fd, buf, p - buf);
-}
-
-
-static u_char *
-nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
- size_t size, const char *format)
-{
- u_char sign;
- time_t gmtoff;
-
- static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- gmtoff = nxt_timezone(tm) / 60;
-
- if (gmtoff < 0) {
- gmtoff = -gmtoff;
- sign = '-';
-
- } else {
- sign = '+';
- }
-
- return nxt_sprintf(buf, buf + size, format,
- tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- sign, gmtoff / 60, gmtoff % 60);
-}
-
-
-static void
-nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
-{
- uint32_t stream;
- nxt_int_t ret;
- nxt_buf_t *b;
- nxt_port_t *main_port, *router_port;
- nxt_runtime_t *rt;
- nxt_router_access_log_t *access_log;
-
- access_log = tmcf->router_conf->access_log;
-
- b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0);
- if (nxt_slow_path(b == NULL)) {
- goto fail;
- }
-
- b->completion_handler = nxt_buf_dummy_completion;
-
- nxt_buf_cpystr(b, &access_log->path);
- *b->mem.free++ = '\0';
-
- rt = task->thread->runtime;
- main_port = rt->port_by_type[NXT_PROCESS_MAIN];
- router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
-
- stream = nxt_port_rpc_register_handler(task, router_port,
- nxt_router_access_log_ready,
- nxt_router_access_log_error,
- -1, tmcf);
- if (nxt_slow_path(stream == 0)) {
- goto fail;
- }
-
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
- stream, router_port->id, b);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_port_rpc_cancel(task, router_port, stream);
- goto fail;
- }
-
- return;
-
-fail:
-
- nxt_router_conf_error(task, tmcf);
-}
-
-
-static void
-nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_temp_conf_t *tmcf;
- nxt_router_access_log_t *access_log;
-
- tmcf = data;
-
- access_log = tmcf->router_conf->access_log;
-
- access_log->fd = msg->fd[0];
-
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- nxt_router_conf_apply, task, tmcf, NULL);
-}
-
-
-static void
-nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_temp_conf_t *tmcf;
-
- tmcf = data;
-
- nxt_router_conf_error(task, tmcf);
-}
-
-
-static void
-nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log)
-{
- if (access_log == NULL) {
- return;
- }
-
- nxt_thread_spin_lock(lock);
-
- access_log->count++;
-
- nxt_thread_spin_unlock(lock);
-}
-
-
-static void
-nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log)
-{
- if (access_log == NULL) {
- return;
- }
-
- nxt_thread_spin_lock(lock);
-
- if (--access_log->count != 0) {
- access_log = NULL;
- }
-
- nxt_thread_spin_unlock(lock);
-
- if (access_log != NULL) {
-
- if (access_log->fd != -1) {
- nxt_fd_close(access_log->fd);
- }
-
- nxt_free(access_log);
- }
-}
-
-
-typedef struct {
- nxt_mp_t *mem_pool;
- nxt_router_access_log_t *access_log;
-} nxt_router_access_log_reopen_t;
-
-
-static void
-nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
-{
- nxt_mp_t *mp;
- uint32_t stream;
- nxt_int_t ret;
- nxt_buf_t *b;
- nxt_port_t *main_port, *router_port;
- nxt_runtime_t *rt;
- nxt_router_access_log_t *access_log;
- nxt_router_access_log_reopen_t *reopen;
-
- access_log = nxt_router->access_log;
-
- if (access_log == NULL) {
- return;
- }
-
- mp = nxt_mp_create(1024, 128, 256, 32);
- if (nxt_slow_path(mp == NULL)) {
- return;
- }
-
- reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t));
- if (nxt_slow_path(reopen == NULL)) {
- goto fail;
- }
-
- reopen->mem_pool = mp;
- reopen->access_log = access_log;
-
- b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0);
- if (nxt_slow_path(b == NULL)) {
- goto fail;
- }
-
- b->completion_handler = nxt_router_access_log_reopen_completion;
-
- nxt_buf_cpystr(b, &access_log->path);
- *b->mem.free++ = '\0';
-
- rt = task->thread->runtime;
- main_port = rt->port_by_type[NXT_PROCESS_MAIN];
- router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
-
- stream = nxt_port_rpc_register_handler(task, router_port,
- nxt_router_access_log_reopen_ready,
- nxt_router_access_log_reopen_error,
- -1, reopen);
- if (nxt_slow_path(stream == 0)) {
- goto fail;
- }
-
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
- stream, router_port->id, b);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_port_rpc_cancel(task, router_port, stream);
- goto fail;
- }
-
- nxt_mp_retain(mp);
-
- return;
-
-fail:
-
- nxt_mp_destroy(mp);
-}
-
-
-static void
-nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data)
-{
- nxt_mp_t *mp;
- nxt_buf_t *b;
-
- b = obj;
- mp = b->data;
-
- nxt_mp_release(mp);
-}
-
-
-static void
-nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_access_log_t *access_log;
- nxt_router_access_log_reopen_t *reopen;
-
- reopen = data;
-
- access_log = reopen->access_log;
-
- if (access_log == nxt_router->access_log) {
-
- if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) {
- nxt_alert(task, "dup2(%FD, %FD) failed %E",
- msg->fd[0], access_log->fd, nxt_errno);
- }
- }
-
- nxt_fd_close(msg->fd[0]);
- nxt_mp_release(reopen->mem_pool);
-}
-
-
-static void
-nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_access_log_reopen_t *reopen;
-
- reopen = data;
-
- nxt_mp_release(reopen->mem_pool);
-}
-
-
-static void
nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data)
{
nxt_port_t *port;
@@ -5390,7 +5086,6 @@ nxt_router_app_prepare_request(nxt_task_t *task,
msg.pm.mmap = 1;
msg.pm.nf = 0;
msg.pm.mf = 0;
- msg.pm.tracking = 0;
nxt_port_mmap_handler_t *mmap_handler = buf->parent;
nxt_port_mmap_header_t *hdr = mmap_handler->hdr;
@@ -5559,7 +5254,7 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r,
p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length);
*p++ = '\0';
- req->tls = (r->tls != NULL);
+ req->tls = r->tls;
req->websocket_handshake = r->websocket_handshake;
req->server_name_length = r->server_name.length;
diff --git a/src/nxt_router.h b/src/nxt_router.h
index 7e337d27..a6add219 100644
--- a/src/nxt_router.h
+++ b/src/nxt_router.h
@@ -18,7 +18,7 @@ typedef struct nxt_http_request_s nxt_http_request_t;
typedef struct nxt_http_action_s nxt_http_action_t;
typedef struct nxt_http_routes_s nxt_http_routes_t;
-typedef struct nxt_http_client_ip_s nxt_http_client_ip_t;
+typedef struct nxt_http_forward_s nxt_http_forward_t;
typedef struct nxt_upstream_s nxt_upstream_t;
typedef struct nxt_upstreams_s nxt_upstreams_t;
typedef struct nxt_router_access_log_s nxt_router_access_log_t;
@@ -43,6 +43,7 @@ typedef struct {
uint32_t threads;
nxt_mp_t *mem_pool;
+ nxt_array_t *var_fields; /* of nxt_var_field_t */
nxt_router_t *router;
nxt_http_routes_t *routes;
@@ -52,6 +53,7 @@ typedef struct {
nxt_lvlhsh_t apps_hash;
nxt_router_access_log_t *access_log;
+ nxt_var_t *log_format;
} nxt_router_conf_t;
@@ -197,7 +199,8 @@ typedef struct {
uint8_t discard_unsafe_fields; /* 1 bit */
- nxt_http_client_ip_t *client_ip;
+ nxt_http_forward_t *forwarded;
+ nxt_http_forward_t *client_ip;
#if (NXT_TLS)
nxt_tls_conf_t *tls;
@@ -221,7 +224,8 @@ typedef struct {
struct nxt_router_access_log_s {
void (*handler)(nxt_task_t *task, nxt_http_request_t *r,
- nxt_router_access_log_t *access_log);
+ nxt_router_access_log_t *access_log,
+ nxt_var_t *format);
nxt_fd_t fd;
nxt_str_t path;
uint32_t count;
@@ -235,7 +239,23 @@ nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name,
nxt_str_t *target, nxt_http_action_t *action);
void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev,
nxt_socket_conf_joint_t *joint);
+
+void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
+void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf);
void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint);
+nxt_int_t nxt_router_access_log_create(nxt_task_t *task,
+ nxt_router_conf_t *rtcf, nxt_conf_value_t *value);
+void nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf);
+void nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log);
+void nxt_router_access_log_release(nxt_task_t *task,
+ nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log);
+void nxt_router_access_log_reopen_handler(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg);
+
+
+extern nxt_router_t *nxt_router;
+
#endif /* _NXT_ROUTER_H_INCLUDED_ */
diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c
new file mode 100644
index 00000000..dc2a6687
--- /dev/null
+++ b/src/nxt_router_access_log.c
@@ -0,0 +1,442 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Valentin V. Bartenev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_router.h>
+#include <nxt_conf.h>
+#include <nxt_http.h>
+
+
+typedef struct {
+ nxt_str_t path;
+ nxt_str_t format;
+} nxt_router_access_log_conf_t;
+
+
+typedef struct {
+ nxt_str_t text;
+ nxt_router_access_log_t *access_log;
+} nxt_router_access_log_ctx_t;
+
+
+static void nxt_router_access_log_writer(nxt_task_t *task,
+ nxt_http_request_t *r, nxt_router_access_log_t *access_log,
+ nxt_var_t *format);
+static void nxt_router_access_log_write_ready(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_write_error(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_ready(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_error(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_reopen_ready(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_reopen_error(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+
+
+static nxt_conf_map_t nxt_router_access_log_conf[] = {
+ {
+ nxt_string("path"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_router_access_log_conf_t, path),
+ },
+
+ {
+ nxt_string("format"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_router_access_log_conf_t, format),
+ },
+};
+
+
+nxt_int_t
+nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf,
+ nxt_conf_value_t *value)
+{
+ u_char *p;
+ nxt_int_t ret;
+ nxt_str_t str;
+ nxt_var_t *format;
+ nxt_router_t *router;
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_conf_t alcf;
+
+ static nxt_str_t log_format_str = nxt_string("$remote_addr - - "
+ "[$time_local] \"$request_line\" $status $body_bytes_sent "
+ "\"$header_referer\" \"$header_user_agent\"");
+
+ alcf.format = log_format_str;
+
+ if (nxt_conf_type(value) == NXT_CONF_STRING) {
+ nxt_conf_get_string(value, &alcf.path);
+
+ } else {
+ ret = nxt_conf_map_object(rtcf->mem_pool, value,
+ nxt_router_access_log_conf,
+ nxt_nitems(nxt_router_access_log_conf),
+ &alcf);
+ if (ret != NXT_OK) {
+ nxt_alert(task, "access log map error");
+ return NXT_ERROR;
+ }
+ }
+
+ router = nxt_router;
+
+ access_log = router->access_log;
+
+ if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) {
+ nxt_router_access_log_use(&router->lock, access_log);
+
+ } else {
+ access_log = nxt_malloc(sizeof(nxt_router_access_log_t)
+ + alcf.path.length);
+ if (access_log == NULL) {
+ nxt_alert(task, "failed to allocate access log structure");
+ return NXT_ERROR;
+ }
+
+ access_log->fd = -1;
+ access_log->handler = &nxt_router_access_log_writer;
+ access_log->count = 1;
+
+ access_log->path.length = alcf.path.length;
+ access_log->path.start = (u_char *) access_log
+ + sizeof(nxt_router_access_log_t);
+
+ nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length);
+ }
+
+ str.length = alcf.format.length + 1;
+
+ str.start = nxt_malloc(str.length);
+ if (str.start == NULL) {
+ nxt_alert(task, "failed to allocate log format structure");
+ return NXT_ERROR;
+ }
+
+ p = nxt_cpymem(str.start, alcf.format.start, alcf.format.length);
+ *p = '\n';
+
+ format = nxt_var_compile(&str, rtcf->mem_pool, rtcf->var_fields,
+ NXT_VAR_LOGGING);
+ if (nxt_slow_path(format == NULL)) {
+ return NXT_ERROR;
+ }
+
+ rtcf->access_log = access_log;
+ rtcf->log_format = format;
+
+ return NXT_OK;
+}
+
+
+static void
+nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r,
+ nxt_router_access_log_t *access_log, nxt_var_t *format)
+{
+ nxt_int_t ret;
+ nxt_router_access_log_ctx_t *ctx;
+
+ ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t));
+ if (nxt_slow_path(ctx == NULL)) {
+ return;
+ }
+
+ ctx->access_log = access_log;
+
+ if (nxt_var_is_const(format)) {
+ nxt_var_raw(format, &ctx->text);
+
+ nxt_router_access_log_write_ready(task, r, ctx);
+
+ } else {
+ ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return;
+ }
+
+ nxt_var_query(task, r->var_query, format, &ctx->text);
+ nxt_var_query_resolve(task, r->var_query, ctx,
+ nxt_router_access_log_write_ready,
+ nxt_router_access_log_write_error);
+ }
+}
+
+
+static void
+nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_http_request_t *r;
+ nxt_router_access_log_ctx_t *ctx;
+
+ r = obj;
+ ctx = data;
+
+ nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length);
+
+ nxt_http_request_close_handler(task, r, r->proto.any);
+}
+
+
+static void
+nxt_router_access_log_write_error(nxt_task_t *task, void *obj, void *data)
+{
+
+}
+
+
+void
+nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
+{
+ uint32_t stream;
+ nxt_int_t ret;
+ nxt_buf_t *b;
+ nxt_port_t *main_port, *router_port;
+ nxt_runtime_t *rt;
+ nxt_router_access_log_t *access_log;
+
+ access_log = tmcf->router_conf->access_log;
+
+ b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0);
+ if (nxt_slow_path(b == NULL)) {
+ goto fail;
+ }
+
+ b->completion_handler = nxt_buf_dummy_completion;
+
+ nxt_buf_cpystr(b, &access_log->path);
+ *b->mem.free++ = '\0';
+
+ rt = task->thread->runtime;
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ stream = nxt_port_rpc_register_handler(task, router_port,
+ nxt_router_access_log_ready,
+ nxt_router_access_log_error,
+ -1, tmcf);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
+ stream, router_port->id, b);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_port_rpc_cancel(task, router_port, stream);
+ goto fail;
+ }
+
+ return;
+
+fail:
+
+ nxt_router_conf_error(task, tmcf);
+}
+
+
+static void
+nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_temp_conf_t *tmcf;
+ nxt_router_access_log_t *access_log;
+
+ tmcf = data;
+
+ access_log = tmcf->router_conf->access_log;
+
+ access_log->fd = msg->fd[0];
+
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ nxt_router_conf_apply, task, tmcf, NULL);
+}
+
+
+static void
+nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_temp_conf_t *tmcf;
+
+ tmcf = data;
+
+ nxt_router_conf_error(task, tmcf);
+}
+
+
+void
+nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log)
+{
+ if (access_log == NULL) {
+ return;
+ }
+
+ nxt_thread_spin_lock(lock);
+
+ access_log->count++;
+
+ nxt_thread_spin_unlock(lock);
+}
+
+
+void
+nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log)
+{
+ if (access_log == NULL) {
+ return;
+ }
+
+ nxt_thread_spin_lock(lock);
+
+ if (--access_log->count != 0) {
+ access_log = NULL;
+ }
+
+ nxt_thread_spin_unlock(lock);
+
+ if (access_log != NULL) {
+
+ if (access_log->fd != -1) {
+ nxt_fd_close(access_log->fd);
+ }
+
+ nxt_free(access_log);
+ }
+}
+
+
+typedef struct {
+ nxt_mp_t *mem_pool;
+ nxt_router_access_log_t *access_log;
+} nxt_router_access_log_reopen_t;
+
+
+void
+nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ nxt_mp_t *mp;
+ uint32_t stream;
+ nxt_int_t ret;
+ nxt_buf_t *b;
+ nxt_port_t *main_port, *router_port;
+ nxt_runtime_t *rt;
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_reopen_t *reopen;
+
+ access_log = nxt_router->access_log;
+
+ if (access_log == NULL) {
+ return;
+ }
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (nxt_slow_path(mp == NULL)) {
+ return;
+ }
+
+ reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t));
+ if (nxt_slow_path(reopen == NULL)) {
+ goto fail;
+ }
+
+ reopen->mem_pool = mp;
+ reopen->access_log = access_log;
+
+ b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0);
+ if (nxt_slow_path(b == NULL)) {
+ goto fail;
+ }
+
+ b->completion_handler = nxt_router_access_log_reopen_completion;
+
+ nxt_buf_cpystr(b, &access_log->path);
+ *b->mem.free++ = '\0';
+
+ rt = task->thread->runtime;
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ stream = nxt_port_rpc_register_handler(task, router_port,
+ nxt_router_access_log_reopen_ready,
+ nxt_router_access_log_reopen_error,
+ -1, reopen);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
+ stream, router_port->id, b);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_port_rpc_cancel(task, router_port, stream);
+ goto fail;
+ }
+
+ nxt_mp_retain(mp);
+
+ return;
+
+fail:
+
+ nxt_mp_destroy(mp);
+}
+
+
+static void
+nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_mp_t *mp;
+ nxt_buf_t *b;
+
+ b = obj;
+ mp = b->data;
+
+ nxt_mp_release(mp);
+}
+
+
+static void
+nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_reopen_t *reopen;
+
+ reopen = data;
+
+ access_log = reopen->access_log;
+
+ if (access_log == nxt_router->access_log) {
+
+ if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) {
+ nxt_alert(task, "dup2(%FD, %FD) failed %E",
+ msg->fd[0], access_log->fd, nxt_errno);
+ }
+ }
+
+ nxt_fd_close(msg->fd[0]);
+ nxt_mp_release(reopen->mem_pool);
+}
+
+
+static void
+nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_access_log_reopen_t *reopen;
+
+ reopen = data;
+
+ nxt_mp_release(reopen->mem_pool);
+}
diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c
index 46955f1c..d9c9f2ef 100644
--- a/src/nxt_runtime.c
+++ b/src/nxt_runtime.c
@@ -1408,6 +1408,7 @@ nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process)
nxt_assert(process->use_count == 0);
nxt_assert(process->registered == 0);
+ nxt_assert(nxt_queue_is_empty(&process->ports));
nxt_port_mmaps_destroy(&process->incoming, 1);
@@ -1579,11 +1580,11 @@ nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process)
process->registered = 1;
- nxt_thread_log_debug("process %PI added", process->pid);
+ nxt_debug(task, "process %PI added", process->pid);
break;
default:
- nxt_thread_log_debug("process %PI failed to add", process->pid);
+ nxt_alert(task, "process %PI failed to add", process->pid);
break;
}
@@ -1597,6 +1598,8 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
nxt_pid_t pid;
nxt_lvlhsh_query_t lhq;
+ nxt_assert(process->registered != 0);
+
pid = process->pid;
nxt_runtime_process_lhq_pid(&lhq, &pid);
@@ -1608,9 +1611,9 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) {
case NXT_OK:
- rt->nprocesses--;
+ nxt_assert(lhq.value == process);
- process = lhq.value;
+ rt->nprocesses--;
process->registered = 0;
@@ -1618,7 +1621,7 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
break;
default:
- nxt_thread_log_debug("process %PI remove failed", pid);
+ nxt_thread_log_alert("process %PI remove failed", pid);
break;
}
diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c
index 730428e4..86c3335e 100644
--- a/src/nxt_sockaddr.c
+++ b/src/nxt_sockaddr.c
@@ -15,10 +15,6 @@ static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr);
static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr);
static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr);
-static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs);
-static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs);
-static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs);
-
nxt_sockaddr_t *
nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls)
@@ -208,8 +204,8 @@ nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s)
#if (NXT_HAVE_UNIX_DOMAIN)
case AF_UNIX:
length = nxt_length("unix:") + socklen;
-#endif
break;
+#endif
case AF_INET:
length = NXT_INET_ADDR_STR_LEN;
@@ -433,82 +429,6 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2)
}
-size_t
-nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, u_char *end, nxt_bool_t port)
-{
- u_char *p;
-
- switch (sa->u.sockaddr.sa_family) {
-
- case AF_INET:
- p = (u_char *) &sa->u.sockaddr_in.sin_addr;
-
- if (port) {
- p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud:%d",
- p[0], p[1], p[2], p[3],
- ntohs(sa->u.sockaddr_in.sin_port));
- } else {
- p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud",
- p[0], p[1], p[2], p[3]);
- }
-
- return p - buf;
-
-#if (NXT_INET6)
-
- case AF_INET6:
- p = buf;
-
- if (port) {
- *p++ = '[';
- }
-
- p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end);
-
- if (port) {
- p = nxt_sprintf(p, end, "]:%d",
- ntohs(sa->u.sockaddr_in6.sin6_port));
- }
-
- return p - buf;
-#endif
-
-#if (NXT_HAVE_UNIX_DOMAIN)
-
- case AF_UNIX:
-
-#if (NXT_LINUX)
-
- p = (u_char *) sa->u.sockaddr_un.sun_path;
-
- if (p[0] == '\0') {
- size_t length;
-
- /* Linux abstract socket address has no trailing zero. */
-
- length = sa->socklen - offsetof(struct sockaddr_un, sun_path) - 1;
- p = nxt_sprintf(buf, end, "unix:\\0%*s", length, p + 1);
-
- } else {
- p = nxt_sprintf(buf, end, "unix:%s", p);
- }
-
-#else /* !(NXT_LINUX) */
-
- p = nxt_sprintf(buf, end, "unix:%s", sa->u.sockaddr_un.sun_path);
-
-#endif
-
- return p - buf;
-
-#endif /* NXT_HAVE_UNIX_DOMAIN */
-
- default:
- return 0;
- }
-}
-
-
#if (NXT_INET6)
static u_char *
@@ -681,8 +601,6 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr)
socklen = offsetof(struct sockaddr_un, sun_path) + length + 1;
-#if (NXT_LINUX)
-
/*
* Linux unix(7):
*
@@ -695,9 +613,12 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr)
if (path[0] == '@') {
path[0] = '\0';
socklen--;
- }
-
+#if !(NXT_LINUX)
+ nxt_thread_log_error(NXT_LOG_ERR,
+ "abstract unix domain sockets are not supported");
+ return NULL;
#endif
+ }
sa = nxt_sockaddr_alloc(mp, socklen, addr->length);
@@ -849,338 +770,6 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr)
}
-void
-nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs)
-{
- u_char *p;
- size_t length;
- nxt_int_t ret;
- nxt_work_handler_t handler;
-
- nxt_job_set_name(&jbs->resolve.job, "job sockaddr parse");
-
- length = jbs->addr.length;
- p = jbs->addr.start;
-
- if (length > 6 && nxt_memcmp(p, "unix:", 5) == 0) {
- ret = nxt_job_sockaddr_unix_parse(jbs);
-
- } else if (length != 0 && *p == '[') {
- ret = nxt_job_sockaddr_inet6_parse(jbs);
-
- } else {
- ret = nxt_job_sockaddr_inet_parse(jbs);
- }
-
- switch (ret) {
-
- case NXT_OK:
- handler = jbs->resolve.ready_handler;
- break;
-
- case NXT_ERROR:
- handler = jbs->resolve.error_handler;
- break;
-
- default: /* NXT_AGAIN */
- return;
- }
-
- nxt_job_return(jbs->resolve.job.task, &jbs->resolve.job, handler);
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs)
-{
-#if (NXT_HAVE_UNIX_DOMAIN)
- size_t length, socklen;
- u_char *path;
- nxt_mp_t *mp;
- nxt_sockaddr_t *sa;
-
- /*
- * Actual sockaddr_un length can be lesser or even larger than defined
- * struct sockaddr_un length (see comment in nxt_socket.h). So
- * limit maximum Unix domain socket address length by defined sun_path[]
- * length because some OSes accept addresses twice larger than defined
- * struct sockaddr_un. Also reserve space for a trailing zero to avoid
- * ambiguity, since many OSes accept Unix domain socket addresses
- * without a trailing zero.
- */
- const size_t max_len = sizeof(struct sockaddr_un)
- - offsetof(struct sockaddr_un, sun_path) - 1;
-
- /* cutting "unix:" */
- length = jbs->addr.length - 5;
- path = jbs->addr.start + 5;
-
- if (length > max_len) {
- nxt_thread_log_error(jbs->resolve.log_level,
- "unix domain socket \"%V\" name is too long",
- &jbs->addr);
- return NXT_ERROR;
- }
-
- socklen = offsetof(struct sockaddr_un, sun_path) + length + 1;
-
-#if (NXT_LINUX)
-
- /*
- * Linux unix(7):
- *
- * abstract: an abstract socket address is distinguished by the fact
- * that sun_path[0] is a null byte ('\0'). The socket's address in
- * this namespace is given by the additional bytes in sun_path that
- * are covered by the specified length of the address structure.
- * (Null bytes in the name have no special significance.)
- */
- if (path[0] == '\0') {
- socklen--;
- }
-
-#endif
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
-
- if (nxt_fast_path(jbs->resolve.sockaddrs != NULL)) {
- sa = nxt_sockaddr_alloc(mp, socklen, jbs->addr.length);
-
- if (nxt_fast_path(sa != NULL)) {
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- sa->u.sockaddr_un.sun_family = AF_UNIX;
- nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length);
-
- return NXT_OK;
- }
- }
-
- return NXT_ERROR;
-
-#else /* !(NXT_HAVE_UNIX_DOMAIN) */
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "unix domain socket \"%V\" is not supported",
- &jbs->addr);
- return NXT_ERROR;
-
-#endif
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs)
-{
-#if (NXT_INET6)
- u_char *p, *addr, *addr_end;
- size_t length;
- nxt_mp_t *mp;
- nxt_int_t port;
- nxt_sockaddr_t *sa;
- struct in6_addr *in6_addr;
-
- length = jbs->addr.length - 1;
- addr = jbs->addr.start + 1;
-
- addr_end = nxt_memchr(addr, ']', length);
-
- if (addr_end == NULL) {
- goto invalid_address;
- }
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
-
- if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
- return NXT_ERROR;
- }
-
- sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6),
- NXT_INET6_ADDR_STR_LEN);
-
- if (nxt_slow_path(sa == NULL)) {
- return NXT_ERROR;
- }
-
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- in6_addr = &sa->u.sockaddr_in6.sin6_addr;
-
- if (nxt_inet6_addr(in6_addr, addr, addr_end - addr) != NXT_OK) {
- goto invalid_address;
- }
-
- p = addr_end + 1;
- length = (addr + length) - p;
-
- if (length == 0) {
- jbs->no_port = 1;
- port = jbs->resolve.port;
- goto found;
- }
-
- if (*p == ':') {
- port = nxt_int_parse(p + 1, length - 1);
-
- if (port >= 1 && port <= 65535) {
- port = htons((in_port_t) port);
- goto found;
- }
- }
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid port in \"%V\"", &jbs->addr);
-
- return NXT_ERROR;
-
-found:
-
- sa->u.sockaddr_in6.sin6_family = AF_INET6;
- sa->u.sockaddr_in6.sin6_port = (in_port_t) port;
-
- if (IN6_IS_ADDR_UNSPECIFIED(in6_addr)) {
- jbs->wildcard = 1;
- }
-
- return NXT_OK;
-
-invalid_address:
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid IPv6 address in \"%V\"", &jbs->addr);
- return NXT_ERROR;
-
-#else
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "IPv6 socket \"%V\" is not supported", &jbs->addr);
- return NXT_ERROR;
-
-#endif
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs)
-{
- u_char *p, *host;
- size_t length;
- nxt_mp_t *mp;
- nxt_int_t port;
- in_addr_t addr;
- nxt_sockaddr_t *sa;
-
- addr = INADDR_ANY;
-
- length = jbs->addr.length;
- host = jbs->addr.start;
-
- p = nxt_memchr(host, ':', length);
-
- if (p == NULL) {
-
- /* single value port, address, or host name */
-
- port = nxt_int_parse(host, length);
-
- if (port > 0) {
- if (port < 1 || port > 65535) {
- goto invalid_port;
- }
-
- /* "*:XX" */
- port = htons((in_port_t) port);
- jbs->resolve.port = (in_port_t) port;
-
- } else {
- jbs->no_port = 1;
-
- addr = nxt_inet_addr(host, length);
-
- if (addr == INADDR_NONE) {
- jbs->resolve.name.length = length;
- jbs->resolve.name.start = host;
-
- nxt_job_resolve(&jbs->resolve);
- return NXT_AGAIN;
- }
-
- /* "x.x.x.x" */
- port = jbs->resolve.port;
- }
-
- } else {
-
- /* x.x.x.x:XX or host:XX */
-
- p++;
- length = (host + length) - p;
- port = nxt_int_parse(p, length);
-
- if (port < 1 || port > 65535) {
- goto invalid_port;
- }
-
- port = htons((in_port_t) port);
-
- length = (p - 1) - host;
-
- if (length != 1 || host[0] != '*') {
- addr = nxt_inet_addr(host, length);
-
- if (addr == INADDR_NONE) {
- jbs->resolve.name.length = length;
- jbs->resolve.name.start = host;
- jbs->resolve.port = (in_port_t) port;
-
- nxt_job_resolve(&jbs->resolve);
- return NXT_AGAIN;
- }
-
- /* "x.x.x.x:XX" */
- }
- }
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
- if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
- return NXT_ERROR;
- }
-
- sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in),
- NXT_INET_ADDR_STR_LEN);
-
- if (nxt_fast_path(sa != NULL)) {
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- jbs->wildcard = (addr == INADDR_ANY);
-
- sa->u.sockaddr_in.sin_family = AF_INET;
- sa->u.sockaddr_in.sin_port = (in_port_t) port;
- sa->u.sockaddr_in.sin_addr.s_addr = addr;
-
- return NXT_OK;
- }
-
- return NXT_ERROR;
-
-invalid_port:
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid port in \"%V\"", &jbs->addr);
-
- return NXT_ERROR;
-}
-
-
in_addr_t
nxt_inet_addr(u_char *buf, size_t length)
{
diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h
index a8f1b393..0f96f6dd 100644
--- a/src/nxt_sockaddr.h
+++ b/src/nxt_sockaddr.h
@@ -58,15 +58,6 @@ struct nxt_sockaddr_s {
};
-typedef struct {
- nxt_job_resolve_t resolve;
- nxt_str_t addr;
-
- uint8_t wildcard; /* 1 bit */
- uint8_t no_port; /* 1 bit */
-} nxt_job_sockaddr_parse_t;
-
-
nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine,
nxt_listen_socket_t *ls);
void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c);
@@ -88,12 +79,9 @@ NXT_EXPORT void nxt_sockaddr_text(nxt_sockaddr_t *sa);
NXT_EXPORT uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa);
NXT_EXPORT nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1,
nxt_sockaddr_t *sa2);
-NXT_EXPORT size_t nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf,
- u_char *end, nxt_bool_t port);
NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr);
NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp,
nxt_str_t *addr);
-NXT_EXPORT void nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs);
NXT_EXPORT in_addr_t nxt_inet_addr(u_char *buf, size_t len);
#if (NXT_INET6)
NXT_EXPORT nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf,
diff --git a/src/nxt_status.c b/src/nxt_status.c
new file mode 100644
index 00000000..f8002e86
--- /dev/null
+++ b/src/nxt_status.c
@@ -0,0 +1,105 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_conf.h>
+#include <nxt_status.h>
+
+
+nxt_conf_value_t *
+nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp)
+{
+ size_t i;
+ nxt_str_t name;
+ nxt_int_t ret;
+ nxt_status_app_t *app;
+ nxt_conf_value_t *status, *obj, *apps, *app_obj;
+
+ static nxt_str_t conns_str = nxt_string("connections");
+ static nxt_str_t acc_str = nxt_string("accepted");
+ static nxt_str_t active_str = nxt_string("active");
+ static nxt_str_t idle_str = nxt_string("idle");
+ static nxt_str_t closed_str = nxt_string("closed");
+ static nxt_str_t reqs_str = nxt_string("requests");
+ static nxt_str_t total_str = nxt_string("total");
+ static nxt_str_t apps_str = nxt_string("applications");
+ static nxt_str_t procs_str = nxt_string("processes");
+ static nxt_str_t run_str = nxt_string("running");
+ static nxt_str_t start_str = nxt_string("starting");
+
+ status = nxt_conf_create_object(mp, 3);
+ if (nxt_slow_path(status == NULL)) {
+ return NULL;
+ }
+
+ obj = nxt_conf_create_object(mp, 4);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &conns_str, obj, 0);
+
+ nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0);
+ nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns
+ - report->closed_conns
+ - report->idle_conns, 1);
+ nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2);
+ nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3);
+
+ obj = nxt_conf_create_object(mp, 1);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &reqs_str, obj, 1);
+
+ nxt_conf_set_member_integer(obj, &total_str, report->requests, 0);
+
+ apps = nxt_conf_create_object(mp, report->apps_count);
+ if (nxt_slow_path(apps == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &apps_str, apps, 2);
+
+ for (i = 0; i < report->apps_count; i++) {
+ app = &report->apps[i];
+
+ app_obj = nxt_conf_create_object(mp, 2);
+ if (nxt_slow_path(app_obj == NULL)) {
+ return NULL;
+ }
+
+ name.length = app->name.length;
+ name.start = nxt_pointer_to(report, (uintptr_t) app->name.start);
+
+ ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ obj = nxt_conf_create_object(mp, 3);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(app_obj, &procs_str, obj, 0);
+
+ nxt_conf_set_member_integer(obj, &run_str, app->processes, 0);
+ nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1);
+ nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2);
+
+ obj = nxt_conf_create_object(mp, 1);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(app_obj, &reqs_str, obj, 1);
+
+ nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0);
+ }
+
+ return status;
+}
diff --git a/src/nxt_status.h b/src/nxt_status.h
new file mode 100644
index 00000000..a99ac7d0
--- /dev/null
+++ b/src/nxt_status.h
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_STATUS_H_INCLUDED_
+#define _NXT_STATUS_H_INCLUDED_
+
+
+typedef struct {
+ nxt_str_t name;
+ uint32_t active_requests;
+ uint32_t pending_processes;
+ uint32_t processes;
+ uint32_t idle_processes;
+} nxt_status_app_t;
+
+
+typedef struct {
+ uint64_t accepted_conns;
+ uint64_t idle_conns;
+ uint64_t closed_conns;
+ uint64_t requests;
+
+ size_t apps_count;
+ nxt_status_app_t apps[];
+} nxt_status_report_t;
+
+
+nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp);
+
+
+#endif /* _NXT_STATUS_H_INCLUDED_ */
diff --git a/src/nxt_string.c b/src/nxt_string.c
index b7aef79e..4d89c23c 100644
--- a/src/nxt_string.c
+++ b/src/nxt_string.c
@@ -338,7 +338,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
size_t
-nxt_str_strip(u_char *start, u_char *end)
+nxt_str_strip(const u_char *start, u_char *end)
{
u_char *p;
diff --git a/src/nxt_string.h b/src/nxt_string.h
index 80cdbb59..a8673c61 100644
--- a/src/nxt_string.h
+++ b/src/nxt_string.h
@@ -96,7 +96,7 @@ NXT_EXPORT u_char *nxt_memcasestrn(const u_char *s, const u_char *end,
const char *ss, size_t length);
NXT_EXPORT u_char *nxt_rmemstrn(const u_char *s, const u_char *end,
const char *ss, size_t length);
-NXT_EXPORT size_t nxt_str_strip(u_char *start, u_char *end);
+NXT_EXPORT size_t nxt_str_strip(const u_char *start, u_char *end);
typedef struct {
diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c
index 94c43289..63620b09 100644
--- a/src/nxt_time_parse.c
+++ b/src/nxt_time_parse.c
@@ -22,7 +22,7 @@ nxt_time_parse(const u_char *p, size_t len)
nxt_uint_t year, days;
const u_char *end;
- static nxt_int_t mday[12] = {
+ static const nxt_int_t mday[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
diff --git a/src/nxt_unit.c b/src/nxt_unit.c
index 32bb07ab..e5cb0b58 100644
--- a/src/nxt_unit.c
+++ b/src/nxt_unit.c
@@ -196,7 +196,8 @@ static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx,
static nxt_unit_request_info_t *nxt_unit_request_hash_find(
nxt_unit_ctx_t *ctx, uint32_t stream, int remove);
-static char * nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level);
+static char * nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid,
+ int level);
static void *nxt_unit_lvlhsh_alloc(void *data, size_t size);
static void nxt_unit_lvlhsh_free(void *data, void *p);
static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length);
@@ -584,9 +585,14 @@ fail:
static nxt_unit_impl_t *
nxt_unit_create(nxt_unit_init_t *init)
{
- int rc;
- nxt_unit_impl_t *lib;
- nxt_unit_callbacks_t *cb;
+ int rc;
+ nxt_unit_impl_t *lib;
+
+ if (nxt_slow_path(init->callbacks.request_handler == NULL)) {
+ nxt_unit_alert(NULL, "request_handler is NULL");
+
+ return NULL;
+ }
lib = nxt_unit_malloc(NULL,
sizeof(nxt_unit_impl_t) + init->request_data_size);
@@ -629,15 +635,6 @@ nxt_unit_create(nxt_unit_init_t *init)
goto fail;
}
- cb = &lib->callbacks;
-
- if (cb->request_handler == NULL) {
- nxt_unit_alert(NULL, "request_handler is NULL");
-
- pthread_mutex_destroy(&lib->mutex);
- goto fail;
- }
-
nxt_unit_mmaps_init(&lib->incoming);
nxt_unit_mmaps_init(&lib->outgoing);
@@ -942,7 +939,6 @@ nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, int queue_fd)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
nxt_socket_msg_oob_init(&oob, fds);
@@ -2644,7 +2640,6 @@ nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req,
m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0;
m.msg.nf = 0;
m.msg.mf = 0;
- m.msg.tracking = 0;
rc = NXT_UNIT_ERROR;
@@ -3077,7 +3072,6 @@ nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, size_t size)
}
req->content_length -= res;
- size -= res;
dst = nxt_pointer_to(dst, res);
@@ -3296,7 +3290,6 @@ skip_response_send:
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
(void) nxt_unit_port_send(req->ctx, req->response_port,
&msg, sizeof(msg), NULL);
@@ -3619,7 +3612,6 @@ nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL);
if (nxt_slow_path(res != sizeof(msg))) {
@@ -3816,13 +3808,12 @@ static int
nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size)
{
int fd;
- nxt_unit_impl_t *lib;
-
- lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit);
#if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN)
char name[64];
+ nxt_unit_impl_t *lib;
+ lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit);
snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p",
lib->pid, (void *) (uintptr_t) pthread_self());
#endif
@@ -3905,7 +3896,6 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int fd)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
nxt_socket_msg_oob_init(&oob, fds);
@@ -4390,7 +4380,6 @@ nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL);
if (nxt_slow_path(res != sizeof(msg))) {
@@ -5356,7 +5345,6 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst,
m.msg.mmap = 0;
m.msg.nf = 0;
m.msg.mf = 0;
- m.msg.tracking = 0;
m.new_port.id = port->id.id;
m.new_port.pid = port->id.pid;
@@ -6673,7 +6661,7 @@ static const char * nxt_unit_log_levels[] = {
static char *
-nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level)
+nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level)
{
struct tm tm;
struct timespec ts;
diff --git a/src/nxt_unix.h b/src/nxt_unix.h
index d8eaabc3..6bc6be5e 100644
--- a/src/nxt_unix.h
+++ b/src/nxt_unix.h
@@ -156,9 +156,7 @@
#include <setjmp.h>
#include <sched.h>
#include <signal.h>
-#if (NXT_HAVE_POSIX_SPAWN)
#include <spawn.h>
-#endif
#include <stdarg.h>
#include <stddef.h> /* offsetof() */
#include <stdio.h>
diff --git a/src/nxt_var.c b/src/nxt_var.c
index 0a722d17..f55a2d30 100644
--- a/src/nxt_var.c
+++ b/src/nxt_var.c
@@ -9,7 +9,7 @@
struct nxt_var_s {
size_t length;
nxt_uint_t vars;
- uint8_t strz; /* 1 bit */
+ nxt_var_flags_t flags;
u_char data[];
/*
@@ -26,19 +26,12 @@ typedef struct {
} nxt_var_sub_t;
-typedef struct {
- nxt_var_t *var;
- nxt_str_t *value;
-} nxt_var_value_t;
-
-
struct nxt_var_query_s {
- nxt_array_t values; /* of nxt_var_value_t */
- nxt_array_t parts; /* of nxt_str_t * */
+ nxt_mp_t *pool;
nxt_lvlhsh_t cache;
-
nxt_str_t *spare;
+
nxt_uint_t waiting;
nxt_uint_t failed; /* 1 bit */
@@ -59,16 +52,18 @@ struct nxt_var_query_s {
static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name);
+static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields,
+ uint32_t *index);
+static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name,
+ uint32_t hash);
+
static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data);
-static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index);
-static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index,
- nxt_str_t *value, nxt_mp_t *mp);
+static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query,
+ uint32_t index);
static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
nxt_bool_t *is_var);
-static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query);
-
static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = {
NXT_LVLHSH_DEFAULT,
@@ -91,21 +86,6 @@ static uint32_t nxt_var_count;
static nxt_var_handler_t *nxt_var_index;
-void
-nxt_var_raw(nxt_var_t *var, nxt_str_t *str)
-{
- str->length = var->length;
- str->start = nxt_var_raw_start(var);
-}
-
-
-nxt_bool_t
-nxt_var_is_const(nxt_var_t *var)
-{
- return (var->vars == 0);
-}
-
-
static nxt_int_t
nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
{
@@ -134,46 +114,166 @@ nxt_var_hash_find(nxt_str_t *name)
}
-static nxt_int_t
-nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
+static nxt_var_decl_t *
+nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index)
{
- return NXT_OK;
+ u_char *p, *end;
+ int64_t hash;
+ uint16_t field;
+ nxt_str_t str;
+ nxt_var_decl_t *decl;
+ nxt_var_field_t *f;
+
+ f = NULL;
+ field = 0;
+ decl = nxt_var_hash_find(name);
+
+ if (decl == NULL) {
+ p = name->start;
+ end = p + name->length;
+
+ while (p < end) {
+ if (*p++ == '_') {
+ break;
+ }
+ }
+
+ if (p == end) {
+ return NULL;
+ }
+
+ str.start = name->start;
+ str.length = p - 1 - name->start;
+
+ decl = nxt_var_hash_find(&str);
+
+ if (decl != NULL) {
+ str.start = p;
+ str.length = end - p;
+
+ hash = decl->field_hash(fields->mem_pool, &str);
+ if (nxt_slow_path(hash == -1)) {
+ return NULL;
+ }
+
+ f = nxt_var_field_add(fields, &str, (uint32_t) hash);
+ if (nxt_slow_path(f == NULL)) {
+ return NULL;
+ }
+
+ field = f->index;
+ }
+ }
+
+ if (decl != NULL) {
+ if (decl->field_hash != NULL && f == NULL) {
+ return NULL;
+ }
+
+ if (index != NULL) {
+ *index = (decl->index << 16) | field;
+ }
+ }
+
+ return decl;
}
-static nxt_str_t *
-nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index)
+static nxt_var_field_t *
+nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash)
{
- nxt_lvlhsh_query_t lhq;
+ nxt_uint_t i;
+ nxt_var_field_t *field;
- lhq.key_hash = nxt_murmur_hash2_uint32(&index);
- lhq.key.length = sizeof(uint32_t);
- lhq.key.start = (u_char *) &index;
- lhq.proto = &nxt_var_cache_proto;
+ field = fields->elts;
- if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) {
+ for (i = 0; i < fields->nelts; i++) {
+ if (field[i].hash == hash
+ && nxt_strstr_eq(&field[i].name, name))
+ {
+ return field;
+ }
+ }
+
+ field = nxt_array_add(fields);
+ if (nxt_slow_path(field == NULL)) {
return NULL;
}
- return lhq.value;
+ field->name = *name;
+ field->hash = hash;
+ field->index = fields->nelts - 1;
+
+ return field;
+}
+
+
+nxt_var_field_t *
+nxt_var_field_get(nxt_array_t *fields, uint16_t index)
+{
+ nxt_uint_t nfields;
+ nxt_var_field_t *field;
+
+ field = fields->elts;
+ nfields = fields->nelts;
+
+ if (nfields > 0 && index <= nfields) {
+ return &field[index];
+ }
+
+ return NULL;
}
static nxt_int_t
-nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value,
- nxt_mp_t *mp)
+nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
{
+ return NXT_OK;
+}
+
+
+static nxt_str_t *
+nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index)
+{
+ nxt_int_t ret;
+ nxt_str_t *value;
nxt_lvlhsh_query_t lhq;
+ value = query->spare;
+
+ if (value == NULL) {
+ value = nxt_mp_zget(query->pool, sizeof(nxt_str_t));
+ if (nxt_slow_path(value == NULL)) {
+ return NULL;
+ }
+
+ query->spare = value;
+ }
+
lhq.key_hash = nxt_murmur_hash2_uint32(&index);
lhq.replace = 0;
lhq.key.length = sizeof(uint32_t);
lhq.key.start = (u_char *) &index;
lhq.value = value;
lhq.proto = &nxt_var_cache_proto;
- lhq.pool = mp;
+ lhq.pool = query->pool;
- return nxt_lvlhsh_insert(lh, &lhq);
+ ret = nxt_lvlhsh_insert(&query->cache, &lhq);
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ return NULL;
+ }
+
+ if (ret == NXT_OK) {
+ ret = nxt_var_index[index >> 16](task, value, query->ctx,
+ index & 0xffff);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ query->spare = NULL;
+ }
+
+ return lhq.value;
}
@@ -230,10 +330,13 @@ nxt_var_index_init(void)
nxt_var_t *
-nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
+nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields,
+ nxt_var_flags_t flags)
{
u_char *p, *end, *next, *src;
size_t size;
+ uint32_t index;
+ nxt_bool_t strz;
nxt_var_t *var;
nxt_str_t part;
nxt_uint_t n;
@@ -241,6 +344,8 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
nxt_var_sub_t *subs;
nxt_var_decl_t *decl;
+ strz = (flags & NXT_VAR_STRZ) != 0;
+
n = 0;
p = str->start;
@@ -266,7 +371,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
var->length = str->length;
var->vars = n;
- var->strz = strz;
+ var->flags = flags;
subs = nxt_var_subs(var);
src = nxt_var_raw_start(var);
@@ -284,12 +389,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
next = nxt_var_next_part(p, end - p, &part, &is_var);
if (is_var) {
- decl = nxt_var_hash_find(&part);
+ decl = nxt_var_decl_get(&part, fields, &index);
if (nxt_slow_path(decl == NULL)) {
return NULL;
}
- subs[n].index = decl->index;
+ subs[n].index = index;
subs[n].length = next - p;
subs[n].position = p - str->start;
@@ -304,7 +409,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
nxt_int_t
-nxt_var_test(nxt_str_t *str, u_char *error)
+nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error)
{
u_char *p, *end, *next;
nxt_str_t part;
@@ -325,7 +430,7 @@ nxt_var_test(nxt_str_t *str, u_char *error)
}
if (is_var) {
- decl = nxt_var_hash_find(&part);
+ decl = nxt_var_decl_get(&part, fields, NULL);
if (decl == NULL) {
nxt_sprintf(error, error + NXT_MAX_ERROR_STR,
@@ -420,6 +525,21 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
}
+inline void
+nxt_var_raw(nxt_var_t *var, nxt_str_t *str)
+{
+ str->length = var->length;
+ str->start = nxt_var_raw_start(var);
+}
+
+
+inline nxt_bool_t
+nxt_var_is_const(nxt_var_t *var)
+{
+ return (var->vars == 0);
+}
+
+
nxt_int_t
nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp)
{
@@ -432,14 +552,9 @@ nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp)
if (nxt_slow_path(query == NULL)) {
return NXT_ERROR;
}
-
- nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t));
- nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *));
-
- } else {
- nxt_array_reset(&query->values);
}
+ query->pool = mp;
query->ctx = ctx;
*query_p = query;
@@ -452,13 +567,13 @@ void
nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
nxt_str_t *str)
{
- uint32_t index;
- nxt_mp_t *mp;
- nxt_str_t *value;
- nxt_int_t ret;
- nxt_uint_t i;
- nxt_var_sub_t *subs;
- nxt_var_value_t *val;
+ u_char *p, *src;
+ size_t length, last, next;
+ nxt_str_t *value, **part;
+ nxt_uint_t i;
+ nxt_bool_t strz, logging;
+ nxt_array_t parts;
+ nxt_var_sub_t *subs;
if (nxt_var_is_const(var)) {
nxt_var_raw(var, str);
@@ -469,53 +584,74 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
return;
}
- mp = query->values.mem_pool;
+ nxt_memzero(&parts, sizeof(nxt_array_t));
+ nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *));
+
+ strz = (var->flags & NXT_VAR_STRZ) != 0;
+ logging = (var->flags & NXT_VAR_LOGGING) != 0;
+
subs = nxt_var_subs(var);
- value = query->spare;
- for (i = 0; i < var->vars; i++) {
+ length = var->length;
- if (value == NULL) {
- value = nxt_mp_zget(mp, sizeof(nxt_str_t));
- if (nxt_slow_path(value == NULL)) {
- goto fail;
- }
+ for (i = 0; i < var->vars; i++) {
+ value = nxt_var_cache_value(task, query, subs[i].index);
+ if (nxt_slow_path(value == NULL)) {
+ goto fail;
}
- index = subs[i].index;
+ part = nxt_array_add(&parts);
+ if (nxt_slow_path(part == NULL)) {
+ goto fail;
+ }
- ret = nxt_var_cache_add(&query->cache, index, value, mp);
+ *part = value;
- if (ret != NXT_OK) {
- if (nxt_slow_path(ret == NXT_ERROR)) {
- goto fail;
- }
+ length += value->length - subs[i].length;
- continue; /* NXT_DECLINED */
+ if (logging && value->start == NULL) {
+ length += 1;
}
+ }
- ret = nxt_var_index[index](task, query, value, query->ctx);
+ p = nxt_mp_nget(query->pool, length + strz);
+ if (nxt_slow_path(p == NULL)) {
+ goto fail;
+ }
- value = NULL;
+ str->length = length;
+ str->start = p;
- if (ret != NXT_OK) {
- if (nxt_slow_path(ret != NXT_AGAIN)) {
- goto fail;
- }
+ part = parts.elts;
+ src = nxt_var_raw_start(var);
+
+ last = 0;
- query->waiting++;
+ for (i = 0; i < var->vars; i++) {
+ next = subs[i].position;
+
+ if (next != last) {
+ p = nxt_cpymem(p, &src[last], next - last);
}
+
+ p = nxt_cpymem(p, part[i]->start, part[i]->length);
+
+ if (logging && part[i]->start == NULL) {
+ *p++ = '-';
+ }
+
+ last = next + subs[i].length;
}
- query->spare = value;
+ if (last != var->length) {
+ p = nxt_cpymem(p, &src[last], var->length - last);
+ }
- val = nxt_array_add(&query->values);
- if (nxt_slow_path(val == NULL)) {
- goto fail;
+ if (strz) {
+ *p = '\0';
}
- val->var = var;
- val->value = str;
+ nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str);
return;
@@ -534,7 +670,9 @@ nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data,
query->error = error;
if (query->waiting == 0) {
- nxt_var_query_finish(task, query);
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ query->failed ? query->error : query->ready,
+ task, query->ctx, query->data);
}
}
@@ -546,94 +684,8 @@ nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query,
query->failed |= failed;
if (--query->waiting == 0) {
- nxt_var_query_finish(task, query);
- }
-}
-
-
-static void
-nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query)
-{
- u_char *p, *src;
- size_t length, last, next;
- nxt_str_t *str, **part;
- nxt_var_t *var;
- nxt_uint_t i, j;
- nxt_var_sub_t *subs;
- nxt_var_value_t *val;
-
- if (query->failed) {
- goto done;
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ query->failed ? query->error : query->ready,
+ task, query->ctx, query->data);
}
-
- val = query->values.elts;
-
- for (i = 0; i < query->values.nelts; i++) {
- var = val[i].var;
-
- subs = nxt_var_subs(var);
- length = var->length;
-
- for (j = 0; j < var->vars; j++) {
- str = nxt_var_cache_find(&query->cache, subs[j].index);
-
- nxt_assert(str != NULL);
-
- part = nxt_array_add(&query->parts);
-
- if (nxt_slow_path(part == NULL)) {
- query->failed = 1;
- goto done;
- }
-
- *part = str;
-
- length += str->length - subs[j].length;
- }
-
- p = nxt_mp_nget(query->values.mem_pool, length + var->strz);
- if (nxt_slow_path(p == NULL)) {
- query->failed = 1;
- goto done;
- }
-
- val[i].value->length = length;
- val[i].value->start = p;
-
- part = query->parts.elts;
- src = nxt_var_raw_start(var);
-
- last = 0;
-
- for (j = 0; j < var->vars; j++) {
- next = subs[j].position;
-
- if (next != last) {
- p = nxt_cpymem(p, &src[last], next - last);
- }
-
- p = nxt_cpymem(p, part[j]->start, part[j]->length);
-
- last = next + subs[j].length;
- }
-
- if (last != var->length) {
- p = nxt_cpymem(p, &src[last], var->length - last);
- }
-
- if (var->strz) {
- *p = '\0';
- }
-
- nxt_array_reset(&query->parts);
-
- nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src,
- val[i].value);
- }
-
-done:
-
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- query->failed ? query->error : query->ready,
- task, query->ctx, query->data);
}
diff --git a/src/nxt_var.h b/src/nxt_var.h
index 3b7d0c28..cc7ff502 100644
--- a/src/nxt_var.h
+++ b/src/nxt_var.h
@@ -12,17 +12,32 @@ typedef struct nxt_var_query_s nxt_var_query_t;
typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task,
- nxt_var_query_t *query,
nxt_str_t *str,
- void *ctx);
+ void *ctx, uint16_t field);
+
+typedef int64_t (*nxt_var_field_hash_t)(nxt_mp_t *mp, nxt_str_t *str);
typedef struct {
- nxt_str_t name;
- nxt_var_handler_t handler;
- uint32_t index;
+ nxt_str_t name;
+ nxt_var_handler_t handler;
+ nxt_var_field_hash_t field_hash;
+ uint32_t index;
} nxt_var_decl_t;
+typedef struct {
+ nxt_str_t name;
+ uint16_t hash;
+ uint32_t index;
+} nxt_var_field_t;
+
+
+typedef enum {
+ NXT_VAR_STRZ = 1 << 0,
+ NXT_VAR_LOGGING = 1 << 1,
+} nxt_var_flags_t;
+
+
nxt_inline nxt_bool_t
nxt_is_var(nxt_str_t *str)
{
@@ -30,13 +45,17 @@ nxt_is_var(nxt_str_t *str)
}
-void nxt_var_raw(nxt_var_t *var, nxt_str_t *str);
-nxt_bool_t nxt_var_is_const(nxt_var_t *var);
-
nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n);
nxt_int_t nxt_var_index_init(void);
-nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz);
-nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error);
+
+nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index);
+
+nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields,
+ nxt_var_flags_t flags);
+nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error);
+
+nxt_bool_t nxt_var_is_const(nxt_var_t *var);
+void nxt_var_raw(nxt_var_t *var, nxt_str_t *str);
nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx,
nxt_mp_t *mp);
diff --git a/src/nxt_websocket_accept.c b/src/nxt_websocket_accept.c
index 05cbcb56..0e2cef58 100644
--- a/src/nxt_websocket_accept.c
+++ b/src/nxt_websocket_accept.c
@@ -11,8 +11,8 @@
static void
nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len)
{
- u_char c0, c1, c2;
- static u_char basis[] =
+ u_char c0, c1, c2;
+ static const u_char basis[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (len > 2) {
diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c
index 91af8f4b..4ad0857d 100644
--- a/src/python/nxt_python_asgi.c
+++ b/src/python/nxt_python_asgi.c
@@ -30,6 +30,8 @@ static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req);
static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req);
static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len,
uint16_t port);
+static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr,
+ uint8_t len, uint16_t port);
static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f);
static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f);
@@ -736,6 +738,48 @@ fail:
static PyObject *
nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
{
+ size_t prefix_len;
+ nxt_str_t addr;
+ PyObject *pair, *v;
+
+ addr.length = len;
+ addr.start = nxt_unit_sptr_get(sptr);
+
+ prefix_len = nxt_length("unix:");
+ if (!nxt_str_start(&addr, "unix:", prefix_len)) {
+ return nxt_py_asgi_create_ip_address(sptr, len, port);
+ }
+
+#if NXT_HAVE_UNIX_DOMAIN
+ pair = PyTuple_New(2);
+ if (nxt_slow_path(pair == NULL)) {
+ return NULL;
+ }
+
+ addr.start += prefix_len;
+ addr.length -= prefix_len;
+
+ v = PyString_FromStringAndSize((const char *) addr.start, addr.length);
+ if (nxt_slow_path(v == NULL)) {
+ Py_DECREF(pair);
+
+ return NULL;
+ }
+
+ PyTuple_SET_ITEM(pair, 0, v);
+ PyTuple_SET_ITEM(pair, 1, Py_None);
+
+ return pair;
+
+#else
+ return NULL;
+#endif
+}
+
+
+static PyObject *
+nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
+{
char *p, *s;
PyObject *pair, *v;
diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c
index 8f4afd35..f316d8a5 100644
--- a/src/ruby/nxt_ruby.c
+++ b/src/ruby/nxt_ruby.c
@@ -29,7 +29,6 @@ typedef struct {
static nxt_int_t nxt_ruby_start(nxt_task_t *task,
nxt_process_data_t *data);
static VALUE nxt_ruby_init_basic(VALUE arg);
-static VALUE nxt_ruby_script_basename(nxt_str_t *script);
static VALUE nxt_ruby_hook_procs_load(VALUE path);
static VALUE nxt_ruby_hook_register(VALUE arg);
@@ -50,7 +49,7 @@ static void *nxt_ruby_thread_create_gvl(void *rctx);
static VALUE nxt_ruby_thread_func(VALUE arg);
static void *nxt_ruby_unit_run(void *ctx);
static void nxt_ruby_ubf(void *ctx);
-static int nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c);
+static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c);
static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx,
nxt_ruby_app_conf_t *c);
@@ -261,7 +260,7 @@ static nxt_int_t
nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
{
int state, rc;
- VALUE res, path, script;
+ VALUE res, path;
nxt_ruby_ctx_t ruby_ctx;
nxt_unit_ctx_t *unit_ctx;
nxt_unit_init_t ruby_unit_init;
@@ -271,6 +270,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" };
+ signal(SIGINT, SIG_IGN);
+
conf = data->app;
c = &conf->u.ruby;
@@ -283,10 +284,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
ruby_options(2, argv);
ruby_script("NGINX_Unit");
- script = nxt_ruby_script_basename(&c->script);
-
ruby_ctx.env = Qnil;
- ruby_ctx.script = script;
ruby_ctx.io_input = Qnil;
ruby_ctx.io_error = Qnil;
ruby_ctx.thread = Qnil;
@@ -356,7 +354,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
goto fail;
}
- rc = nxt_ruby_init_threads(script, c);
+ rc = nxt_ruby_init_threads(c);
if (nxt_slow_path(rc == NXT_UNIT_ERROR)) {
goto fail;
}
@@ -381,8 +379,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
}
}
- rc = (intptr_t) rb_thread_call_without_gvl(nxt_ruby_unit_run, unit_ctx,
- nxt_ruby_ubf, unit_ctx);
+ rc = (intptr_t) rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx,
+ nxt_ruby_ubf, unit_ctx);
if (nxt_ruby_hook_procs != Qnil) {
rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state);
@@ -425,37 +423,6 @@ fail:
static VALUE
-nxt_ruby_script_basename(nxt_str_t *script)
-{
- size_t len;
- u_char *p, *last;
-
- last = NULL;
- p = script->start + script->length;
-
- while (p > script->start) {
-
- if (p[-1] == '/') {
- last = p;
- break;
- }
-
- p--;
- }
-
- if (last != NULL) {
- len = script->length - (last - script->start);
-
- } else {
- last = script->start;
- len = script->length;
- }
-
- return rb_str_new((const char *) last, len);
-}
-
-
-static VALUE
nxt_ruby_init_basic(VALUE arg)
{
int state;
@@ -598,7 +565,7 @@ nxt_ruby_rack_env_create(VALUE arg)
rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR));
rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR));
- rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rctx->script);
+ rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0));
rb_hash_aset(hash_env, rb_str_new2("rack.version"), version);
rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input);
rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error);
@@ -1393,7 +1360,7 @@ nxt_ruby_ubf(void *ctx)
static int
-nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c)
+nxt_ruby_init_threads(nxt_ruby_app_conf_t *c)
{
int state;
uint32_t i;
@@ -1415,7 +1382,6 @@ nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c)
rctx = &nxt_ruby_ctxs[i];
rctx->env = Qnil;
- rctx->script = script;
rctx->io_input = Qnil;
rctx->io_error = Qnil;
rctx->thread = Qnil;
diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h
index 3bdd567a..26430021 100644
--- a/src/ruby/nxt_ruby.h
+++ b/src/ruby/nxt_ruby.h
@@ -22,7 +22,6 @@
typedef struct {
VALUE env;
- VALUE script;
VALUE io_input;
VALUE io_error;
VALUE thread;