diff options
author | Konstantin Pavlov <thresh@nginx.com> | 2022-12-15 08:17:39 -0800 |
---|---|---|
committer | Konstantin Pavlov <thresh@nginx.com> | 2022-12-15 08:17:39 -0800 |
commit | e22669f2728814aba82da14702d18bfa9685311e (patch) | |
tree | c9c9471dab359e8e33fca24c5d4f035ab5b278db /src | |
parent | a1d28488f9df8e28ee25ea438c275b96b9afe5b6 (diff) | |
parent | 4409a10ff0bd6bb45fb88716bd383cd867958a8a (diff) | |
download | unit-e22669f2728814aba82da14702d18bfa9685311e.tar.gz unit-e22669f2728814aba82da14702d18bfa9685311e.tar.bz2 |
Merged with the default branch.
Diffstat (limited to 'src')
69 files changed, 2457 insertions, 777 deletions
diff --git a/src/java/nxt_jni_Request.c b/src/java/nxt_jni_Request.c index 2e9dce67..980a26b6 100644 --- a/src/java/nxt_jni_Request.c +++ b/src/java/nxt_jni_Request.c @@ -461,8 +461,8 @@ nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - return nxt_java_newString(env, nxt_unit_sptr_get(&r->local), - r->local_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&r->local_addr), + r->local_addr_length); } @@ -474,11 +474,11 @@ nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - local = nxt_unit_sptr_get(&r->local); - colon = memchr(local, ':', r->local_length); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); if (colon == NULL) { - colon = local + r->local_length; + colon = local + r->local_addr_length; } return nxt_java_newString(env, local, colon - local); @@ -494,20 +494,20 @@ nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - local = nxt_unit_sptr_get(&r->local); - colon = memchr(local, ':', r->local_length); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); if (colon == NULL) { return 80; } - tmp = local[r->local_length]; + tmp = local[r->local_addr_length]; - local[r->local_length] = '\0'; + local[r->local_addr_length] = '\0'; res = strtol(colon + 1, NULL, 10); - local[r->local_length] = tmp; + local[r->local_addr_length] = tmp; return res; } diff --git a/src/nodejs/unit-http/loader.mjs b/src/nodejs/unit-http/loader.mjs index 546548f5..83985b0f 100644 --- a/src/nodejs/unit-http/loader.mjs +++ b/src/nodejs/unit-http/loader.mjs @@ -4,13 +4,15 @@ export async function resolve(specifier, context, defaultResolver) { case "websocket": return { url: new URL("./websocket.js", import.meta.url).href, - format: "commonjs" + format: "commonjs", + shortCircuit: true, } case "http": return { url: new URL("./http.js", import.meta.url).href, - format: "commonjs" + format: "commonjs", + shortCircuit: true, } } diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index ee5dc46f..7912d0ac 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -657,7 +657,8 @@ Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) req_data->sock_ref = wrap(res, req, sock_destroy); set_named_property(res, "remoteAddress", r->remote, r->remote_length); - set_named_property(res, "localAddress", r->local, r->local_length); + set_named_property(res, "localAddress", r->local_addr, + r->local_addr_length); return res; } diff --git a/src/nxt_application.c b/src/nxt_application.c index 556f1ffb..786c768b 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -366,7 +366,7 @@ nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, &app->type, app->version, name); if (app->compat_length != sizeof(compat) - || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) + || memcmp(app->compat, compat, sizeof(compat)) != 0) { nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); diff --git a/src/nxt_application.h b/src/nxt_application.h index 30a1a12f..4d624448 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -49,8 +49,6 @@ typedef struct { typedef struct { char *home; nxt_conf_value_t *path; - nxt_str_t module; - char *callable; nxt_str_t protocol; uint32_t threads; uint32_t thread_stack_size; diff --git a/src/nxt_capability.c b/src/nxt_capability.c index 24fd55d0..9f36ab99 100644 --- a/src/nxt_capability.c +++ b/src/nxt_capability.c @@ -50,7 +50,7 @@ nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap) #if (NXT_HAVE_LINUX_CAPABILITY) static uint32_t -nxt_capability_linux_get_version() +nxt_capability_linux_get_version(void) { struct __user_cap_header_struct hdr; diff --git a/src/nxt_cgroup.c b/src/nxt_cgroup.c new file mode 100644 index 00000000..2c404acc --- /dev/null +++ b/src/nxt_cgroup.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#include <nxt_main.h> + +#include <nxt_cgroup.h> + + +static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, + char *cgpath); +static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, + char *cgpath); + + +nxt_int_t +nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process) +{ + int len; + char cgprocs[NXT_MAX_PATH_LEN]; + FILE *fp; + nxt_int_t ret; + + if (task->thread->runtime->type != NXT_PROCESS_MAIN + || nxt_process_type(process) != NXT_PROCESS_PROTOTYPE + || process->isolation.cgroup.path == NULL) + { + return NXT_OK; + } + + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgprocs); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } + + ret = nxt_fs_mkdir_all((const u_char *) cgprocs, 0777); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } + + len = strlen(cgprocs); + + len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs"); + if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } + + fp = nxt_file_fopen(task, cgprocs, "we"); + if (nxt_slow_path(fp == NULL)) { + return NXT_ERROR; + } + + setvbuf(fp, NULL, _IONBF, 0); + len = fprintf(fp, "%d\n", process->pid); + nxt_file_fclose(task, fp); + + if (nxt_slow_path(len < 0)) { + return NXT_ERROR; + } + + return NXT_OK; +} + + +void +nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process) +{ + char *ptr; + char cgroot[NXT_MAX_PATH_LEN], cgpath[NXT_MAX_PATH_LEN]; + nxt_int_t ret; + + ret = nxt_mk_cgpath(task, "", cgroot); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgpath); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + while (*cgpath != '\0' && strcmp(cgroot, cgpath) != 0) { + rmdir(cgpath); + ptr = strrchr(cgpath, '/'); + *ptr = '\0'; + } +} + + +static int +nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, char *cgpath) +{ + int i, len; + char *buf, *ptr; + FILE *fp; + size_t size; + ssize_t nread; + nxt_bool_t found; + + fp = nxt_file_fopen(task, "/proc/self/cgroup", "re"); + if (nxt_slow_path(fp == NULL)) { + return -1; + } + + len = -1; + buf = NULL; + found = 0; + while ((nread = getline(&buf, &size, fp)) != -1) { + if (strncmp(buf, "0::", 3) == 0) { + found = 1; + break; + } + } + + nxt_file_fclose(task, fp); + + if (!found) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + buf[nread - 1] = '\0'; /* lose the trailing '\n' */ + ptr = buf; + for (i = 0; i < 2; i++) { + ptr = strchr(ptr, ':'); + if (ptr == NULL) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + ptr++; + } + + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s/%s", + ptr, dir); + +out_free_buf: + + nxt_free(buf); + + return len; +} + + +static nxt_int_t +nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath) +{ + int len; + + /* + * If the path from the config is relative, we need to make + * the cgroup path include the main unit processes cgroup. I.e + * + * NXT_CGROUP_ROOT/<main process cgroup>/<cgroup path> + */ + if (dir[0] != '/') { + len = nxt_mk_cgpath_relative(task, dir, cgpath); + } else { + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s", dir); + } + + if (len == -1) { + return NXT_ERROR; + } + + if (len >= NXT_MAX_PATH_LEN) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } + + return NXT_OK; +} diff --git a/src/nxt_cgroup.h b/src/nxt_cgroup.h new file mode 100644 index 00000000..0b9055d2 --- /dev/null +++ b/src/nxt_cgroup.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#ifndef _NXT_CGROUP_H_INCLUDED_ +#define _NXT_CGROUP_H_INCLUDED_ + + +nxt_int_t nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process); +void nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process); + + +#endif /* _NXT_CGROUP_H_INCLUDED_ */ diff --git a/src/nxt_conf.c b/src/nxt_conf.c index c6312f3d..d04aa45c 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -1389,7 +1389,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 't': if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "true", 4) == 0)) + && memcmp(start, "true", 4) == 0)) { value->u.boolean = 1; value->type = NXT_CONF_VALUE_BOOLEAN; @@ -1401,7 +1401,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 'f': if (nxt_fast_path(end - start >= 5 - && nxt_memcmp(start, "false", 5) == 0)) + && memcmp(start, "false", 5) == 0)) { value->u.boolean = 0; value->type = NXT_CONF_VALUE_BOOLEAN; @@ -1413,7 +1413,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 'n': if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "null", 4) == 0)) + && memcmp(start, "null", 4) == 0)) { value->type = NXT_CONF_VALUE_NULL; return start + 4; diff --git a/src/nxt_conf.h b/src/nxt_conf.h index c8a276c0..1b13f5ae 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -72,7 +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_tstr_state_t *tstr_state; nxt_mp_t *conf_pool; nxt_uint_t ver; } nxt_conf_validation_t; diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index fe6c22e5..bf8aa760 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -34,7 +34,7 @@ typedef enum { typedef enum { NXT_CONF_VLDT_REQUIRED = 1 << 0, - NXT_CONF_VLDT_VAR = 1 << 1, + NXT_CONF_VLDT_TSTR = 1 << 1, } nxt_conf_vldt_flags_t; @@ -128,6 +128,8 @@ static nxt_int_t nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, @@ -219,6 +221,11 @@ static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); #endif +#if (NXT_HAVE_CGROUP) +static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); +#endif + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; @@ -240,6 +247,9 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; +#if (NXT_HAVE_CGROUP) +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[]; +#endif #if (NXT_HAVE_ISOLATION_ROOTFS) static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; #endif @@ -307,6 +317,12 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { .name = nxt_string("idle_timeout"), .type = NXT_CONF_VLDT_INTEGER, }, { + .name = nxt_string("large_header_buffer_size"), + .type = NXT_CONF_VLDT_INTEGER, + }, { + .name = nxt_string("large_header_buffers"), + .type = NXT_CONF_VLDT_INTEGER, + }, { .name = nxt_string("body_buffer_size"), .type = NXT_CONF_VLDT_INTEGER, }, { @@ -367,7 +383,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { .name = nxt_string("pass"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, { .name = nxt_string("application"), .type = NXT_CONF_VLDT_STRING, @@ -652,7 +668,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { .name = nxt_string("pass"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, NXT_CONF_VLDT_END @@ -667,7 +683,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { }, { .name = nxt_string("location"), .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, NXT_CONF_VLDT_END @@ -697,7 +713,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { .validator = nxt_conf_vldt_unsupported, .u.string = "chroot", #endif - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, { .name = nxt_string("follow_symlinks"), .type = NXT_CONF_VLDT_BOOLEAN, @@ -782,6 +798,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { .validator = nxt_conf_vldt_targets_exclusive, .u.string = "callable", }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "prefix", + }, { .name = nxt_string("targets"), .type = NXT_CONF_VLDT_OBJECT, .validator = nxt_conf_vldt_targets, @@ -800,6 +821,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = { }, { .name = nxt_string("callable"), .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, NXT_CONF_VLDT_END @@ -814,6 +839,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = { }, { .name = nxt_string("callable"), .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members) @@ -1094,6 +1123,15 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { }, #endif +#if (NXT_HAVE_CGROUP) + { + .name = nxt_string("cgroup"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_app_cgroup_members, + }, +#endif + NXT_CONF_VLDT_END }; @@ -1166,6 +1204,22 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = { #endif +#if (NXT_HAVE_CGROUP) + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[] = { + { + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + .validator = nxt_conf_vldt_cgroup_path, + }, + + NXT_CONF_VLDT_END +}; + +#endif + + #if (NXT_HAVE_CLONE_NEWUSER) static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = { @@ -1226,9 +1280,10 @@ nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt) { nxt_int_t ret; + u_char error[NXT_MAX_ERROR_STR]; - vldt->var_fields = nxt_array_create(vldt->pool, 4, sizeof(nxt_var_field_t)); - if (nxt_slow_path(vldt->var_fields == NULL)) { + vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1); + if (nxt_slow_path(vldt->tstr_state == NULL)) { return NXT_ERROR; } @@ -1237,7 +1292,17 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) return ret; } - return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); + ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); + if (ret != NXT_OK) { + return ret; + } + + ret = nxt_tstr_state_done(vldt->tstr_state, error); + if (ret != NXT_OK) { + return nxt_conf_vldt_error(vldt, "%s", error); + } + + return NXT_OK; } @@ -1364,7 +1429,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, vldt->var_fields, error) != NXT_OK) { + if (nxt_tstr_test(vldt->tstr_state, value, error) != NXT_OK) { return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.", error, name); } @@ -1690,11 +1755,6 @@ static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) { - u_char *p; - nxt_str_t name, temp; - - static nxt_str_t uri = nxt_string("$uri"); - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { if (nxt_conf_array_elements_count(value) == 0) { return nxt_conf_vldt_error(vldt, "The \"share\" array " @@ -1707,22 +1767,6 @@ nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, /* NXT_CONF_STRING */ - if (vldt->ver < 12600) { - nxt_conf_get_string(value, &name); - - temp.length = name.length + uri.length; - - temp.start = nxt_mp_get(vldt->conf_pool, temp.length); - if (nxt_slow_path(temp.start == NULL)) { - return NXT_ERROR; - } - - p = nxt_cpymem(temp.start, name.start, name.length); - nxt_memcpy(p, uri.start, uri.length); - - nxt_conf_set_string(value, &temp); - } - return nxt_conf_vldt_share_element(vldt, value); } @@ -1742,7 +1786,7 @@ nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, nxt_conf_get_string(value, &str); - if (nxt_is_var(&str)) { + if (nxt_is_tstr(&str)) { return nxt_conf_vldt_var(vldt, &share, &str); } @@ -1842,6 +1886,28 @@ nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, static nxt_int_t +nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) +{ + nxt_str_t prefix; + + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } + + nxt_conf_get_string(value, &prefix); + + if (!nxt_strchr_start(&prefix, '/')) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } + + return NXT_OK; +} + + +static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) { @@ -2522,12 +2588,12 @@ nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, continue; } - if (vals->flags & NXT_CONF_VLDT_VAR + if (vals->flags & NXT_CONF_VLDT_TSTR && nxt_conf_type(member) == NXT_CONF_STRING) { nxt_conf_get_string(member, &var); - if (nxt_is_var(&var)) { + if (nxt_is_tstr(&var)) { ret = nxt_conf_vldt_var(vldt, &name, &var); if (ret != NXT_OK) { return ret; @@ -2731,12 +2797,12 @@ nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, "The environment name must not be empty."); } - if (nxt_memchr(name->start, '\0', name->length) != NULL) { + if (memchr(name->start, '\0', name->length) != NULL) { return nxt_conf_vldt_error(vldt, "The environment name must not " "contain null character."); } - if (nxt_memchr(name->start, '=', name->length) != NULL) { + if (memchr(name->start, '=', name->length) != NULL) { return nxt_conf_vldt_error(vldt, "The environment name must not " "contain '=' character."); } @@ -2748,7 +2814,7 @@ nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must " "not contain null character.", name); } @@ -2808,6 +2874,35 @@ nxt_conf_vldt_target(nxt_conf_validation_t *vldt, nxt_str_t *name, } +#if (NXT_HAVE_CGROUP) + +static nxt_int_t +nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + char path[NXT_MAX_PATH_LEN]; + nxt_str_t cgpath; + + nxt_conf_get_string(value, &cgpath); + if (cgpath.length >= NXT_MAX_PATH_LEN - strlen(NXT_CGROUP_ROOT) - 1) { + return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is too long.", + &cgpath); + } + + sprintf(path, "/%*s/", (int) cgpath.length, cgpath.start); + + if (cgpath.length == 0 || strstr(path, "/../") != NULL) { + return nxt_conf_vldt_error(vldt, + "The cgroup path \"%V\" is invalid.", + &cgpath); + } + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) @@ -2947,7 +3042,7 @@ nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " "contain strings with null character."); } @@ -3006,7 +3101,7 @@ nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not " "contain strings with null character."); } @@ -3027,7 +3122,7 @@ nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"options\" array must not " "contain strings with null character."); } @@ -3168,7 +3263,7 @@ nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, "The \"path\" string must not be empty."); } - if (nxt_is_var(&conf.format)) { + if (nxt_is_tstr(&conf.format)) { return nxt_conf_vldt_var(vldt, &format_str, &conf.format); } diff --git a/src/nxt_conn.h b/src/nxt_conn.h index 8a703e9a..5717d3c9 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -312,8 +312,7 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, \ nxt_queue_remove(&c->link); \ \ - c->idle = 0; \ - e->idle_conns_cnt--; \ + e->idle_conns_cnt -= c->idle; \ } while (0) diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index 92bd8d1b..bdd66951 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -119,7 +119,9 @@ 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 (c->idle) { + engine->closed_conns_cnt++; + } if (timers_pending == 0) { nxt_work_queue_add(&engine->fast_work_queue, @@ -155,7 +157,9 @@ nxt_conn_close_timer_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 (c->idle) { + engine->closed_conns_cnt++; + } } nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 09168821..b5e0d831 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -666,6 +666,14 @@ nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) #endif ls->handler = nxt_controller_conn_init; +#if (NXT_HAVE_UNIX_DOMAIN) + if (ls->sockaddr->u.sockaddr.sa_family == AF_UNIX) { + const char *path = ls->sockaddr->u.sockaddr_un.sun_path; + + nxt_fs_mkdir_parent((const u_char *) path, 0755); + } +#endif + if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) { return NXT_ERROR; } @@ -1255,7 +1263,7 @@ nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, /* Skip UTF-8 BOM. */ if (nxt_buf_mem_used_size(mbuf) >= 3 - && nxt_memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) + && memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) { mbuf->pos += 3; } @@ -1629,7 +1637,7 @@ nxt_controller_process_cert(nxt_task_t *task, name.length = path->length - 1; name.start = path->start + 1; - p = nxt_memchr(name.start, '/', name.length); + p = memchr(name.start, '/', name.length); if (p != NULL) { name.length = p - name.start; @@ -1932,7 +1940,7 @@ nxt_controller_process_control(nxt_task_t *task, } if (!nxt_str_start(path, "applications/", 13) - || nxt_memcmp(path->start + path->length - 8, "/restart", 8) != 0) + || memcmp(path->start + path->length - 8, "/restart", 8) != 0) { goto not_found; } diff --git a/src/nxt_errno.c b/src/nxt_errno.c index 869a970f..47479a82 100644 --- a/src/nxt_errno.c +++ b/src/nxt_errno.c @@ -78,7 +78,7 @@ nxt_strerror_start(void) if (length == 0 /* HP-UX empty strings. */ || nxt_errno == NXT_EINVAL - || nxt_memcmp(msg, "Unknown error", 13) == 0) + || memcmp(msg, "Unknown error", 13) == 0) { invalid++; continue; @@ -86,8 +86,8 @@ nxt_strerror_start(void) #if (NXT_AIX) - if (nxt_memcmp(msg, "Error ", 6) == 0 - && nxt_memcmp(msg + length - 10, " occurred.", 9) == 0) + if (memcmp(msg, "Error ", 6) == 0 + && memcmp(msg + length - 10, " occurred.", 9) == 0) { invalid++; continue; diff --git a/src/nxt_file.c b/src/nxt_file.c index 5d38d57e..a3fcda76 100644 --- a/src/nxt_file.c +++ b/src/nxt_file.c @@ -500,6 +500,43 @@ nxt_fd_close(nxt_fd_t fd) } +FILE * +nxt_file_fopen(nxt_task_t *task, const char *pathname, const char *mode) +{ + int err; + FILE *fp; + +#if (NXT_DEBUG) + nxt_thread_time_update(task->thread); +#endif + + fp = fopen(pathname, mode); + err = (fp == NULL) ? nxt_errno : 0; + + nxt_debug(task, "fopen(\"%s\", \"%s\"): fp:%p err:%d", pathname, mode, fp, + err); + + if (nxt_fast_path(fp != NULL)) { + return fp; + } + + nxt_alert(task, "fopen(\"%s\") failed %E", pathname, err); + + return NULL; +} + + +void +nxt_file_fclose(nxt_task_t *task, FILE *fp) +{ + nxt_debug(task, "fclose(%p)", fp); + + if (nxt_slow_path(fclose(fp) == -1)) { + nxt_alert(task, "fclose() failed %E", nxt_errno); + } +} + + /* * nxt_file_redirect() redirects the file to the fd descriptor. * Then the fd descriptor is closed. diff --git a/src/nxt_file.h b/src/nxt_file.h index 07c7a22b..945717b3 100644 --- a/src/nxt_file.h +++ b/src/nxt_file.h @@ -186,6 +186,10 @@ NXT_EXPORT ssize_t nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size); NXT_EXPORT ssize_t nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size); NXT_EXPORT void nxt_fd_close(nxt_fd_t fd); +NXT_EXPORT FILE *nxt_file_fopen(nxt_task_t *task, const char *pathname, + const char *mode); +NXT_EXPORT void nxt_file_fclose(nxt_task_t *task, FILE *fp); + NXT_EXPORT nxt_int_t nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd); NXT_EXPORT nxt_int_t nxt_file_stderr(nxt_file_t *file); NXT_EXPORT nxt_int_t nxt_stderr_start(void); diff --git a/src/nxt_fs.c b/src/nxt_fs.c index 71498f99..a467da98 100644 --- a/src/nxt_fs.c +++ b/src/nxt_fs.c @@ -4,235 +4,10 @@ #include <nxt_main.h> -#if (NXT_HAVE_FREEBSD_NMOUNT) -#include <sys/param.h> -#include <sys/uio.h> -#endif - static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode); -#if (NXT_HAVE_LINUX_MOUNT) - -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int rc; - const char *fsname; - unsigned long flags; - - flags = 0; - - switch (mnt->type) { - case NXT_FS_BIND: - if (nxt_slow_path(mnt->flags != 0)) { - nxt_log(task, NXT_LOG_WARN, - "bind mount ignores additional flags"); - } - - fsname = "bind"; - flags = MS_BIND | MS_REC; - break; - - case NXT_FS_PROC: - fsname = "proc"; - goto getflags; - - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; - - default: - fsname = (const char *) mnt->name; - - getflags: - - if (mnt->flags & NXT_FS_FLAGS_NODEV) { - flags |= MS_NODEV; - } - - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MS_NOEXEC; - } - - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MS_NOSUID; - } - - if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { - flags |= MS_RELATIME; - } - } - - rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, - mnt->data); - - if (nxt_slow_path(rc < 0)) { - nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", - mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); - - return NXT_ERROR; - } - - return NXT_OK; -} - -#elif (NXT_HAVE_FREEBSD_NMOUNT) - -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int flags; - u_char *data, *p, *end; - size_t iovlen; - nxt_int_t ret; - const char *fsname; - struct iovec iov[128]; - char errmsg[256]; - - if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { - nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); - - return NXT_ERROR; - } - - flags = 0; - - switch (mnt->type) { - case NXT_FS_BIND: - fsname = "nullfs"; - break; - - case NXT_FS_PROC: - fsname = "procfs"; - goto getflags; - - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; - - default: - fsname = (const char *) mnt->name; - - getflags: - - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MNT_NOEXEC; - } - - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MNT_NOSUID; - } - - if (mnt->flags & NXT_FS_FLAGS_NOTIME) { - flags |= MNT_NOATIME; - } - - if (mnt->flags & NXT_FS_FLAGS_RDONLY) { - flags |= MNT_RDONLY; - } - } - - iov[0].iov_base = (void *) "fstype"; - iov[0].iov_len = 7; - iov[1].iov_base = (void *) fsname; - iov[1].iov_len = nxt_strlen(fsname) + 1; - iov[2].iov_base = (void *) "fspath"; - iov[2].iov_len = 7; - iov[3].iov_base = (void *) mnt->dst; - iov[3].iov_len = nxt_strlen(mnt->dst) + 1; - iov[4].iov_base = (void *) "target"; - iov[4].iov_len = 7; - iov[5].iov_base = (void *) mnt->src; - iov[5].iov_len = nxt_strlen(mnt->src) + 1; - iov[6].iov_base = (void *) "errmsg"; - iov[6].iov_len = 7; - iov[7].iov_base = (void *) errmsg; - iov[7].iov_len = sizeof(errmsg); - - iovlen = 8; - - data = NULL; - - if (mnt->data != NULL) { - data = (u_char *) nxt_strdup(mnt->data); - if (nxt_slow_path(data == NULL)) { - return NXT_ERROR; - } - - end = data - 1; - - do { - p = end + 1; - end = nxt_strchr(p, '='); - if (end == NULL) { - break; - } - - *end = '\0'; - - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = (end - p) + 1; - - iovlen++; - - p = end + 1; - - end = nxt_strchr(p, ','); - if (end != NULL) { - *end = '\0'; - } - - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = nxt_strlen(p) + 1; - - iovlen++; - - } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); - } - - ret = NXT_OK; - - if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { - nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); - ret = NXT_ERROR; - } - - if (data != NULL) { - free(data); - } - - return ret; -} - -#endif - - -#if (NXT_HAVE_LINUX_UMOUNT2) - -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", - path, nxt_errno); - } -} - -#elif (NXT_HAVE_UNMOUNT) - -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); - } -} - -#endif - - nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode) { @@ -273,6 +48,31 @@ nxt_fs_mkdir_all(const u_char *dir, mode_t mode) } +nxt_int_t +nxt_fs_mkdir_parent(const u_char *path, mode_t mode) +{ + char *ptr, *dir; + nxt_int_t ret; + + dir = nxt_strdup(path); + if (nxt_slow_path(dir == NULL)) { + return NXT_ERROR; + } + + ret = NXT_OK; + + ptr = strrchr(dir, '/'); + if (nxt_fast_path(ptr != NULL)) { + *ptr = '\0'; + ret = nxt_fs_mkdir((const u_char *) dir, mode); + } + + nxt_free(dir); + + return ret; +} + + static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode) { diff --git a/src/nxt_fs.h b/src/nxt_fs.h index ff589979..c8868d80 100644 --- a/src/nxt_fs.h +++ b/src/nxt_fs.h @@ -6,39 +6,8 @@ #define _NXT_FS_H_INCLUDED_ -typedef enum { - NXT_FS_UNKNOWN = 0, - NXT_FS_BIND, - NXT_FS_TMP, - NXT_FS_PROC, - NXT_FS_LAST, -} nxt_fs_type_t; - - -typedef enum { - NXT_FS_FLAGS_NOSUID = 1 << 0, - NXT_FS_FLAGS_NOEXEC = 1 << 1, - NXT_FS_FLAGS_NOTIME = 1 << 2, - NXT_FS_FLAGS_NODEV = 1 << 3, - NXT_FS_FLAGS_RDONLY = 1 << 4, -} nxt_fs_flags_t; - - -typedef struct { - u_char *src; - u_char *dst; - nxt_fs_type_t type; - u_char *name; - nxt_fs_flags_t flags; - u_char *data; - nxt_uint_t builtin; /* 1-bit */ - nxt_uint_t deps; /* 1-bit */ -} nxt_fs_mount_t; - - +nxt_int_t nxt_fs_mkdir_parent(const u_char *path, mode_t mode); nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode); -nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); -void nxt_fs_unmount(const u_char *path); #endif /* _NXT_FS_H_INCLUDED_ */ diff --git a/src/nxt_fs_mount.c b/src/nxt_fs_mount.c new file mode 100644 index 00000000..d9b384e4 --- /dev/null +++ b/src/nxt_fs_mount.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + +#if (NXT_HAVE_FREEBSD_NMOUNT) +#include <sys/param.h> +#include <sys/uio.h> +#endif + + +#if (NXT_HAVE_LINUX_MOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int rc; + const char *fsname; + unsigned long flags; + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + if (nxt_slow_path(mnt->flags != 0)) { + nxt_log(task, NXT_LOG_WARN, + "bind mount ignores additional flags"); + } + + fsname = "bind"; + flags = MS_BIND | MS_REC; + break; + + case NXT_FS_PROC: + fsname = "proc"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NODEV) { + flags |= MS_NODEV; + } + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MS_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MS_NOSUID; + } + + if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { + flags |= MS_RELATIME; + } + } + + rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, + mnt->data); + + if (nxt_slow_path(rc < 0)) { + nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", + mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); + + return NXT_ERROR; + } + + return NXT_OK; +} + +#elif (NXT_HAVE_FREEBSD_NMOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int flags; + u_char *data, *p, *end; + size_t iovlen; + nxt_int_t ret; + const char *fsname; + struct iovec iov[128]; + char errmsg[256]; + + if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { + nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); + + return NXT_ERROR; + } + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + fsname = "nullfs"; + break; + + case NXT_FS_PROC: + fsname = "procfs"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MNT_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MNT_NOSUID; + } + + if (mnt->flags & NXT_FS_FLAGS_NOTIME) { + flags |= MNT_NOATIME; + } + + if (mnt->flags & NXT_FS_FLAGS_RDONLY) { + flags |= MNT_RDONLY; + } + } + + iov[0].iov_base = (void *) "fstype"; + iov[0].iov_len = 7; + iov[1].iov_base = (void *) fsname; + iov[1].iov_len = nxt_strlen(fsname) + 1; + iov[2].iov_base = (void *) "fspath"; + iov[2].iov_len = 7; + iov[3].iov_base = (void *) mnt->dst; + iov[3].iov_len = nxt_strlen(mnt->dst) + 1; + iov[4].iov_base = (void *) "target"; + iov[4].iov_len = 7; + iov[5].iov_base = (void *) mnt->src; + iov[5].iov_len = nxt_strlen(mnt->src) + 1; + iov[6].iov_base = (void *) "errmsg"; + iov[6].iov_len = 7; + iov[7].iov_base = (void *) errmsg; + iov[7].iov_len = sizeof(errmsg); + + iovlen = 8; + + data = NULL; + + if (mnt->data != NULL) { + data = (u_char *) nxt_strdup(mnt->data); + if (nxt_slow_path(data == NULL)) { + return NXT_ERROR; + } + + end = data - 1; + + do { + p = end + 1; + end = nxt_strchr(p, '='); + if (end == NULL) { + break; + } + + *end = '\0'; + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = (end - p) + 1; + + iovlen++; + + p = end + 1; + + end = nxt_strchr(p, ','); + if (end != NULL) { + *end = '\0'; + } + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = nxt_strlen(p) + 1; + + iovlen++; + + } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); + } + + ret = NXT_OK; + + if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { + nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); + ret = NXT_ERROR; + } + + if (data != NULL) { + free(data); + } + + return ret; +} + +#endif + + +#if (NXT_HAVE_LINUX_UMOUNT2) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", + path, nxt_errno); + } +} + +#elif (NXT_HAVE_UNMOUNT) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); + } +} + +#endif diff --git a/src/nxt_fs_mount.h b/src/nxt_fs_mount.h new file mode 100644 index 00000000..e0fe6eb2 --- /dev/null +++ b/src/nxt_fs_mount.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_FS_MOUNT_H_INCLUDED_ +#define _NXT_FS_MOUNT_H_INCLUDED_ + + +typedef enum nxt_fs_type_s nxt_fs_type_t; +typedef enum nxt_fs_flags_s nxt_fs_flags_t; +typedef struct nxt_fs_mount_s nxt_fs_mount_t; + + +enum nxt_fs_type_s { + NXT_FS_UNKNOWN = 0, + NXT_FS_BIND, + NXT_FS_TMP, + NXT_FS_PROC, + NXT_FS_LAST, +}; + + +enum nxt_fs_flags_s { + NXT_FS_FLAGS_NOSUID = 1 << 0, + NXT_FS_FLAGS_NOEXEC = 1 << 1, + NXT_FS_FLAGS_NOTIME = 1 << 2, + NXT_FS_FLAGS_NODEV = 1 << 3, + NXT_FS_FLAGS_RDONLY = 1 << 4, +}; + + +struct nxt_fs_mount_s { + u_char *src; + u_char *dst; + nxt_fs_type_t type; + u_char *name; + nxt_fs_flags_t flags; + u_char *data; + nxt_uint_t builtin; /* 1-bit */ + nxt_uint_t deps; /* 1-bit */ +}; + + +nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); +void nxt_fs_unmount(const u_char *path); + + +#endif /* _NXT_FS_MOUNT_H_INCLUDED_ */ diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 852b4866..1e37273f 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -823,7 +823,7 @@ nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) field->hopbyhop = 1; if (field->value_length == 7 - && nxt_memcmp(field->value, "chunked", 7) == 0) + && memcmp(field->value, "chunked", 7) == 0) { te = NXT_HTTP_TE_CHUNKED; @@ -2594,7 +2594,7 @@ nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) p = bm->pos; - if (nxt_slow_path(nxt_memcmp(p, "HTTP/1.", 7) != 0 + if (nxt_slow_path(memcmp(p, "HTTP/1.", 7) != 0 || (p[7] != '0' && p[7] != '1'))) { return NXT_ERROR; @@ -2609,7 +2609,7 @@ nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) p += 12; length -= 12; - p = nxt_memchr(p, '\n', length); + p = memchr(p, '\n', length); if (nxt_slow_path(p == NULL)) { return NXT_AGAIN; @@ -2868,7 +2868,7 @@ nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field, field->skip = 1; if (field->value_length == 7 - && nxt_memcmp(field->value, "chunked", 7) == 0) + && memcmp(field->value, "chunked", 7) == 0) { r->peer->proto.h1->chunked = 1; } diff --git a/src/nxt_http.h b/src/nxt_http.h index c2e85840..a8725d9f 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -140,6 +140,8 @@ struct nxt_http_request_s { nxt_buf_t *out; const nxt_http_request_state_t *state; + nxt_nsec_t start_time; + nxt_str_t host; nxt_str_t server_name; nxt_str_t target; @@ -167,7 +169,8 @@ struct nxt_http_request_s { nxt_timer_t timer; void *timer_data; - nxt_var_query_t *var_query; + nxt_tstr_query_t *tstr_query; + nxt_tstr_cache_t tstr_cache; void *req_rpc_data; @@ -243,7 +246,7 @@ struct nxt_http_action_s { nxt_http_route_t *route; nxt_upstream_t *upstream; uint32_t upstream_number; - nxt_var_t *var; + nxt_tstr_t *tstr; nxt_str_t *pass; } u; diff --git a/src/nxt_http_js.c b/src/nxt_http_js.c new file mode 100644 index 00000000..5a08a309 --- /dev/null +++ b/src/nxt_http_js.c @@ -0,0 +1,273 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_router.h> +#include <nxt_http.h> +#include <njs.h> + + +static njs_int_t nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t nxt_http_js_ext_remote_addr(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_arg(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_header(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_cookie(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); + + +static njs_external_t nxt_http_js_proto[] = { + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("uri"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_uri, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("host"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_host, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("remoteAddr"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_remote_addr, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("args"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_arg, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("headers"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_header, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("cookies"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_cookie, + } + }, +}; + + +void +nxt_http_register_js_proto(nxt_js_conf_t *jcf) +{ + nxt_js_set_proto(jcf, nxt_http_js_proto, njs_nitems(nxt_http_js_proto)); +} + + +static njs_int_t +nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, r->path->start, r->path->length); +} + + +static njs_int_t +nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, r->host.start, r->host.length); +} + + +static njs_int_t +nxt_http_js_ext_remote_addr(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, + nxt_sockaddr_address(r->remote), + r->remote->address_length); +} + + +static njs_int_t +nxt_http_js_ext_get_arg(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_array_t *args; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NJS_ERROR; + } + + start = args->elts; + end = start + args->nelts; + + for (nv = start; nv < end; nv++) { + + if (key.length == nv->name_length + && memcmp(key.start, nv->name, nv->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, nv->value, + nv->value_length); + } + } + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} + + +static njs_int_t +nxt_http_js_ext_get_header(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_http_field_t *f; + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + nxt_list_each(f, r->fields) { + + if (key.length == f->name_length + && memcmp(key.start, f->name, f->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, f->value, + f->value_length); + } + + } nxt_list_loop; + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} + + +static njs_int_t +nxt_http_js_ext_get_cookie(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_array_t *cookies; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NJS_ERROR; + } + + start = cookies->elts; + end = start + cookies->nelts; + + for (nv = start; nv < end; nv++) { + + if (key.length == nv->name_length + && memcmp(key.start, nv->name, nv->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, nv->value, + nv->value_length); + } + } + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 1bb4291f..f39d8f67 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -357,7 +357,7 @@ space_after_target: } while (*p == ' '); - if (nxt_memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { + if (memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { switch (end - p) { case 8: @@ -412,7 +412,7 @@ space_after_target: if (nxt_fast_path(ver.ui64 == http11.ui64 || ver.ui64 == http10.ui64 - || (nxt_memcmp(ver.str, "HTTP/1.", 7) == 0 + || (memcmp(ver.str, "HTTP/1.", 7) == 0 && ver.s.minor >= '0' && ver.s.minor <= '9'))) { rp->version.ui64 = ver.ui64; @@ -464,7 +464,7 @@ space_after_target: return nxt_http_parse_field_name(rp, pos, end); } - if (nxt_memcmp(ver.s.prefix, "HTTP/", 5) == 0 + if (memcmp(ver.s.prefix, "HTTP/", 5) == 0 && ver.s.major >= '0' && ver.s.major <= '9' && ver.s.point == '.' && ver.s.minor >= '0' && ver.s.minor <= '9') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 943ad82d..73ffd2f0 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -278,8 +278,12 @@ nxt_http_request_create(nxt_task_t *task) r->resp.content_length_n = -1; r->state = &nxt_http_request_init_state; + r->start_time = nxt_thread_monotonic_time(task->thread); + task->thread->engine->requests_cnt++; + r->tstr_cache.var.pool = mp; + return r; fail: @@ -793,7 +797,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_tstr_t *log_format; nxt_http_proto_t proto; nxt_http_request_t *r; nxt_http_protocol_t protocol; @@ -1035,14 +1039,11 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end) for (p = start; p < end; p++) { c = *p; - if (c == '=') { + if (c == '=' && name == NULL) { while (start[0] == ' ') { start++; } name_length = p - start; - - if (name_length != 0) { - name = start; - } + name = start; start = p + 1; diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 9f3c4fc5..b50e4ad0 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -9,7 +9,7 @@ typedef struct { nxt_http_status_t status; - nxt_var_t *location; + nxt_tstr_t *location; nxt_str_t encoded; } nxt_http_return_conf_t; @@ -25,7 +25,7 @@ static nxt_http_action_t *nxt_http_return(nxt_task_t *task, static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, const nxt_str_t *location); static void nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_return_send_error(nxt_task_t *task, void *obj, void *data); static const nxt_http_request_state_t nxt_http_return_send_state; @@ -57,13 +57,13 @@ nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, nxt_conf_get_string(acf->location, &str); - conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0); + conf->location = nxt_tstr_compile(rtcf->tstr_state, &str, 0); if (nxt_slow_path(conf->location == NULL)) { return NXT_ERROR; } - if (nxt_var_is_const(conf->location)) { - nxt_var_raw(conf->location, &str); + if (nxt_tstr_is_const(conf->location)) { + nxt_tstr_str(conf->location, &str); return nxt_http_return_encode(mp, &conf->encoded, &str); } @@ -76,6 +76,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_return_ctx_t *ctx; nxt_http_return_conf_t *conf; @@ -88,7 +89,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_str_set(&loc, ""); } else { - nxt_var_raw(conf->location, &loc); + nxt_tstr_str(conf->location, &loc); } nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); @@ -114,7 +115,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, r->status = conf->status; r->resp.content_length_n = 0; - if (ctx == NULL || nxt_var_is_const(conf->location)) { + if (ctx == NULL || nxt_tstr_is_const(conf->location)) { if (ctx != NULL) { ctx->encoded = conf->encoded; } @@ -122,16 +123,19 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_return_send_ready(task, r, ctx); } else { - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - nxt_var_query(task, r->var_query, conf->location, &ctx->location); + nxt_tstr_query(task, r->tstr_query, conf->location, &ctx->location); - nxt_var_query_resolve(task, r->var_query, ctx, - nxt_http_return_send_ready, - nxt_http_return_var_error); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_http_return_send_ready, + nxt_http_return_send_error); } return NULL; @@ -213,7 +217,7 @@ fail: static void -nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_return_send_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index cdc9077f..7081ff7e 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -193,8 +193,8 @@ static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); -static void nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data); +static void nxt_http_pass_query_error(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass, nxt_http_action_t *action); static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, @@ -673,8 +673,8 @@ 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, rtcf->var_fields, 0); - if (nxt_slow_path(action->u.var == NULL)) { + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, &pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { return NXT_ERROR; } @@ -1016,7 +1016,7 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { tmp.start = test.start; - p = nxt_memchr(test.start, '*', test.length); + p = memchr(test.start, '*', test.length); if (p == NULL) { /* No '*' found - EXACT pattern. */ @@ -1272,8 +1272,8 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return NXT_OK; } - if (nxt_var_is_const(action->u.var)) { - nxt_var_raw(action->u.var, &pass); + if (nxt_tstr_is_const(action->u.tstr)) { + nxt_tstr_str(action->u.tstr, &pass); ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, action); @@ -1293,17 +1293,21 @@ static nxt_http_action_t * nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_int_t ret; - nxt_str_t str; - nxt_var_t *var; + nxt_int_t ret; + nxt_str_t str; + nxt_tstr_t *tstr; + nxt_router_conf_t *rtcf; - var = action->u.var; + tstr = action->u.tstr; - nxt_var_raw(var, &str); + nxt_tstr_str(tstr, &str); nxt_debug(task, "http pass: \"%V\"", &str); - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, + r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -1316,10 +1320,10 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); - nxt_var_query(task, r->var_query, var, action->u.pass); - nxt_var_query_resolve(task, r->var_query, action, - nxt_http_pass_var_ready, - nxt_http_pass_var_error); + nxt_tstr_query(task, r->tstr_query, tstr, action->u.pass); + nxt_tstr_query_resolve(task, r->tstr_query, action, + nxt_http_pass_query_ready, + nxt_http_pass_query_error); return NULL; fail: @@ -1330,7 +1334,7 @@ fail: static void -nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; nxt_router_conf_t *rtcf; @@ -1359,7 +1363,7 @@ nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) static void -nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_query_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; @@ -1414,7 +1418,7 @@ nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments, nxt_memzero(segments, n * sizeof(nxt_str_t)); do { - p = nxt_memchr(rest.start, '/', rest.length); + p = memchr(rest.start, '/', rest.length); if (p != NULL) { n--; @@ -1497,8 +1501,8 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return NULL; } - action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0); - if (nxt_slow_path(action->u.var == NULL)) { + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { return NULL; } @@ -1740,15 +1744,15 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, sizeof(struct in_addr)) == 0); break; case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, sizeof(struct in_addr)) >= 0 - && nxt_memcmp(&sin->sin_addr, &p->addr.v4.end, + && memcmp(&sin->sin_addr, &p->addr.v4.end, sizeof(struct in_addr)) <= 0); break; @@ -1786,15 +1790,15 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, sizeof(struct in6_addr)) == 0); break; case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, sizeof(struct in6_addr)) >= 0 - && nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.end, + && memcmp(&sin6->sin6_addr, &p->addr.v6.end, sizeof(struct in6_addr)) <= 0); break; @@ -1937,7 +1941,7 @@ nxt_http_route_test_argument(nxt_http_request_t *r, if (rule->u.name.hash == nv->hash && rule->u.name.length == nv->name_length - && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) + && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); @@ -2015,7 +2019,7 @@ nxt_http_route_test_cookie(nxt_http_request_t *r, if (rule->u.name.hash == nv->hash && rule->u.name.length == nv->name_length - && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) + && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); @@ -2158,7 +2162,7 @@ nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, nxt_int_t n; if (case_sensitive) { - n = nxt_memcmp(start, test, test_length); + n = memcmp(start, test, test_length); } else { n = nxt_memcasecmp(start, test, test_length); diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 34455af4..5a0d7679 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -93,7 +93,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, inet6 = &pattern->addr.v6; - delim = nxt_memchr(addr.start, '-', addr.length); + delim = memchr(addr.start, '-', addr.length); if (delim != NULL) { len = delim - addr.start; if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, len))) { @@ -115,7 +115,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, return NXT_ADDR_PATTERN_FORMAT_ERROR; } - if (nxt_slow_path(nxt_memcmp(&inet6->start, &inet6->end, + if (nxt_slow_path(memcmp(&inet6->start, &inet6->end, sizeof(struct in6_addr)) > 0)) { return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; @@ -126,7 +126,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, goto parse_port; } - delim = nxt_memchr(addr.start, '/', addr.length); + delim = memchr(addr.start, '/', addr.length); if (delim != NULL) { cidr_prefix = nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); @@ -201,7 +201,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, base->addr_family = AF_INET; - delim = nxt_memchr(addr.start, ':', addr.length); + delim = memchr(addr.start, ':', addr.length); if (delim != NULL) { port.start = delim + 1; port.length = addr.start + addr.length - port.start; @@ -210,7 +210,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, inet = &pattern->addr.v4; - delim = nxt_memchr(addr.start, '-', addr.length); + delim = memchr(addr.start, '-', addr.length); if (delim != NULL) { inet->start = nxt_inet_addr(addr.start, delim - addr.start); if (nxt_slow_path(inet->start == INADDR_NONE)) { @@ -223,7 +223,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, return NXT_ADDR_PATTERN_FORMAT_ERROR; } - if (nxt_slow_path(nxt_memcmp(&inet->start, &inet->end, + if (nxt_slow_path(memcmp(&inet->start, &inet->end, sizeof(struct in_addr)) > 0)) { return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; @@ -234,7 +234,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, goto parse_port; } - delim = nxt_memchr(addr.start, '/', addr.length); + delim = memchr(addr.start, '/', addr.length); if (delim != NULL) { cidr_prefix = nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); @@ -283,7 +283,7 @@ parse_port: return NXT_OK; } - delim = nxt_memchr(port.start, '-', port.length - 1); + delim = memchr(port.start, '-', port.length - 1); if (delim != NULL) { ret = nxt_int_parse(port.start, delim - port.start); if (nxt_slow_path(ret < 0 || ret > 65535)) { diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 0507e038..68174b9d 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -8,7 +8,7 @@ typedef struct { - nxt_var_t *var; + nxt_tstr_t *tstr; #if (NXT_HAVE_OPENAT2) u_char *fname; #endif @@ -21,7 +21,7 @@ typedef struct { nxt_http_static_share_t *shares; nxt_str_t index; #if (NXT_HAVE_OPENAT2) - nxt_var_t *chroot; + nxt_tstr_t *chroot; nxt_uint_t resolve; #endif nxt_http_route_rule_t *types; @@ -48,7 +48,7 @@ static nxt_http_action_t *nxt_http_static(nxt_task_t *task, static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx); static void nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_static_send_error(nxt_task_t *task, void *obj, void *data); static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx, nxt_http_status_t status); #if (NXT_HAVE_OPENAT2) @@ -77,7 +77,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, uint32_t i; nxt_mp_t *mp; nxt_str_t str, *ret; - nxt_var_t *var; + nxt_tstr_t *tstr; nxt_conf_value_t *cv; nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; @@ -104,13 +104,13 @@ 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, rtcf->var_fields, NXT_VAR_STRZ); - if (nxt_slow_path(var == NULL)) { + tstr = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_STRZ); + if (nxt_slow_path(tstr == NULL)) { return NXT_ERROR; } - conf->shares[i].var = var; - conf->shares[i].is_const = nxt_var_is_const(var); + conf->shares[i].tstr = tstr; + conf->shares[i].is_const = nxt_tstr_is_const(tstr); } if (acf->index == NULL) { @@ -130,20 +130,20 @@ 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, rtcf->var_fields, - NXT_VAR_STRZ); + conf->chroot = nxt_tstr_compile(rtcf->tstr_state, &acf->chroot, + NXT_TSTR_STRZ); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } - is_const = nxt_var_is_const(conf->chroot); + is_const = nxt_tstr_is_const(conf->chroot); for (i = 0; i < conf->nshares; i++) { conf->shares[i].is_const &= is_const; if (conf->shares[i].is_const) { - nxt_var_raw(conf->chroot, &chr); - nxt_var_raw(conf->shares[i].var, &shr); + nxt_tstr_str(conf->chroot, &chr); + nxt_tstr_str(conf->shares[i].tstr, &shr); conf->shares[i].fname = nxt_http_static_chroot_match(chr.start, shr.start); @@ -229,6 +229,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; nxt_http_static_share_t *share; @@ -240,14 +241,14 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_str_t shr; nxt_str_t idx; - nxt_var_raw(share->var, &shr); + nxt_tstr_str(share->tstr, &shr); idx = conf->index; #if (NXT_HAVE_OPENAT2) nxt_str_t chr; if (conf->chroot != NULL) { - nxt_var_raw(conf->chroot, &chr); + nxt_tstr_str(conf->chroot, &chr); } else { nxt_str_set(&chr, ""); @@ -261,34 +262,37 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, #endif /* NXT_DEBUG */ if (share->is_const) { - nxt_var_raw(share->var, &ctx->share); + nxt_tstr_str(share->tstr, &ctx->share); #if (NXT_HAVE_OPENAT2) if (conf->chroot != NULL && ctx->share_idx == 0) { - nxt_var_raw(conf->chroot, &ctx->chroot); + nxt_tstr_str(conf->chroot, &ctx->chroot); } #endif nxt_http_static_send_ready(task, r, ctx); } else { - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); return; } - nxt_var_query(task, r->var_query, share->var, &ctx->share); + nxt_tstr_query(task, r->tstr_query, share->tstr, &ctx->share); #if (NXT_HAVE_OPENAT2) if (conf->chroot != NULL && ctx->share_idx == 0) { - nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); + nxt_tstr_query(task, r->tstr_query, conf->chroot, &ctx->chroot); } #endif - nxt_var_query_resolve(task, r->var_query, ctx, - nxt_http_static_send_ready, - nxt_http_static_var_error); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_http_static_send_ready, + nxt_http_static_send_error); } } @@ -658,7 +662,7 @@ fail: static void -nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_static_send_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 5a632b24..fa0244db 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -9,6 +9,8 @@ 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_request_time(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, @@ -46,6 +48,9 @@ static nxt_var_decl_t nxt_http_vars[] = { .name = nxt_string("dollar"), .handler = nxt_http_var_dollar, }, { + .name = nxt_string("request_time"), + .handler = nxt_http_var_request_time, + }, { .name = nxt_string("method"), .handler = nxt_http_var_method, }, { @@ -111,6 +116,34 @@ nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) static nxt_int_t +nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + u_char *p; + nxt_msec_t ms; + nxt_nsec_t now; + nxt_http_request_t *r; + + r = ctx; + + now = nxt_thread_monotonic_time(task->thread); + ms = (now - r->start_time) / 1000000; + + str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M", + (nxt_time_t) ms / 1000, ms % 1000); + + str->length = p - str->start; + + 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; @@ -374,7 +407,7 @@ nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); args = nxt_http_arguments_parse(r); if (nxt_slow_path(args == NULL)) { @@ -388,7 +421,7 @@ nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) if (vf->hash == nv->hash && vf->name.length == nv->name_length - && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + && memcmp(vf->name.start, nv->name, nv->name_length) == 0) { str->start = nv->value; str->length = nv->value_length; @@ -417,7 +450,7 @@ nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); nxt_list_each(f, r->fields) { @@ -452,7 +485,7 @@ nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); cookies = nxt_http_cookies_parse(r); if (nxt_slow_path(cookies == NULL)) { @@ -466,7 +499,7 @@ nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) if (vf->hash == nv->hash && vf->name.length == nv->name_length - && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + && memcmp(vf->name.start, nv->name, nv->name_length) == 0) { str->start = nv->value; str->length = nv->value_length; diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 796da4c6..b6b13c59 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -6,6 +6,7 @@ #include <nxt_application.h> #include <nxt_process.h> #include <nxt_isolation.h> +#include <nxt_cgroup.h> #if (NXT_HAVE_MNTENT_H) #include <mntent.h> @@ -15,6 +16,11 @@ static nxt_int_t nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process); +#if (NXT_HAVE_CGROUP) +static nxt_int_t nxt_isolation_set_cgroup(nxt_task_t *task, + nxt_conf_value_t *isolation, nxt_process_t *process); +#endif + #if (NXT_HAVE_CLONE) static nxt_int_t nxt_isolation_set_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process); @@ -155,6 +161,14 @@ static nxt_int_t nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process) { +#if (NXT_HAVE_CGROUP) + if (nxt_slow_path(nxt_isolation_set_cgroup(task, isolation, process) + != NXT_OK)) + { + return NXT_ERROR; + } +#endif + #if (NXT_HAVE_CLONE) if (nxt_slow_path(nxt_isolation_set_namespaces(task, isolation, process) != NXT_OK)) @@ -197,6 +211,42 @@ nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, } +#if (NXT_HAVE_CGROUP) + +static nxt_int_t +nxt_isolation_set_cgroup(nxt_task_t *task, nxt_conf_value_t *isolation, + nxt_process_t *process) +{ + nxt_str_t str; + nxt_conf_value_t *obj; + + static nxt_str_t cgname = nxt_string("cgroup"); + static nxt_str_t path = nxt_string("path"); + + obj = nxt_conf_get_object_member(isolation, &cgname, NULL); + if (obj == NULL) { + return NXT_OK; + } + + obj = nxt_conf_get_object_member(obj, &path, NULL); + if (obj == NULL) { + return NXT_ERROR; + } + + nxt_conf_get_string(obj, &str); + process->isolation.cgroup.path = nxt_mp_alloc(process->mem_pool, + str.length + 1); + nxt_memcpy(process->isolation.cgroup.path, str.start, str.length); + process->isolation.cgroup.path[str.length] = '\0'; + + process->isolation.cgroup_cleanup = nxt_cgroup_cleanup; + + return NXT_OK; +} + +#endif + + #if (NXT_HAVE_CLONE) static nxt_int_t diff --git a/src/nxt_js.c b/src/nxt_js.c new file mode 100644 index 00000000..aa3c4af5 --- /dev/null +++ b/src/nxt_js.c @@ -0,0 +1,299 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + + +struct nxt_js_s { + uint32_t index; + njs_vm_t *vm; +}; + + +struct nxt_js_conf_s { + nxt_mp_t *pool; + njs_vm_t *vm; + njs_uint_t protos; + njs_external_t *proto; + nxt_array_t *funcs; +}; + + +njs_int_t nxt_js_proto_id; + + +nxt_js_conf_t * +nxt_js_conf_new(nxt_mp_t *mp) +{ + njs_vm_opt_t opts; + nxt_js_conf_t *jcf; + + jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t)); + if (nxt_slow_path(jcf == NULL)) { + return NULL; + } + + jcf->pool = mp; + + njs_vm_opt_init(&opts); + + jcf->vm = njs_vm_create(&opts); + if (nxt_slow_path(jcf->vm == NULL)) { + return NULL; + } + + jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t)); + if (nxt_slow_path(jcf->funcs == NULL)) { + return NULL; + } + + return jcf; +} + + +void +nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n) +{ + jcf->protos = n; + jcf->proto = proto; +} + + +nxt_js_t * +nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz) +{ + size_t size; + u_char *p, *start; + nxt_js_t *js; + nxt_str_t *func; + + static nxt_str_t func_str = nxt_string("function(uri, host, remoteAddr, " + "args, headers, cookies) {" + " return "); + + /* + * Appending a terminating null character if strz is true. + */ + static nxt_str_t strz_str = nxt_string(" + '\\x00'"); + + size = func_str.length + str->length + 1; + + if (strz) { + size += strz_str.length; + } + + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NULL; + } + + p = start; + + p = nxt_cpymem(p, func_str.start, func_str.length); + p = nxt_cpymem(p, str->start, str->length); + + if (strz) { + p = nxt_cpymem(p, strz_str.start, strz_str.length); + } + + *p++ = '}'; + + js = nxt_mp_get(jcf->pool, sizeof(nxt_js_t)); + if (nxt_slow_path(js == NULL)) { + return NULL; + } + + js->vm = jcf->vm; + + func = nxt_array_add(jcf->funcs); + if (nxt_slow_path(func == NULL)) { + return NULL; + } + + func->start = start; + func->length = p - start; + + js->index = jcf->funcs->nelts - 1; + + return js; +} + + +nxt_int_t +nxt_js_compile(nxt_js_conf_t *jcf) +{ + size_t size; + u_char *p, *start; + njs_int_t ret; + nxt_str_t *func; + nxt_uint_t i; + + size = 2; + func = jcf->funcs->elts; + + for (i = 0; i < jcf->funcs->nelts; i++) { + size += func[i].length + 1; + } + + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + p = start; + *p++ = '['; + + func = jcf->funcs->elts; + + for (i = 0; i < jcf->funcs->nelts; i++) { + p = nxt_cpymem(p, func[i].start, func[i].length); + *p++ = ','; + } + + *p++ = ']'; + + nxt_js_proto_id = njs_vm_external_prototype(jcf->vm, jcf->proto, + jcf->protos); + if (nxt_slow_path(nxt_js_proto_id < 0)) { + return NXT_ERROR; + } + + ret = njs_vm_compile(jcf->vm, &start, p); + + return (ret == NJS_OK) ? NXT_OK : NXT_ERROR; +} + + +nxt_int_t +nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error) +{ + u_char *start; + nxt_str_t err; + njs_int_t ret; + njs_str_t res; + + start = nxt_mp_nget(jcf->pool, str->length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + nxt_memcpy(start, str->start, str->length); + + ret = njs_vm_compile(jcf->vm, &start, start + str->length); + + if (nxt_slow_path(ret != NJS_OK)) { + (void) njs_vm_retval_string(jcf->vm, &res); + + err.start = res.start; + err.length = res.length; + + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err); + + return NXT_ERROR; + } + + return NXT_OK; +} + + +nxt_int_t +nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, + nxt_str_t *str, void *ctx) +{ + njs_vm_t *vm; + njs_int_t rc, ret; + njs_str_t res; + njs_value_t *array, *value; + njs_function_t *func; + njs_opaque_value_t opaque_value, arguments[6]; + + static const njs_str_t uri_str = njs_str("uri"); + static const njs_str_t host_str = njs_str("host"); + static const njs_str_t remote_addr_str = njs_str("remoteAddr"); + static const njs_str_t args_str = njs_str("args"); + static const njs_str_t headers_str = njs_str("headers"); + static const njs_str_t cookies_str = njs_str("cookies"); + + vm = cache->vm; + + if (vm == NULL) { + vm = njs_vm_clone(js->vm, ctx); + if (nxt_slow_path(vm == NULL)) { + return NXT_ERROR; + } + + ret = njs_vm_start(vm); + if (ret != NJS_OK) { + return NXT_ERROR; + } + + array = njs_vm_retval(vm); + + cache->vm = vm; + cache->array = *array; + } + + value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value); + func = njs_value_function(value); + + ret = njs_vm_external_create(vm, njs_value_arg(&opaque_value), + nxt_js_proto_id, ctx, 0); + if (nxt_slow_path(ret != NJS_OK)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &uri_str, + &arguments[0]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &host_str, + &arguments[1]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), + &remote_addr_str, &arguments[2]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &args_str, + &arguments[3]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &headers_str, + &arguments[4]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &cookies_str, + &arguments[5]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + ret = njs_vm_call(vm, func, njs_value_arg(&arguments), 6); + + rc = njs_vm_retval_string(vm, &res); + if (rc != NJS_OK) { + return NXT_ERROR; + } + + if (ret != NJS_OK) { + nxt_alert(task, "js exception: %V", &res); + return NXT_ERROR; + } + + str->length = res.length; + str->start = res.start; + + return NXT_OK; +} diff --git a/src/nxt_js.h b/src/nxt_js.h new file mode 100644 index 00000000..dea43fe3 --- /dev/null +++ b/src/nxt_js.h @@ -0,0 +1,38 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_JS_H_INCLUDED_ +#define _NXT_JS_H_INCLUDED_ + +#if (NXT_HAVE_NJS) + +#include <njs_main.h> + + +typedef struct nxt_js_s nxt_js_t; +typedef struct nxt_js_conf_s nxt_js_conf_t; + + +typedef struct { + njs_vm_t *vm; + njs_value_t array; +} nxt_js_cache_t; + + +nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp); +void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n); +nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz); +nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf); +nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error); +nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, + nxt_str_t *str, void *ctx); + + +extern njs_int_t nxt_js_proto_id; + + +#endif /* NXT_HAVE_NJS */ + +#endif /* _NXT_JS_H_INCLUDED_ */ diff --git a/src/nxt_main.h b/src/nxt_main.h index dca4b6dc..b0cdc2d3 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -59,6 +59,7 @@ typedef uint16_t nxt_port_id_t; #include <nxt_process_type.h> #include <nxt_capability.h> #include <nxt_credential.h> +#include <nxt_fs_mount.h> #include <nxt_fs.h> #include <nxt_process.h> #include <nxt_utf8.h> @@ -67,6 +68,7 @@ typedef uint16_t nxt_port_id_t; #include <nxt_sprintf.h> #include <nxt_parse.h> #include <nxt_var.h> +#include <nxt_tstr.h> /* TODO: remove unused */ diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 39a8e112..de41e8d7 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -191,18 +191,6 @@ static nxt_conf_map_t nxt_python_app_conf[] = { }, { - nxt_string("module"), - NXT_CONF_MAP_STR, - offsetof(nxt_common_app_conf_t, u.python.module), - }, - - { - nxt_string("callable"), - NXT_CONF_MAP_CSTRZ, - offsetof(nxt_common_app_conf_t, u.python.callable), - }, - - { nxt_string("protocol"), NXT_CONF_MAP_STR, offsetof(nxt_common_app_conf_t, u.python.protocol), @@ -1019,6 +1007,10 @@ nxt_main_process_cleanup(nxt_task_t *task, nxt_process_t *process) if (process->isolation.cleanup != NULL) { process->isolation.cleanup(task, process); } + + if (process->isolation.cgroup_cleanup != NULL) { + process->isolation.cgroup_cleanup(task, process); + } } diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index e19b1381..f56135f3 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -295,7 +295,7 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, nxt_tls_init_t *tls_init, nxt_bool_t last) { SSL_CTX *ctx; - const char *ciphers, *ca_certificate; + const char *ca_certificate; nxt_tls_conf_t *conf; STACK_OF(X509_NAME) *list; nxt_tls_bundle_conf_t *bundle; @@ -361,13 +361,13 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, } */ - ciphers = (conf->ciphers != NULL) ? conf->ciphers : "HIGH:!aNULL:!MD5"; - - if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, + if (conf->ciphers) { /* else use system crypto policy */ + if (SSL_CTX_set_cipher_list(ctx, conf->ciphers) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CTX_set_cipher_list(\"%s\") failed", - ciphers); - goto fail; + conf->ciphers); + goto fail; + } } #if (NXT_HAVE_OPENSSL_CONF_CMD) @@ -780,7 +780,7 @@ nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, unsigned char *iv, /* decrypt session ticket */ do { - if (nxt_memcmp(name, ticket[i].name, 16) == 0) { + if (memcmp(name, ticket[i].name, 16) == 0) { goto found; } @@ -1777,7 +1777,11 @@ nxt_openssl_copy_error(u_char *p, u_char *end) clear = 0; for ( ;; ) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + err = ERR_get_error_all(NULL, NULL, NULL, &data, &flags); +#else err = ERR_get_error_line_data(NULL, NULL, &data, &flags); +#endif if (err == 0) { break; } diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index 68ef07eb..126a4684 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -14,22 +14,23 @@ #include <nxt_router.h> #include <nxt_unit.h> #include <nxt_unit_request.h> +#include <nxt_http.h> -#if PHP_VERSION_ID >= 50400 +#if (PHP_VERSION_ID >= 50400) #define NXT_HAVE_PHP_IGNORE_CWD 1 #endif -#if PHP_VERSION_ID >= 70100 +#if (PHP_VERSION_ID >= 70100) #define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1 #else #define NXT_HAVE_PHP_INTERRUPTS 1 #endif -#if PHP_VERSION_ID >= 70000 +#if (PHP_VERSION_ID >= 70000) #define NXT_PHP7 1 #endif -#if PHP_VERSION_ID >= 80000 +#if (PHP_VERSION_ID >= 80000) #define NXT_PHP8 1 #endif @@ -73,7 +74,7 @@ typedef int (*nxt_php_disable_t)(char *p, size_t size); typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC); #endif -#if PHP_VERSION_ID < 70200 +#if (PHP_VERSION_ID < 70200) typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); #endif @@ -100,6 +101,8 @@ static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t); static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t); nxt_inline u_char *nxt_realpath(const void *c); +static nxt_int_t nxt_php_do_301(nxt_unit_request_info_t *req); + static void nxt_php_request_handler(nxt_unit_request_info_t *req); static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r); @@ -139,7 +142,7 @@ static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC); #ifdef NXT_PHP7 -#if PHP_VERSION_ID < 70200 +#if (PHP_VERSION_ID < 70200) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, _IS_BOOL, NULL, 0) #else @@ -355,7 +358,7 @@ static nxt_php_target_t *nxt_php_targets; static nxt_int_t nxt_php_last_target = -1; static nxt_unit_ctx_t *nxt_php_unit_ctx; -#if defined(ZTS) && PHP_VERSION_ID < 70400 +#if defined(ZTS) && (PHP_VERSION_ID < 70400) static void ***tsrm_ls; #endif @@ -377,7 +380,7 @@ nxt_php_setup(nxt_task_t *task, nxt_process_t *process, #ifdef ZTS -#if PHP_VERSION_ID >= 70400 +#if (PHP_VERSION_ID >= 70400) php_tsrm_startup(); #else tsrm_startup(1, 1, 0, NULL); @@ -920,6 +923,63 @@ nxt_realpath(const void *c) } +static nxt_int_t +nxt_php_do_301(nxt_unit_request_info_t *req) +{ + char *p, *url, *port; + uint32_t size; + const char *proto; + nxt_unit_request_t *r; + + r = req->request; + + url = nxt_malloc(sizeof("https://") - 1 + + r->server_name_length + + r->local_port_length + 1 + + r->path_length + 1 + + r->query_length + 1 + + 1); + if (nxt_slow_path(url == NULL)) { + return NXT_UNIT_ERROR; + } + + proto = r->tls ? "https://" : "http://"; + p = nxt_cpymem(url, proto, strlen(proto)); + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->server_name), + r->server_name_length); + + port = nxt_unit_sptr_get(&r->local_port); + if (r->local_port_length > 0 + && !(r->tls && strcmp(port, "443") == 0) + && !(!r->tls && strcmp(port, "80") == 0)) + { + *p++ = ':'; + p = nxt_cpymem(p, port, r->local_port_length); + } + + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->path), r->path_length); + *p++ = '/'; + + if (r->query_length > 0) { + *p++ = '?'; + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->query), r->query_length); + } + + *p = '\0'; + + size = p - url; + + nxt_unit_response_init(req, NXT_HTTP_MOVED_PERMANENTLY, 1, + nxt_length("Location") + size); + nxt_unit_response_add_field(req, "Location", nxt_length("Location"), + url, size); + + nxt_free(url); + + return NXT_UNIT_OK; +} + + static void nxt_php_request_handler(nxt_unit_request_info_t *req) { @@ -975,15 +1035,33 @@ nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) } else if (path.start[path.length - 1] == '/') { script_name = *ctx->index; - } else { - if (nxt_slow_path(path.length < 4 - || nxt_memcmp(path.start + (path.length - 4), - ".php", 4))) - { - nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); + } else if (path.length < 4 + || memcmp(path.start + (path.length - 4), ".php", 4) != 0) + { + char tpath[PATH_MAX]; + nxt_int_t ec; + struct stat sb; + + ec = NXT_UNIT_ERROR; + + if (ctx->root->length + path.length + 1 > PATH_MAX) { + nxt_unit_request_done(ctx->req, ec); return; } + + p = nxt_cpymem(tpath, ctx->root->start, ctx->root->length); + p = nxt_cpymem(p, path.start, path.length); + *p = '\0'; + + ret = stat(tpath, &sb); + if (ret == 0 && S_ISDIR(sb.st_mode)) { + ec = nxt_php_do_301(ctx->req); + } + + nxt_unit_request_done(ctx->req, ec); + + return; } ctx->script_filename.length = ctx->root->length @@ -1150,7 +1228,11 @@ nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir) static int nxt_php_startup(sapi_module_struct *sapi_module) { +#if (PHP_VERSION_ID < 80200) return php_module_startup(sapi_module, &nxt_php_unit_module, 1); +#else + return php_module_startup(sapi_module, &nxt_php_unit_module); +#endif } @@ -1365,7 +1447,7 @@ nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, track_vars_array TSRMLS_CC); - nxt_php_set_sptr(req, "SERVER_ADDR", &r->local, r->local_length, + nxt_php_set_sptr(req, "SERVER_ADDR", &r->local_addr, r->local_addr_length, track_vars_array TSRMLS_CC); nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length, diff --git a/src/nxt_port.c b/src/nxt_port.c index ed7050f3..b9964df4 100644 --- a/src/nxt_port.c +++ b/src/nxt_port.c @@ -144,14 +144,14 @@ nxt_port_release(nxt_task_t *task, nxt_port_t *port) nxt_port_id_t -nxt_port_get_next_id() +nxt_port_get_next_id(void) { return nxt_atomic_fetch_add(&nxt_port_last_id, 1); } void -nxt_port_reset_next_id() +nxt_port_reset_next_id(void) { nxt_port_last_id = 1; } diff --git a/src/nxt_process.c b/src/nxt_process.c index 738a03bf..d8836ad2 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -5,6 +5,7 @@ */ #include <nxt_main.h> +#include <nxt_cgroup.h> #if (NXT_HAVE_CLONE) #include <nxt_clone.h> @@ -378,6 +379,17 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process) nxt_runtime_process_add(task, process); } +#if (NXT_HAVE_CGROUP) + ret = nxt_cgroup_proc_add(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "cgroup: failed to add process %s to %s %E", + process->name, process->isolation.cgroup.path, nxt_errno); + nxt_cgroup_cleanup(task, process); + kill(pid, SIGTERM); + return -1; + } +#endif + return pid; } diff --git a/src/nxt_process.h b/src/nxt_process.h index 15fd4e7f..0db68d45 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -61,8 +61,11 @@ typedef enum { typedef struct nxt_port_mmap_s nxt_port_mmap_t; typedef struct nxt_process_s nxt_process_t; +typedef struct nxt_cgroup_s nxt_cgroup_t; typedef void (*nxt_isolation_cleanup_t)(nxt_task_t *task, nxt_process_t *process); +typedef void (*nxt_cgroup_cleanup_t)(nxt_task_t *task, + const nxt_process_t *process); typedef struct { @@ -80,6 +83,11 @@ typedef struct { } nxt_process_automount_t; +struct nxt_cgroup_s { + char *path; +}; + + typedef struct { u_char *rootfs; nxt_process_automount_t automount; @@ -87,6 +95,11 @@ typedef struct { nxt_isolation_cleanup_t cleanup; + nxt_cgroup_cleanup_t cgroup_cleanup; +#if (NXT_HAVE_CGROUP) + nxt_cgroup_t cgroup; +#endif + #if (NXT_HAVE_CLONE) nxt_clone_t clone; #endif diff --git a/src/nxt_router.c b/src/nxt_router.c index f02bf3f2..edc015c5 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1060,11 +1060,15 @@ 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)) { + rtcf->tstr_state = nxt_tstr_state_new(mp, 0); + if (nxt_slow_path(rtcf->tstr_state == NULL)) { goto fail; } +#if (NXT_HAVE_NJS) + nxt_http_register_js_proto(rtcf->tstr_state->jcf); +#endif + tmp = nxt_mp_create(1024, 128, 256, 32); if (nxt_slow_path(tmp == NULL)) { goto fail; @@ -2042,6 +2046,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } } + ret = nxt_tstr_state_done(rtcf->tstr_state, NULL); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + nxt_queue_add(&deleting_sockets, &router->sockets); nxt_queue_init(&router->sockets); @@ -5249,11 +5258,17 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, r->remote->address_length); *p++ = '\0'; - req->local_length = r->local->address_length; - nxt_unit_sptr_set(&req->local, p); + req->local_addr_length = r->local->address_length; + nxt_unit_sptr_set(&req->local_addr, p); p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); *p++ = '\0'; + req->local_port_length = nxt_sockaddr_port_length(r->local); + nxt_unit_sptr_set(&req->local_port, p); + p = nxt_cpymem(p, nxt_sockaddr_port(r->local), + nxt_sockaddr_port_length(r->local)); + *p++ = '\0'; + req->tls = r->tls; req->websocket_handshake = r->websocket_handshake; diff --git a/src/nxt_router.h b/src/nxt_router.h index a6add219..11094960 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -43,7 +43,7 @@ typedef struct { uint32_t threads; nxt_mp_t *mem_pool; - nxt_array_t *var_fields; /* of nxt_var_field_t */ + nxt_tstr_state_t *tstr_state; nxt_router_t *router; nxt_http_routes_t *routes; @@ -53,7 +53,7 @@ typedef struct { nxt_lvlhsh_t apps_hash; nxt_router_access_log_t *access_log; - nxt_var_t *log_format; + nxt_tstr_t *log_format; } nxt_router_conf_t; @@ -225,7 +225,7 @@ 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_var_t *format); + nxt_tstr_t *format); nxt_fd_t fd; nxt_str_t path; uint32_t count; diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c index dc2a6687..ccbddb96 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -24,7 +24,7 @@ typedef struct { 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_tstr_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, @@ -63,7 +63,7 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, u_char *p; nxt_int_t ret; nxt_str_t str; - nxt_var_t *format; + nxt_tstr_t *format; nxt_router_t *router; nxt_router_access_log_t *access_log; nxt_router_access_log_conf_t alcf; @@ -125,8 +125,7 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, 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); + format = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_LOGGING); if (nxt_slow_path(format == NULL)) { return NXT_ERROR; } @@ -140,9 +139,10 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, 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_router_access_log_t *access_log, nxt_tstr_t *format) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_router_access_log_ctx_t *ctx; ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); @@ -152,21 +152,24 @@ nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, ctx->access_log = access_log; - if (nxt_var_is_const(format)) { - nxt_var_raw(format, &ctx->text); + if (nxt_tstr_is_const(format)) { + nxt_tstr_str(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); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, 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); + nxt_tstr_query(task, r->tstr_query, format, &ctx->text); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_router_access_log_write_ready, + nxt_router_access_log_write_error); } } diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index d9c9f2ef..c7e4455e 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -1369,6 +1369,8 @@ nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file) file.name = pid_file; + nxt_fs_mkdir_parent(pid_file, 0755); + n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, NXT_FILE_DEFAULT_ACCESS); diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h index d7fe2f38..687914f0 100644 --- a/src/nxt_runtime.h +++ b/src/nxt_runtime.h @@ -138,6 +138,9 @@ void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, void nxt_stream_connection_init(nxt_task_t *task, void *obj, void *data); nxt_int_t nxt_http_register_variables(void); +#if (NXT_HAVE_NJS) +void nxt_http_register_js_proto(nxt_js_conf_t *jcf); +#endif #define nxt_runtime_process_each(rt, process) \ diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 86c3335e..32941893 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -382,7 +382,7 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) return 0; } - if (nxt_memcmp(&sa1->u.sockaddr_in6.sin6_addr, + if (memcmp(&sa1->u.sockaddr_in6.sin6_addr, &sa2->u.sockaddr_in6.sin6_addr, 16) != 0) { @@ -401,7 +401,7 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) length = sa1->socklen - offsetof(struct sockaddr_un, sun_path); - if (nxt_memcmp(&sa1->u.sockaddr_un.sun_path, + if (memcmp(&sa1->u.sockaddr_un.sun_path, &sa2->u.sockaddr_un.sun_path, length) != 0) { @@ -550,7 +550,7 @@ nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr) return NULL; } - if (addr->length > 6 && nxt_memcmp(addr->start, "unix:", 5) == 0) { + if (addr->length > 6 && memcmp(addr->start, "unix:", 5) == 0) { sa = nxt_sockaddr_unix_parse(mp, addr); } else if (addr->start[0] == '[' || nxt_inet6_probe(addr)) { @@ -653,7 +653,7 @@ nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr) length = addr->length - 1; start = addr->start + 1; - end = nxt_memchr(start, ']', length); + end = memchr(start, ']', length); if (nxt_slow_path(end == NULL)) { return NULL; } @@ -723,7 +723,7 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) in_addr_t inaddr; nxt_sockaddr_t *sa; - p = nxt_memchr(addr->start, ':', addr->length); + p = memchr(addr->start, ':', addr->length); if (p == NULL) { length = addr->length; @@ -964,11 +964,11 @@ nxt_inet6_probe(nxt_str_t *str) { u_char *colon, *end; - colon = nxt_memchr(str->start, ':', str->length); + colon = memchr(str->start, ':', str->length); if (colon != NULL) { end = str->start + str->length; - colon = nxt_memchr(colon + 1, ':', end - (colon + 1)); + colon = memchr(colon + 1, ':', end - (colon + 1)); } return (colon != NULL); diff --git a/src/nxt_string.c b/src/nxt_string.c index 4d89c23c..1ca595a1 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -257,7 +257,7 @@ nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length) return NULL; } - if (nxt_memcmp(s, s2, length) == 0) { + if (memcmp(s, s2, length) == 0) { return (u_char *) s - 1; } } @@ -325,7 +325,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) c1 = *s1; if (c1 == c2) { - if (nxt_memcmp(s1 + 1, s2, length) == 0) { + if (memcmp(s1 + 1, s2, length) == 0) { return (u_char *) s1; } } diff --git a/src/nxt_string.h b/src/nxt_string.h index a8673c61..18ea5490 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -66,14 +66,6 @@ nxt_cpymem(void *dst, const void *src, size_t length) (void) memmove(dst, src, length) -#define nxt_memcmp(s1, s2, length) \ - memcmp((char *) s1, (char *) s2, length) - - -#define nxt_memchr(s, c, length) \ - memchr((char *) s, c, length) - - #define nxt_strcmp(s1, s2) \ strcmp((char *) s1, (char *) s2) @@ -132,7 +124,7 @@ NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); #define nxt_strstr_eq(s1, s2) \ (((s1)->length == (s2)->length) \ - && (nxt_memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) + && (memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) #define nxt_strcasestr_eq(s1, s2) \ @@ -141,11 +133,11 @@ NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); #define nxt_str_eq(s, p, _length) \ - (((s)->length == _length) && (nxt_memcmp((s)->start, p, _length) == 0)) + (((s)->length == _length) && (memcmp((s)->start, p, _length) == 0)) #define nxt_str_start(s, p, _length) \ - (((s)->length >= _length) && (nxt_memcmp((s)->start, p, _length) == 0)) + (((s)->length >= _length) && (memcmp((s)->start, p, _length) == 0)) #define nxt_strchr_eq(s, c) \ diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c new file mode 100644 index 00000000..fd01797c --- /dev/null +++ b/src/nxt_tstr.c @@ -0,0 +1,317 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + + +typedef enum { + NXT_TSTR_CONST = 0, + NXT_TSTR_VAR, +#if (NXT_HAVE_NJS) + NXT_TSTR_JS, +#endif +} nxt_tstr_type_t; + + +struct nxt_tstr_s { + nxt_str_t str; + + union { + nxt_var_t *var; +#if (NXT_HAVE_NJS) + nxt_js_t *js; +#endif + } u; + + nxt_tstr_flags_t flags; + nxt_tstr_type_t type; +}; + + +struct nxt_tstr_query_s { + nxt_mp_t *pool; + + nxt_tstr_state_t *state; + nxt_tstr_cache_t *cache; + + nxt_uint_t waiting; + nxt_uint_t failed; /* 1 bit */ + + void *ctx; + void *data; + + nxt_work_handler_t ready; + nxt_work_handler_t error; +}; + + +#define nxt_tstr_is_js(str) \ + nxt_strchr_start(str, '`') + + +nxt_tstr_state_t * +nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test) +{ + nxt_tstr_state_t *state; + + state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t)); + if (nxt_slow_path(state == NULL)) { + return NULL; + } + + state->pool = mp; + state->test = test; + + state->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(state->var_fields == NULL)) { + return NULL; + } + +#if (NXT_HAVE_NJS) + state->jcf = nxt_js_conf_new(mp); + if (nxt_slow_path(state->jcf == NULL)) { + return NULL; + } +#endif + + return state; +} + + +nxt_tstr_t * +nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, + nxt_tstr_flags_t flags) +{ + u_char *p; + nxt_tstr_t *tstr; + nxt_bool_t strz; + + strz = (flags & NXT_TSTR_STRZ) != 0; + + tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t)); + if (nxt_slow_path(tstr == NULL)) { + return NULL; + } + + tstr->str.length = str->length + strz; + + tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length); + if (nxt_slow_path(tstr->str.start == NULL)) { + return NULL; + } + + p = nxt_cpymem(tstr->str.start, str->start, str->length); + + if (strz) { + *p = '\0'; + } + + tstr->flags = flags; + + if (nxt_tstr_is_js(str)) { + +#if (NXT_HAVE_NJS) + + nxt_str_t tpl; + + tstr->type = NXT_TSTR_JS; + + nxt_tstr_str(tstr, &tpl); + + tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, strz); + if (nxt_slow_path(tstr->u.js == NULL)) { + return NULL; + } + +#endif + + } else { + p = memchr(str->start, '$', str->length); + + if (p != NULL) { + tstr->type = NXT_TSTR_VAR; + + tstr->u.var = nxt_var_compile(&tstr->str, state->pool, + state->var_fields); + if (nxt_slow_path(tstr->u.var == NULL)) { + return NULL; + } + + } else { + tstr->type = NXT_TSTR_CONST; + } + } + + return tstr; +} + + +nxt_int_t +nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) +{ + u_char *p; + + if (nxt_tstr_is_js(str)) { +#if (NXT_HAVE_NJS) + return nxt_js_test(state->jcf, str, error); + +#else + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, + "Unit is built without support of njs: " + "\"--njs\" ./configure option is missing."); + return NXT_ERROR; +#endif + + } else { + p = memchr(str->start, '$', str->length); + + if (p != NULL) { + return nxt_var_test(str, state->var_fields, error); + } + } + + return NXT_OK; +} + + +nxt_int_t +nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error) +{ +#if (NXT_HAVE_NJS) + if (!state->test) { + nxt_int_t ret; + + ret = nxt_js_compile(state->jcf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } +#endif + + return NXT_OK; +} + + +nxt_bool_t +nxt_tstr_is_const(nxt_tstr_t *tstr) +{ + return (tstr->type == NXT_TSTR_CONST); +} + + +void +nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) +{ + *str = tstr->str; + + if (tstr->flags & NXT_TSTR_STRZ) { + str->length--; + } +} + + +nxt_int_t +nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state, + nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp) +{ + nxt_tstr_query_t *query; + + query = *query_p; + + if (*query_p == NULL) { + query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t)); + if (nxt_slow_path(query == NULL)) { + return NXT_ERROR; + } + } + + query->pool = mp; + query->state = state; + query->cache = cache; + query->ctx = ctx; + + *query_p = query; + + return NXT_OK; +} + + +void +nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, + nxt_str_t *val) +{ + nxt_int_t ret; + + if (nxt_tstr_is_const(tstr)) { + nxt_tstr_str(tstr, val); + return; + } + + if (nxt_slow_path(query->failed)) { + return; + } + + if (tstr->type == NXT_TSTR_VAR) { + ret = nxt_var_interpreter(task, &query->cache->var, tstr->u.var, val, + query->ctx, tstr->flags & NXT_TSTR_LOGGING); + + if (nxt_slow_path(ret != NXT_OK)) { + query->failed = 1; + return; + } + + } else { +#if (NXT_HAVE_NJS) + ret = nxt_js_call(task, &query->cache->js, tstr->u.js, val, query->ctx); + + if (nxt_slow_path(ret != NXT_OK)) { + query->failed = 1; + return; + } +#endif + } + + if (tstr->flags & NXT_TSTR_STRZ) { + val->length--; + } + +#if (NXT_DEBUG) + nxt_str_t str; + + nxt_tstr_str(tstr, &str); + + nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val); +#endif +} + + +void +nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data, + nxt_work_handler_t ready, nxt_work_handler_t error) +{ + query->data = data; + query->ready = ready; + query->error = error; + + if (query->waiting == 0) { + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); + } +} + + +void +nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, + nxt_bool_t failed) +{ + query->failed |= failed; + + if (--query->waiting == 0) { + 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_tstr.h b/src/nxt_tstr.h new file mode 100644 index 00000000..0cc24292 --- /dev/null +++ b/src/nxt_tstr.h @@ -0,0 +1,79 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_TSTR_H_INCLUDED_ +#define _NXT_TSTR_H_INCLUDED_ + + +#include <nxt_js.h> + +typedef struct nxt_tstr_s nxt_tstr_t; +typedef struct nxt_tstr_query_s nxt_tstr_query_t; + + +typedef struct { + nxt_mp_t *pool; + nxt_array_t *var_fields; +#if (NXT_HAVE_NJS) + nxt_js_conf_t *jcf; +#endif + uint8_t test; /* 1 bit */ +} nxt_tstr_state_t; + + +typedef struct { + nxt_var_cache_t var; +#if (NXT_HAVE_NJS) + nxt_js_cache_t js; +#endif +} nxt_tstr_cache_t; + + +typedef enum { + NXT_TSTR_STRZ = 1 << 0, + NXT_TSTR_LOGGING = 1 << 1, +} nxt_tstr_flags_t; + + +nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test); +nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, + nxt_tstr_flags_t flags); +nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error); +nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error); + +nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr); +void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str); + +nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, + nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, void *ctx, + nxt_mp_t *mp); +void nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, + nxt_str_t *val); +void nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, + void *data, nxt_work_handler_t ready, nxt_work_handler_t error); +void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, + nxt_bool_t failed); + + +nxt_inline nxt_bool_t +nxt_is_tstr(nxt_str_t *str) +{ + u_char *p; + + p = memchr(str->start, '`', str->length); + if (p != NULL) { + return 1; + } + + p = memchr(str->start, '$', str->length); + if (p != NULL) { + return 1; + } + + return 0; +} + + +#endif /* _NXT_TSTR_H_INCLUDED_ */ diff --git a/src/nxt_unit.c b/src/nxt_unit.c index e5cb0b58..e1b1897a 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -116,7 +116,7 @@ static int nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd); static void nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, nxt_unit_ctx_impl_t *ctx_impl); -static void nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps); +static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps); nxt_inline void nxt_unit_process_use(nxt_unit_process_t *process); nxt_inline void nxt_unit_process_release(nxt_unit_process_t *process); static void nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps); @@ -196,7 +196,7 @@ 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, const char *end, pid_t pid, +static char * nxt_unit_snprint_prefix(char *p, 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); @@ -606,7 +606,7 @@ nxt_unit_create(nxt_unit_init_t *init) if (nxt_slow_path(rc != 0)) { nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - goto fail; + goto out_unit_free; } lib->unit.data = init->data; @@ -631,17 +631,35 @@ nxt_unit_create(nxt_unit_init_t *init) rc = nxt_unit_ctx_init(lib, &lib->main_ctx, init->ctx_data); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - pthread_mutex_destroy(&lib->mutex); - goto fail; + goto out_mutex_destroy; + } + + rc = nxt_unit_mmaps_init(&lib->incoming); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + + goto out_ctx_free; } - nxt_unit_mmaps_init(&lib->incoming); - nxt_unit_mmaps_init(&lib->outgoing); + rc = nxt_unit_mmaps_init(&lib->outgoing); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + + goto out_mmaps_destroy; + } return lib; -fail: +out_mmaps_destroy: + nxt_unit_mmaps_destroy(&lib->incoming); + +out_ctx_free: + nxt_unit_ctx_free(&lib->main_ctx); + +out_mutex_destroy: + pthread_mutex_destroy(&lib->mutex); +out_unit_free: nxt_unit_free(NULL, lib); return NULL; @@ -4093,15 +4111,15 @@ nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, nxt_unit_ctx_impl_t *ctx_impl) } -static void +static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps) { - pthread_mutex_init(&mmaps->mutex, NULL); - mmaps->size = 0; mmaps->cap = 0; mmaps->elts = NULL; mmaps->allocated_chunks = 0; + + return pthread_mutex_init(&mmaps->mutex, NULL); } @@ -6661,7 +6679,7 @@ static const char * nxt_unit_log_levels[] = { static char * -nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) +nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) { struct tm tm; struct timespec ts; diff --git a/src/nxt_unit_request.h b/src/nxt_unit_request.h index 5dbf648d..a6ebf0b6 100644 --- a/src/nxt_unit_request.h +++ b/src/nxt_unit_request.h @@ -18,7 +18,8 @@ struct nxt_unit_request_s { uint8_t method_length; uint8_t version_length; uint8_t remote_length; - uint8_t local_length; + uint8_t local_addr_length; + uint8_t local_port_length; uint8_t tls; uint8_t websocket_handshake; uint8_t app_target; @@ -38,7 +39,8 @@ struct nxt_unit_request_s { nxt_unit_sptr_t method; nxt_unit_sptr_t version; nxt_unit_sptr_t remote; - nxt_unit_sptr_t local; + nxt_unit_sptr_t local_addr; + nxt_unit_sptr_t local_port; nxt_unit_sptr_t server_name; nxt_unit_sptr_t target; nxt_unit_sptr_t path; diff --git a/src/nxt_var.c b/src/nxt_var.c index f55a2d30..e113969f 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -9,7 +9,6 @@ struct nxt_var_s { size_t length; nxt_uint_t vars; - nxt_var_flags_t flags; u_char data[]; /* @@ -29,8 +28,7 @@ typedef struct { struct nxt_var_query_s { nxt_mp_t *pool; - nxt_lvlhsh_t cache; - nxt_str_t *spare; + nxt_var_cache_t cache; nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -58,11 +56,10 @@ 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_value(nxt_task_t *task, nxt_var_query_t *query, - uint32_t index); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, + uint32_t index, void *ctx); -static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, - nxt_bool_t *is_var); +static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part); static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { @@ -233,21 +230,22 @@ nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) static nxt_str_t * -nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) +nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index, + void *ctx) { nxt_int_t ret; nxt_str_t *value; nxt_lvlhsh_query_t lhq; - value = query->spare; + value = cache->spare; if (value == NULL) { - value = nxt_mp_zget(query->pool, sizeof(nxt_str_t)); + value = nxt_mp_zget(cache->pool, sizeof(nxt_str_t)); if (nxt_slow_path(value == NULL)) { return NULL; } - query->spare = value; + cache->spare = value; } lhq.key_hash = nxt_murmur_hash2_uint32(&index); @@ -256,21 +254,20 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) lhq.key.start = (u_char *) &index; lhq.value = value; lhq.proto = &nxt_var_cache_proto; - lhq.pool = query->pool; + lhq.pool = cache->pool; - ret = nxt_lvlhsh_insert(&query->cache, &lhq); + ret = nxt_lvlhsh_insert(&cache->hash, &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); + ret = nxt_var_index[index >> 16](task, value, ctx, index & 0xffff); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } - query->spare = NULL; + cache->spare = NULL; } return lhq.value; @@ -330,65 +327,55 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_var_flags_t flags) +nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) { 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; - nxt_bool_t is_var; nxt_var_sub_t *subs; nxt_var_decl_t *decl; - strz = (flags & NXT_VAR_STRZ) != 0; - n = 0; p = str->start; end = p + str->length; while (p < end) { - p = nxt_var_next_part(p, end - p, &part, &is_var); + p = nxt_var_next_part(p, end, &part); if (nxt_slow_path(p == NULL)) { return NULL; } - if (is_var) { + if (part.start != NULL) { n++; } } size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; - var = nxt_mp_get(mp, size + strz); + var = nxt_mp_get(mp, size); if (nxt_slow_path(var == NULL)) { return NULL; } var->length = str->length; var->vars = n; - var->flags = flags; subs = nxt_var_subs(var); src = nxt_var_raw_start(var); nxt_memcpy(src, str->start, str->length); - if (strz) { - src[str->length] = '\0'; - } - n = 0; p = str->start; while (p < end) { - next = nxt_var_next_part(p, end - p, &part, &is_var); + next = nxt_var_next_part(p, end, &part); - if (is_var) { + if (part.start != NULL) { decl = nxt_var_decl_get(&part, fields, &index); if (nxt_slow_path(decl == NULL)) { return NULL; @@ -413,14 +400,13 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) { u_char *p, *end, *next; nxt_str_t part; - nxt_bool_t is_var; nxt_var_decl_t *decl; p = str->start; end = p + str->length; while (p < end) { - next = nxt_var_next_part(p, end - p, &part, &is_var); + next = nxt_var_next_part(p, end, &part); if (next == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, @@ -429,7 +415,7 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) return NXT_ERROR; } - if (is_var) { + if (part.start != NULL) { decl = nxt_var_decl_get(&part, fields, NULL); if (decl == NULL) { @@ -448,19 +434,15 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) static u_char * -nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, - nxt_bool_t *is_var) +nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part) { - u_char *p, *end, ch, c; + size_t length; + u_char *p, ch, c; nxt_bool_t bracket; - end = start + length; - - p = nxt_memchr(start, '$', length); + p = memchr(start, '$', end - start); if (p == start) { - *is_var = 1; - p++; if (p == end) { @@ -480,129 +462,74 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, bracket = 0; } + length = 0; start = p; - for ( ;; ) { + while (p < end) { ch = *p; c = (u_char) (ch | 0x20); - if ((c < 'a' || c > 'z') && ch != '_') { - if (bracket && ch != '}') { - return NULL; - } - - break; + if ((c >= 'a' && c <= 'z') || ch == '_') { + p++; + length++; + continue; } - p++; + if (bracket && ch == '}') { + p++; + bracket = 0; + } - if (p == end) { - if (bracket) { - return NULL; - } + break; + } - break; - } + if (bracket || length == 0) { + return NULL; } - length = p - start; - end = p + bracket; + part->length = length; + part->start = start; } else { - *is_var = 0; - - if (p != NULL) { - length = p - start; - end = p; + if (p == NULL) { + p = end; } - } - - part->length = length; - part->start = start; - - return end; -} - - -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) -{ - nxt_var_query_t *query; - - query = *query_p; - if (*query_p == NULL) { - query = nxt_mp_zget(mp, sizeof(nxt_var_query_t)); - if (nxt_slow_path(query == NULL)) { - return NXT_ERROR; - } + nxt_str_null(part); } - query->pool = mp; - query->ctx = ctx; - - *query_p = query; - - return NXT_OK; + return p; } -void -nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, - nxt_str_t *str) +nxt_int_t +nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var, + nxt_str_t *str, void *ctx, nxt_bool_t logging) { 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); - return; - } - - if (nxt_slow_path(query->failed)) { - return; - } - 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; + nxt_array_init(&parts, cache->pool, sizeof(nxt_str_t *)); subs = nxt_var_subs(var); length = var->length; for (i = 0; i < var->vars; i++) { - value = nxt_var_cache_value(task, query, subs[i].index); + value = nxt_var_cache_value(task, cache, subs[i].index, ctx); if (nxt_slow_path(value == NULL)) { - goto fail; + return NXT_ERROR; } part = nxt_array_add(&parts); if (nxt_slow_path(part == NULL)) { - goto fail; + return NXT_ERROR; } *part = value; @@ -614,9 +541,9 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, } } - p = nxt_mp_nget(query->pool, length + strz); + p = nxt_mp_nget(cache->pool, length); if (nxt_slow_path(p == NULL)) { - goto fail; + return NXT_ERROR; } str->length = length; @@ -647,45 +574,5 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, p = nxt_cpymem(p, &src[last], var->length - last); } - if (strz) { - *p = '\0'; - } - - nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str); - - return; - -fail: - - query->failed = 1; -} - - -void -nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, - nxt_work_handler_t ready, nxt_work_handler_t error) -{ - query->data = data; - query->ready = ready; - query->error = error; - - if (query->waiting == 0) { - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); - } -} - - -void -nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, - nxt_bool_t failed) -{ - query->failed |= failed; - - if (--query->waiting == 0) { - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); - } + return NXT_OK; } diff --git a/src/nxt_var.h b/src/nxt_var.h index cc7ff502..ab25800d 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -32,17 +32,11 @@ typedef struct { } 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) -{ - return (nxt_memchr(str->start, '$', str->length) != NULL); -} +typedef struct { + nxt_mp_t *pool; + nxt_lvlhsh_t hash; + nxt_str_t *spare; +} nxt_var_cache_t; nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); @@ -50,21 +44,13 @@ nxt_int_t nxt_var_index_init(void); 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_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields); 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); -void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, - nxt_var_t *var, nxt_str_t *str); -void nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, - nxt_work_handler_t ready, nxt_work_handler_t error); -void nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, - nxt_bool_t failed); +nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, + nxt_var_t *var, nxt_str_t *str, void *ctx, nxt_bool_t logging); +nxt_str_t *nxt_var_get(nxt_task_t *task, nxt_var_cache_t *cache, + nxt_str_t *name, void *ctx); #endif /* _NXT_VAR_H_INCLUDED_ */ diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c index 08a6f29e..5e8d1aee 100644 --- a/src/perl/nxt_perl_psgi.c +++ b/src/perl/nxt_perl_psgi.c @@ -671,7 +671,7 @@ nxt_perl_psgi_env_create(PerlInterpreter *my_perl, RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REMOTE_ADDR"), &r->remote, r->remote_length)); RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_ADDR"), - &r->local, r->local_length)); + &r->local_addr, r->local_addr_length)); RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_NAME"), &r->server_name, r->server_name_length)); @@ -765,7 +765,7 @@ nxt_perl_psgi_result_status(PerlInterpreter *my_perl, SV *result) status.start = (u_char *) SvPV(*sv_status, status.length); - space = nxt_memchr(status.start, ' ', status.length); + space = memchr(status.start, ' ', status.length); if (space != NULL) { status.length = space - status.start; } diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 188c4920..bdb04579 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -22,10 +22,16 @@ typedef struct { } nxt_py_thread_info_t; +#if PY_MAJOR_VERSION == 3 +static nxt_int_t nxt_python3_init_config(nxt_int_t pep405); +#endif + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, nxt_conf_value_t *conf); +nxt_inline nxt_int_t nxt_python_set_prefix(nxt_task_t *task, + nxt_python_target_t *target, nxt_conf_value_t *value); static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value); static int nxt_python_init_threads(nxt_python_app_conf_t *c); static int nxt_python_ready_handler(nxt_unit_ctx_t *ctx); @@ -64,13 +70,70 @@ static nxt_py_thread_info_t *nxt_py_threads; static nxt_python_proto_t nxt_py_proto; +#if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 8) + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + PyStatus status; + PyConfig config; + + PyConfig_InitIsolatedConfig(&config); + + if (pep405) { + status = PyConfig_SetString(&config, &config.program_name, + nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + + } else { + status =PyConfig_SetString(&config, &config.home, nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + PyConfig_Clear(&config); + + return NXT_OK; + +pyinit_exception: + + PyConfig_Clear(&config); + + return NXT_ERROR; +} + +#elif PY_MAJOR_VERSION == 3 + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + if (pep405) { + Py_SetProgramName(nxt_py_home); + + } else { + Py_SetPythonHome(nxt_py_home); + } + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) { int rc; size_t len, size; uint32_t next; - PyObject *obj, *module; + PyObject *obj; nxt_str_t proto, probe_proto, name; nxt_int_t ret, n, i; nxt_unit_ctx_t *unit_ctx; @@ -127,11 +190,15 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) if (pep405) { mbstowcs(nxt_py_home, c->home, len); mbstowcs(nxt_py_home + len, bin_python, sizeof(bin_python)); - Py_SetProgramName(nxt_py_home); } else { mbstowcs(nxt_py_home, c->home, len + 1); - Py_SetPythonHome(nxt_py_home); + } + + ret = nxt_python3_init_config(pep405); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_alert(task, "Failed to initialise config"); + return NXT_ERROR; } #else @@ -154,7 +221,6 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) } #endif - module = NULL; obj = NULL; python_init.ctx_data = NULL; @@ -307,7 +373,6 @@ fail: } Py_XDECREF(obj); - Py_XDECREF(module); nxt_python_atexit(); @@ -326,6 +391,7 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, static nxt_str_t module_str = nxt_string("module"); static nxt_str_t callable_str = nxt_string("callable"); + static nxt_str_t prefix_str = nxt_string("prefix"); module = obj = NULL; @@ -373,6 +439,11 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, goto fail; } + value = nxt_conf_get_object_member(conf, &prefix_str, NULL); + if (nxt_slow_path(nxt_python_set_prefix(task, target, value) != NXT_OK)) { + goto fail; + } + target->application = obj; obj = NULL; @@ -390,6 +461,48 @@ fail: } +nxt_inline nxt_int_t +nxt_python_set_prefix(nxt_task_t *task, nxt_python_target_t *target, + nxt_conf_value_t *value) +{ + u_char *prefix; + nxt_str_t str; + + if (value == NULL) { + return NXT_OK; + } + + nxt_conf_get_string(value, &str); + + if (str.length == 0) { + return NXT_OK; + } + + if (str.start[str.length - 1] == '/') { + str.length--; + } + target->prefix.length = str.length; + prefix = nxt_malloc(str.length); + if (nxt_slow_path(prefix == NULL)) { + nxt_alert(task, "Failed to allocate target prefix string"); + return NXT_ERROR; + } + + target->py_prefix = PyString_FromStringAndSize((char *)str.start, + str.length); + if (nxt_slow_path(target->py_prefix == NULL)) { + nxt_free(prefix); + nxt_alert(task, "Python failed to allocate target prefix " + "string"); + return NXT_ERROR; + } + nxt_memcpy(prefix, str.start, str.length); + target->prefix.start = prefix; + + return NXT_OK; +} + + static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) { @@ -667,7 +780,8 @@ nxt_python_done_strings(nxt_python_string_t *pstr) static void nxt_python_atexit(void) { - nxt_int_t i; + nxt_int_t i; + nxt_python_target_t *target; if (nxt_py_proto.done != NULL) { nxt_py_proto.done(); @@ -677,7 +791,12 @@ nxt_python_atexit(void) if (nxt_py_targets != NULL) { for (i = 0; i < nxt_py_targets->count; i++) { - Py_XDECREF(nxt_py_targets->target[i].application); + target = &nxt_py_targets->target[i]; + + Py_XDECREF(target->application); + Py_XDECREF(target->py_prefix); + + nxt_free(target->prefix.start); } nxt_unit_free(NULL, nxt_py_targets); diff --git a/src/python/nxt_python.h b/src/python/nxt_python.h index eddb1cfc..37e6265e 100644 --- a/src/python/nxt_python.h +++ b/src/python/nxt_python.h @@ -40,6 +40,8 @@ typedef struct { PyObject *application; + PyObject *py_prefix; + nxt_str_t prefix; nxt_bool_t asgi_legacy; } nxt_python_target_t; diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 4ad0857d..587a17cf 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -27,7 +27,8 @@ static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); 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_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target); 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, @@ -455,16 +456,16 @@ nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) goto release_send; } - scope = nxt_py_asgi_create_http_scope(req); + req->data = asgi; + target = &nxt_py_targets->target[req->request->app_target]; + + scope = nxt_py_asgi_create_http_scope(req, target); if (nxt_slow_path(scope == NULL)) { nxt_unit_request_done(req, NXT_UNIT_ERROR); goto release_done; } - req->data = asgi; - target = &nxt_py_targets->target[req->request->app_target]; - if (!target->asgi_legacy) { nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); @@ -573,12 +574,14 @@ 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) +nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target) { char *p, *target, *query; - uint32_t target_length, i; + uint32_t target_length, i, path_length; PyObject *scope, *v, *type, *scheme; PyObject *headers, *header; + nxt_str_t prefix; nxt_unit_field_t *f; nxt_unit_request_t *r; @@ -612,6 +615,17 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) return NULL; } + prefix = app_target->prefix; + path_length = r->path_length; + p = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && p[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, p, prefix.length) == 0) + { + SET_ITEM(scope, root_path, app_target->py_prefix); + } + p = nxt_unit_sptr_get(&r->version); SET_ITEM(scope, http_version, p[7] == '1' ? nxt_py_1_1_str : nxt_py_1_0_str) @@ -674,7 +688,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, client, v) Py_DECREF(v); - v = nxt_py_asgi_create_address(&r->local, r->local_length, 80); + v = nxt_py_asgi_create_address(&r->local_addr, r->local_addr_length, 80); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'server' pair"); goto fail; @@ -738,42 +752,40 @@ fail: static PyObject * nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) { +#if (NXT_HAVE_UNIX_DOMAIN) size_t prefix_len; - nxt_str_t addr; PyObject *pair, *v; + nxt_str_t addr; 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_str_start(&addr, "unix:", prefix_len)) { -#if NXT_HAVE_UNIX_DOMAIN - pair = PyTuple_New(2); - if (nxt_slow_path(pair == NULL)) { - return NULL; - } + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } - addr.start += prefix_len; - addr.length -= prefix_len; + 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); + v = PyString_FromStringAndSize((const char *) addr.start, addr.length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); - return NULL; - } + return NULL; + } - PyTuple_SET_ITEM(pair, 0, v); - PyTuple_SET_ITEM(pair, 1, Py_None); + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); - return pair; + return pair; + } -#else - return NULL; #endif + return nxt_py_asgi_create_ip_address(sptr, len, port); } diff --git a/src/python/nxt_python_asgi_str.c b/src/python/nxt_python_asgi_str.c index 34422973..7171d52b 100644 --- a/src/python/nxt_python_asgi_str.c +++ b/src/python/nxt_python_asgi_str.c @@ -99,7 +99,7 @@ static nxt_python_string_t nxt_py_asgi_strings[] = { { nxt_string("query_string"), &nxt_py_query_string_str }, { nxt_string("raw_path"), &nxt_py_raw_path_str }, { nxt_string("result"), &nxt_py_result_str }, - { nxt_string("root_path"), &nxt_py_root_path_str }, // not used + { nxt_string("root_path"), &nxt_py_root_path_str }, { nxt_string("scheme"), &nxt_py_scheme_str }, { nxt_string("server"), &nxt_py_server_str }, { nxt_string("set_exception"), &nxt_py_set_exception_str }, diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 87dcfaa2..dfb31509 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -60,9 +60,14 @@ static void nxt_python_request_handler(nxt_unit_request_info_t *req); static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c); static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); -static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx); +static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target); static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size); +static int nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size); +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value); static int nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, int n, uint32_t vl); static PyObject *nxt_python_field_name(const char *name, uint8_t len); @@ -137,6 +142,7 @@ static PyObject *nxt_py_query_string_str; static PyObject *nxt_py_remote_addr_str; static PyObject *nxt_py_request_method_str; static PyObject *nxt_py_request_uri_str; +static PyObject *nxt_py_script_name_str; static PyObject *nxt_py_server_addr_str; static PyObject *nxt_py_server_name_str; static PyObject *nxt_py_server_port_str; @@ -156,6 +162,7 @@ static nxt_python_string_t nxt_python_strings[] = { { nxt_string("REMOTE_ADDR"), &nxt_py_remote_addr_str }, { nxt_string("REQUEST_METHOD"), &nxt_py_request_method_str }, { nxt_string("REQUEST_URI"), &nxt_py_request_uri_str }, + { nxt_string("SCRIPT_NAME"), &nxt_py_script_name_str }, { nxt_string("SERVER_ADDR"), &nxt_py_server_addr_str }, { nxt_string("SERVER_NAME"), &nxt_py_server_name_str }, { nxt_string("SERVER_PORT"), &nxt_py_server_port_str }, @@ -300,11 +307,12 @@ nxt_python_wsgi_done(void) static void nxt_python_request_handler(nxt_unit_request_info_t *req) { - int rc; - PyObject *environ, *args, *response, *iterator, *item; - PyObject *close, *result, *application; - nxt_bool_t prepare_environ; - nxt_python_ctx_t *pctx; + int rc; + PyObject *environ, *args, *response, *iterator, *item; + PyObject *close, *result; + nxt_bool_t prepare_environ; + nxt_python_ctx_t *pctx; + nxt_python_target_t *target; pctx = req->ctx->data; @@ -327,7 +335,9 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) prepare_environ = 1; - environ = nxt_python_get_environ(pctx); + target = &nxt_py_targets->target[req->request->app_target]; + + environ = nxt_python_get_environ(pctx, target); if (nxt_slow_path(environ == NULL)) { rc = NXT_UNIT_ERROR; goto done; @@ -348,8 +358,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) Py_INCREF(pctx->start_resp); PyTuple_SET_ITEM(args, 1, pctx->start_resp); - application = nxt_py_targets->target[req->request->app_target].application; - response = PyObject_CallObject(application, args); + response = PyObject_CallObject(target->application, args); Py_DECREF(args); @@ -580,11 +589,14 @@ nxt_python_copy_environ(nxt_unit_request_info_t *req) static PyObject * -nxt_python_get_environ(nxt_python_ctx_t *pctx) +nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target) { int rc; - uint32_t i, j, vl; + char *path; + uint32_t i, j, vl, path_length; PyObject *environ; + nxt_str_t prefix; nxt_unit_field_t *f, *f2; nxt_unit_request_t *r; @@ -604,13 +616,28 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) r->target_length)); RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query, r->query_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_path_info_str, &r->path, - r->path_length)); + + prefix = app_target->prefix; + path_length = r->path_length; + path = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && path[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, path, prefix.length) == 0) + { + RC(nxt_python_add_py_string(pctx, nxt_py_script_name_str, + app_target->py_prefix)); + + path += prefix.length; + path_length -= prefix.length; + } + + RC(nxt_python_add_char(pctx, nxt_py_path_info_str, path, path_length)); RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, r->remote_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local, - r->local_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local_addr, + r->local_addr_length)); if (r->tls) { RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, @@ -692,10 +719,16 @@ static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size) { - char *src; - PyObject *value; + return nxt_python_add_char(pctx, name, nxt_unit_sptr_get(sptr), size); +} + - src = nxt_unit_sptr_get(sptr); +static int +nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size) +{ + int res; + PyObject *value; value = PyString_FromStringAndSize(src, size); if (nxt_slow_path(value == NULL)) { @@ -707,17 +740,25 @@ nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, return NXT_UNIT_ERROR; } + res = nxt_python_add_py_string(pctx, name, value); + + Py_DECREF(value); + + return res; +} + + +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value) +{ if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { nxt_unit_req_error(pctx->req, "Python failed to set the \"%s\" environ value", PyUnicode_AsUTF8(name)); - Py_DECREF(value); return NXT_UNIT_ERROR; } - Py_DECREF(value); - return NXT_UNIT_OK; } diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index f316d8a5..bcb48f6b 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -480,14 +480,19 @@ nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init) rackup = rb_protect(nxt_ruby_rack_parse_script, (VALUE) (uintptr_t) rack_init, &state); - if (nxt_slow_path(TYPE(rackup) != T_ARRAY || state != 0)) { + + if (nxt_slow_path(state != 0)) { nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Failed to parse rack script"); return Qnil; } + if (TYPE(rackup) != T_ARRAY) { + return rackup; + } + if (nxt_slow_path(RARRAY_LEN(rackup) < 1)) { - nxt_alert(rack_init->task, "Ruby: Invalid rack config file"); + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Invalid rack config file"); return Qnil; } @@ -747,8 +752,8 @@ nxt_ruby_read_request(nxt_unit_request_info_t *req, VALUE hash_env) r->version_length); nxt_ruby_add_sptr(hash_env, nxt_rb_remote_addr_str, &r->remote, r->remote_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local, - r->local_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local_addr, + r->local_addr_length); nxt_ruby_add_sptr(hash_env, nxt_rb_server_name_str, &r->server_name, r->server_name_length); diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c index 540309c1..5f1a518c 100644 --- a/src/test/nxt_http_parse_test.c +++ b/src/test/nxt_http_parse_test.c @@ -753,7 +753,7 @@ nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, return NXT_ERROR; } - if (nxt_memcmp(rp->version.str, test->version, 8) != 0) { + if (memcmp(rp->version.str, test->version, 8) != 0) { nxt_log_alert(log, "http parse test case failed:\n" " - request:\n\"%V\"\n" " - version: \"%*s\" (expected: \"%*s\")", request, diff --git a/src/test/nxt_tests.c b/src/test/nxt_tests.c index f5a1cbd4..03a2a1df 100644 --- a/src/test/nxt_tests.c +++ b/src/test/nxt_tests.c @@ -41,7 +41,7 @@ main(int argc, char **argv) #if (NXT_TEST_RTDTSC) if (nxt_process_argv[1] != NULL - && nxt_memcmp(nxt_process_argv[1], "rbm", 3) == 0) + && memcmp(nxt_process_argv[1], "rbm", 3) == 0) { if (nxt_rbtree1_mb_start(thr) != NXT_OK) { return 1; diff --git a/src/test/nxt_unit_app_test.c b/src/test/nxt_unit_app_test.c index 8fda9740..d83bd83a 100644 --- a/src/test/nxt_unit_app_test.c +++ b/src/test/nxt_unit_app_test.c @@ -225,7 +225,7 @@ greeting_app_request_handler(nxt_unit_request_info_t *req) *p++ = '\n'; p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR)); - p = copy(p, nxt_unit_sptr_get(&r->local), r->local_length); + p = copy(p, nxt_unit_sptr_get(&r->local_addr), r->local_addr_length); *p++ = '\n'; p = copy(p, TARGET, nxt_length(TARGET)); diff --git a/src/test/nxt_unit_websocket_chat.c b/src/test/nxt_unit_websocket_chat.c index 39f8a440..ec7c2cc3 100644 --- a/src/test/nxt_unit_websocket_chat.c +++ b/src/test/nxt_unit_websocket_chat.c @@ -201,7 +201,7 @@ ws_chat_close_handler(nxt_unit_request_info_t *req) int -main() +main(void) { nxt_unit_ctx_t *ctx; nxt_unit_init_t init; diff --git a/src/test/nxt_unit_websocket_echo.c b/src/test/nxt_unit_websocket_echo.c index 2a89cdc0..eab2e45f 100644 --- a/src/test/nxt_unit_websocket_echo.c +++ b/src/test/nxt_unit_websocket_echo.c @@ -83,7 +83,7 @@ ws_echo_websocket_handler(nxt_unit_websocket_frame_t *ws) int -main() +main(void) { nxt_unit_ctx_t *ctx; nxt_unit_init_t init; diff --git a/src/test/nxt_utf8_file_name_test.c b/src/test/nxt_utf8_file_name_test.c index 30546ffb..5723e19b 100644 --- a/src/test/nxt_utf8_file_name_test.c +++ b/src/test/nxt_utf8_file_name_test.c @@ -129,7 +129,7 @@ nxt_utf8_file_name_test(nxt_thread_t *thr) nxt_file_close(&task, &lc_file); - if (n != 4 || nxt_memcmp(utf8, test, 4) != 0) { + if (n != 4 || memcmp(utf8, test, 4) != 0) { nxt_log_alert(thr->log, "nxt_file_read() mismatch"); nxt_file_delete(lc_file.name); diff --git a/src/test/nxt_utf8_test.c b/src/test/nxt_utf8_test.c index bca9a737..31e5bff9 100644 --- a/src/test/nxt_utf8_test.c +++ b/src/test/nxt_utf8_test.c @@ -59,7 +59,7 @@ nxt_utf8_overlong(nxt_thread_t *thr, u_char *overlong, size_t len) size = (p != NULL) ? p - utf8 : 0; - if (len != size || nxt_memcmp(overlong, utf8, size) != 0) { + if (len != size || memcmp(overlong, utf8, size) != 0) { u = 0; for (i = 0; i < len; i++) { |