NJS: supported loadable modules.
This commit is contained in:
parent
56af7bb825
commit
a3c3a29493
16 changed files with 1592 additions and 51 deletions
|
@ -124,7 +124,7 @@ NXT_LIB_PCRE_SRCS="src/nxt_pcre.c"
|
|||
NXT_LIB_PCRE2_SRCS="src/nxt_pcre2.c"
|
||||
|
||||
if [ "$NXT_NJS" != "NO" ]; then
|
||||
NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_js.c src/nxt_http_js.c"
|
||||
NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_js.c src/nxt_http_js.c src/nxt_script.c"
|
||||
fi
|
||||
|
||||
NXT_LIB_EPOLL_SRCS="src/nxt_epoll_engine.c"
|
||||
|
|
|
@ -38,6 +38,12 @@ basic URI rewrite support.
|
|||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
njs loadable modules support.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
added conditional logging of route selection for HTTP requests.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <nxt_main.h>
|
||||
#include <nxt_conf.h>
|
||||
#include <nxt_cert.h>
|
||||
#include <nxt_script.h>
|
||||
#include <nxt_router.h>
|
||||
#include <nxt_http.h>
|
||||
#include <nxt_sockaddr.h>
|
||||
|
@ -226,6 +227,13 @@ static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt,
|
|||
nxt_conf_value_t *value, void *data);
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
static nxt_int_t nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value, void *data);
|
||||
static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value);
|
||||
#endif
|
||||
|
||||
|
||||
static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[];
|
||||
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[];
|
||||
|
@ -297,6 +305,12 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = {
|
|||
.type = NXT_CONF_VLDT_OBJECT,
|
||||
.validator = nxt_conf_vldt_object,
|
||||
.u.members = nxt_conf_vldt_http_members,
|
||||
#if (NXT_HAVE_NJS)
|
||||
}, {
|
||||
.name = nxt_string("js_module"),
|
||||
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
||||
.validator = nxt_conf_vldt_js_module,
|
||||
#endif
|
||||
},
|
||||
|
||||
NXT_CONF_VLDT_END
|
||||
|
@ -1306,35 +1320,26 @@ nxt_conf_validate(nxt_conf_validation_t *vldt)
|
|||
|
||||
vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1);
|
||||
if (nxt_slow_path(vldt->tstr_state == NULL)) {
|
||||
ret = NXT_ERROR;
|
||||
goto fail;
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
|
||||
if (ret != NXT_OK) {
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
|
||||
if (ret != NXT_OK) {
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nxt_tstr_state_done(vldt->tstr_state, error);
|
||||
if (ret != NXT_OK) {
|
||||
ret = nxt_conf_vldt_error(vldt, "%s", error);
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxt_tstr_state_release(vldt->tstr_state);
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
nxt_tstr_state_release(vldt->tstr_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3241,6 +3246,49 @@ nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
|
|||
}
|
||||
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
|
||||
static nxt_int_t
|
||||
nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
||||
void *data)
|
||||
{
|
||||
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
||||
return nxt_conf_vldt_array_iterator(vldt, value,
|
||||
&nxt_conf_vldt_js_module_element);
|
||||
}
|
||||
|
||||
/* NXT_CONF_STRING */
|
||||
|
||||
return nxt_conf_vldt_js_module_element(vldt, value);
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value)
|
||||
{
|
||||
nxt_str_t name;
|
||||
nxt_conf_value_t *module;
|
||||
|
||||
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
||||
return nxt_conf_vldt_error(vldt, "The \"js_module\" array must "
|
||||
"contain only string values.");
|
||||
}
|
||||
|
||||
nxt_conf_get_string(value, &name);
|
||||
|
||||
module = nxt_script_info_get(&name);
|
||||
if (module == NULL) {
|
||||
return nxt_conf_vldt_error(vldt, "JS module \"%V\" is not found.",
|
||||
&name);
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t path;
|
||||
nxt_str_t format;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <nxt_conf.h>
|
||||
#include <nxt_status.h>
|
||||
#include <nxt_cert.h>
|
||||
#include <nxt_script.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -101,6 +102,15 @@ static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name);
|
|||
static void nxt_controller_cert_cleanup(nxt_task_t *task, void *obj,
|
||||
void *data);
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
static void nxt_controller_process_script(nxt_task_t *task,
|
||||
nxt_controller_request_t *req, nxt_str_t *path);
|
||||
static void nxt_controller_process_script_save(nxt_task_t *task,
|
||||
nxt_port_recv_msg_t *msg, void *data);
|
||||
static nxt_bool_t nxt_controller_script_in_use(nxt_str_t *name);
|
||||
static void nxt_controller_script_cleanup(nxt_task_t *task, void *obj,
|
||||
void *data);
|
||||
#endif
|
||||
static void nxt_controller_process_control(nxt_task_t *task,
|
||||
nxt_controller_request_t *req, nxt_str_t *path);
|
||||
static void nxt_controller_app_restart_handler(nxt_task_t *task,
|
||||
|
@ -213,6 +223,13 @@ nxt_controller_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
|
|||
nxt_mp_cleanup(mp, nxt_controller_cert_cleanup, task, ctrl_init.certs, rt);
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
ctrl_init.scripts = nxt_script_store_load(task, mp);
|
||||
|
||||
nxt_mp_cleanup(mp, nxt_controller_script_cleanup, task, ctrl_init.scripts,
|
||||
rt);
|
||||
#endif
|
||||
|
||||
process->data.controller = ctrl_init;
|
||||
|
||||
return NXT_OK;
|
||||
|
@ -321,6 +338,13 @@ nxt_controller_start(nxt_task_t *task, nxt_process_data_t *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
if (init->scripts != NULL) {
|
||||
nxt_script_info_init(task, init->scripts);
|
||||
nxt_script_store_release(init->scripts);
|
||||
}
|
||||
#endif
|
||||
|
||||
json = &init->conf;
|
||||
|
||||
if (json->start == NULL) {
|
||||
|
@ -1047,9 +1071,19 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
|
|||
nxt_controller_response_t resp;
|
||||
#if (NXT_TLS)
|
||||
nxt_conf_value_t *certs;
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_conf_value_t *scripts;
|
||||
#endif
|
||||
|
||||
#if (NXT_TLS)
|
||||
static nxt_str_t certificates = nxt_string("certificates");
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
static nxt_str_t scripts_str = nxt_string("js_modules");
|
||||
#endif
|
||||
|
||||
static nxt_str_t config = nxt_string("config");
|
||||
static nxt_str_t status = nxt_string("status");
|
||||
|
||||
|
@ -1118,6 +1152,25 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
|
|||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
|
||||
if (nxt_str_start(&path, "/js_modules", 11)
|
||||
&& (path.length == 11 || path.start[11] == '/'))
|
||||
{
|
||||
if (path.length == 11) {
|
||||
path.length = 1;
|
||||
|
||||
} else {
|
||||
path.length -= 11;
|
||||
path.start += 11;
|
||||
}
|
||||
|
||||
nxt_controller_process_script(task, req, &path);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (nxt_str_start(&path, "/control/", 9)) {
|
||||
|
@ -1143,6 +1196,9 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
|
|||
#if (NXT_TLS)
|
||||
count++;
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
count++;
|
||||
#endif
|
||||
|
||||
value = nxt_conf_create_object(c->mem_pool, count);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
|
@ -1160,6 +1216,15 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
|
|||
nxt_conf_set_member(value, &certificates, certs, i++);
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
scripts = nxt_script_info_get_all(c->mem_pool);
|
||||
if (nxt_slow_path(scripts == NULL)) {
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
nxt_conf_set_member(value, &scripts_str, scripts, i++);
|
||||
#endif
|
||||
|
||||
nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++);
|
||||
nxt_conf_set_member(value, &status, nxt_controller_status, i);
|
||||
|
||||
|
@ -1879,6 +1944,294 @@ nxt_controller_cert_in_use(nxt_str_t *name)
|
|||
#endif
|
||||
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
|
||||
static void
|
||||
nxt_controller_process_script(nxt_task_t *task,
|
||||
nxt_controller_request_t *req, nxt_str_t *path)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_int_t ret;
|
||||
nxt_str_t name;
|
||||
nxt_conn_t *c;
|
||||
nxt_script_t *script;
|
||||
nxt_buf_mem_t *bm;
|
||||
nxt_conf_value_t *value;
|
||||
nxt_controller_response_t resp;
|
||||
u_char error[NXT_MAX_ERROR_STR];
|
||||
|
||||
name.length = path->length - 1;
|
||||
name.start = path->start + 1;
|
||||
|
||||
p = memchr(name.start, '/', name.length);
|
||||
|
||||
if (p != NULL) {
|
||||
name.length = p - name.start;
|
||||
|
||||
path->length -= p - path->start;
|
||||
path->start = p;
|
||||
|
||||
} else {
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
nxt_memzero(&resp, sizeof(nxt_controller_response_t));
|
||||
|
||||
c = req->conn;
|
||||
|
||||
if (nxt_str_eq(&req->parser.method, "GET", 3)) {
|
||||
|
||||
if (name.length != 0) {
|
||||
value = nxt_script_info_get(&name);
|
||||
if (value == NULL) {
|
||||
goto script_not_found;
|
||||
}
|
||||
|
||||
if (path != NULL) {
|
||||
value = nxt_conf_get_path(value, path);
|
||||
if (value == NULL) {
|
||||
goto not_found;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
value = nxt_script_info_get_all(c->mem_pool);
|
||||
if (value == NULL) {
|
||||
goto alloc_fail;
|
||||
}
|
||||
}
|
||||
|
||||
resp.status = 200;
|
||||
resp.conf = value;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name.length == 0 || path != NULL) {
|
||||
goto invalid_name;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&req->parser.method, "PUT", 3)) {
|
||||
value = nxt_script_info_get(&name);
|
||||
if (value != NULL) {
|
||||
goto exists_script;
|
||||
}
|
||||
|
||||
bm = &c->read->mem;
|
||||
|
||||
script = nxt_script_new(task, &name, bm->pos,
|
||||
nxt_buf_mem_used_size(bm), error);
|
||||
if (script == NULL) {
|
||||
goto invalid_script;
|
||||
}
|
||||
|
||||
ret = nxt_script_info_save(&name, script);
|
||||
|
||||
nxt_script_destroy(script);
|
||||
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
nxt_script_store_get(task, &name, c->mem_pool,
|
||||
nxt_controller_process_script_save, req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&req->parser.method, "DELETE", 6)) {
|
||||
|
||||
if (nxt_controller_script_in_use(&name)) {
|
||||
goto script_in_use;
|
||||
}
|
||||
|
||||
if (nxt_script_info_delete(&name) != NXT_OK) {
|
||||
goto script_not_found;
|
||||
}
|
||||
|
||||
nxt_script_store_delete(task, &name, c->mem_pool);
|
||||
|
||||
resp.status = 200;
|
||||
resp.title = (u_char *) "JS module deleted.";
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
}
|
||||
|
||||
resp.status = 405;
|
||||
resp.title = (u_char *) "Invalid method.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
invalid_name:
|
||||
|
||||
resp.status = 400;
|
||||
resp.title = (u_char *) "Invalid JS module name.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
invalid_script:
|
||||
|
||||
resp.status = 400;
|
||||
resp.title = (u_char *) "Invalid JS module.";
|
||||
resp.offset = -1;
|
||||
|
||||
resp.detail.start = error;
|
||||
resp.detail.length = nxt_strlen(error);
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
exists_script:
|
||||
|
||||
resp.status = 400;
|
||||
resp.title = (u_char *) "JS module already exists.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
script_in_use:
|
||||
|
||||
resp.status = 400;
|
||||
resp.title = (u_char *) "JS module is used in the configuration.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
script_not_found:
|
||||
|
||||
resp.status = 404;
|
||||
resp.title = (u_char *) "JS module doesn't exist.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
not_found:
|
||||
|
||||
resp.status = 404;
|
||||
resp.title = (u_char *) "Invalid path.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
|
||||
alloc_fail:
|
||||
|
||||
resp.status = 500;
|
||||
resp.title = (u_char *) "Memory allocation failed.";
|
||||
resp.offset = -1;
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_controller_process_script_save(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
void *data)
|
||||
{
|
||||
nxt_conn_t *c;
|
||||
nxt_buf_mem_t *mbuf;
|
||||
nxt_controller_request_t *req;
|
||||
nxt_controller_response_t resp;
|
||||
|
||||
req = data;
|
||||
|
||||
nxt_memzero(&resp, sizeof(nxt_controller_response_t));
|
||||
|
||||
if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
|
||||
resp.status = 500;
|
||||
resp.title = (u_char *) "Failed to store script.";
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
return;
|
||||
}
|
||||
|
||||
c = req->conn;
|
||||
|
||||
mbuf = &c->read->mem;
|
||||
|
||||
nxt_fd_write(msg->fd[0], mbuf->pos, nxt_buf_mem_used_size(mbuf));
|
||||
|
||||
nxt_fd_close(msg->fd[0]);
|
||||
|
||||
nxt_memzero(&resp, sizeof(nxt_controller_response_t));
|
||||
|
||||
resp.status = 200;
|
||||
resp.title = (u_char *) "JS module uploaded.";
|
||||
|
||||
nxt_controller_response(task, req, &resp);
|
||||
}
|
||||
|
||||
|
||||
static nxt_bool_t
|
||||
nxt_controller_script_in_use(nxt_str_t *name)
|
||||
{
|
||||
uint32_t i, n;
|
||||
nxt_str_t str;
|
||||
nxt_conf_value_t *js_module, *element;
|
||||
|
||||
static nxt_str_t js_module_path = nxt_string("/settings/js_module");
|
||||
|
||||
js_module = nxt_conf_get_path(nxt_controller_conf.root,
|
||||
&js_module_path);
|
||||
|
||||
if (js_module != NULL) {
|
||||
|
||||
if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) {
|
||||
n = nxt_conf_array_elements_count(js_module);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
element = nxt_conf_get_array_element(js_module, i);
|
||||
|
||||
nxt_conf_get_string(element, &str);
|
||||
|
||||
if (nxt_strstr_eq(&str, name)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* NXT_CONF_STRING */
|
||||
|
||||
nxt_conf_get_string(js_module, &str);
|
||||
|
||||
if (nxt_strstr_eq(&str, name)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_controller_script_cleanup(nxt_task_t *task, void *obj, void *data)
|
||||
{
|
||||
pid_t main_pid;
|
||||
nxt_array_t *scripts;
|
||||
nxt_runtime_t *rt;
|
||||
|
||||
scripts = obj;
|
||||
rt = data;
|
||||
|
||||
main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid;
|
||||
|
||||
if (nxt_pid == main_pid && scripts != NULL) {
|
||||
nxt_script_store_release(scripts);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
nxt_controller_conf_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
void *data)
|
||||
|
|
250
src/nxt_js.c
250
src/nxt_js.c
|
@ -8,16 +8,72 @@
|
|||
|
||||
struct nxt_js_s {
|
||||
uint32_t index;
|
||||
njs_vm_t *vm;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t name;
|
||||
nxt_str_t text;
|
||||
} nxt_js_module_t;
|
||||
|
||||
|
||||
struct nxt_js_conf_s {
|
||||
nxt_mp_t *pool;
|
||||
njs_vm_t *vm;
|
||||
njs_uint_t protos;
|
||||
njs_external_t *proto;
|
||||
nxt_str_t init;
|
||||
nxt_array_t *modules; /* of nxt_js_module_t */
|
||||
nxt_array_t *funcs;
|
||||
uint8_t test; /* 1 bit */
|
||||
};
|
||||
|
||||
|
||||
njs_mod_t *
|
||||
nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name)
|
||||
{
|
||||
nxt_str_t text;
|
||||
nxt_uint_t i, n;
|
||||
nxt_js_conf_t *jcf;
|
||||
nxt_js_module_t *modules, *module;
|
||||
|
||||
jcf = external;
|
||||
|
||||
module = NULL;
|
||||
|
||||
n = jcf->modules->nelts;
|
||||
modules = jcf->modules->elts;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (nxt_strstr_eq(name, &modules[i].name)) {
|
||||
module = &modules[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (module == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
text.length = module->text.length;
|
||||
|
||||
text.start = njs_mp_alloc(vm->mem_pool, text.length);
|
||||
if (nxt_slow_path(text.start == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxt_memcpy(text.start, module->text.start, text.length);
|
||||
|
||||
return njs_vm_compile_module(vm, name, &text.start,
|
||||
&text.start[text.length]);
|
||||
}
|
||||
|
||||
|
||||
static njs_vm_ops_t nxt_js_ops = {
|
||||
NULL,
|
||||
NULL,
|
||||
nxt_js_module_loader,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
|
@ -25,9 +81,8 @@ njs_int_t nxt_js_proto_id;
|
|||
|
||||
|
||||
nxt_js_conf_t *
|
||||
nxt_js_conf_new(nxt_mp_t *mp)
|
||||
nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test)
|
||||
{
|
||||
njs_vm_opt_t opts;
|
||||
nxt_js_conf_t *jcf;
|
||||
|
||||
jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t));
|
||||
|
@ -36,17 +91,15 @@ nxt_js_conf_new(nxt_mp_t *mp)
|
|||
}
|
||||
|
||||
jcf->pool = mp;
|
||||
jcf->test = test;
|
||||
|
||||
njs_vm_opt_init(&opts);
|
||||
|
||||
jcf->vm = njs_vm_create(&opts);
|
||||
if (nxt_slow_path(jcf->vm == NULL)) {
|
||||
jcf->modules = nxt_array_create(mp, 4, sizeof(nxt_js_module_t));
|
||||
if (nxt_slow_path(jcf->modules == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t));
|
||||
if (nxt_slow_path(jcf->funcs == NULL)) {
|
||||
njs_vm_destroy(jcf->vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -69,6 +122,115 @@ nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n)
|
|||
}
|
||||
|
||||
|
||||
static njs_vm_t *
|
||||
nxt_js_vm_create(nxt_js_conf_t *jcf)
|
||||
{
|
||||
u_char *p;
|
||||
size_t size;
|
||||
nxt_uint_t i;
|
||||
njs_vm_opt_t opts;
|
||||
nxt_js_module_t *module, *mod;
|
||||
|
||||
static nxt_str_t import_str = nxt_string("import");
|
||||
static nxt_str_t from_str = nxt_string("from");
|
||||
static nxt_str_t global_str = nxt_string("globalThis");
|
||||
|
||||
njs_vm_opt_init(&opts);
|
||||
|
||||
opts.backtrace = 1;
|
||||
|
||||
opts.file.start = (u_char *) "default";
|
||||
opts.file.length = 7;
|
||||
|
||||
if (jcf->test || jcf->modules->nelts == 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
opts.ops = &nxt_js_ops;
|
||||
opts.external = jcf;
|
||||
|
||||
size = 0;
|
||||
module = jcf->modules->elts;
|
||||
|
||||
for (i = 0; i < jcf->modules->nelts; i++) {
|
||||
mod = &module[i];
|
||||
|
||||
size += import_str.length + 1 + mod->name.length + 1
|
||||
+ from_str.length + 2 + mod->name.length + 3;
|
||||
|
||||
size += global_str.length + 1 + mod->name.length + 3
|
||||
+ mod->name.length + 2;
|
||||
}
|
||||
|
||||
p = nxt_mp_nget(jcf->pool, size);
|
||||
if (nxt_slow_path(p == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jcf->init.length = size;
|
||||
jcf->init.start = p;
|
||||
|
||||
for (i = 0; i < jcf->modules->nelts; i++) {
|
||||
mod = &module[i];
|
||||
|
||||
p = nxt_cpymem(p, import_str.start, import_str.length);
|
||||
*p++ = ' ';
|
||||
|
||||
p = nxt_cpymem(p, mod->name.start, mod->name.length);
|
||||
*p++ = ' ';
|
||||
|
||||
p = nxt_cpymem(p, from_str.start, from_str.length);
|
||||
*p++ = ' ';
|
||||
|
||||
*p++ = '\"';
|
||||
p = nxt_cpymem(p, mod->name.start, mod->name.length);
|
||||
*p++ = '\"';
|
||||
*p++ = ';';
|
||||
*p++ = '\n';
|
||||
|
||||
p = nxt_cpymem(p, global_str.start, global_str.length);
|
||||
*p++ = '.';
|
||||
|
||||
p = nxt_cpymem(p, mod->name.start, mod->name.length);
|
||||
*p++ = ' ';
|
||||
*p++ = '=';
|
||||
*p++ = ' ';
|
||||
|
||||
p = nxt_cpymem(p, mod->name.start, mod->name.length);
|
||||
*p++ = ';';
|
||||
*p++ = '\n';
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
return njs_vm_create(&opts);
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name, nxt_str_t *text)
|
||||
{
|
||||
nxt_js_module_t *module;
|
||||
|
||||
module = nxt_array_add(jcf->modules);
|
||||
if (nxt_slow_path(module == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
module->name = *name;
|
||||
|
||||
module->text.length = text->length;
|
||||
module->text.start = nxt_mp_nget(jcf->pool, text->length);
|
||||
if (nxt_slow_path(module->text.start == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
nxt_memcpy(module->text.start, text->start, text->length);
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
nxt_js_t *
|
||||
nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
|
||||
{
|
||||
|
@ -113,8 +275,6 @@ nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
js->vm = jcf->vm;
|
||||
|
||||
func = nxt_array_add(jcf->funcs);
|
||||
if (nxt_slow_path(func == NULL)) {
|
||||
return NULL;
|
||||
|
@ -138,7 +298,16 @@ nxt_js_compile(nxt_js_conf_t *jcf)
|
|||
nxt_str_t *func;
|
||||
nxt_uint_t i;
|
||||
|
||||
size = 2;
|
||||
if (jcf->test) {
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
jcf->vm = nxt_js_vm_create(jcf);
|
||||
if (nxt_slow_path(jcf->vm == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
size = jcf->init.length + 2;
|
||||
func = jcf->funcs->elts;
|
||||
|
||||
for (i = 0; i < jcf->funcs->nelts; i++) {
|
||||
|
@ -150,7 +319,7 @@ nxt_js_compile(nxt_js_conf_t *jcf)
|
|||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
p = start;
|
||||
p = nxt_cpymem(start, jcf->init.start, jcf->init.length);
|
||||
*p++ = '[';
|
||||
|
||||
func = jcf->funcs->elts;
|
||||
|
@ -178,37 +347,43 @@ 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_vm_t *vm;
|
||||
njs_int_t ret;
|
||||
njs_str_t res;
|
||||
|
||||
vm = nxt_js_vm_create(jcf);
|
||||
if (nxt_slow_path(vm == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
start = nxt_mp_nget(jcf->pool, str->length);
|
||||
if (nxt_slow_path(start == NULL)) {
|
||||
return NXT_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nxt_memcpy(start, str->start, str->length);
|
||||
|
||||
ret = njs_vm_compile(jcf->vm, &start, start + str->length);
|
||||
ret = njs_vm_compile(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;
|
||||
(void) nxt_js_error(vm, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
njs_vm_destroy(vm);
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
njs_vm_destroy(vm);
|
||||
|
||||
return NXT_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)
|
||||
nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf, nxt_js_cache_t *cache,
|
||||
nxt_js_t *js, nxt_str_t *str, void *ctx)
|
||||
{
|
||||
njs_vm_t *vm;
|
||||
njs_int_t rc, ret;
|
||||
|
@ -227,7 +402,7 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
|
|||
vm = cache->vm;
|
||||
|
||||
if (vm == NULL) {
|
||||
vm = njs_vm_clone(js->vm, ctx);
|
||||
vm = njs_vm_clone(jcf->vm, ctx);
|
||||
if (nxt_slow_path(vm == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
@ -314,3 +489,24 @@ nxt_js_release(nxt_js_cache_t *cache)
|
|||
njs_vm_destroy(cache->vm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_js_error(njs_vm_t *vm, u_char *error)
|
||||
{
|
||||
njs_int_t ret;
|
||||
njs_str_t res;
|
||||
nxt_str_t err;
|
||||
|
||||
ret = njs_vm_retval_string(vm, &res);
|
||||
if (nxt_slow_path(ret != NJS_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
err.start = res.start;
|
||||
err.length = res.length;
|
||||
|
||||
nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err);
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
|
11
src/nxt_js.h
11
src/nxt_js.h
|
@ -21,15 +21,20 @@ typedef struct {
|
|||
} nxt_js_cache_t;
|
||||
|
||||
|
||||
nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp);
|
||||
njs_mod_t *nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external,
|
||||
njs_str_t *name);
|
||||
nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test);
|
||||
void nxt_js_conf_release(nxt_js_conf_t *jcf);
|
||||
void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n);
|
||||
nxt_int_t nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name,
|
||||
nxt_str_t *text);
|
||||
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);
|
||||
nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf,
|
||||
nxt_js_cache_t *cache, nxt_js_t *js, nxt_str_t *str, void *ctx);
|
||||
void nxt_js_release(nxt_js_cache_t *cache);
|
||||
nxt_int_t nxt_js_error(njs_vm_t *vm, u_char *error);
|
||||
|
||||
|
||||
extern njs_int_t nxt_js_proto_id;
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#if (NXT_TLS)
|
||||
#include <nxt_cert.h>
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
#include <nxt_script.h>
|
||||
#endif
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
|
@ -607,6 +610,10 @@ static nxt_port_handlers_t nxt_main_process_port_handlers = {
|
|||
#if (NXT_TLS)
|
||||
.cert_get = nxt_cert_store_get_handler,
|
||||
.cert_delete = nxt_cert_store_delete_handler,
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
.script_get = nxt_script_store_get_handler,
|
||||
.script_delete = nxt_script_store_delete_handler,
|
||||
#endif
|
||||
.access_log = nxt_main_port_access_log_handler,
|
||||
.rpc_ready = nxt_port_rpc_handler,
|
||||
|
|
|
@ -21,6 +21,8 @@ struct nxt_port_handlers_s {
|
|||
nxt_port_handler_t conf_store;
|
||||
nxt_port_handler_t cert_get;
|
||||
nxt_port_handler_t cert_delete;
|
||||
nxt_port_handler_t script_get;
|
||||
nxt_port_handler_t script_delete;
|
||||
nxt_port_handler_t access_log;
|
||||
|
||||
/* File descriptor exchange. */
|
||||
|
@ -87,6 +89,8 @@ typedef enum {
|
|||
_NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store),
|
||||
_NXT_PORT_MSG_CERT_GET = nxt_port_handler_idx(cert_get),
|
||||
_NXT_PORT_MSG_CERT_DELETE = nxt_port_handler_idx(cert_delete),
|
||||
_NXT_PORT_MSG_SCRIPT_GET = nxt_port_handler_idx(script_get),
|
||||
_NXT_PORT_MSG_SCRIPT_DELETE = nxt_port_handler_idx(script_delete),
|
||||
_NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log),
|
||||
|
||||
_NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file),
|
||||
|
@ -129,6 +133,8 @@ typedef enum {
|
|||
NXT_PORT_MSG_CONF_STORE = nxt_msg_last(_NXT_PORT_MSG_CONF_STORE),
|
||||
NXT_PORT_MSG_CERT_GET = nxt_msg_last(_NXT_PORT_MSG_CERT_GET),
|
||||
NXT_PORT_MSG_CERT_DELETE = nxt_msg_last(_NXT_PORT_MSG_CERT_DELETE),
|
||||
NXT_PORT_MSG_SCRIPT_GET = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_GET),
|
||||
NXT_PORT_MSG_SCRIPT_DELETE = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_DELETE),
|
||||
NXT_PORT_MSG_ACCESS_LOG = nxt_msg_last(_NXT_PORT_MSG_ACCESS_LOG),
|
||||
NXT_PORT_MSG_CHANGE_FILE = nxt_msg_last(_NXT_PORT_MSG_CHANGE_FILE),
|
||||
NXT_PORT_MSG_NEW_PORT = nxt_msg_last(_NXT_PORT_MSG_NEW_PORT),
|
||||
|
|
|
@ -29,6 +29,9 @@ typedef struct {
|
|||
#if (NXT_TLS)
|
||||
nxt_array_t *certs;
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_array_t *scripts;
|
||||
#endif
|
||||
} nxt_controller_init_t;
|
||||
|
||||
|
||||
|
|
158
src/nxt_router.c
158
src/nxt_router.c
|
@ -11,6 +11,9 @@
|
|||
#if (NXT_TLS)
|
||||
#include <nxt_cert.h>
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
#include <nxt_script.h>
|
||||
#endif
|
||||
#include <nxt_http.h>
|
||||
#include <nxt_port_memory_int.h>
|
||||
#include <nxt_unit_request.h>
|
||||
|
@ -55,6 +58,17 @@ typedef struct {
|
|||
#endif
|
||||
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t name;
|
||||
nxt_router_temp_conf_t *temp_conf;
|
||||
nxt_queue_link_t link;
|
||||
} nxt_router_js_module_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t *name;
|
||||
nxt_socket_conf_t *socket_conf;
|
||||
|
@ -139,6 +153,12 @@ static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
|
|||
nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init,
|
||||
nxt_bool_t last);
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
static void nxt_router_js_module_rpc_handler(nxt_task_t *task,
|
||||
nxt_port_recv_msg_t *msg, void *data);
|
||||
static nxt_int_t nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf,
|
||||
nxt_conf_value_t *value);
|
||||
#endif
|
||||
static void nxt_router_app_rpc_create(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_app_t *app);
|
||||
static void nxt_router_app_prefork_ready(nxt_task_t *task,
|
||||
|
@ -1100,6 +1120,10 @@ nxt_router_temp_conf(nxt_task_t *task)
|
|||
nxt_queue_init(&tmcf->tls);
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_queue_init(&tmcf->js_modules);
|
||||
#endif
|
||||
|
||||
nxt_queue_init(&tmcf->apps);
|
||||
nxt_queue_init(&tmcf->previous);
|
||||
|
||||
|
@ -1154,6 +1178,9 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
|
|||
#if (NXT_TLS)
|
||||
nxt_router_tlssock_t *tls;
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_router_js_module_t *js_module;
|
||||
#endif
|
||||
|
||||
tmcf = obj;
|
||||
|
||||
|
@ -1184,6 +1211,27 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
qlk = nxt_queue_last(&tmcf->js_modules);
|
||||
|
||||
if (qlk != nxt_queue_head(&tmcf->js_modules)) {
|
||||
nxt_queue_remove(qlk);
|
||||
|
||||
js_module = nxt_queue_link_data(qlk, nxt_router_js_module_t, link);
|
||||
|
||||
nxt_script_store_get(task, &js_module->name, tmcf->mem_pool,
|
||||
nxt_router_js_module_rpc_handler, js_module);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
rtcf = tmcf->router_conf;
|
||||
|
||||
ret = nxt_tstr_state_done(rtcf->tstr_state, NULL);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
|
||||
|
||||
if (nxt_router_app_need_start(app)) {
|
||||
|
@ -1193,8 +1241,6 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
|
|||
|
||||
} nxt_queue_loop;
|
||||
|
||||
rtcf = tmcf->router_conf;
|
||||
|
||||
if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) {
|
||||
nxt_router_access_log_open(task, tmcf);
|
||||
return;
|
||||
|
@ -1569,6 +1615,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||
#if (NXT_TLS)
|
||||
nxt_tls_init_t *tls_init;
|
||||
nxt_conf_value_t *certificate;
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_conf_value_t *js_module;
|
||||
#endif
|
||||
nxt_conf_value_t *root, *conf, *http, *value, *websocket;
|
||||
nxt_conf_value_t *applications, *application;
|
||||
|
@ -1592,6 +1641,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||
static nxt_str_t conf_cache_path = nxt_string("/tls/session/cache_size");
|
||||
static nxt_str_t conf_timeout_path = nxt_string("/tls/session/timeout");
|
||||
static nxt_str_t conf_tickets = nxt_string("/tls/session/tickets");
|
||||
#endif
|
||||
#if (NXT_HAVE_NJS)
|
||||
static nxt_str_t js_module_path = nxt_string("/settings/js_module");
|
||||
#endif
|
||||
static nxt_str_t static_path = nxt_string("/settings/http/static");
|
||||
static nxt_str_t websocket_path = nxt_string("/settings/http/websocket");
|
||||
|
@ -2064,11 +2116,34 @@ 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;
|
||||
#if (NXT_HAVE_NJS)
|
||||
js_module = nxt_conf_get_path(root, &js_module_path);
|
||||
|
||||
if (js_module != NULL) {
|
||||
if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) {
|
||||
n = nxt_conf_array_elements_count(js_module);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
value = nxt_conf_get_array_element(js_module, i);
|
||||
|
||||
ret = nxt_router_js_module_insert(tmcf, value);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* NXT_CONF_STRING */
|
||||
|
||||
ret = nxt_router_js_module_insert(tmcf, js_module);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
nxt_queue_add(&deleting_sockets, &router->sockets);
|
||||
nxt_queue_init(&router->sockets);
|
||||
|
||||
|
@ -2120,6 +2195,79 @@ nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
|
|||
#endif
|
||||
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
|
||||
static void
|
||||
nxt_router_js_module_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
void *data)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_str_t text;
|
||||
nxt_router_conf_t *rtcf;
|
||||
nxt_router_temp_conf_t *tmcf;
|
||||
nxt_router_js_module_t *js_module;
|
||||
|
||||
nxt_debug(task, "auto module rpc handler");
|
||||
|
||||
js_module = data;
|
||||
tmcf = js_module->temp_conf;
|
||||
|
||||
if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rtcf = tmcf->router_conf;
|
||||
|
||||
ret = nxt_script_file_read(msg->fd[0], &text);
|
||||
|
||||
nxt_fd_close(msg->fd[0]);
|
||||
|
||||
if (nxt_slow_path(ret == NXT_ERROR)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (text.length > 0) {
|
||||
ret = nxt_js_add_module(rtcf->tstr_state->jcf, &js_module->name, &text);
|
||||
|
||||
nxt_free(text.start);
|
||||
|
||||
if (nxt_slow_path(ret == NXT_ERROR)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
nxt_work_queue_add(&task->thread->engine->fast_work_queue,
|
||||
nxt_router_conf_apply, task, tmcf, NULL);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
||||
nxt_router_conf_error(task, tmcf);
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf,
|
||||
nxt_conf_value_t *value)
|
||||
{
|
||||
nxt_router_js_module_t *js_module;
|
||||
|
||||
js_module = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_js_module_t));
|
||||
if (nxt_slow_path(js_module == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
js_module->temp_conf = tmcf;
|
||||
nxt_conf_get_string(value, &js_module->name);
|
||||
|
||||
nxt_queue_insert_tail(&tmcf->js_modules, &js_module->link);
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf,
|
||||
nxt_conf_value_t *conf)
|
||||
|
|
|
@ -74,6 +74,10 @@ typedef struct {
|
|||
nxt_queue_t tls; /* of nxt_router_tlssock_t */
|
||||
#endif
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_queue_t js_modules;
|
||||
#endif
|
||||
|
||||
nxt_queue_t apps; /* of nxt_app_t */
|
||||
nxt_queue_t previous; /* of nxt_app_t */
|
||||
|
||||
|
|
|
@ -906,6 +906,23 @@ nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt)
|
|||
"mkdir(%s) failed %E", file_name.start, nxt_errno);
|
||||
}
|
||||
|
||||
ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sscripts/%Z",
|
||||
rt->state, slash);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
ret = mkdir((char *) file_name.start, S_IRWXU);
|
||||
|
||||
if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) {
|
||||
rt->scripts.length = file_name.len;
|
||||
rt->scripts.start = file_name.start;
|
||||
|
||||
} else {
|
||||
nxt_alert(task, "Unable to create scripts storage directory: "
|
||||
"mkdir(%s) failed %E", file_name.start, nxt_errno);
|
||||
}
|
||||
|
||||
control.length = nxt_strlen(rt->control);
|
||||
control.start = (u_char *) rt->control;
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ struct nxt_runtime_s {
|
|||
const char *tmp;
|
||||
|
||||
nxt_str_t certs;
|
||||
nxt_str_t scripts;
|
||||
|
||||
nxt_queue_t engines; /* of nxt_event_engine_t */
|
||||
|
||||
|
|
709
src/nxt_script.c
Normal file
709
src/nxt_script.c
Normal file
|
@ -0,0 +1,709 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
* Copyright (C) Zhidao HONG
|
||||
*/
|
||||
|
||||
#include <nxt_main.h>
|
||||
#include <nxt_conf.h>
|
||||
#include <nxt_script.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
struct nxt_script_s {
|
||||
nxt_str_t text;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t name;
|
||||
nxt_conf_value_t *value;
|
||||
nxt_mp_t *mp;
|
||||
} nxt_script_info_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_str_t name;
|
||||
nxt_fd_t fd;
|
||||
} nxt_script_item_t;
|
||||
|
||||
|
||||
static nxt_script_t *nxt_script_get(nxt_task_t *task, nxt_str_t *name,
|
||||
nxt_fd_t fd);
|
||||
static nxt_conf_value_t *nxt_script_details(nxt_mp_t *mp, nxt_script_t *cert);
|
||||
static void nxt_script_buf_completion(nxt_task_t *task, void *obj, void *data);
|
||||
|
||||
|
||||
static nxt_lvlhsh_t nxt_script_info;
|
||||
|
||||
|
||||
static njs_vm_ops_t nxt_js_ops = {
|
||||
NULL,
|
||||
NULL,
|
||||
nxt_js_module_loader,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
nxt_script_t *
|
||||
nxt_script_new(nxt_task_t *task, nxt_str_t *name, u_char *data, size_t size,
|
||||
u_char *error)
|
||||
{
|
||||
u_char *start;
|
||||
njs_vm_t *vm;
|
||||
njs_str_t mod_name;
|
||||
njs_mod_t *mod;
|
||||
njs_vm_opt_t opts;
|
||||
nxt_script_t *script;
|
||||
|
||||
njs_vm_opt_init(&opts);
|
||||
|
||||
opts.backtrace = 1;
|
||||
|
||||
opts.file.start = (u_char *) "default";
|
||||
opts.file.length = 7;
|
||||
|
||||
opts.ops = &nxt_js_ops;
|
||||
|
||||
vm = njs_vm_create(&opts);
|
||||
if (nxt_slow_path(vm == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod_name.length = name->length;
|
||||
mod_name.start = name->start;
|
||||
|
||||
start = data;
|
||||
|
||||
mod = njs_vm_compile_module(vm, &mod_name, &start, start + size);
|
||||
|
||||
if (nxt_slow_path(mod == NULL)) {
|
||||
(void) nxt_js_error(vm, error);
|
||||
nxt_alert(task, "JS compile module(%V) failed: %s", name, error);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
script = nxt_zalloc(sizeof(nxt_script_t) + size);
|
||||
if (nxt_slow_path(script == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
script->text.length = size;
|
||||
script->text.start = (u_char *) script + sizeof(nxt_script_t);
|
||||
|
||||
nxt_memcpy(script->text.start, data, size);
|
||||
|
||||
njs_vm_destroy(vm);
|
||||
|
||||
return script;
|
||||
|
||||
fail:
|
||||
|
||||
njs_vm_destroy(vm);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static nxt_script_t *
|
||||
nxt_script_get(nxt_task_t *task, nxt_str_t *name, nxt_fd_t fd)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_str_t text;
|
||||
nxt_script_t *script;
|
||||
u_char error[NXT_MAX_ERROR_STR];
|
||||
|
||||
ret = nxt_script_file_read(fd, &text);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
script = nxt_script_new(task, name, text.start, text.length, error);
|
||||
|
||||
nxt_free(text.start);
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_destroy(nxt_script_t *script)
|
||||
{
|
||||
nxt_free(script);
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_script_info_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
|
||||
{
|
||||
nxt_script_info_t *info;
|
||||
|
||||
info = data;
|
||||
|
||||
if (nxt_strcasestr_eq(&lhq->key, &info->name)) {
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
return NXT_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static const nxt_lvlhsh_proto_t nxt_script_info_hash_proto
|
||||
nxt_aligned(64) =
|
||||
{
|
||||
NXT_LVLHSH_DEFAULT,
|
||||
nxt_script_info_hash_test,
|
||||
nxt_lvlhsh_alloc,
|
||||
nxt_lvlhsh_free,
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
nxt_script_info_init(nxt_task_t *task, nxt_array_t *scripts)
|
||||
{
|
||||
uint32_t i;
|
||||
nxt_script_t *script;
|
||||
nxt_script_item_t *item;
|
||||
|
||||
item = scripts->elts;
|
||||
|
||||
for (i = 0; i < scripts->nelts; i++) {
|
||||
script = nxt_script_get(task, &item->name, item->fd);
|
||||
|
||||
if (nxt_slow_path(script == NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(void) nxt_script_info_save(&item->name, script);
|
||||
|
||||
nxt_script_destroy(script);
|
||||
|
||||
item++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_script_info_save(nxt_str_t *name, nxt_script_t *script)
|
||||
{
|
||||
nxt_mp_t *mp;
|
||||
nxt_int_t ret;
|
||||
nxt_conf_value_t *value;
|
||||
nxt_script_info_t *info;
|
||||
nxt_lvlhsh_query_t lhq;
|
||||
|
||||
mp = nxt_mp_create(1024, 128, 256, 32);
|
||||
if (nxt_slow_path(mp == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
info = nxt_mp_get(mp, sizeof(nxt_script_info_t));
|
||||
if (nxt_slow_path(info == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
name = nxt_str_dup(mp, &info->name, name);
|
||||
if (nxt_slow_path(name == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
value = nxt_script_details(mp, script);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
info->mp = mp;
|
||||
info->value = value;
|
||||
|
||||
lhq.key_hash = nxt_djb_hash(name->start, name->length);
|
||||
lhq.replace = 1;
|
||||
lhq.key = *name;
|
||||
lhq.value = info;
|
||||
lhq.proto = &nxt_script_info_hash_proto;
|
||||
|
||||
ret = nxt_lvlhsh_insert(&nxt_script_info, &lhq);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (lhq.value != info) {
|
||||
info = lhq.value;
|
||||
nxt_mp_destroy(info->mp);
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
nxt_mp_destroy(mp);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
nxt_conf_value_t *
|
||||
nxt_script_info_get(nxt_str_t *name)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_script_info_t *info;
|
||||
nxt_lvlhsh_query_t lhq;
|
||||
|
||||
lhq.key_hash = nxt_djb_hash(name->start, name->length);
|
||||
lhq.key = *name;
|
||||
lhq.proto = &nxt_script_info_hash_proto;
|
||||
|
||||
ret = nxt_lvlhsh_find(&nxt_script_info, &lhq);
|
||||
if (ret != NXT_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = lhq.value;
|
||||
|
||||
return info->value;
|
||||
}
|
||||
|
||||
|
||||
nxt_conf_value_t *
|
||||
nxt_script_info_get_all(nxt_mp_t *mp)
|
||||
{
|
||||
uint32_t i;
|
||||
nxt_conf_value_t *all;
|
||||
nxt_script_info_t *info;
|
||||
nxt_lvlhsh_each_t lhe;
|
||||
|
||||
nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto);
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
info = nxt_lvlhsh_each(&nxt_script_info, &lhe);
|
||||
|
||||
if (info == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
all = nxt_conf_create_object(mp, i);
|
||||
if (nxt_slow_path(all == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto);
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
info = nxt_lvlhsh_each(&nxt_script_info, &lhe);
|
||||
|
||||
if (info == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_set_member(all, &info->name, info->value, i);
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
|
||||
static nxt_conf_value_t *
|
||||
nxt_script_details(nxt_mp_t *mp, nxt_script_t *script)
|
||||
{
|
||||
nxt_conf_value_t *value;
|
||||
|
||||
value = nxt_conf_create_object(mp, 0);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxt_conf_set_string_dup(value, mp, &script->text);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_script_info_delete(nxt_str_t *name)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_script_info_t *info;
|
||||
nxt_lvlhsh_query_t lhq;
|
||||
|
||||
lhq.key_hash = nxt_djb_hash(name->start, name->length);
|
||||
lhq.key = *name;
|
||||
lhq.proto = &nxt_script_info_hash_proto;
|
||||
|
||||
ret = nxt_lvlhsh_delete(&nxt_script_info, &lhq);
|
||||
|
||||
if (ret == NXT_OK) {
|
||||
info = lhq.value;
|
||||
nxt_mp_destroy(info->mp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
nxt_array_t *
|
||||
nxt_script_store_load(nxt_task_t *task, nxt_mp_t *mp)
|
||||
{
|
||||
DIR *dir;
|
||||
size_t size, alloc;
|
||||
u_char *buf, *p;
|
||||
nxt_str_t name;
|
||||
nxt_int_t ret;
|
||||
nxt_file_t file;
|
||||
nxt_array_t *scripts;
|
||||
nxt_runtime_t *rt;
|
||||
struct dirent *de;
|
||||
nxt_script_item_t *item;
|
||||
|
||||
rt = task->thread->runtime;
|
||||
|
||||
if (nxt_slow_path(rt->scripts.start == NULL)) {
|
||||
nxt_alert(task, "no scripts storage directory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scripts = nxt_array_create(mp, 16, sizeof(nxt_script_item_t));
|
||||
if (nxt_slow_path(scripts == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
alloc = 0;
|
||||
|
||||
dir = opendir((char *) rt->scripts.start);
|
||||
if (nxt_slow_path(dir == NULL)) {
|
||||
nxt_alert(task, "opendir(\"%s\") failed %E",
|
||||
rt->scripts.start, nxt_errno);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for ( ;; ) {
|
||||
de = readdir(dir);
|
||||
if (de == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_debug(task, "readdir(\"%s\"): \"%s\"",
|
||||
rt->scripts.start, de->d_name);
|
||||
|
||||
name.length = nxt_strlen(de->d_name);
|
||||
name.start = (u_char *) de->d_name;
|
||||
|
||||
if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
item = nxt_array_add(scripts);
|
||||
if (nxt_slow_path(item == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
item->fd = -1;
|
||||
|
||||
size = rt->scripts.length + name.length + 1;
|
||||
|
||||
if (size > alloc) {
|
||||
size += 32;
|
||||
|
||||
p = nxt_realloc(buf, size);
|
||||
if (p == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
alloc = size;
|
||||
buf = p;
|
||||
}
|
||||
|
||||
p = nxt_cpymem(buf, rt->scripts.start, rt->scripts.length);
|
||||
p = nxt_cpymem(p, name.start, name.length + 1);
|
||||
|
||||
nxt_memzero(&file, sizeof(nxt_file_t));
|
||||
|
||||
file.name = buf;
|
||||
|
||||
ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN,
|
||||
NXT_FILE_OWNER_ACCESS);
|
||||
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
nxt_array_remove_last(scripts);
|
||||
continue;
|
||||
}
|
||||
|
||||
item->fd = file.fd;
|
||||
|
||||
if (nxt_slow_path(nxt_str_dup(mp, &item->name, &name) == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf != NULL) {
|
||||
nxt_free(buf);
|
||||
}
|
||||
|
||||
(void) closedir(dir);
|
||||
|
||||
return scripts;
|
||||
|
||||
fail:
|
||||
|
||||
if (buf != NULL) {
|
||||
nxt_free(buf);
|
||||
}
|
||||
|
||||
if (dir != NULL) {
|
||||
(void) closedir(dir);
|
||||
}
|
||||
|
||||
nxt_script_store_release(scripts);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_store_release(nxt_array_t *scripts)
|
||||
{
|
||||
uint32_t i;
|
||||
nxt_script_item_t *item;
|
||||
|
||||
item = scripts->elts;
|
||||
|
||||
for (i = 0; i < scripts->nelts; i++) {
|
||||
nxt_fd_close(item[i].fd);
|
||||
}
|
||||
|
||||
nxt_array_destroy(scripts);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp,
|
||||
nxt_port_rpc_handler_t handler, void *ctx)
|
||||
{
|
||||
uint32_t stream;
|
||||
nxt_int_t ret;
|
||||
nxt_buf_t *b;
|
||||
nxt_port_t *main_port, *recv_port;
|
||||
nxt_runtime_t *rt;
|
||||
|
||||
b = nxt_buf_mem_alloc(mp, name->length + 1, 0);
|
||||
if (nxt_slow_path(b == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nxt_mp_retain(mp);
|
||||
b->completion_handler = nxt_script_buf_completion;
|
||||
|
||||
nxt_buf_cpystr(b, name);
|
||||
*b->mem.free++ = '\0';
|
||||
|
||||
rt = task->thread->runtime;
|
||||
main_port = rt->port_by_type[NXT_PROCESS_MAIN];
|
||||
recv_port = rt->port_by_type[rt->type];
|
||||
|
||||
stream = nxt_port_rpc_register_handler(task, recv_port, handler, handler,
|
||||
-1, ctx);
|
||||
if (nxt_slow_path(stream == 0)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SCRIPT_GET, -1,
|
||||
stream, recv_port->id, b);
|
||||
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
nxt_port_rpc_cancel(task, recv_port, stream);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
||||
handler(task, NULL, ctx);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_script_buf_completion(nxt_task_t *task, void *obj, void *data)
|
||||
{
|
||||
nxt_mp_t *mp;
|
||||
nxt_buf_t *b;
|
||||
|
||||
b = obj;
|
||||
mp = b->data;
|
||||
nxt_assert(b->next == NULL);
|
||||
|
||||
nxt_mp_free(mp, b);
|
||||
nxt_mp_release(mp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_int_t ret;
|
||||
nxt_str_t name;
|
||||
nxt_file_t file;
|
||||
nxt_port_t *port;
|
||||
nxt_runtime_t *rt;
|
||||
nxt_port_msg_type_t type;
|
||||
|
||||
port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
|
||||
msg->port_msg.reply_port);
|
||||
|
||||
if (nxt_slow_path(port == NULL)) {
|
||||
nxt_alert(task, "process port not found (pid %PI, reply_port %d)",
|
||||
msg->port_msg.pid, msg->port_msg.reply_port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(port->type != NXT_PROCESS_CONTROLLER
|
||||
&& port->type != NXT_PROCESS_ROUTER))
|
||||
{
|
||||
nxt_alert(task, "process %PI cannot store scripts",
|
||||
msg->port_msg.pid);
|
||||
return;
|
||||
}
|
||||
|
||||
nxt_memzero(&file, sizeof(nxt_file_t));
|
||||
|
||||
file.fd = -1;
|
||||
type = NXT_PORT_MSG_RPC_ERROR;
|
||||
|
||||
rt = task->thread->runtime;
|
||||
|
||||
if (nxt_slow_path(rt->certs.start == NULL)) {
|
||||
nxt_alert(task, "no scripts storage directory");
|
||||
goto error;
|
||||
}
|
||||
|
||||
name.start = msg->buf->mem.pos;
|
||||
name.length = nxt_strlen(name.start);
|
||||
|
||||
file.name = nxt_malloc(rt->scripts.length + name.length + 1);
|
||||
if (nxt_slow_path(file.name == NULL)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_cpymem(file.name, rt->scripts.start, rt->scripts.length);
|
||||
p = nxt_cpymem(p, name.start, name.length + 1);
|
||||
|
||||
ret = nxt_file_open(task, &file, NXT_FILE_RDWR, NXT_FILE_CREATE_OR_OPEN,
|
||||
NXT_FILE_OWNER_ACCESS);
|
||||
|
||||
nxt_free(file.name);
|
||||
|
||||
if (nxt_fast_path(ret == NXT_OK)) {
|
||||
type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD;
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
(void) nxt_port_socket_write(task, port, type, file.fd,
|
||||
msg->port_msg.stream, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp)
|
||||
{
|
||||
nxt_buf_t *b;
|
||||
nxt_port_t *main_port;
|
||||
nxt_runtime_t *rt;
|
||||
|
||||
b = nxt_buf_mem_alloc(mp, name->length + 1, 0);
|
||||
|
||||
if (nxt_fast_path(b != NULL)) {
|
||||
nxt_buf_cpystr(b, name);
|
||||
*b->mem.free++ = '\0';
|
||||
|
||||
rt = task->thread->runtime;
|
||||
main_port = rt->port_by_type[NXT_PROCESS_MAIN];
|
||||
|
||||
(void) nxt_port_socket_write(task, main_port,
|
||||
NXT_PORT_MSG_SCRIPT_DELETE, -1, 0, 0, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_script_store_delete_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_str_t name;
|
||||
nxt_port_t *ctl_port;
|
||||
nxt_runtime_t *rt;
|
||||
nxt_file_name_t *path;
|
||||
|
||||
rt = task->thread->runtime;
|
||||
ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
|
||||
|
||||
if (nxt_slow_path(ctl_port == NULL)) {
|
||||
nxt_alert(task, "controller port not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(nxt_recv_msg_cmsg_pid(msg) != ctl_port->pid)) {
|
||||
nxt_alert(task, "process %PI cannot delete scripts",
|
||||
nxt_recv_msg_cmsg_pid(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(rt->scripts.start == NULL)) {
|
||||
nxt_alert(task, "no scripts storage directory");
|
||||
return;
|
||||
}
|
||||
|
||||
name.start = msg->buf->mem.pos;
|
||||
name.length = nxt_strlen(name.start);
|
||||
|
||||
path = nxt_malloc(rt->scripts.length + name.length + 1);
|
||||
|
||||
if (nxt_fast_path(path != NULL)) {
|
||||
p = nxt_cpymem(path, rt->scripts.start, rt->scripts.length);
|
||||
p = nxt_cpymem(p, name.start, name.length + 1);
|
||||
|
||||
(void) nxt_file_delete(path);
|
||||
|
||||
nxt_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_script_file_read(nxt_fd_t fd, nxt_str_t *str)
|
||||
{
|
||||
ssize_t n;
|
||||
nxt_int_t ret;
|
||||
nxt_file_t file;
|
||||
nxt_file_info_t fi;
|
||||
|
||||
nxt_memzero(&file, sizeof(nxt_file_t));
|
||||
|
||||
file.fd = fd;
|
||||
|
||||
ret = nxt_file_info(&file, &fi);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(!nxt_is_file(&fi))) {
|
||||
nxt_str_null(str);
|
||||
return NXT_DECLINED;
|
||||
}
|
||||
|
||||
str->length = nxt_file_size(&fi);
|
||||
str->start = nxt_malloc(str->length);
|
||||
if (nxt_slow_path(str->start == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
n = nxt_file_read(&file, str->start, str->length, 0);
|
||||
|
||||
if (nxt_slow_path(n != (ssize_t) str->length)) {
|
||||
nxt_free(str->start);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
37
src/nxt_script.h
Normal file
37
src/nxt_script.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
* Copyright (C) Zhidao HONG
|
||||
*/
|
||||
|
||||
#ifndef _NXT_SCRIPT_INCLUDED_
|
||||
#define _NXT_SCRIPT_INCLUDED_
|
||||
|
||||
|
||||
typedef struct nxt_script_s nxt_script_t;
|
||||
|
||||
nxt_script_t *nxt_script_new(nxt_task_t *task, nxt_str_t *name, u_char *data,
|
||||
size_t size, u_char *error);
|
||||
void nxt_script_destroy(nxt_script_t *script);
|
||||
|
||||
void nxt_script_info_init(nxt_task_t *task, nxt_array_t *scripts);
|
||||
nxt_int_t nxt_script_info_save(nxt_str_t *name, nxt_script_t *script);
|
||||
nxt_conf_value_t *nxt_script_info_get(nxt_str_t *name);
|
||||
nxt_conf_value_t *nxt_script_info_get_all(nxt_mp_t *mp);
|
||||
nxt_int_t nxt_script_info_delete(nxt_str_t *name);
|
||||
|
||||
nxt_array_t *nxt_script_store_load(nxt_task_t *task, nxt_mp_t *mem_pool);
|
||||
void nxt_script_store_release(nxt_array_t *scripts);
|
||||
|
||||
void nxt_script_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp,
|
||||
nxt_port_rpc_handler_t handler, void *ctx);
|
||||
void nxt_script_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp);
|
||||
|
||||
void nxt_script_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg);
|
||||
void nxt_script_store_delete_handler(nxt_task_t *task,
|
||||
nxt_port_recv_msg_t *msg);
|
||||
|
||||
nxt_int_t nxt_script_file_read(nxt_fd_t fd, nxt_str_t *str);
|
||||
|
||||
|
||||
#endif /* _NXT_SCRIPT_INCLUDED_ */
|
|
@ -70,7 +70,7 @@ nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test)
|
|||
}
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
state->jcf = nxt_js_conf_new(mp);
|
||||
state->jcf = nxt_js_conf_new(mp, test);
|
||||
if (nxt_slow_path(state->jcf == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -273,7 +273,8 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
|
|||
|
||||
} else {
|
||||
#if (NXT_HAVE_NJS)
|
||||
ret = nxt_js_call(task, &query->cache->js, tstr->u.js, val, query->ctx);
|
||||
ret = nxt_js_call(task, query->state->jcf, &query->cache->js,
|
||||
tstr->u.js, val, query->ctx);
|
||||
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
query->failed = 1;
|
||||
|
|
Loading…
Reference in a new issue