120Sigor@sysoev.ru
220Sigor@sysoev.ru /*
320Sigor@sysoev.ru * Copyright (C) Igor Sysoev
420Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev
520Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
620Sigor@sysoev.ru */
720Sigor@sysoev.ru
853Sigor@sysoev.ru #include <nxt_router.h>
9115Sigor@sysoev.ru #include <nxt_conf.h>
102185Svbart@nginx.com #include <nxt_status.h>
11774Svbart@nginx.com #if (NXT_TLS)
12774Svbart@nginx.com #include <nxt_cert.h>
13774Svbart@nginx.com #endif
142450Sz.hong@f5.com #if (NXT_HAVE_NJS)
152450Sz.hong@f5.com #include <nxt_script.h>
162450Sz.hong@f5.com #endif
17431Sigor@sysoev.ru #include <nxt_http.h>
18743Smax.romanov@nginx.com #include <nxt_port_memory_int.h>
19743Smax.romanov@nginx.com #include <nxt_unit_request.h>
20743Smax.romanov@nginx.com #include <nxt_unit_response.h>
211131Smax.romanov@nginx.com #include <nxt_router_request.h>
221555Smax.romanov@nginx.com #include <nxt_app_queue.h>
231555Smax.romanov@nginx.com #include <nxt_port_queue.h>
2420Sigor@sysoev.ru
251926Smax.romanov@nginx.com #define NXT_SHARED_PORT_ID 0xFFFFu
261926Smax.romanov@nginx.com
27115Sigor@sysoev.ru typedef struct {
28318Smax.romanov@nginx.com nxt_str_t type;
29507Smax.romanov@nginx.com uint32_t processes;
30507Smax.romanov@nginx.com uint32_t max_processes;
31507Smax.romanov@nginx.com uint32_t spare_processes;
32318Smax.romanov@nginx.com nxt_msec_t timeout;
33507Smax.romanov@nginx.com nxt_msec_t idle_timeout;
34318Smax.romanov@nginx.com nxt_conf_value_t *limits_value;
35507Smax.romanov@nginx.com nxt_conf_value_t *processes_value;
361473Svbart@nginx.com nxt_conf_value_t *targets_value;
37133Sigor@sysoev.ru } nxt_router_app_conf_t;
38133Sigor@sysoev.ru
39133Sigor@sysoev.ru
40133Sigor@sysoev.ru typedef struct {
41964Sigor@sysoev.ru nxt_str_t pass;
42964Sigor@sysoev.ru nxt_str_t application;
43115Sigor@sysoev.ru } nxt_router_listener_conf_t;
44115Sigor@sysoev.ru
45115Sigor@sysoev.ru
46774Svbart@nginx.com #if (NXT_TLS)
47774Svbart@nginx.com
48774Svbart@nginx.com typedef struct {
491885Sa.suvorov@f5.com nxt_str_t name;
501885Sa.suvorov@f5.com nxt_socket_conf_t *socket_conf;
511885Sa.suvorov@f5.com nxt_router_temp_conf_t *temp_conf;
521920Sa.suvorov@f5.com nxt_tls_init_t *tls_init;
531885Sa.suvorov@f5.com nxt_bool_t last;
54774Svbart@nginx.com
551920Sa.suvorov@f5.com nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */
56774Svbart@nginx.com } nxt_router_tlssock_t;
57774Svbart@nginx.com
58774Svbart@nginx.com #endif
59774Svbart@nginx.com
60774Svbart@nginx.com
612450Sz.hong@f5.com #if (NXT_HAVE_NJS)
622450Sz.hong@f5.com
632450Sz.hong@f5.com typedef struct {
642450Sz.hong@f5.com nxt_str_t name;
652450Sz.hong@f5.com nxt_router_temp_conf_t *temp_conf;
662450Sz.hong@f5.com nxt_queue_link_t link;
672450Sz.hong@f5.com } nxt_router_js_module_t;
682450Sz.hong@f5.com
692450Sz.hong@f5.com #endif
702450Sz.hong@f5.com
712450Sz.hong@f5.com
72198Sigor@sysoev.ru typedef struct {
731828Sa.suvorov@f5.com nxt_str_t *name;
74198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf;
75198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf;
761828Sa.suvorov@f5.com nxt_bool_t last;
77198Sigor@sysoev.ru } nxt_socket_rpc_t;
78198Sigor@sysoev.ru
79198Sigor@sysoev.ru
80507Smax.romanov@nginx.com typedef struct {
81507Smax.romanov@nginx.com nxt_app_t *app;
82507Smax.romanov@nginx.com nxt_router_temp_conf_t *temp_conf;
831998St.nateldemoura@f5.com uint8_t proto; /* 1 bit */
84507Smax.romanov@nginx.com } nxt_app_rpc_t;
85507Smax.romanov@nginx.com
86507Smax.romanov@nginx.com
871926Smax.romanov@nginx.com typedef struct {
881926Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
891926Smax.romanov@nginx.com uint32_t generation;
901998St.nateldemoura@f5.com uint8_t proto; /* 1 bit */
911926Smax.romanov@nginx.com } nxt_app_joint_rpc_t;
921926Smax.romanov@nginx.com
931926Smax.romanov@nginx.com
941488St.nateldemoura@f5.com static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process,
951488St.nateldemoura@f5.com nxt_mp_t *mp);
961488St.nateldemoura@f5.com static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data);
97662Smax.romanov@nginx.com static void nxt_router_greet_controller(nxt_task_t *task,
98662Smax.romanov@nginx.com nxt_port_t *controller_port);
99662Smax.romanov@nginx.com
100507Smax.romanov@nginx.com static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app);
101425Smax.romanov@nginx.com
1021552Smax.romanov@nginx.com static void nxt_router_new_port_handler(nxt_task_t *task,
1031552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
1041552Smax.romanov@nginx.com static void nxt_router_conf_data_handler(nxt_task_t *task,
1051552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
1061926Smax.romanov@nginx.com static void nxt_router_app_restart_handler(nxt_task_t *task,
1071926Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
1082185Svbart@nginx.com static void nxt_router_status_handler(nxt_task_t *task,
1092185Svbart@nginx.com nxt_port_recv_msg_t *msg);
1101552Smax.romanov@nginx.com static void nxt_router_remove_pid_handler(nxt_task_t *task,
1111552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
1121552Smax.romanov@nginx.com
113139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
114198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task,
115139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf);
116139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task,
117193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
11853Sigor@sysoev.ru
119115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
120115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
1211183Svbart@nginx.com static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task,
1221183Svbart@nginx.com nxt_router_conf_t *rtcf, nxt_conf_value_t *conf);
1232133Sz.hong@f5.com static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task,
1242133Sz.hong@f5.com nxt_mp_t *mp, nxt_conf_value_t *conf);
1252133Sz.hong@f5.com static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp,
1262133Sz.hong@f5.com nxt_conf_value_t *conf, nxt_http_forward_header_t *fh);
1271563Svbart@nginx.com
128133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
1291563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
1301563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf,
1311563Svbart@nginx.com nxt_app_t *app);
1321563Svbart@nginx.com static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf,
1331563Svbart@nginx.com nxt_str_t *name);
1341563Svbart@nginx.com static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf,
1351563Svbart@nginx.com int i);
1361563Svbart@nginx.com
1371555Smax.romanov@nginx.com static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task,
1381555Smax.romanov@nginx.com nxt_port_t *port);
1391555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task,
1401555Smax.romanov@nginx.com nxt_port_t *port);
1411555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task,
1421555Smax.romanov@nginx.com nxt_port_t *port, nxt_fd_t fd);
143198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task,
144198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf);
145198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task,
146198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data);
147198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task,
148198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data);
149774Svbart@nginx.com #if (NXT_TLS)
150774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task,
151774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data);
1521828Sa.suvorov@f5.com static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
1531920Sa.suvorov@f5.com nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init,
1541920Sa.suvorov@f5.com nxt_bool_t last);
155774Svbart@nginx.com #endif
1562450Sz.hong@f5.com #if (NXT_HAVE_NJS)
1572450Sz.hong@f5.com static void nxt_router_js_module_rpc_handler(nxt_task_t *task,
1582450Sz.hong@f5.com nxt_port_recv_msg_t *msg, void *data);
1592450Sz.hong@f5.com static nxt_int_t nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf,
1602450Sz.hong@f5.com nxt_conf_value_t *value);
1612450Sz.hong@f5.com #endif
162507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task,
163507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app);
164507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task,
165507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data);
166507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task,
167507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data);
168359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task,
169359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
170359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf,
171359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa);
17253Sigor@sysoev.ru
17353Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task,
17453Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf,
17553Sigor@sysoev.ru const nxt_event_interface_t *interface);
176115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf,
177115Sigor@sysoev.ru nxt_router_engine_conf_t *recf);
178115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf,
179115Sigor@sysoev.ru nxt_router_engine_conf_t *recf);
180115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf,
181115Sigor@sysoev.ru nxt_router_engine_conf_t *recf);
182154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf,
183154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets,
184154Sigor@sysoev.ru nxt_work_handler_t handler);
185313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf,
186313Sigor@sysoev.ru nxt_router_engine_conf_t *recf);
187139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
188139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets);
18953Sigor@sysoev.ru
19053Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
19153Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf);
19253Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
19353Sigor@sysoev.ru nxt_event_engine_t *engine);
194343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router,
195133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf);
19653Sigor@sysoev.ru
197315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router,
198315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf);
199315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine,
200315Sigor@sysoev.ru nxt_work_t *jobs);
20153Sigor@sysoev.ru
20253Sigor@sysoev.ru static void nxt_router_thread_start(void *data);
2031545Smax.romanov@nginx.com static void nxt_router_rt_add_port(nxt_task_t *task, void *obj,
2041545Smax.romanov@nginx.com void *data);
20553Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj,
20653Sigor@sysoev.ru void *data);
20753Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj,
20853Sigor@sysoev.ru void *data);
20953Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj,
21053Sigor@sysoev.ru void *data);
211313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj,
212313Sigor@sysoev.ru void *data);
21353Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj,
21453Sigor@sysoev.ru void *data);
21553Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj,
21653Sigor@sysoev.ru void *data);
2171547Smax.romanov@nginx.com static void nxt_router_req_headers_ack_handler(nxt_task_t *task,
2181547Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data);
219359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task,
220359Sigor@sysoev.ru nxt_socket_conf_t *skcf);
22153Sigor@sysoev.ru
222343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task,
223343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data);
224343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task,
225343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data);
226343Smax.romanov@nginx.com
2271563Svbart@nginx.com static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i);
228753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app);
2291123Smax.romanov@nginx.com
2301978Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app,
2311978Smax.romanov@nginx.com nxt_port_t *port, nxt_apr_action_t action);
2321547Smax.romanov@nginx.com static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app,
2331547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data);
2341561Smax.romanov@nginx.com static void nxt_router_http_request_error(nxt_task_t *task, void *obj,
2351561Smax.romanov@nginx.com void *data);
2361547Smax.romanov@nginx.com static void nxt_router_http_request_done(nxt_task_t *task, void *obj,
2371547Smax.romanov@nginx.com void *data);
238141Smax.romanov@nginx.com
239425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task,
2401547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data);
2411007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task,
2421547Smax.romanov@nginx.com nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix);
243510Salexander.borisov@nginx.com
244318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data);
245507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj,
246507Smax.romanov@nginx.com void *data);
247507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj,
248507Smax.romanov@nginx.com void *data);
249753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj,
250507Smax.romanov@nginx.com void *data);
251753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data);
252431Sigor@sysoev.ru
253431Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_state;
254431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data);
255141Smax.romanov@nginx.com
256753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task,
257753Smax.romanov@nginx.com nxt_app_joint_t *app_joint, int i);
258753Smax.romanov@nginx.com
2591547Smax.romanov@nginx.com static void nxt_router_http_request_release_post(nxt_task_t *task,
2601007Salexander.borisov@nginx.com nxt_http_request_t *r);
2611007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj,
2621007Salexander.borisov@nginx.com void *data);
2631321Smax.romanov@nginx.com static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg);
2641545Smax.romanov@nginx.com static void nxt_router_get_port_handler(nxt_task_t *task,
2651545Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
2661546Smax.romanov@nginx.com static void nxt_router_get_mmap_handler(nxt_task_t *task,
2671546Smax.romanov@nginx.com nxt_port_recv_msg_t *msg);
2681007Salexander.borisov@nginx.com
2691149Smax.romanov@nginx.com extern const nxt_http_request_state_t nxt_http_websocket;
2701131Smax.romanov@nginx.com
2712165Sz.hong@f5.com nxt_router_t *nxt_router;
27220Sigor@sysoev.ru
273743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_");
274743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string("");
275743Smax.romanov@nginx.com
276743Smax.romanov@nginx.com static const nxt_str_t *nxt_app_msg_prefix[] = {
2772513Sa.clayton@nginx.com [NXT_APP_EXTERNAL] = &empty_prefix,
2782513Sa.clayton@nginx.com [NXT_APP_PYTHON] = &empty_prefix,
2792513Sa.clayton@nginx.com [NXT_APP_PHP] = &http_prefix,
2802513Sa.clayton@nginx.com [NXT_APP_PERL] = &http_prefix,
2812513Sa.clayton@nginx.com [NXT_APP_RUBY] = &http_prefix,
2822513Sa.clayton@nginx.com [NXT_APP_JAVA] = &empty_prefix,
2832514Sa.clayton@nginx.com [NXT_APP_WASM] = &empty_prefix,
2842677Sa.clayton@nginx.com [NXT_APP_WASM_WC] = &empty_prefix,
285216Sigor@sysoev.ru };
286216Sigor@sysoev.ru
287216Sigor@sysoev.ru
2881488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_router_process_port_handlers = {
2891488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler,
290662Smax.romanov@nginx.com .new_port = nxt_router_new_port_handler,
2911545Smax.romanov@nginx.com .get_port = nxt_router_get_port_handler,
292662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler,
293662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler,
2941546Smax.romanov@nginx.com .get_mmap = nxt_router_get_mmap_handler,
295662Smax.romanov@nginx.com .data = nxt_router_conf_data_handler,
2961926Smax.romanov@nginx.com .app_restart = nxt_router_app_restart_handler,
2972185Svbart@nginx.com .status = nxt_router_status_handler,
298662Smax.romanov@nginx.com .remove_pid = nxt_router_remove_pid_handler,
299662Smax.romanov@nginx.com .access_log = nxt_router_access_log_reopen_handler,
300662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler,
301662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler,
3021321Smax.romanov@nginx.com .oosm = nxt_router_oosm_handler,
303662Smax.romanov@nginx.com };
304662Smax.romanov@nginx.com
305662Smax.romanov@nginx.com
3061488St.nateldemoura@f5.com const nxt_process_init_t nxt_router_process = {
3071488St.nateldemoura@f5.com .name = "router",
3081488St.nateldemoura@f5.com .type = NXT_PROCESS_ROUTER,
3091488St.nateldemoura@f5.com .prefork = nxt_router_prefork,
3101488St.nateldemoura@f5.com .restart = 1,
3111488St.nateldemoura@f5.com .setup = nxt_process_core_setup,
3121488St.nateldemoura@f5.com .start = nxt_router_start,
3131488St.nateldemoura@f5.com .port_handlers = &nxt_router_process_port_handlers,
3141488St.nateldemoura@f5.com .signals = nxt_process_signals,
3151488St.nateldemoura@f5.com };
3161488St.nateldemoura@f5.com
3171488St.nateldemoura@f5.com
3181509Sigor@sysoev.ru /* Queues of nxt_socket_conf_t */
3191509Sigor@sysoev.ru nxt_queue_t creating_sockets;
3201509Sigor@sysoev.ru nxt_queue_t pending_sockets;
3211509Sigor@sysoev.ru nxt_queue_t updating_sockets;
3221509Sigor@sysoev.ru nxt_queue_t keeping_sockets;
3231509Sigor@sysoev.ru nxt_queue_t deleting_sockets;
3241509Sigor@sysoev.ru
3251509Sigor@sysoev.ru
3261488St.nateldemoura@f5.com static nxt_int_t
nxt_router_prefork(nxt_task_t * task,nxt_process_t * process,nxt_mp_t * mp)3271488St.nateldemoura@f5.com nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
3281488St.nateldemoura@f5.com {
3291488St.nateldemoura@f5.com nxt_runtime_stop_app_processes(task, task->thread->runtime);
3301488St.nateldemoura@f5.com
3311488St.nateldemoura@f5.com return NXT_OK;
3321488St.nateldemoura@f5.com }
3331488St.nateldemoura@f5.com
3341488St.nateldemoura@f5.com
3351488St.nateldemoura@f5.com static nxt_int_t
nxt_router_start(nxt_task_t * task,nxt_process_data_t * data)3361488St.nateldemoura@f5.com nxt_router_start(nxt_task_t *task, nxt_process_data_t *data)
33720Sigor@sysoev.ru {
338141Smax.romanov@nginx.com nxt_int_t ret;
339662Smax.romanov@nginx.com nxt_port_t *controller_port;
340141Smax.romanov@nginx.com nxt_router_t *router;
341141Smax.romanov@nginx.com nxt_runtime_t *rt;
342141Smax.romanov@nginx.com
343141Smax.romanov@nginx.com rt = task->thread->runtime;
34453Sigor@sysoev.ru
3451488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "router started");
3461488St.nateldemoura@f5.com
347771Sigor@sysoev.ru #if (NXT_TLS)
348771Sigor@sysoev.ru rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL");
349771Sigor@sysoev.ru if (nxt_slow_path(rt->tls == NULL)) {
350771Sigor@sysoev.ru return NXT_ERROR;
351771Sigor@sysoev.ru }
352771Sigor@sysoev.ru
353771Sigor@sysoev.ru ret = rt->tls->library_init(task);
354771Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
355771Sigor@sysoev.ru return ret;
356771Sigor@sysoev.ru }
357771Sigor@sysoev.ru #endif
358771Sigor@sysoev.ru
3591459Smax.romanov@nginx.com ret = nxt_http_init(task);
36088Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
36188Smax.romanov@nginx.com return ret;
36288Smax.romanov@nginx.com }
36388Smax.romanov@nginx.com
36453Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t));
36553Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) {
36653Sigor@sysoev.ru return NXT_ERROR;
36753Sigor@sysoev.ru }
36853Sigor@sysoev.ru
36953Sigor@sysoev.ru nxt_queue_init(&router->engines);
37053Sigor@sysoev.ru nxt_queue_init(&router->sockets);
371133Sigor@sysoev.ru nxt_queue_init(&router->apps);
37253Sigor@sysoev.ru
373119Smax.romanov@nginx.com nxt_router = router;
374119Smax.romanov@nginx.com
375662Smax.romanov@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
376662Smax.romanov@nginx.com if (controller_port != NULL) {
377662Smax.romanov@nginx.com nxt_router_greet_controller(task, controller_port);
378662Smax.romanov@nginx.com }
379662Smax.romanov@nginx.com
380115Sigor@sysoev.ru return NXT_OK;
381115Sigor@sysoev.ru }
382115Sigor@sysoev.ru
383115Sigor@sysoev.ru
384343Smax.romanov@nginx.com static void
nxt_router_greet_controller(nxt_task_t * task,nxt_port_t * controller_port)385662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port)
386662Smax.romanov@nginx.com {
387662Smax.romanov@nginx.com nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY,
388662Smax.romanov@nginx.com -1, 0, 0, NULL);
389662Smax.romanov@nginx.com }
390662Smax.romanov@nginx.com
391662Smax.romanov@nginx.com
392662Smax.romanov@nginx.com static void
nxt_router_start_app_process_handler(nxt_task_t * task,nxt_port_t * port,void * data)393507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port,
394507Smax.romanov@nginx.com void *data)
395167Smax.romanov@nginx.com {
3961926Smax.romanov@nginx.com size_t size;
3971926Smax.romanov@nginx.com uint32_t stream;
3982014Smax.romanov@nginx.com nxt_fd_t port_fd, queue_fd;
3991926Smax.romanov@nginx.com nxt_int_t ret;
4001926Smax.romanov@nginx.com nxt_app_t *app;
4011926Smax.romanov@nginx.com nxt_buf_t *b;
4021998St.nateldemoura@f5.com nxt_port_t *dport;
4031926Smax.romanov@nginx.com nxt_runtime_t *rt;
4041926Smax.romanov@nginx.com nxt_app_joint_rpc_t *app_joint_rpc;
405343Smax.romanov@nginx.com
406343Smax.romanov@nginx.com app = data;
407167Smax.romanov@nginx.com
4081998St.nateldemoura@f5.com nxt_thread_mutex_lock(&app->mutex);
4091998St.nateldemoura@f5.com
4101998St.nateldemoura@f5.com dport = app->proto_port;
4111998St.nateldemoura@f5.com
4121998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex);
4131998St.nateldemoura@f5.com
4141998St.nateldemoura@f5.com if (dport != NULL) {
4151998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start process", &app->name, app);
4161998St.nateldemoura@f5.com
4171998St.nateldemoura@f5.com b = NULL;
4182014Smax.romanov@nginx.com port_fd = -1;
4192014Smax.romanov@nginx.com queue_fd = -1;
4201998St.nateldemoura@f5.com
4211998St.nateldemoura@f5.com } else {
4221998St.nateldemoura@f5.com if (app->proto_port_requests > 0) {
4231998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p wait for prototype process",
4241998St.nateldemoura@f5.com &app->name, app);
4251998St.nateldemoura@f5.com
4261998St.nateldemoura@f5.com app->proto_port_requests++;
4271998St.nateldemoura@f5.com
4281998St.nateldemoura@f5.com goto skip;
4291998St.nateldemoura@f5.com }
4301998St.nateldemoura@f5.com
4311998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start prototype process", &app->name, app);
4321998St.nateldemoura@f5.com
4331998St.nateldemoura@f5.com rt = task->thread->runtime;
4341998St.nateldemoura@f5.com dport = rt->port_by_type[NXT_PROCESS_MAIN];
4351998St.nateldemoura@f5.com
4361998St.nateldemoura@f5.com size = app->name.length + 1 + app->conf.length;
4371998St.nateldemoura@f5.com
4381998St.nateldemoura@f5.com b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0);
4391998St.nateldemoura@f5.com if (nxt_slow_path(b == NULL)) {
4401998St.nateldemoura@f5.com goto failed;
4411998St.nateldemoura@f5.com }
4421998St.nateldemoura@f5.com
4431998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->name);
4441998St.nateldemoura@f5.com *b->mem.free++ = '\0';
4451998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->conf);
4462014Smax.romanov@nginx.com
4472014Smax.romanov@nginx.com port_fd = app->shared_port->pair[0];
4482014Smax.romanov@nginx.com queue_fd = app->shared_port->queue_fd;
4491998St.nateldemoura@f5.com }
450343Smax.romanov@nginx.com
4511926Smax.romanov@nginx.com app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port,
4521926Smax.romanov@nginx.com nxt_router_app_port_ready,
4531926Smax.romanov@nginx.com nxt_router_app_port_error,
4541926Smax.romanov@nginx.com sizeof(nxt_app_joint_rpc_t));
4551926Smax.romanov@nginx.com if (nxt_slow_path(app_joint_rpc == NULL)) {
456343Smax.romanov@nginx.com goto failed;
457343Smax.romanov@nginx.com }
458343Smax.romanov@nginx.com
4591926Smax.romanov@nginx.com stream = nxt_port_rpc_ex_stream(app_joint_rpc);
4601926Smax.romanov@nginx.com
4612014Smax.romanov@nginx.com ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS,
4622014Smax.romanov@nginx.com port_fd, queue_fd, stream, port->id, b);
463648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
464648Svbart@nginx.com nxt_port_rpc_cancel(task, port, stream);
465753Smax.romanov@nginx.com
466648Svbart@nginx.com goto failed;
467648Svbart@nginx.com }
468343Smax.romanov@nginx.com
4691926Smax.romanov@nginx.com app_joint_rpc->app_joint = app->joint;
4701926Smax.romanov@nginx.com app_joint_rpc->generation = app->generation;
4711998St.nateldemoura@f5.com app_joint_rpc->proto = (b != NULL);
4721998St.nateldemoura@f5.com
4731998St.nateldemoura@f5.com if (b != NULL) {
4741998St.nateldemoura@f5.com app->proto_port_requests++;
4751998St.nateldemoura@f5.com
4761998St.nateldemoura@f5.com b = NULL;
4771998St.nateldemoura@f5.com }
4781926Smax.romanov@nginx.com
4791926Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, 1);
4801926Smax.romanov@nginx.com
481343Smax.romanov@nginx.com failed:
482343Smax.romanov@nginx.com
483648Svbart@nginx.com if (b != NULL) {
4841998St.nateldemoura@f5.com nxt_mp_free(b->data, b);
4851998St.nateldemoura@f5.com }
4861998St.nateldemoura@f5.com
4871998St.nateldemoura@f5.com skip:
488343Smax.romanov@nginx.com
489343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1);
490167Smax.romanov@nginx.com }
491167Smax.romanov@nginx.com
492167Smax.romanov@nginx.com
493753Smax.romanov@nginx.com static void
nxt_router_app_joint_use(nxt_task_t * task,nxt_app_joint_t * app_joint,int i)494753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i)
495753Smax.romanov@nginx.com {
496753Smax.romanov@nginx.com app_joint->use_count += i;
497753Smax.romanov@nginx.com
498753Smax.romanov@nginx.com if (app_joint->use_count == 0) {
499753Smax.romanov@nginx.com nxt_assert(app_joint->app == NULL);
500753Smax.romanov@nginx.com
501753Smax.romanov@nginx.com nxt_free(app_joint);
502753Smax.romanov@nginx.com }
503753Smax.romanov@nginx.com }
504753Smax.romanov@nginx.com
505753Smax.romanov@nginx.com
506343Smax.romanov@nginx.com static nxt_int_t
nxt_router_start_app_process(nxt_task_t * task,nxt_app_t * app)507507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app)
508141Smax.romanov@nginx.com {
509343Smax.romanov@nginx.com nxt_int_t res;
510343Smax.romanov@nginx.com nxt_port_t *router_port;
511343Smax.romanov@nginx.com nxt_runtime_t *rt;
512343Smax.romanov@nginx.com
5131549Smax.romanov@nginx.com nxt_debug(task, "app '%V' start process", &app->name);
5141549Smax.romanov@nginx.com
515343Smax.romanov@nginx.com rt = task->thread->runtime;
516343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
517343Smax.romanov@nginx.com
518343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1);
519343Smax.romanov@nginx.com
520507Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler,
521343Smax.romanov@nginx.com app);
522343Smax.romanov@nginx.com
523343Smax.romanov@nginx.com if (res == NXT_OK) {
524343Smax.romanov@nginx.com return res;
525318Smax.romanov@nginx.com }
526318Smax.romanov@nginx.com
527343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
528343Smax.romanov@nginx.com
529507Smax.romanov@nginx.com app->pending_processes--;
530343Smax.romanov@nginx.com
531343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
532343Smax.romanov@nginx.com
533343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1);
534343Smax.romanov@nginx.com
535343Smax.romanov@nginx.com return NXT_ERROR;
536318Smax.romanov@nginx.com }
537318Smax.romanov@nginx.com
538318Smax.romanov@nginx.com
539423Smax.romanov@nginx.com nxt_inline nxt_bool_t
nxt_router_msg_cancel(nxt_task_t * task,nxt_request_rpc_data_t * req_rpc_data)5401555Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data)
541423Smax.romanov@nginx.com {
5421555Smax.romanov@nginx.com nxt_buf_t *b, *next;
5431555Smax.romanov@nginx.com nxt_bool_t cancelled;
5441926Smax.romanov@nginx.com nxt_port_t *app_port;
5451555Smax.romanov@nginx.com nxt_msg_info_t *msg_info;
5461555Smax.romanov@nginx.com
5471555Smax.romanov@nginx.com msg_info = &req_rpc_data->msg_info;
548423Smax.romanov@nginx.com
549423Smax.romanov@nginx.com if (msg_info->buf == NULL) {
550423Smax.romanov@nginx.com return 0;
551423Smax.romanov@nginx.com }
552423Smax.romanov@nginx.com
5531926Smax.romanov@nginx.com app_port = req_rpc_data->app_port;
5541926Smax.romanov@nginx.com
5551926Smax.romanov@nginx.com if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) {
5561926Smax.romanov@nginx.com cancelled = nxt_app_queue_cancel(app_port->queue,
5571926Smax.romanov@nginx.com msg_info->tracking_cookie,
5581926Smax.romanov@nginx.com req_rpc_data->stream);
5591926Smax.romanov@nginx.com
5601926Smax.romanov@nginx.com if (cancelled) {
5611926Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router",
5621926Smax.romanov@nginx.com req_rpc_data->stream);
5631926Smax.romanov@nginx.com }
5641926Smax.romanov@nginx.com
5651926Smax.romanov@nginx.com } else {
5661926Smax.romanov@nginx.com cancelled = 0;
567423Smax.romanov@nginx.com }
568423Smax.romanov@nginx.com
569423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) {
570423Smax.romanov@nginx.com next = b->next;
5711269Sigor@sysoev.ru b->next = NULL;
572423Smax.romanov@nginx.com
573423Smax.romanov@nginx.com if (b->is_port_mmap_sent) {
574423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0;
575423Smax.romanov@nginx.com }
5761829Smax.romanov@nginx.com
5771829Smax.romanov@nginx.com b->completion_handler(task, b, b->parent);
578423Smax.romanov@nginx.com }
579423Smax.romanov@nginx.com
580423Smax.romanov@nginx.com msg_info->buf = NULL;
581423Smax.romanov@nginx.com
582423Smax.romanov@nginx.com return cancelled;
583423Smax.romanov@nginx.com }
584423Smax.romanov@nginx.com
585423Smax.romanov@nginx.com
586425Smax.romanov@nginx.com nxt_inline nxt_bool_t
nxt_queue_chk_remove(nxt_queue_link_t * lnk)587425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk)
588425Smax.romanov@nginx.com {
589425Smax.romanov@nginx.com if (lnk->next != NULL) {
590425Smax.romanov@nginx.com nxt_queue_remove(lnk);
591425Smax.romanov@nginx.com
592425Smax.romanov@nginx.com lnk->next = NULL;
593425Smax.romanov@nginx.com
594425Smax.romanov@nginx.com return 1;
595425Smax.romanov@nginx.com }
596425Smax.romanov@nginx.com
597425Smax.romanov@nginx.com return 0;
598425Smax.romanov@nginx.com }
599425Smax.romanov@nginx.com
600425Smax.romanov@nginx.com
601343Smax.romanov@nginx.com nxt_inline void
nxt_request_rpc_data_unlink(nxt_task_t * task,nxt_request_rpc_data_t * req_rpc_data)6021123Smax.romanov@nginx.com nxt_request_rpc_data_unlink(nxt_task_t *task,
6031123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data)
604343Smax.romanov@nginx.com {
6051561Smax.romanov@nginx.com nxt_app_t *app;
6061561Smax.romanov@nginx.com nxt_bool_t unlinked;
6071547Smax.romanov@nginx.com nxt_http_request_t *r;
6081547Smax.romanov@nginx.com
6091555Smax.romanov@nginx.com nxt_router_msg_cancel(task, req_rpc_data);
6101123Smax.romanov@nginx.com
6111978Smax.romanov@nginx.com app = req_rpc_data->app;
6121978Smax.romanov@nginx.com
6131123Smax.romanov@nginx.com if (req_rpc_data->app_port != NULL) {
6141978Smax.romanov@nginx.com nxt_router_app_port_release(task, app, req_rpc_data->app_port,
6151123Smax.romanov@nginx.com req_rpc_data->apr_action);
6161123Smax.romanov@nginx.com
6171123Smax.romanov@nginx.com req_rpc_data->app_port = NULL;
6181123Smax.romanov@nginx.com }
6191123Smax.romanov@nginx.com
6201547Smax.romanov@nginx.com r = req_rpc_data->request;
6211547Smax.romanov@nginx.com
6221547Smax.romanov@nginx.com if (r != NULL) {
6231547Smax.romanov@nginx.com r->timer_data = NULL;
6241547Smax.romanov@nginx.com
6251547Smax.romanov@nginx.com nxt_router_http_request_release_post(task, r);
6261547Smax.romanov@nginx.com
6271547Smax.romanov@nginx.com r->req_rpc_data = NULL;
6281123Smax.romanov@nginx.com req_rpc_data->request = NULL;
6291561Smax.romanov@nginx.com
6301561Smax.romanov@nginx.com if (app != NULL) {
6311561Smax.romanov@nginx.com unlinked = 0;
6321561Smax.romanov@nginx.com
6331561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
6341561Smax.romanov@nginx.com
6351561Smax.romanov@nginx.com if (r->app_link.next != NULL) {
6361561Smax.romanov@nginx.com nxt_queue_remove(&r->app_link);
6371561Smax.romanov@nginx.com r->app_link.next = NULL;
6381561Smax.romanov@nginx.com
6391561Smax.romanov@nginx.com unlinked = 1;
6401561Smax.romanov@nginx.com }
6411561Smax.romanov@nginx.com
6421561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
6431561Smax.romanov@nginx.com
6441561Smax.romanov@nginx.com if (unlinked) {
6451561Smax.romanov@nginx.com nxt_mp_release(r->mem_pool);
6461561Smax.romanov@nginx.com }
6471561Smax.romanov@nginx.com }
6481561Smax.romanov@nginx.com }
6491561Smax.romanov@nginx.com
6501561Smax.romanov@nginx.com if (app != NULL) {
6511561Smax.romanov@nginx.com nxt_router_app_use(task, app, -1);
6521561Smax.romanov@nginx.com
6531561Smax.romanov@nginx.com req_rpc_data->app = NULL;
654346Smax.romanov@nginx.com }
6551547Smax.romanov@nginx.com
6561547Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1) {
6571547Smax.romanov@nginx.com nxt_fd_close(req_rpc_data->msg_info.body_fd);
6581547Smax.romanov@nginx.com
6591547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1;
6601547Smax.romanov@nginx.com }
6611547Smax.romanov@nginx.com
6621547Smax.romanov@nginx.com if (req_rpc_data->rpc_cancel) {
6631547Smax.romanov@nginx.com req_rpc_data->rpc_cancel = 0;
6641547Smax.romanov@nginx.com
6651547Smax.romanov@nginx.com nxt_port_rpc_cancel(task, task->thread->engine->port,
6661547Smax.romanov@nginx.com req_rpc_data->stream);
6671547Smax.romanov@nginx.com }
668343Smax.romanov@nginx.com }
669343Smax.romanov@nginx.com
670343Smax.romanov@nginx.com
6711552Smax.romanov@nginx.com static void
nxt_router_new_port_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)672141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
673141Smax.romanov@nginx.com {
6741555Smax.romanov@nginx.com nxt_int_t res;
6751547Smax.romanov@nginx.com nxt_app_t *app;
6761547Smax.romanov@nginx.com nxt_port_t *port, *main_app_port;
6771547Smax.romanov@nginx.com nxt_runtime_t *rt;
6781547Smax.romanov@nginx.com
679141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg);
680141Smax.romanov@nginx.com
6811547Smax.romanov@nginx.com port = msg->u.new_port;
6821547Smax.romanov@nginx.com
6831547Smax.romanov@nginx.com if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) {
684662Smax.romanov@nginx.com nxt_router_greet_controller(task, msg->u.new_port);
685662Smax.romanov@nginx.com }
686662Smax.romanov@nginx.com
6871998St.nateldemoura@f5.com if (port != NULL && port->type == NXT_PROCESS_PROTOTYPE) {
6881998St.nateldemoura@f5.com nxt_port_rpc_handler(task, msg);
6891998St.nateldemoura@f5.com
6901998St.nateldemoura@f5.com return;
6911998St.nateldemoura@f5.com }
6921998St.nateldemoura@f5.com
6931547Smax.romanov@nginx.com if (port == NULL || port->type != NXT_PROCESS_APP) {
6941547Smax.romanov@nginx.com
6951547Smax.romanov@nginx.com if (msg->port_msg.stream == 0) {
6961547Smax.romanov@nginx.com return;
6971547Smax.romanov@nginx.com }
6981547Smax.romanov@nginx.com
6991547Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
7001555Smax.romanov@nginx.com
7011555Smax.romanov@nginx.com } else {
7021558Smax.romanov@nginx.com if (msg->fd[1] != -1) {
7031558Smax.romanov@nginx.com res = nxt_router_port_queue_map(task, port, msg->fd[1]);
7041555Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) {
7051555Smax.romanov@nginx.com return;
7061555Smax.romanov@nginx.com }
7071555Smax.romanov@nginx.com
7081558Smax.romanov@nginx.com nxt_fd_close(msg->fd[1]);
7091558Smax.romanov@nginx.com msg->fd[1] = -1;
7101555Smax.romanov@nginx.com }
7111547Smax.romanov@nginx.com }
7121547Smax.romanov@nginx.com
7131547Smax.romanov@nginx.com if (msg->port_msg.stream != 0) {
7141547Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg);
715141Smax.romanov@nginx.com return;
716141Smax.romanov@nginx.com }
717141Smax.romanov@nginx.com
7181998St.nateldemoura@f5.com nxt_debug(task, "new port id %d (%d)", port->id, port->type);
7191998St.nateldemoura@f5.com
7201547Smax.romanov@nginx.com /*
7211547Smax.romanov@nginx.com * Port with "id == 0" is application 'main' port and it always
7221547Smax.romanov@nginx.com * should come with non-zero stream.
7231547Smax.romanov@nginx.com */
7241547Smax.romanov@nginx.com nxt_assert(port->id != 0);
7251547Smax.romanov@nginx.com
7261547Smax.romanov@nginx.com /* Find 'main' app port and get app reference. */
7271547Smax.romanov@nginx.com rt = task->thread->runtime;
7281547Smax.romanov@nginx.com
7291547Smax.romanov@nginx.com /*
7301547Smax.romanov@nginx.com * It is safe to access 'runtime->ports' hash because 'NEW_PORT'
7311547Smax.romanov@nginx.com * sent to main port (with id == 0) and processed in main thread.
7321547Smax.romanov@nginx.com */
7331547Smax.romanov@nginx.com main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0);
7341547Smax.romanov@nginx.com nxt_assert(main_app_port != NULL);
7351547Smax.romanov@nginx.com
7361547Smax.romanov@nginx.com app = main_app_port->app;
7371915Smax.romanov@nginx.com
7381915Smax.romanov@nginx.com if (nxt_fast_path(app != NULL)) {
7391915Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
7401915Smax.romanov@nginx.com
7411915Smax.romanov@nginx.com /* TODO here should be find-and-add code because there can be
7421915Smax.romanov@nginx.com port waiters in port_hash */
7431915Smax.romanov@nginx.com nxt_port_hash_add(&app->port_hash, port);
7441915Smax.romanov@nginx.com app->port_hash_count++;
7451915Smax.romanov@nginx.com
7461915Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
7471915Smax.romanov@nginx.com
7481915Smax.romanov@nginx.com port->app = app;
7491915Smax.romanov@nginx.com }
7501915Smax.romanov@nginx.com
7511547Smax.romanov@nginx.com port->main_app_port = main_app_port;
7521666Smax.romanov@nginx.com
7531666Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL);
754141Smax.romanov@nginx.com }
755141Smax.romanov@nginx.com
756141Smax.romanov@nginx.com
7571552Smax.romanov@nginx.com static void
nxt_router_conf_data_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)758139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
759115Sigor@sysoev.ru {
7601526Smax.romanov@nginx.com void *p;
7611526Smax.romanov@nginx.com size_t size;
762198Sigor@sysoev.ru nxt_int_t ret;
7631779Smax.romanov@nginx.com nxt_port_t *port;
764139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf;
765139Sigor@sysoev.ru
7661779Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime,
7671779Smax.romanov@nginx.com msg->port_msg.pid,
7681779Smax.romanov@nginx.com msg->port_msg.reply_port);
7691779Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) {
7701779Smax.romanov@nginx.com nxt_alert(task, "conf_data_handler: reply port not found");
7711779Smax.romanov@nginx.com return;
7721779Smax.romanov@nginx.com }
7731779Smax.romanov@nginx.com
7741779Smax.romanov@nginx.com p = MAP_FAILED;
7751779Smax.romanov@nginx.com
7761779Smax.romanov@nginx.com /*
7771779Smax.romanov@nginx.com * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be
7781779Smax.romanov@nginx.com * initialized in 'cleanup' section.
7791779Smax.romanov@nginx.com */
7801779Smax.romanov@nginx.com size = 0;
7811779Smax.romanov@nginx.com
782139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task);
783139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) {
7841779Smax.romanov@nginx.com goto fail;
78553Sigor@sysoev.ru }
78653Sigor@sysoev.ru
7871558Smax.romanov@nginx.com if (nxt_slow_path(msg->fd[0] == -1)) {
7881779Smax.romanov@nginx.com nxt_alert(task, "conf_data_handler: invalid shm fd");
7891779Smax.romanov@nginx.com goto fail;
7901526Smax.romanov@nginx.com }
7911526Smax.romanov@nginx.com
7921526Smax.romanov@nginx.com if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) {
7931526Smax.romanov@nginx.com nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)",
7941526Smax.romanov@nginx.com (int) nxt_buf_mem_used_size(&msg->buf->mem));
7951779Smax.romanov@nginx.com goto fail;
7961526Smax.romanov@nginx.com }
7971526Smax.romanov@nginx.com
7981526Smax.romanov@nginx.com nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t));
7991526Smax.romanov@nginx.com
8001558Smax.romanov@nginx.com p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0);
8011558Smax.romanov@nginx.com
8021558Smax.romanov@nginx.com nxt_fd_close(msg->fd[0]);
8031558Smax.romanov@nginx.com msg->fd[0] = -1;
8041526Smax.romanov@nginx.com
8051526Smax.romanov@nginx.com if (nxt_slow_path(p == MAP_FAILED)) {
8061779Smax.romanov@nginx.com goto fail;
8071526Smax.romanov@nginx.com }
8081526Smax.romanov@nginx.com
8091526Smax.romanov@nginx.com nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p);
810423Smax.romanov@nginx.com
811591Sigor@sysoev.ru tmcf->router_conf->router = nxt_router;
812139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream;
8131779Smax.romanov@nginx.com tmcf->port = port;
814779Smax.romanov@nginx.com
815779Smax.romanov@nginx.com nxt_port_use(task, tmcf->port, 1);
816779Smax.romanov@nginx.com
8171526Smax.romanov@nginx.com ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size));
818198Sigor@sysoev.ru
819198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) {
820198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL);
821198Sigor@sysoev.ru
822198Sigor@sysoev.ru } else {
823198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf);
824139Sigor@sysoev.ru }
8251526Smax.romanov@nginx.com
8261779Smax.romanov@nginx.com goto cleanup;
8271779Smax.romanov@nginx.com
8281526Smax.romanov@nginx.com fail:
8291526Smax.romanov@nginx.com
8301779Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1,
8311779Smax.romanov@nginx.com msg->port_msg.stream, 0, NULL);
8321779Smax.romanov@nginx.com
8331779Smax.romanov@nginx.com if (tmcf != NULL) {
8341869Sa.suvorov@f5.com nxt_mp_release(tmcf->mem_pool);
8351779Smax.romanov@nginx.com }
8361779Smax.romanov@nginx.com
8371779Smax.romanov@nginx.com cleanup:
8381779Smax.romanov@nginx.com
8391779Smax.romanov@nginx.com if (p != MAP_FAILED) {
8401779Smax.romanov@nginx.com nxt_mem_munmap(p, size);
8411779Smax.romanov@nginx.com }
8421779Smax.romanov@nginx.com
8431779Smax.romanov@nginx.com if (msg->fd[0] != -1) {
8441779Smax.romanov@nginx.com nxt_fd_close(msg->fd[0]);
8451779Smax.romanov@nginx.com msg->fd[0] = -1;
8461779Smax.romanov@nginx.com }
84753Sigor@sysoev.ru }
84853Sigor@sysoev.ru
84953Sigor@sysoev.ru
850347Smax.romanov@nginx.com static void
nxt_router_app_restart_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)8511926Smax.romanov@nginx.com nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
8521926Smax.romanov@nginx.com {
8531926Smax.romanov@nginx.com nxt_app_t *app;
8541926Smax.romanov@nginx.com nxt_int_t ret;
8551926Smax.romanov@nginx.com nxt_str_t app_name;
8561998St.nateldemoura@f5.com nxt_port_t *reply_port, *shared_port, *old_shared_port;
8571998St.nateldemoura@f5.com nxt_port_t *proto_port;
8581926Smax.romanov@nginx.com nxt_port_msg_type_t reply;
8591926Smax.romanov@nginx.com
8601926Smax.romanov@nginx.com reply_port = nxt_runtime_port_find(task->thread->runtime,
8611926Smax.romanov@nginx.com msg->port_msg.pid,
8621926Smax.romanov@nginx.com msg->port_msg.reply_port);
8631926Smax.romanov@nginx.com if (nxt_slow_path(reply_port == NULL)) {
8641926Smax.romanov@nginx.com nxt_alert(task, "app_restart_handler: reply port not found");
8651926Smax.romanov@nginx.com return;
8661926Smax.romanov@nginx.com }
8671926Smax.romanov@nginx.com
8681926Smax.romanov@nginx.com app_name.length = nxt_buf_mem_used_size(&msg->buf->mem);
8691926Smax.romanov@nginx.com app_name.start = msg->buf->mem.pos;
8701926Smax.romanov@nginx.com
8711926Smax.romanov@nginx.com nxt_debug(task, "app_restart_handler: %V", &app_name);
8721926Smax.romanov@nginx.com
8731926Smax.romanov@nginx.com app = nxt_router_app_find(&nxt_router->apps, &app_name);
8741926Smax.romanov@nginx.com
8751926Smax.romanov@nginx.com if (nxt_fast_path(app != NULL)) {
8761926Smax.romanov@nginx.com shared_port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid,
8771926Smax.romanov@nginx.com NXT_PROCESS_APP);
8781926Smax.romanov@nginx.com if (nxt_slow_path(shared_port == NULL)) {
8791926Smax.romanov@nginx.com goto fail;
8801926Smax.romanov@nginx.com }
8811926Smax.romanov@nginx.com
8821926Smax.romanov@nginx.com ret = nxt_port_socket_init(task, shared_port, 0);
8831926Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
8841926Smax.romanov@nginx.com nxt_port_use(task, shared_port, -1);
8851926Smax.romanov@nginx.com goto fail;
8861926Smax.romanov@nginx.com }
8871926Smax.romanov@nginx.com
8881926Smax.romanov@nginx.com ret = nxt_router_app_queue_init(task, shared_port);
8891926Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
8901926Smax.romanov@nginx.com nxt_port_write_close(shared_port);
8911926Smax.romanov@nginx.com nxt_port_read_close(shared_port);
8921926Smax.romanov@nginx.com nxt_port_use(task, shared_port, -1);
8931926Smax.romanov@nginx.com goto fail;
8941926Smax.romanov@nginx.com }
8951926Smax.romanov@nginx.com
8961926Smax.romanov@nginx.com nxt_port_write_enable(task, shared_port);
8971926Smax.romanov@nginx.com
8981926Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
8991926Smax.romanov@nginx.com
9001998St.nateldemoura@f5.com proto_port = app->proto_port;
9011998St.nateldemoura@f5.com
9021998St.nateldemoura@f5.com if (proto_port != NULL) {
9031998St.nateldemoura@f5.com nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name,
9041998St.nateldemoura@f5.com proto_port->pid);
9051998St.nateldemoura@f5.com
9061998St.nateldemoura@f5.com app->proto_port = NULL;
9071998St.nateldemoura@f5.com proto_port->app = NULL;
9081998St.nateldemoura@f5.com }
9091926Smax.romanov@nginx.com
9101926Smax.romanov@nginx.com app->generation++;
9111926Smax.romanov@nginx.com
9121926Smax.romanov@nginx.com shared_port->app = app;
9131926Smax.romanov@nginx.com
9141926Smax.romanov@nginx.com old_shared_port = app->shared_port;
9151926Smax.romanov@nginx.com old_shared_port->app = NULL;
9161926Smax.romanov@nginx.com
9171926Smax.romanov@nginx.com app->shared_port = shared_port;
9181926Smax.romanov@nginx.com
9191926Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
9201926Smax.romanov@nginx.com
9211926Smax.romanov@nginx.com nxt_port_close(task, old_shared_port);
9221926Smax.romanov@nginx.com nxt_port_use(task, old_shared_port, -1);
9231926Smax.romanov@nginx.com
9241998St.nateldemoura@f5.com if (proto_port != NULL) {
9251998St.nateldemoura@f5.com (void) nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT,
9261998St.nateldemoura@f5.com -1, 0, 0, NULL);
9271998St.nateldemoura@f5.com
9281998St.nateldemoura@f5.com nxt_port_close(task, proto_port);
9291998St.nateldemoura@f5.com
9301998St.nateldemoura@f5.com nxt_port_use(task, proto_port, -1);
9311998St.nateldemoura@f5.com }
9321998St.nateldemoura@f5.com
9331926Smax.romanov@nginx.com reply = NXT_PORT_MSG_RPC_READY_LAST;
9341926Smax.romanov@nginx.com
9351926Smax.romanov@nginx.com } else {
9361926Smax.romanov@nginx.com
9371926Smax.romanov@nginx.com fail:
9381926Smax.romanov@nginx.com
9391926Smax.romanov@nginx.com reply = NXT_PORT_MSG_RPC_ERROR;
9401926Smax.romanov@nginx.com }
9411926Smax.romanov@nginx.com
9421926Smax.romanov@nginx.com nxt_port_socket_write(task, reply_port, reply, -1, msg->port_msg.stream,
9431926Smax.romanov@nginx.com 0, NULL);
9441926Smax.romanov@nginx.com }
9451926Smax.romanov@nginx.com
9461926Smax.romanov@nginx.com
9471926Smax.romanov@nginx.com static void
nxt_router_status_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)9482185Svbart@nginx.com nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
9492185Svbart@nginx.com {
9502185Svbart@nginx.com u_char *p;
9512185Svbart@nginx.com size_t alloc;
9522185Svbart@nginx.com nxt_app_t *app;
9532185Svbart@nginx.com nxt_buf_t *b;
9542185Svbart@nginx.com nxt_uint_t type;
9552185Svbart@nginx.com nxt_port_t *port;
9562185Svbart@nginx.com nxt_status_app_t *app_stat;
9572185Svbart@nginx.com nxt_event_engine_t *engine;
9582185Svbart@nginx.com nxt_status_report_t *report;
9592185Svbart@nginx.com
9602185Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime,
9612185Svbart@nginx.com msg->port_msg.pid,
9622185Svbart@nginx.com msg->port_msg.reply_port);
9632185Svbart@nginx.com if (nxt_slow_path(port == NULL)) {
9642185Svbart@nginx.com nxt_alert(task, "nxt_router_status_handler(): reply port not found");
9652185Svbart@nginx.com return;
9662185Svbart@nginx.com }
9672185Svbart@nginx.com
9682185Svbart@nginx.com alloc = sizeof(nxt_status_report_t);
9692185Svbart@nginx.com
9702185Svbart@nginx.com nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
9712185Svbart@nginx.com
9722185Svbart@nginx.com alloc += sizeof(nxt_status_app_t) + app->name.length;
9732185Svbart@nginx.com
9742185Svbart@nginx.com } nxt_queue_loop;
9752185Svbart@nginx.com
9762185Svbart@nginx.com b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0);
9772185Svbart@nginx.com if (nxt_slow_path(b == NULL)) {
9782185Svbart@nginx.com type = NXT_PORT_MSG_RPC_ERROR;
9792185Svbart@nginx.com goto fail;
9802185Svbart@nginx.com }
9812185Svbart@nginx.com
9822185Svbart@nginx.com report = (nxt_status_report_t *) b->mem.free;
9832185Svbart@nginx.com b->mem.free = b->mem.end;
9842185Svbart@nginx.com
9852185Svbart@nginx.com nxt_memzero(report, sizeof(nxt_status_report_t));
9862185Svbart@nginx.com
9872185Svbart@nginx.com nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) {
9882185Svbart@nginx.com
9892185Svbart@nginx.com report->accepted_conns += engine->accepted_conns_cnt;
9902185Svbart@nginx.com report->idle_conns += engine->idle_conns_cnt;
9912185Svbart@nginx.com report->closed_conns += engine->closed_conns_cnt;
9922186Sz.hong@f5.com report->requests += engine->requests_cnt;
9932185Svbart@nginx.com
9942185Svbart@nginx.com } nxt_queue_loop;
9952185Svbart@nginx.com
9962185Svbart@nginx.com report->apps_count = 0;
9972185Svbart@nginx.com app_stat = report->apps;
9982185Svbart@nginx.com p = b->mem.end;
9992185Svbart@nginx.com
10002185Svbart@nginx.com nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
10012185Svbart@nginx.com p -= app->name.length;
10022185Svbart@nginx.com
10032185Svbart@nginx.com nxt_memcpy(p, app->name.start, app->name.length);
10042185Svbart@nginx.com
10052185Svbart@nginx.com app_stat->name.length = app->name.length;
10062185Svbart@nginx.com app_stat->name.start = (u_char *) (p - b->mem.pos);
10072185Svbart@nginx.com
10082185Svbart@nginx.com app_stat->active_requests = app->active_requests;
10092185Svbart@nginx.com app_stat->pending_processes = app->pending_processes;
10102185Svbart@nginx.com app_stat->processes = app->processes;
10112185Svbart@nginx.com app_stat->idle_processes = app->idle_processes;
10122185Svbart@nginx.com
10132185Svbart@nginx.com report->apps_count++;
10142185Svbart@nginx.com app_stat++;
10152185Svbart@nginx.com } nxt_queue_loop;
10162185Svbart@nginx.com
10172185Svbart@nginx.com type = NXT_PORT_MSG_RPC_READY_LAST;
10182185Svbart@nginx.com
10192185Svbart@nginx.com fail:
10202185Svbart@nginx.com
10212185Svbart@nginx.com nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b);
10222185Svbart@nginx.com }
10232185Svbart@nginx.com
10242185Svbart@nginx.com
10252185Svbart@nginx.com static void
nxt_router_app_process_remove_pid(nxt_task_t * task,nxt_port_t * port,void * data)1026507Smax.romanov@nginx.com nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port,
1027507Smax.romanov@nginx.com void *data)
1028347Smax.romanov@nginx.com {
1029347Smax.romanov@nginx.com union {
1030347Smax.romanov@nginx.com nxt_pid_t removed_pid;
1031347Smax.romanov@nginx.com void *data;
1032347Smax.romanov@nginx.com } u;
1033347Smax.romanov@nginx.com
1034347Smax.romanov@nginx.com u.data = data;
1035347Smax.romanov@nginx.com
1036347Smax.romanov@nginx.com nxt_port_rpc_remove_peer(task, port, u.removed_pid);
1037347Smax.romanov@nginx.com }
1038347Smax.romanov@nginx.com
1039347Smax.romanov@nginx.com
10401552Smax.romanov@nginx.com static void
nxt_router_remove_pid_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)1041192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1042192Smax.romanov@nginx.com {
1043347Smax.romanov@nginx.com nxt_event_engine_t *engine;
1044318Smax.romanov@nginx.com
1045192Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, msg);
1046192Smax.romanov@nginx.com
1047318Smax.romanov@nginx.com nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0)
1048318Smax.romanov@nginx.com {
10491486Smax.romanov@nginx.com if (nxt_fast_path(engine->port != NULL)) {
10501486Smax.romanov@nginx.com nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid,
10511486Smax.romanov@nginx.com msg->u.data);
10521486Smax.romanov@nginx.com }
1053318Smax.romanov@nginx.com }
1054318Smax.romanov@nginx.com nxt_queue_loop;
1055318Smax.romanov@nginx.com
10561085Smax.romanov@nginx.com if (msg->port_msg.stream == 0) {
10571085Smax.romanov@nginx.com return;
10581085Smax.romanov@nginx.com }
10591085Smax.romanov@nginx.com
1060192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
1061192Smax.romanov@nginx.com
1062192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg);
1063192Smax.romanov@nginx.com }
1064192Smax.romanov@nginx.com
1065192Smax.romanov@nginx.com
106653Sigor@sysoev.ru static nxt_router_temp_conf_t *
nxt_router_temp_conf(nxt_task_t * task)1067139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task)
106853Sigor@sysoev.ru {
106965Sigor@sysoev.ru nxt_mp_t *mp, *tmp;
107053Sigor@sysoev.ru nxt_router_conf_t *rtcf;
107153Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf;
107253Sigor@sysoev.ru
107365Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32);
107453Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) {
107553Sigor@sysoev.ru return NULL;
107653Sigor@sysoev.ru }
107753Sigor@sysoev.ru
107865Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t));
107953Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) {
1080*2716Sa.clayton@nginx.com goto fail;
108153Sigor@sysoev.ru }
108253Sigor@sysoev.ru
108353Sigor@sysoev.ru rtcf->mem_pool = mp;
108453Sigor@sysoev.ru
10852247Sz.hong@f5.com rtcf->tstr_state = nxt_tstr_state_new(mp, 0);
10862246Sz.hong@f5.com if (nxt_slow_path(rtcf->tstr_state == NULL)) {
1087*2716Sa.clayton@nginx.com goto fail;
10882147Sz.hong@f5.com }
10892147Sz.hong@f5.com
10902248Sz.hong@f5.com #if (NXT_HAVE_NJS)
10912248Sz.hong@f5.com nxt_http_register_js_proto(rtcf->tstr_state->jcf);
10922248Sz.hong@f5.com #endif
10932248Sz.hong@f5.com
109465Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32);
109553Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) {
1096*2716Sa.clayton@nginx.com goto fail;
109753Sigor@sysoev.ru }
109853Sigor@sysoev.ru
109965Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t));
110053Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) {
1101*2716Sa.clayton@nginx.com goto temp_fail;
110253Sigor@sysoev.ru }
110353Sigor@sysoev.ru
110453Sigor@sysoev.ru tmcf->mem_pool = tmp;
1105591Sigor@sysoev.ru tmcf->router_conf = rtcf;
1106139Sigor@sysoev.ru tmcf->count = 1;
1107139Sigor@sysoev.ru tmcf->engine = task->thread->engine;
110853Sigor@sysoev.ru
110953Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4,
111053Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t));
111153Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) {
1112*2716Sa.clayton@nginx.com goto temp_fail;
111353Sigor@sysoev.ru }
111453Sigor@sysoev.ru
11151509Sigor@sysoev.ru nxt_queue_init(&creating_sockets);
11161509Sigor@sysoev.ru nxt_queue_init(&pending_sockets);
11171509Sigor@sysoev.ru nxt_queue_init(&updating_sockets);
11181509Sigor@sysoev.ru nxt_queue_init(&keeping_sockets);
11191509Sigor@sysoev.ru nxt_queue_init(&deleting_sockets);
1120416Smax.romanov@nginx.com
1121774Svbart@nginx.com #if (NXT_TLS)
1122774Svbart@nginx.com nxt_queue_init(&tmcf->tls);
1123774Svbart@nginx.com #endif
1124774Svbart@nginx.com
11252450Sz.hong@f5.com #if (NXT_HAVE_NJS)
11262450Sz.hong@f5.com nxt_queue_init(&tmcf->js_modules);
11272450Sz.hong@f5.com #endif
11282450Sz.hong@f5.com
1129133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps);
1130133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous);
113153Sigor@sysoev.ru
113253Sigor@sysoev.ru return tmcf;
113353Sigor@sysoev.ru
1134*2716Sa.clayton@nginx.com temp_fail:
113553Sigor@sysoev.ru
113665Sigor@sysoev.ru nxt_mp_destroy(tmp);
113753Sigor@sysoev.ru
1138*2716Sa.clayton@nginx.com fail:
113953Sigor@sysoev.ru
11402318Sz.hong@f5.com if (rtcf->tstr_state != NULL) {
11412318Sz.hong@f5.com nxt_tstr_state_release(rtcf->tstr_state);
11422318Sz.hong@f5.com }
11432318Sz.hong@f5.com
1144*2716Sa.clayton@nginx.com nxt_mp_destroy(mp);
1145*2716Sa.clayton@nginx.com
114665Sigor@sysoev.ru return NULL;
114753Sigor@sysoev.ru }
114853Sigor@sysoev.ru
114953Sigor@sysoev.ru
115053Sigor@sysoev.ru nxt_inline nxt_bool_t
nxt_router_app_can_start(nxt_app_t * app)115153Sigor@sysoev.ru nxt_router_app_can_start(nxt_app_t *app)
1152507Smax.romanov@nginx.com {
1153507Smax.romanov@nginx.com return app->processes + app->pending_processes < app->max_processes
1154507Smax.romanov@nginx.com && app->pending_processes < app->max_pending_processes;
1155507Smax.romanov@nginx.com }
1156507Smax.romanov@nginx.com
1157507Smax.romanov@nginx.com
1158507Smax.romanov@nginx.com nxt_inline nxt_bool_t
nxt_router_app_need_start(nxt_app_t * app)1159507Smax.romanov@nginx.com nxt_router_app_need_start(nxt_app_t *app)
1160507Smax.romanov@nginx.com {
1161507Smax.romanov@nginx.com return (app->active_requests
1162507Smax.romanov@nginx.com > app->port_hash_count + app->pending_processes)
11631547Smax.romanov@nginx.com || (app->spare_processes
11641547Smax.romanov@nginx.com > app->idle_processes + app->pending_processes);
11651547Smax.romanov@nginx.com }
11661547Smax.romanov@nginx.com
1167507Smax.romanov@nginx.com
1168507Smax.romanov@nginx.com void
nxt_router_conf_apply(nxt_task_t * task,void * obj,void * data)1169507Smax.romanov@nginx.com nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
11702165Sz.hong@f5.com {
1171198Sigor@sysoev.ru nxt_int_t ret;
1172139Sigor@sysoev.ru nxt_app_t *app;
1173139Sigor@sysoev.ru nxt_router_t *router;
1174507Smax.romanov@nginx.com nxt_runtime_t *rt;
1175139Sigor@sysoev.ru nxt_queue_link_t *qlk;
1176139Sigor@sysoev.ru nxt_socket_conf_t *skcf;
1177198Sigor@sysoev.ru nxt_router_conf_t *rtcf;
1178198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf;
1179630Svbart@nginx.com const nxt_event_interface_t *interface;
1180198Sigor@sysoev.ru #if (NXT_TLS)
1181139Sigor@sysoev.ru nxt_router_tlssock_t *tls;
1182774Svbart@nginx.com #endif
1183774Svbart@nginx.com #if (NXT_HAVE_NJS)
1184774Svbart@nginx.com nxt_router_js_module_t *js_module;
11852450Sz.hong@f5.com #endif
11862450Sz.hong@f5.com
11872450Sz.hong@f5.com tmcf = obj;
1188139Sigor@sysoev.ru
1189198Sigor@sysoev.ru qlk = nxt_queue_first(&pending_sockets);
1190198Sigor@sysoev.ru
11911509Sigor@sysoev.ru if (qlk != nxt_queue_tail(&pending_sockets)) {
11921509Sigor@sysoev.ru nxt_queue_remove(qlk);
11931509Sigor@sysoev.ru nxt_queue_insert_tail(&creating_sockets, qlk);
1194198Sigor@sysoev.ru
11951509Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
1196198Sigor@sysoev.ru
1197198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(task, tmcf, skcf);
1198198Sigor@sysoev.ru
1199198Sigor@sysoev.ru return;
1200198Sigor@sysoev.ru }
1201198Sigor@sysoev.ru
1202139Sigor@sysoev.ru #if (NXT_TLS)
1203139Sigor@sysoev.ru qlk = nxt_queue_last(&tmcf->tls);
1204774Svbart@nginx.com
12051828Sa.suvorov@f5.com if (qlk != nxt_queue_head(&tmcf->tls)) {
12061828Sa.suvorov@f5.com nxt_queue_remove(qlk);
12071828Sa.suvorov@f5.com
1208774Svbart@nginx.com tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link);
1209774Svbart@nginx.com
1210774Svbart@nginx.com nxt_cert_store_get(task, &tls->name, tmcf->mem_pool,
1211774Svbart@nginx.com nxt_router_tls_rpc_handler, tls);
12121885Sa.suvorov@f5.com return;
12131885Sa.suvorov@f5.com }
1214774Svbart@nginx.com #endif
1215774Svbart@nginx.com
1216774Svbart@nginx.com #if (NXT_HAVE_NJS)
1217774Svbart@nginx.com qlk = nxt_queue_last(&tmcf->js_modules);
12182450Sz.hong@f5.com
12192450Sz.hong@f5.com if (qlk != nxt_queue_head(&tmcf->js_modules)) {
12202450Sz.hong@f5.com nxt_queue_remove(qlk);
12212450Sz.hong@f5.com
12222450Sz.hong@f5.com js_module = nxt_queue_link_data(qlk, nxt_router_js_module_t, link);
12232450Sz.hong@f5.com
12242450Sz.hong@f5.com nxt_script_store_get(task, &js_module->name, tmcf->mem_pool,
12252450Sz.hong@f5.com nxt_router_js_module_rpc_handler, js_module);
12262450Sz.hong@f5.com return;
12272450Sz.hong@f5.com }
12282450Sz.hong@f5.com #endif
12292450Sz.hong@f5.com
12302450Sz.hong@f5.com rtcf = tmcf->router_conf;
12312450Sz.hong@f5.com
12322450Sz.hong@f5.com ret = nxt_tstr_state_done(rtcf->tstr_state, NULL);
12332450Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
12342450Sz.hong@f5.com goto fail;
12352450Sz.hong@f5.com }
12362450Sz.hong@f5.com
12372450Sz.hong@f5.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
12382450Sz.hong@f5.com
1239507Smax.romanov@nginx.com if (nxt_router_app_need_start(app)) {
1240507Smax.romanov@nginx.com nxt_router_app_rpc_create(task, tmcf, app);
1241507Smax.romanov@nginx.com return;
1242507Smax.romanov@nginx.com }
1243507Smax.romanov@nginx.com
1244507Smax.romanov@nginx.com } nxt_queue_loop;
1245507Smax.romanov@nginx.com
1246507Smax.romanov@nginx.com if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) {
1247507Smax.romanov@nginx.com nxt_router_access_log_open(task, tmcf);
1248630Svbart@nginx.com return;
1249630Svbart@nginx.com }
1250630Svbart@nginx.com
1251630Svbart@nginx.com rt = task->thread->runtime;
1252630Svbart@nginx.com
1253139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL);
1254139Sigor@sysoev.ru
1255139Sigor@sysoev.ru router = rtcf->router;
1256139Sigor@sysoev.ru
1257630Svbart@nginx.com ret = nxt_router_engines_create(task, router, tmcf, interface);
1258198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
1259139Sigor@sysoev.ru goto fail;
1260139Sigor@sysoev.ru }
1261198Sigor@sysoev.ru
1262139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf);
1263139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
1264139Sigor@sysoev.ru goto fail;
1265139Sigor@sysoev.ru }
1266198Sigor@sysoev.ru
1267139Sigor@sysoev.ru nxt_router_apps_sort(task, router, tmcf);
1268139Sigor@sysoev.ru
1269343Smax.romanov@nginx.com nxt_router_apps_hash_use(task, rtcf, 1);
1270139Sigor@sysoev.ru
12711828Sa.suvorov@f5.com nxt_router_engines_post(router, tmcf);
12721563Svbart@nginx.com
1273315Sigor@sysoev.ru nxt_queue_add(&router->sockets, &updating_sockets);
1274139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &creating_sockets);
12751509Sigor@sysoev.ru
12761509Sigor@sysoev.ru if (router->access_log != rtcf->access_log) {
1277139Sigor@sysoev.ru nxt_router_access_log_use(&router->lock, rtcf->access_log);
12782033Smax.romanov@nginx.com
12792033Smax.romanov@nginx.com nxt_router_access_log_release(task, &router->lock, router->access_log);
12802033Smax.romanov@nginx.com
12812033Smax.romanov@nginx.com router->access_log = rtcf->access_log;
12822033Smax.romanov@nginx.com }
12832033Smax.romanov@nginx.com
12842033Smax.romanov@nginx.com nxt_router_conf_ready(task, tmcf);
1285630Svbart@nginx.com
1286198Sigor@sysoev.ru return;
1287198Sigor@sysoev.ru
1288198Sigor@sysoev.ru fail:
1289198Sigor@sysoev.ru
1290198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf);
1291198Sigor@sysoev.ru
1292198Sigor@sysoev.ru return;
1293198Sigor@sysoev.ru }
1294198Sigor@sysoev.ru
1295139Sigor@sysoev.ru
1296139Sigor@sysoev.ru static void
nxt_router_conf_wait(nxt_task_t * task,void * obj,void * data)1297139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data)
1298139Sigor@sysoev.ru {
1299139Sigor@sysoev.ru nxt_joint_job_t *job;
1300139Sigor@sysoev.ru
1301153Sigor@sysoev.ru job = obj;
1302153Sigor@sysoev.ru
1303153Sigor@sysoev.ru nxt_router_conf_ready(task, job->tmcf);
1304153Sigor@sysoev.ru }
1305198Sigor@sysoev.ru
1306139Sigor@sysoev.ru
1307139Sigor@sysoev.ru static void
nxt_router_conf_ready(nxt_task_t * task,nxt_router_temp_conf_t * tmcf)1308139Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
1309139Sigor@sysoev.ru {
1310198Sigor@sysoev.ru uint32_t count;
1311139Sigor@sysoev.ru nxt_router_conf_t *rtcf;
13121542Smax.romanov@nginx.com nxt_thread_spinlock_t *lock;
13131542Smax.romanov@nginx.com
13141542Smax.romanov@nginx.com nxt_debug(task, "temp conf %p count: %D", tmcf, tmcf->count);
13151542Smax.romanov@nginx.com
13161542Smax.romanov@nginx.com if (--tmcf->count > 0) {
13171542Smax.romanov@nginx.com return;
13181542Smax.romanov@nginx.com }
13191542Smax.romanov@nginx.com
13201542Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST);
13211542Smax.romanov@nginx.com
13221542Smax.romanov@nginx.com rtcf = tmcf->router_conf;
13231542Smax.romanov@nginx.com
13241542Smax.romanov@nginx.com lock = &rtcf->router->lock;
13251542Smax.romanov@nginx.com
13261542Smax.romanov@nginx.com nxt_thread_spin_lock(lock);
13271542Smax.romanov@nginx.com
13281542Smax.romanov@nginx.com count = rtcf->count;
13291542Smax.romanov@nginx.com
13301542Smax.romanov@nginx.com nxt_thread_spin_unlock(lock);
13311542Smax.romanov@nginx.com
13321542Smax.romanov@nginx.com nxt_debug(task, "rtcf %p: %D", rtcf, count);
13331542Smax.romanov@nginx.com
13341542Smax.romanov@nginx.com if (count == 0) {
13351542Smax.romanov@nginx.com nxt_router_apps_hash_use(task, rtcf, -1);
13361542Smax.romanov@nginx.com
13371563Svbart@nginx.com nxt_router_access_log_release(task, lock, rtcf->access_log);
13381542Smax.romanov@nginx.com
13391542Smax.romanov@nginx.com nxt_mp_destroy(rtcf->mem_pool);
13401542Smax.romanov@nginx.com }
13411542Smax.romanov@nginx.com
13421542Smax.romanov@nginx.com nxt_mp_release(tmcf->mem_pool);
13431542Smax.romanov@nginx.com }
13441869Sa.suvorov@f5.com
1345139Sigor@sysoev.ru
1346139Sigor@sysoev.ru void
nxt_router_conf_error(nxt_task_t * task,nxt_router_temp_conf_t * tmcf)1347139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
13482165Sz.hong@f5.com {
1349139Sigor@sysoev.ru nxt_app_t *app;
1350139Sigor@sysoev.ru nxt_socket_t s;
1351507Smax.romanov@nginx.com nxt_router_t *router;
1352148Sigor@sysoev.ru nxt_queue_link_t *qlk;
1353149Sigor@sysoev.ru nxt_socket_conf_t *skcf;
1354148Sigor@sysoev.ru nxt_router_conf_t *rtcf;
1355148Sigor@sysoev.ru
1356630Svbart@nginx.com nxt_alert(task, "failed to apply new conf");
1357148Sigor@sysoev.ru
1358564Svbart@nginx.com for (qlk = nxt_queue_first(&creating_sockets);
1359198Sigor@sysoev.ru qlk != nxt_queue_tail(&creating_sockets);
13601509Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
13611509Sigor@sysoev.ru {
1362148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
1363148Sigor@sysoev.ru s = skcf->listen->socket;
1364148Sigor@sysoev.ru
1365359Sigor@sysoev.ru if (s != -1) {
1366148Sigor@sysoev.ru nxt_socket_close(task, s);
1367148Sigor@sysoev.ru }
1368148Sigor@sysoev.ru
1369148Sigor@sysoev.ru nxt_free(skcf->listen);
1370148Sigor@sysoev.ru }
1371359Sigor@sysoev.ru
1372148Sigor@sysoev.ru rtcf = tmcf->router_conf;
1373148Sigor@sysoev.ru
1374964Sigor@sysoev.ru nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
1375964Sigor@sysoev.ru
1376507Smax.romanov@nginx.com nxt_router_app_unlink(task, app);
1377507Smax.romanov@nginx.com
1378753Smax.romanov@nginx.com } nxt_queue_loop;
1379507Smax.romanov@nginx.com
1380507Smax.romanov@nginx.com router = rtcf->router;
1381507Smax.romanov@nginx.com
1382630Svbart@nginx.com nxt_queue_add(&router->sockets, &keeping_sockets);
1383149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &deleting_sockets);
13841509Sigor@sysoev.ru
13851509Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous);
1386149Sigor@sysoev.ru
1387416Smax.romanov@nginx.com // TODO: new engines and threads
1388416Smax.romanov@nginx.com
1389148Sigor@sysoev.ru nxt_router_access_log_release(task, &router->lock, rtcf->access_log);
1390148Sigor@sysoev.ru
1391630Svbart@nginx.com nxt_mp_destroy(rtcf->mem_pool);
1392630Svbart@nginx.com
1393630Svbart@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR);
1394139Sigor@sysoev.ru
1395193Smax.romanov@nginx.com nxt_mp_release(tmcf->mem_pool);
13961509Sigor@sysoev.ru }
13971869Sa.suvorov@f5.com
1398139Sigor@sysoev.ru
1399139Sigor@sysoev.ru static void
nxt_router_conf_send(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_port_msg_type_t type)1400139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
1401139Sigor@sysoev.ru nxt_port_msg_type_t type)
1402139Sigor@sysoev.ru {
1403193Smax.romanov@nginx.com nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL);
1404139Sigor@sysoev.ru
1405193Smax.romanov@nginx.com nxt_port_use(task, tmcf->port, -1);
1406779Smax.romanov@nginx.com
1407779Smax.romanov@nginx.com tmcf->port = NULL;
1408779Smax.romanov@nginx.com }
1409779Smax.romanov@nginx.com
1410139Sigor@sysoev.ru
1411139Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = {
1412139Sigor@sysoev.ru {
1413115Sigor@sysoev.ru nxt_string("listeners_threads"),
1414115Sigor@sysoev.ru NXT_CONF_MAP_INT32,
1415133Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads),
1416115Sigor@sysoev.ru },
1417115Sigor@sysoev.ru };
1418115Sigor@sysoev.ru
1419115Sigor@sysoev.ru
1420115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = {
1421115Sigor@sysoev.ru {
1422133Sigor@sysoev.ru nxt_string("type"),
1423115Sigor@sysoev.ru NXT_CONF_MAP_STR,
1424133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type),
1425115Sigor@sysoev.ru },
1426133Sigor@sysoev.ru
1427115Sigor@sysoev.ru {
1428115Sigor@sysoev.ru nxt_string("limits"),
1429115Sigor@sysoev.ru NXT_CONF_MAP_PTR,
1430507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, limits_value),
1431507Smax.romanov@nginx.com },
1432507Smax.romanov@nginx.com
1433133Sigor@sysoev.ru {
1434318Smax.romanov@nginx.com nxt_string("processes"),
1435318Smax.romanov@nginx.com NXT_CONF_MAP_INT32,
1436507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, processes),
1437507Smax.romanov@nginx.com },
1438507Smax.romanov@nginx.com
1439507Smax.romanov@nginx.com {
1440507Smax.romanov@nginx.com nxt_string("processes"),
1441507Smax.romanov@nginx.com NXT_CONF_MAP_PTR,
1442507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, processes_value),
1443318Smax.romanov@nginx.com },
1444507Smax.romanov@nginx.com
1445318Smax.romanov@nginx.com {
14461473Svbart@nginx.com nxt_string("targets"),
14471473Svbart@nginx.com NXT_CONF_MAP_PTR,
14481473Svbart@nginx.com offsetof(nxt_router_app_conf_t, targets_value),
14491473Svbart@nginx.com },
14501473Svbart@nginx.com };
14511473Svbart@nginx.com
1452318Smax.romanov@nginx.com
1453318Smax.romanov@nginx.com static nxt_conf_map_t nxt_router_app_limits_conf[] = {
1454318Smax.romanov@nginx.com {
1455318Smax.romanov@nginx.com nxt_string("timeout"),
1456318Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
1457318Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, timeout),
1458318Smax.romanov@nginx.com },
1459318Smax.romanov@nginx.com };
1460318Smax.romanov@nginx.com
1461133Sigor@sysoev.ru
1462133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_processes_conf[] = {
1463133Sigor@sysoev.ru {
1464507Smax.romanov@nginx.com nxt_string("spare"),
1465507Smax.romanov@nginx.com NXT_CONF_MAP_INT32,
1466507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, spare_processes),
1467507Smax.romanov@nginx.com },
1468507Smax.romanov@nginx.com
1469507Smax.romanov@nginx.com {
1470507Smax.romanov@nginx.com nxt_string("max"),
1471507Smax.romanov@nginx.com NXT_CONF_MAP_INT32,
1472507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, max_processes),
1473507Smax.romanov@nginx.com },
1474507Smax.romanov@nginx.com
1475507Smax.romanov@nginx.com {
1476507Smax.romanov@nginx.com nxt_string("idle_timeout"),
1477507Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
1478507Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, idle_timeout),
1479507Smax.romanov@nginx.com },
1480507Smax.romanov@nginx.com };
1481507Smax.romanov@nginx.com
1482507Smax.romanov@nginx.com
1483507Smax.romanov@nginx.com static nxt_conf_map_t nxt_router_listener_conf[] = {
1484507Smax.romanov@nginx.com {
1485133Sigor@sysoev.ru nxt_string("pass"),
1486133Sigor@sysoev.ru NXT_CONF_MAP_STR_COPY,
1487964Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, pass),
1488964Sigor@sysoev.ru },
1489964Sigor@sysoev.ru
1490964Sigor@sysoev.ru {
1491964Sigor@sysoev.ru nxt_string("application"),
1492964Sigor@sysoev.ru NXT_CONF_MAP_STR_COPY,
1493133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application),
1494964Sigor@sysoev.ru },
1495133Sigor@sysoev.ru };
1496115Sigor@sysoev.ru
1497115Sigor@sysoev.ru
1498115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = {
1499115Sigor@sysoev.ru {
1500115Sigor@sysoev.ru nxt_string("header_buffer_size"),
1501115Sigor@sysoev.ru NXT_CONF_MAP_SIZE,
1502115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size),
1503115Sigor@sysoev.ru },
1504115Sigor@sysoev.ru
1505115Sigor@sysoev.ru {
1506115Sigor@sysoev.ru nxt_string("large_header_buffer_size"),
1507115Sigor@sysoev.ru NXT_CONF_MAP_SIZE,
1508115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size),
1509115Sigor@sysoev.ru },
1510115Sigor@sysoev.ru
1511115Sigor@sysoev.ru {
1512115Sigor@sysoev.ru nxt_string("large_header_buffers"),
1513115Sigor@sysoev.ru NXT_CONF_MAP_SIZE,
1514206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, large_header_buffers),
1515206Smax.romanov@nginx.com },
1516206Smax.romanov@nginx.com
1517206Smax.romanov@nginx.com {
1518206Smax.romanov@nginx.com nxt_string("body_buffer_size"),
1519206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE,
1520206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_buffer_size),
1521206Smax.romanov@nginx.com },
1522206Smax.romanov@nginx.com
1523206Smax.romanov@nginx.com {
1524206Smax.romanov@nginx.com nxt_string("max_body_size"),
1525206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE,
1526206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, max_body_size),
1527206Smax.romanov@nginx.com },
1528206Smax.romanov@nginx.com
1529206Smax.romanov@nginx.com {
1530206Smax.romanov@nginx.com nxt_string("idle_timeout"),
1531206Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
1532431Sigor@sysoev.ru offsetof(nxt_socket_conf_t, idle_timeout),
1533431Sigor@sysoev.ru },
1534431Sigor@sysoev.ru
1535431Sigor@sysoev.ru {
1536431Sigor@sysoev.ru nxt_string("header_read_timeout"),
1537431Sigor@sysoev.ru NXT_CONF_MAP_MSEC,
1538115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout),
1539115Sigor@sysoev.ru },
1540115Sigor@sysoev.ru
1541115Sigor@sysoev.ru {
1542206Smax.romanov@nginx.com nxt_string("body_read_timeout"),
1543206Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
1544206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_read_timeout),
1545206Smax.romanov@nginx.com },
1546206Smax.romanov@nginx.com
1547206Smax.romanov@nginx.com {
1548431Sigor@sysoev.ru nxt_string("send_timeout"),
1549431Sigor@sysoev.ru NXT_CONF_MAP_MSEC,
1550431Sigor@sysoev.ru offsetof(nxt_socket_conf_t, send_timeout),
1551431Sigor@sysoev.ru },
1552431Sigor@sysoev.ru
1553431Sigor@sysoev.ru {
15541403Smax.romanov@nginx.com nxt_string("body_temp_path"),
15551403Smax.romanov@nginx.com NXT_CONF_MAP_STR,
15561403Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_temp_path),
15571403Smax.romanov@nginx.com },
15581403Smax.romanov@nginx.com
15591403Smax.romanov@nginx.com {
15601709Svbart@nginx.com nxt_string("discard_unsafe_fields"),
15611709Svbart@nginx.com NXT_CONF_MAP_INT8,
15621709Svbart@nginx.com offsetof(nxt_socket_conf_t, discard_unsafe_fields),
15631709Svbart@nginx.com },
15641709Svbart@nginx.com
15651709Svbart@nginx.com {
15662381Salx@nginx.com nxt_string("log_route"),
15672381Salx@nginx.com NXT_CONF_MAP_INT8,
15682381Salx@nginx.com offsetof(nxt_socket_conf_t, log_route),
15692381Salx@nginx.com },
15702381Salx@nginx.com
15712381Salx@nginx.com {
15722437Sa.clayton@nginx.com nxt_string("server_version"),
15732437Sa.clayton@nginx.com NXT_CONF_MAP_INT8,
15742437Sa.clayton@nginx.com offsetof(nxt_socket_conf_t, server_version),
15752437Sa.clayton@nginx.com },
15762437Sa.clayton@nginx.com };
15772437Sa.clayton@nginx.com
1578115Sigor@sysoev.ru
1579115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_websocket_conf[] = {
1580115Sigor@sysoev.ru {
15811131Smax.romanov@nginx.com nxt_string("max_frame_size"),
15821131Smax.romanov@nginx.com NXT_CONF_MAP_SIZE,
15831131Smax.romanov@nginx.com offsetof(nxt_websocket_conf_t, max_frame_size),
15841131Smax.romanov@nginx.com },
15851131Smax.romanov@nginx.com
15861131Smax.romanov@nginx.com {
15871131Smax.romanov@nginx.com nxt_string("read_timeout"),
15881131Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
15891131Smax.romanov@nginx.com offsetof(nxt_websocket_conf_t, read_timeout),
15901131Smax.romanov@nginx.com },
15911131Smax.romanov@nginx.com
15921131Smax.romanov@nginx.com {
15931131Smax.romanov@nginx.com nxt_string("keepalive_interval"),
15941131Smax.romanov@nginx.com NXT_CONF_MAP_MSEC,
15951131Smax.romanov@nginx.com offsetof(nxt_websocket_conf_t, keepalive_interval),
15961131Smax.romanov@nginx.com },
15971131Smax.romanov@nginx.com
15981131Smax.romanov@nginx.com };
15991131Smax.romanov@nginx.com
16001131Smax.romanov@nginx.com
16011131Smax.romanov@nginx.com static nxt_int_t
nxt_router_conf_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,u_char * start,u_char * end)16021131Smax.romanov@nginx.com nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
160353Sigor@sysoev.ru u_char *start, u_char *end)
1604115Sigor@sysoev.ru {
1605115Sigor@sysoev.ru u_char *p;
160653Sigor@sysoev.ru size_t size;
1607133Sigor@sysoev.ru nxt_mp_t *mp, *app_mp;
1608133Sigor@sysoev.ru uint32_t next, next_target;
16091473Svbart@nginx.com nxt_int_t ret;
16101473Svbart@nginx.com nxt_str_t name, target;
1611115Sigor@sysoev.ru nxt_app_t *app, *prev;
16122165Sz.hong@f5.com nxt_str_t *t, *s, *targets;
1613133Sigor@sysoev.ru nxt_uint_t n, i;
16141473Svbart@nginx.com nxt_port_t *port;
16151473Svbart@nginx.com nxt_router_t *router;
16161547Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
1617359Sigor@sysoev.ru #if (NXT_TLS)
1618753Smax.romanov@nginx.com nxt_tls_init_t *tls_init;
16191828Sa.suvorov@f5.com nxt_conf_value_t *certificate;
16201920Sa.suvorov@f5.com #endif
16211920Sa.suvorov@f5.com #if (NXT_HAVE_NJS)
16221828Sa.suvorov@f5.com nxt_conf_value_t *js_module;
16232450Sz.hong@f5.com #endif
16242450Sz.hong@f5.com nxt_conf_value_t *root, *conf, *http, *value, *websocket;
16252450Sz.hong@f5.com nxt_conf_value_t *applications, *application;
16262131Sz.hong@f5.com nxt_conf_value_t *listeners, *listener;
1627133Sigor@sysoev.ru nxt_socket_conf_t *skcf;
1628133Sigor@sysoev.ru nxt_router_conf_t *rtcf;
1629115Sigor@sysoev.ru nxt_http_routes_t *routes;
16302131Sz.hong@f5.com nxt_event_engine_t *engine;
1631964Sigor@sysoev.ru nxt_app_lang_module_t *lang;
1632507Smax.romanov@nginx.com nxt_router_app_conf_t apcf;
1633216Sigor@sysoev.ru nxt_router_listener_conf_t lscf;
1634133Sigor@sysoev.ru
1635115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/settings/http");
1636115Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications");
1637716Svbart@nginx.com static nxt_str_t listeners_path = nxt_string("/listeners");
1638133Sigor@sysoev.ru static nxt_str_t routes_path = nxt_string("/routes");
1639115Sigor@sysoev.ru static nxt_str_t access_log_path = nxt_string("/access_log");
1640964Sigor@sysoev.ru #if (NXT_TLS)
1641630Svbart@nginx.com static nxt_str_t certificate_path = nxt_string("/tls/certificate");
1642774Svbart@nginx.com static nxt_str_t conf_commands_path = nxt_string("/tls/conf_commands");
1643774Svbart@nginx.com static nxt_str_t conf_cache_path = nxt_string("/tls/session/cache_size");
16441885Sa.suvorov@f5.com static nxt_str_t conf_timeout_path = nxt_string("/tls/session/timeout");
16451920Sa.suvorov@f5.com static nxt_str_t conf_tickets = nxt_string("/tls/session/tickets");
16461920Sa.suvorov@f5.com #endif
16471942Sa.suvorov@f5.com #if (NXT_HAVE_NJS)
1648774Svbart@nginx.com static nxt_str_t js_module_path = nxt_string("/settings/js_module");
16492450Sz.hong@f5.com #endif
16502450Sz.hong@f5.com static nxt_str_t static_path = nxt_string("/settings/http/static");
16512450Sz.hong@f5.com static nxt_str_t websocket_path = nxt_string("/settings/http/websocket");
16521183Svbart@nginx.com static nxt_str_t forwarded_path = nxt_string("/forwarded");
16531131Smax.romanov@nginx.com static nxt_str_t client_ip_path = nxt_string("/client_ip");
16542133Sz.hong@f5.com
16551936So.canty@f5.com root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
1656115Sigor@sysoev.ru if (root == NULL) {
16572131Sz.hong@f5.com nxt_alert(task, "configuration parsing error");
16582131Sz.hong@f5.com return NXT_ERROR;
1659564Svbart@nginx.com }
1660115Sigor@sysoev.ru
1661115Sigor@sysoev.ru rtcf = tmcf->router_conf;
1662115Sigor@sysoev.ru mp = rtcf->mem_pool;
16632131Sz.hong@f5.com
16642131Sz.hong@f5.com ret = nxt_conf_map_object(mp, root, nxt_router_conf,
16652131Sz.hong@f5.com nxt_nitems(nxt_router_conf), rtcf);
16662131Sz.hong@f5.com if (ret != NXT_OK) {
16672131Sz.hong@f5.com nxt_alert(task, "root map error");
1668115Sigor@sysoev.ru return NXT_ERROR;
1669564Svbart@nginx.com }
1670115Sigor@sysoev.ru
1671115Sigor@sysoev.ru if (rtcf->threads == 0) {
1672115Sigor@sysoev.ru rtcf->threads = nxt_ncpu;
16732131Sz.hong@f5.com }
16742131Sz.hong@f5.com
16752131Sz.hong@f5.com conf = nxt_conf_get_path(root, &static_path);
16762131Sz.hong@f5.com
16772131Sz.hong@f5.com ret = nxt_router_conf_process_static(task, rtcf, conf);
16782131Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
16792131Sz.hong@f5.com return NXT_ERROR;
16801183Svbart@nginx.com }
16811183Svbart@nginx.com
16821183Svbart@nginx.com router = rtcf->router;
16831183Svbart@nginx.com
16842131Sz.hong@f5.com applications = nxt_conf_get_path(root, &applications_path);
16852131Sz.hong@f5.com
16862131Sz.hong@f5.com if (applications != NULL) {
16871115Svbart@nginx.com next = 0;
16881115Svbart@nginx.com
16891115Svbart@nginx.com for ( ;; ) {
16901115Svbart@nginx.com application = nxt_conf_next_object_member(applications,
16911115Svbart@nginx.com &name, &next);
16921235Sigor@sysoev.ru if (application == NULL) {
16931235Sigor@sysoev.ru break;
16941115Svbart@nginx.com }
16951115Svbart@nginx.com
16961115Svbart@nginx.com nxt_debug(task, "application \"%V\"", &name);
16971115Svbart@nginx.com
16981115Svbart@nginx.com size = nxt_conf_json_length(application, NULL);
16991115Svbart@nginx.com
17001115Svbart@nginx.com app_mp = nxt_mp_create(4096, 128, 1024, 64);
17011115Svbart@nginx.com if (nxt_slow_path(app_mp == NULL)) {
17021473Svbart@nginx.com goto fail;
17031473Svbart@nginx.com }
17041473Svbart@nginx.com
17051473Svbart@nginx.com app = nxt_mp_get(app_mp, sizeof(nxt_app_t) + name.length + size);
17061473Svbart@nginx.com if (app == NULL) {
17071473Svbart@nginx.com goto app_fail;
17081115Svbart@nginx.com }
17091473Svbart@nginx.com
17101115Svbart@nginx.com nxt_memzero(app, sizeof(nxt_app_t));
17111115Svbart@nginx.com
17121115Svbart@nginx.com app->mem_pool = app_mp;
17131115Svbart@nginx.com
17141473Svbart@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t));
17151473Svbart@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t)
17161115Svbart@nginx.com + name.length);
17171115Svbart@nginx.com
17181115Svbart@nginx.com p = nxt_conf_json_print(app->conf.start, application, NULL);
17191115Svbart@nginx.com app->conf.length = p - app->conf.start;
17201115Svbart@nginx.com
17211115Svbart@nginx.com nxt_assert(app->conf.length <= size);
17221115Svbart@nginx.com
17231115Svbart@nginx.com nxt_debug(task, "application conf \"%V\"", &app->conf);
17241115Svbart@nginx.com
17251115Svbart@nginx.com prev = nxt_router_app_find(&router->apps, &name);
17261115Svbart@nginx.com
17271115Svbart@nginx.com if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) {
17281115Svbart@nginx.com nxt_mp_destroy(app_mp);
17291115Svbart@nginx.com
17301473Svbart@nginx.com nxt_queue_remove(&prev->link);
17311115Svbart@nginx.com nxt_queue_insert_tail(&tmcf->previous, &prev->link);
17321115Svbart@nginx.com
17331115Svbart@nginx.com ret = nxt_router_apps_hash_add(rtcf, prev);
17341563Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
17352131Sz.hong@f5.com goto fail;
17361563Svbart@nginx.com }
17371563Svbart@nginx.com
17381563Svbart@nginx.com continue;
17391563Svbart@nginx.com }
17401115Svbart@nginx.com
17411115Svbart@nginx.com apcf.processes = 1;
17421115Svbart@nginx.com apcf.max_processes = 1;
17431115Svbart@nginx.com apcf.spare_processes = 0;
17441115Svbart@nginx.com apcf.timeout = 0;
17451115Svbart@nginx.com apcf.idle_timeout = 15000;
17461115Svbart@nginx.com apcf.limits_value = NULL;
17471115Svbart@nginx.com apcf.processes_value = NULL;
17481115Svbart@nginx.com apcf.targets_value = NULL;
17491115Svbart@nginx.com
17501473Svbart@nginx.com app_joint = nxt_malloc(sizeof(nxt_app_joint_t));
17511115Svbart@nginx.com if (nxt_slow_path(app_joint == NULL)) {
17521115Svbart@nginx.com goto app_fail;
17531115Svbart@nginx.com }
1754318Smax.romanov@nginx.com
1755318Smax.romanov@nginx.com nxt_memzero(app_joint, sizeof(nxt_app_joint_t));
1756318Smax.romanov@nginx.com
17571115Svbart@nginx.com ret = nxt_conf_map_object(mp, application, nxt_router_app_conf,
17581115Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf);
17591115Svbart@nginx.com if (ret != NXT_OK) {
17601115Svbart@nginx.com nxt_alert(task, "application map error");
1761318Smax.romanov@nginx.com goto app_fail;
17621115Svbart@nginx.com }
1763318Smax.romanov@nginx.com
1764318Smax.romanov@nginx.com if (apcf.limits_value != NULL) {
17651115Svbart@nginx.com
17661115Svbart@nginx.com if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) {
17671115Svbart@nginx.com nxt_alert(task, "application limits is not object");
17681115Svbart@nginx.com goto app_fail;
17691115Svbart@nginx.com }
17701115Svbart@nginx.com
17711115Svbart@nginx.com ret = nxt_conf_map_object(mp, apcf.limits_value,
17721115Svbart@nginx.com nxt_router_app_limits_conf,
17731115Svbart@nginx.com nxt_nitems(nxt_router_app_limits_conf),
17741115Svbart@nginx.com &apcf);
17751115Svbart@nginx.com if (ret != NXT_OK) {
17761115Svbart@nginx.com nxt_alert(task, "application limits map error");
17771115Svbart@nginx.com goto app_fail;
17781115Svbart@nginx.com }
17791115Svbart@nginx.com }
17801115Svbart@nginx.com
17811115Svbart@nginx.com if (apcf.processes_value != NULL
17821115Svbart@nginx.com && nxt_conf_type(apcf.processes_value) == NXT_CONF_OBJECT)
17831115Svbart@nginx.com {
17841115Svbart@nginx.com ret = nxt_conf_map_object(mp, apcf.processes_value,
17851115Svbart@nginx.com nxt_router_app_processes_conf,
17861115Svbart@nginx.com nxt_nitems(nxt_router_app_processes_conf),
17871115Svbart@nginx.com &apcf);
17881115Svbart@nginx.com if (ret != NXT_OK) {
17891115Svbart@nginx.com nxt_alert(task, "application processes map error");
17901115Svbart@nginx.com goto app_fail;
17911115Svbart@nginx.com }
17921115Svbart@nginx.com
17931115Svbart@nginx.com } else {
17941115Svbart@nginx.com apcf.max_processes = apcf.processes;
17951115Svbart@nginx.com apcf.spare_processes = apcf.processes;
17961115Svbart@nginx.com }
17971115Svbart@nginx.com
17981115Svbart@nginx.com if (apcf.targets_value != NULL) {
17991115Svbart@nginx.com n = nxt_conf_object_members_count(apcf.targets_value);
18001473Svbart@nginx.com
18011473Svbart@nginx.com targets = nxt_mp_get(app_mp, sizeof(nxt_str_t) * n);
18021473Svbart@nginx.com if (nxt_slow_path(targets == NULL)) {
18031473Svbart@nginx.com goto app_fail;
18041473Svbart@nginx.com }
18051473Svbart@nginx.com
18061473Svbart@nginx.com next_target = 0;
18071473Svbart@nginx.com
18081473Svbart@nginx.com for (i = 0; i < n; i++) {
18091473Svbart@nginx.com (void) nxt_conf_next_object_member(apcf.targets_value,
18101473Svbart@nginx.com &target, &next_target);
18111480Svbart@nginx.com
18121480Svbart@nginx.com s = nxt_str_dup(app_mp, &targets[i], &target);
18131473Svbart@nginx.com if (nxt_slow_path(s == NULL)) {
18141473Svbart@nginx.com goto app_fail;
18151473Svbart@nginx.com }
18161473Svbart@nginx.com }
18171473Svbart@nginx.com
18181473Svbart@nginx.com } else {
18191473Svbart@nginx.com targets = NULL;
18201473Svbart@nginx.com }
18211473Svbart@nginx.com
18221473Svbart@nginx.com nxt_debug(task, "application type: %V", &apcf.type);
18231473Svbart@nginx.com nxt_debug(task, "application processes: %D", apcf.processes);
18241115Svbart@nginx.com nxt_debug(task, "application request timeout: %M", apcf.timeout);
18251115Svbart@nginx.com
18261115Svbart@nginx.com lang = nxt_app_lang_module(task->thread->runtime, &apcf.type);
18271115Svbart@nginx.com
18281115Svbart@nginx.com if (lang == NULL) {
18291115Svbart@nginx.com nxt_alert(task, "unknown application type: \"%V\"", &apcf.type);
18301115Svbart@nginx.com goto app_fail;
18311115Svbart@nginx.com }
1832507Smax.romanov@nginx.com
1833507Smax.romanov@nginx.com nxt_debug(task, "application language module: \"%s\"", lang->file);
1834507Smax.romanov@nginx.com
18351115Svbart@nginx.com ret = nxt_thread_mutex_create(&app->mutex);
18361115Svbart@nginx.com if (ret != NXT_OK) {
18371115Svbart@nginx.com goto app_fail;
18381115Svbart@nginx.com }
18391115Svbart@nginx.com
18401115Svbart@nginx.com nxt_queue_init(&app->ports);
18411115Svbart@nginx.com nxt_queue_init(&app->spare_ports);
18421115Svbart@nginx.com nxt_queue_init(&app->idle_ports);
18431115Svbart@nginx.com nxt_queue_init(&app->ack_waiting_req);
18441115Svbart@nginx.com
18451561Smax.romanov@nginx.com app->name.length = name.length;
18461115Svbart@nginx.com nxt_memcpy(app->name.start, name.start, name.length);
18471115Svbart@nginx.com
18481115Svbart@nginx.com app->type = lang->type;
18491115Svbart@nginx.com app->max_processes = apcf.max_processes;
18501115Svbart@nginx.com app->spare_processes = apcf.spare_processes;
18511115Svbart@nginx.com app->max_pending_processes = apcf.spare_processes
18521115Svbart@nginx.com ? apcf.spare_processes : 1;
18531115Svbart@nginx.com app->timeout = apcf.timeout;
18541115Svbart@nginx.com app->idle_timeout = apcf.idle_timeout;
18551115Svbart@nginx.com
18561115Svbart@nginx.com app->targets = targets;
18571115Svbart@nginx.com
18581473Svbart@nginx.com engine = task->thread->engine;
18591473Svbart@nginx.com
18601115Svbart@nginx.com app->engine = engine;
18611115Svbart@nginx.com
18621115Svbart@nginx.com app->adjust_idle_work.handler = nxt_router_adjust_idle_timer;
18631115Svbart@nginx.com app->adjust_idle_work.task = &engine->task;
18641115Svbart@nginx.com app->adjust_idle_work.obj = app;
18651115Svbart@nginx.com
18661115Svbart@nginx.com nxt_queue_insert_tail(&tmcf->apps, &app->link);
18671115Svbart@nginx.com
18681115Svbart@nginx.com ret = nxt_router_apps_hash_add(rtcf, app);
18691115Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
18702131Sz.hong@f5.com goto app_fail;
18711563Svbart@nginx.com }
18721563Svbart@nginx.com
18731563Svbart@nginx.com nxt_router_app_use(task, app, 1);
18741563Svbart@nginx.com
18751115Svbart@nginx.com app->joint = app_joint;
18761115Svbart@nginx.com
18771115Svbart@nginx.com app_joint->use_count = 1;
18781115Svbart@nginx.com app_joint->app = app;
18791115Svbart@nginx.com
18801115Svbart@nginx.com app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS;
18811115Svbart@nginx.com app_joint->idle_timer.work_queue = &engine->fast_work_queue;
18821115Svbart@nginx.com app_joint->idle_timer.handler = nxt_router_app_idle_timeout;
18831115Svbart@nginx.com app_joint->idle_timer.task = &engine->task;
18841115Svbart@nginx.com app_joint->idle_timer.log = app_joint->idle_timer.task->log;
18851115Svbart@nginx.com
18861115Svbart@nginx.com app_joint->free_app_work.handler = nxt_router_free_app;
18871115Svbart@nginx.com app_joint->free_app_work.task = &engine->task;
18881115Svbart@nginx.com app_joint->free_app_work.obj = app_joint;
18891115Svbart@nginx.com
18901115Svbart@nginx.com port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid,
18911547Smax.romanov@nginx.com NXT_PROCESS_APP);
18921926Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) {
18931547Smax.romanov@nginx.com return NXT_ERROR;
18941547Smax.romanov@nginx.com }
18951547Smax.romanov@nginx.com
18961547Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0);
18971547Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
18981547Smax.romanov@nginx.com nxt_port_use(task, port, -1);
18991547Smax.romanov@nginx.com return NXT_ERROR;
19001547Smax.romanov@nginx.com }
19011547Smax.romanov@nginx.com
19021547Smax.romanov@nginx.com ret = nxt_router_app_queue_init(task, port);
19031547Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
19041555Smax.romanov@nginx.com nxt_port_write_close(port);
19051555Smax.romanov@nginx.com nxt_port_read_close(port);
19061777Smax.romanov@nginx.com nxt_port_use(task, port, -1);
19071777Smax.romanov@nginx.com return NXT_ERROR;
19081555Smax.romanov@nginx.com }
19091555Smax.romanov@nginx.com
19101555Smax.romanov@nginx.com nxt_port_write_enable(task, port);
19111555Smax.romanov@nginx.com port->app = app;
19121547Smax.romanov@nginx.com
19131547Smax.romanov@nginx.com app->shared_port = port;
19141547Smax.romanov@nginx.com
19151547Smax.romanov@nginx.com nxt_thread_mutex_create(&app->outgoing.mutex);
19161547Smax.romanov@nginx.com }
19171547Smax.romanov@nginx.com }
1918133Sigor@sysoev.ru
1919133Sigor@sysoev.ru conf = nxt_conf_get_path(root, &routes_path);
1920133Sigor@sysoev.ru if (nxt_fast_path(conf != NULL)) {
19212131Sz.hong@f5.com routes = nxt_http_routes_create(task, tmcf, conf);
19222131Sz.hong@f5.com if (nxt_slow_path(routes == NULL)) {
19232131Sz.hong@f5.com return NXT_ERROR;
1924964Sigor@sysoev.ru }
1925964Sigor@sysoev.ru
1926964Sigor@sysoev.ru rtcf->routes = routes;
19272165Sz.hong@f5.com }
19282131Sz.hong@f5.com
19292131Sz.hong@f5.com ret = nxt_upstreams_create(task, tmcf, root);
19302131Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
19312131Sz.hong@f5.com return ret;
19321394Sigor@sysoev.ru }
19331394Sigor@sysoev.ru
19341394Sigor@sysoev.ru http = nxt_conf_get_path(root, &http_path);
19351394Sigor@sysoev.ru #if 0
19362131Sz.hong@f5.com if (http == NULL) {
1937133Sigor@sysoev.ru nxt_alert(task, "no \"http\" block");
1938133Sigor@sysoev.ru return NXT_ERROR;
1939564Svbart@nginx.com }
1940133Sigor@sysoev.ru #endif
1941133Sigor@sysoev.ru
1942133Sigor@sysoev.ru websocket = nxt_conf_get_path(root, &websocket_path);
1943133Sigor@sysoev.ru
19442131Sz.hong@f5.com listeners = nxt_conf_get_path(root, &listeners_path);
19452131Sz.hong@f5.com
19462131Sz.hong@f5.com if (listeners != NULL) {
19471115Svbart@nginx.com next = 0;
19481115Svbart@nginx.com
19491115Svbart@nginx.com for ( ;; ) {
19501115Svbart@nginx.com listener = nxt_conf_next_object_member(listeners, &name, &next);
19511115Svbart@nginx.com if (listener == NULL) {
19521115Svbart@nginx.com break;
19531115Svbart@nginx.com }
19541115Svbart@nginx.com
19551115Svbart@nginx.com skcf = nxt_router_socket_conf(task, tmcf, &name);
19561115Svbart@nginx.com if (skcf == NULL) {
19571115Svbart@nginx.com goto fail;
19581115Svbart@nginx.com }
19591115Svbart@nginx.com
19601115Svbart@nginx.com nxt_memzero(&lscf, sizeof(lscf));
19611115Svbart@nginx.com
19621115Svbart@nginx.com ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf,
19631115Svbart@nginx.com nxt_nitems(nxt_router_listener_conf),
19641115Svbart@nginx.com &lscf);
19651115Svbart@nginx.com if (ret != NXT_OK) {
19661115Svbart@nginx.com nxt_alert(task, "listener map error");
1967133Sigor@sysoev.ru goto fail;
19681115Svbart@nginx.com }
1969133Sigor@sysoev.ru
1970133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application);
19711115Svbart@nginx.com
19721115Svbart@nginx.com // STUB, default values if http block is not defined.
19731115Svbart@nginx.com skcf->header_buffer_size = 2048;
19741115Svbart@nginx.com skcf->large_header_buffer_size = 8192;
19751115Svbart@nginx.com skcf->large_header_buffers = 4;
19761115Svbart@nginx.com skcf->discard_unsafe_fields = 1;
19771115Svbart@nginx.com skcf->body_buffer_size = 16 * 1024;
19781709Svbart@nginx.com skcf->max_body_size = 8 * 1024 * 1024;
19791115Svbart@nginx.com skcf->proxy_header_buffer_size = 64 * 1024;
19801115Svbart@nginx.com skcf->proxy_buffer_size = 4096;
19811270Sigor@sysoev.ru skcf->proxy_buffers = 256;
19821270Sigor@sysoev.ru skcf->idle_timeout = 180 * 1000;
19831270Sigor@sysoev.ru skcf->header_read_timeout = 30 * 1000;
19841115Svbart@nginx.com skcf->body_read_timeout = 30 * 1000;
19851115Svbart@nginx.com skcf->send_timeout = 30 * 1000;
19861115Svbart@nginx.com skcf->proxy_timeout = 60 * 1000;
19871115Svbart@nginx.com skcf->proxy_send_timeout = 30 * 1000;
19881270Sigor@sysoev.ru skcf->proxy_read_timeout = 30 * 1000;
19891270Sigor@sysoev.ru
19901270Sigor@sysoev.ru skcf->server_version = 1;
19911115Svbart@nginx.com
19922437Sa.clayton@nginx.com skcf->websocket_conf.max_frame_size = 1024 * 1024;
19932437Sa.clayton@nginx.com skcf->websocket_conf.read_timeout = 60 * 1000;
19941131Smax.romanov@nginx.com skcf->websocket_conf.keepalive_interval = 30 * 1000;
19951131Smax.romanov@nginx.com
19961131Smax.romanov@nginx.com nxt_str_null(&skcf->body_temp_path);
19971131Smax.romanov@nginx.com
19981403Smax.romanov@nginx.com if (http != NULL) {
19991403Smax.romanov@nginx.com ret = nxt_conf_map_object(mp, http, nxt_router_http_conf,
20001115Svbart@nginx.com nxt_nitems(nxt_router_http_conf),
20011115Svbart@nginx.com skcf);
20021115Svbart@nginx.com if (ret != NXT_OK) {
20031115Svbart@nginx.com nxt_alert(task, "http map error");
20041115Svbart@nginx.com goto fail;
20051115Svbart@nginx.com }
20061115Svbart@nginx.com }
20071115Svbart@nginx.com
20081115Svbart@nginx.com if (websocket != NULL) {
2009115Sigor@sysoev.ru ret = nxt_conf_map_object(mp, websocket,
20101131Smax.romanov@nginx.com nxt_router_websocket_conf,
20111131Smax.romanov@nginx.com nxt_nitems(nxt_router_websocket_conf),
20121131Smax.romanov@nginx.com &skcf->websocket_conf);
20131131Smax.romanov@nginx.com if (ret != NXT_OK) {
20141131Smax.romanov@nginx.com nxt_alert(task, "websocket map error");
20151131Smax.romanov@nginx.com goto fail;
20161131Smax.romanov@nginx.com }
20171131Smax.romanov@nginx.com }
20181131Smax.romanov@nginx.com
20191131Smax.romanov@nginx.com t = &skcf->body_temp_path;
20201131Smax.romanov@nginx.com
20211403Smax.romanov@nginx.com if (t->length == 0) {
20221403Smax.romanov@nginx.com t->start = (u_char *) task->thread->runtime->tmp;
20231403Smax.romanov@nginx.com t->length = nxt_strlen(t->start);
20241403Smax.romanov@nginx.com }
20251403Smax.romanov@nginx.com
20261403Smax.romanov@nginx.com conf = nxt_conf_get_path(listener, &forwarded_path);
20271403Smax.romanov@nginx.com
20282133Sz.hong@f5.com if (conf != NULL) {
20292133Sz.hong@f5.com skcf->forwarded = nxt_router_conf_forward(task, mp, conf);
20302133Sz.hong@f5.com if (nxt_slow_path(skcf->forwarded == NULL)) {
20312133Sz.hong@f5.com return NXT_ERROR;
20322133Sz.hong@f5.com }
20332133Sz.hong@f5.com }
20342133Sz.hong@f5.com
20352133Sz.hong@f5.com conf = nxt_conf_get_path(listener, &client_ip_path);
20362133Sz.hong@f5.com
20372131Sz.hong@f5.com if (conf != NULL) {
20382132Sz.hong@f5.com skcf->client_ip = nxt_router_conf_forward(task, mp, conf);
20392132Sz.hong@f5.com if (nxt_slow_path(skcf->client_ip == NULL)) {
20402133Sz.hong@f5.com return NXT_ERROR;
20412133Sz.hong@f5.com }
20422132Sz.hong@f5.com }
20432132Sz.hong@f5.com
20441936So.canty@f5.com #if (NXT_TLS)
20451936So.canty@f5.com certificate = nxt_conf_get_path(listener, &certificate_path);
2046774Svbart@nginx.com
20471828Sa.suvorov@f5.com if (certificate != NULL) {
20481828Sa.suvorov@f5.com tls_init = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_tls_init_t));
20491828Sa.suvorov@f5.com if (nxt_slow_path(tls_init == NULL)) {
20501920Sa.suvorov@f5.com return NXT_ERROR;
20511920Sa.suvorov@f5.com }
20521920Sa.suvorov@f5.com
20531920Sa.suvorov@f5.com tls_init->cache_size = 0;
20541920Sa.suvorov@f5.com tls_init->timeout = 300;
20551920Sa.suvorov@f5.com
20561920Sa.suvorov@f5.com value = nxt_conf_get_path(listener, &conf_cache_path);
20571920Sa.suvorov@f5.com if (value != NULL) {
20581920Sa.suvorov@f5.com tls_init->cache_size = nxt_conf_get_number(value);
20591920Sa.suvorov@f5.com }
20601920Sa.suvorov@f5.com
20611920Sa.suvorov@f5.com value = nxt_conf_get_path(listener, &conf_timeout_path);
20621920Sa.suvorov@f5.com if (value != NULL) {
20631920Sa.suvorov@f5.com tls_init->timeout = nxt_conf_get_number(value);
20641920Sa.suvorov@f5.com }
20651920Sa.suvorov@f5.com
20661920Sa.suvorov@f5.com tls_init->conf_cmds = nxt_conf_get_path(listener,
20671920Sa.suvorov@f5.com &conf_commands_path);
20681920Sa.suvorov@f5.com
20691920Sa.suvorov@f5.com tls_init->tickets_conf = nxt_conf_get_path(listener,
20701885Sa.suvorov@f5.com &conf_tickets);
20711942Sa.suvorov@f5.com
20721942Sa.suvorov@f5.com n = nxt_conf_array_elements_count_or_1(certificate);
20731942Sa.suvorov@f5.com
20742077Salx.manpages@gmail.com for (i = 0; i < n; i++) {
20752077Salx.manpages@gmail.com value = nxt_conf_get_array_element_or_itself(certificate,
20762077Salx.manpages@gmail.com i);
20772077Salx.manpages@gmail.com nxt_assert(value != NULL);
20782077Salx.manpages@gmail.com
20792077Salx.manpages@gmail.com ret = nxt_router_conf_tls_insert(tmcf, value, skcf,
20802077Salx.manpages@gmail.com tls_init, i == 0);
20812077Salx.manpages@gmail.com if (nxt_slow_path(ret != NXT_OK)) {
20822077Salx.manpages@gmail.com goto fail;
20831828Sa.suvorov@f5.com }
20841828Sa.suvorov@f5.com }
20851828Sa.suvorov@f5.com }
20861115Svbart@nginx.com #endif
2087774Svbart@nginx.com
2088774Svbart@nginx.com skcf->listen->handler = nxt_http_conn_init;
2089774Svbart@nginx.com skcf->router_conf = rtcf;
20901115Svbart@nginx.com skcf->router_conf->count++;
20912131Sz.hong@f5.com
20921115Svbart@nginx.com if (lscf.pass.length != 0) {
20931115Svbart@nginx.com skcf->action = nxt_http_action_create(task, tmcf, &lscf.pass);
20941115Svbart@nginx.com
20951264Sigor@sysoev.ru /* COMPATIBILITY: listener application. */
20961115Svbart@nginx.com } else if (lscf.application.length > 0) {
20971115Svbart@nginx.com skcf->action = nxt_http_pass_application(task, rtcf,
20981115Svbart@nginx.com &lscf.application);
20992131Sz.hong@f5.com }
21001264Sigor@sysoev.ru
21011115Svbart@nginx.com if (nxt_slow_path(skcf->action == NULL)) {
21021597Shongzhidao@gmail.com goto fail;
21031597Shongzhidao@gmail.com }
21041597Shongzhidao@gmail.com }
21051597Shongzhidao@gmail.com }
2106770Smax.romanov@nginx.com
2107115Sigor@sysoev.ru ret = nxt_http_routes_resolve(task, tmcf);
210853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
21091472Svbart@nginx.com goto fail;
21101472Svbart@nginx.com }
21111472Svbart@nginx.com
21121472Svbart@nginx.com value = nxt_conf_get_path(root, &access_log_path);
21131472Svbart@nginx.com
21142131Sz.hong@f5.com if (value != NULL) {
2115630Svbart@nginx.com ret = nxt_router_access_log_create(task, rtcf, value);
2116630Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
21172165Sz.hong@f5.com goto fail;
21182165Sz.hong@f5.com }
21192165Sz.hong@f5.com }
2120630Svbart@nginx.com
2121630Svbart@nginx.com #if (NXT_HAVE_NJS)
2122630Svbart@nginx.com js_module = nxt_conf_get_path(root, &js_module_path);
21232450Sz.hong@f5.com
21242450Sz.hong@f5.com if (js_module != NULL) {
21252450Sz.hong@f5.com if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) {
21262450Sz.hong@f5.com n = nxt_conf_array_elements_count(js_module);
21272450Sz.hong@f5.com
21282450Sz.hong@f5.com for (i = 0; i < n; i++) {
21292450Sz.hong@f5.com value = nxt_conf_get_array_element(js_module, i);
21302450Sz.hong@f5.com
21312450Sz.hong@f5.com ret = nxt_router_js_module_insert(tmcf, value);
21322450Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
21332450Sz.hong@f5.com goto fail;
21342450Sz.hong@f5.com }
21352450Sz.hong@f5.com }
21362450Sz.hong@f5.com
21372450Sz.hong@f5.com } else {
21382450Sz.hong@f5.com /* NXT_CONF_STRING */
21392450Sz.hong@f5.com
21402450Sz.hong@f5.com ret = nxt_router_js_module_insert(tmcf, js_module);
21412450Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
21422450Sz.hong@f5.com goto fail;
21432450Sz.hong@f5.com }
21442450Sz.hong@f5.com }
21452450Sz.hong@f5.com }
21462450Sz.hong@f5.com
21472450Sz.hong@f5.com #endif
21482450Sz.hong@f5.com
21492450Sz.hong@f5.com nxt_queue_add(&deleting_sockets, &router->sockets);
21502247Sz.hong@f5.com nxt_queue_init(&router->sockets);
21511509Sigor@sysoev.ru
2152359Sigor@sysoev.ru return NXT_OK;
2153198Sigor@sysoev.ru
215453Sigor@sysoev.ru app_fail:
2155133Sigor@sysoev.ru
2156133Sigor@sysoev.ru nxt_mp_destroy(app_mp);
2157133Sigor@sysoev.ru
21581473Svbart@nginx.com fail:
2159133Sigor@sysoev.ru
2160133Sigor@sysoev.ru nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
2161133Sigor@sysoev.ru
2162141Smax.romanov@nginx.com nxt_queue_remove(&app->link);
2163141Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->mutex);
2164141Smax.romanov@nginx.com nxt_mp_destroy(app->mem_pool);
2165133Sigor@sysoev.ru
21661473Svbart@nginx.com } nxt_queue_loop;
2167141Smax.romanov@nginx.com
2168141Smax.romanov@nginx.com return NXT_ERROR;
2169133Sigor@sysoev.ru }
2170133Sigor@sysoev.ru
2171133Sigor@sysoev.ru
2172133Sigor@sysoev.ru #if (NXT_TLS)
2173133Sigor@sysoev.ru
21741828Sa.suvorov@f5.com 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)21751828Sa.suvorov@f5.com nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf,
21761828Sa.suvorov@f5.com nxt_conf_value_t *value, nxt_socket_conf_t *skcf,
21771828Sa.suvorov@f5.com nxt_tls_init_t *tls_init, nxt_bool_t last)
21781885Sa.suvorov@f5.com {
21791920Sa.suvorov@f5.com nxt_router_tlssock_t *tls;
21801828Sa.suvorov@f5.com
21811828Sa.suvorov@f5.com tls = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_tlssock_t));
21821828Sa.suvorov@f5.com if (nxt_slow_path(tls == NULL)) {
21831885Sa.suvorov@f5.com return NXT_ERROR;
21841828Sa.suvorov@f5.com }
21851828Sa.suvorov@f5.com
21861828Sa.suvorov@f5.com tls->tls_init = tls_init;
21871828Sa.suvorov@f5.com tls->socket_conf = skcf;
21881920Sa.suvorov@f5.com tls->temp_conf = tmcf;
21891885Sa.suvorov@f5.com tls->last = last;
21901885Sa.suvorov@f5.com nxt_conf_get_string(value, &tls->name);
21911904Smax.romanov@nginx.com
21921885Sa.suvorov@f5.com nxt_queue_insert_tail(&tmcf->tls, &tls->link);
21931828Sa.suvorov@f5.com
21941828Sa.suvorov@f5.com return NXT_OK;
21951828Sa.suvorov@f5.com }
21961828Sa.suvorov@f5.com
21971828Sa.suvorov@f5.com #endif
21981828Sa.suvorov@f5.com
21991828Sa.suvorov@f5.com
22001828Sa.suvorov@f5.com #if (NXT_HAVE_NJS)
22011828Sa.suvorov@f5.com
22022450Sz.hong@f5.com static void
nxt_router_js_module_rpc_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)22032450Sz.hong@f5.com nxt_router_js_module_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
22042450Sz.hong@f5.com void *data)
22052450Sz.hong@f5.com {
22062450Sz.hong@f5.com nxt_int_t ret;
22072450Sz.hong@f5.com nxt_str_t text;
22082450Sz.hong@f5.com nxt_router_conf_t *rtcf;
22092450Sz.hong@f5.com nxt_router_temp_conf_t *tmcf;
22102450Sz.hong@f5.com nxt_router_js_module_t *js_module;
22112450Sz.hong@f5.com
22122450Sz.hong@f5.com nxt_debug(task, "auto module rpc handler");
22132450Sz.hong@f5.com
22142450Sz.hong@f5.com js_module = data;
22152450Sz.hong@f5.com tmcf = js_module->temp_conf;
22162450Sz.hong@f5.com
22172450Sz.hong@f5.com if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
22182450Sz.hong@f5.com goto fail;
22192450Sz.hong@f5.com }
22202450Sz.hong@f5.com
22212450Sz.hong@f5.com rtcf = tmcf->router_conf;
22222450Sz.hong@f5.com
22232450Sz.hong@f5.com ret = nxt_script_file_read(msg->fd[0], &text);
22242450Sz.hong@f5.com
22252450Sz.hong@f5.com nxt_fd_close(msg->fd[0]);
22262450Sz.hong@f5.com
22272450Sz.hong@f5.com if (nxt_slow_path(ret == NXT_ERROR)) {
22282450Sz.hong@f5.com goto fail;
22292450Sz.hong@f5.com }
22302450Sz.hong@f5.com
22312450Sz.hong@f5.com if (text.length > 0) {
22322450Sz.hong@f5.com ret = nxt_js_add_module(rtcf->tstr_state->jcf, &js_module->name, &text);
22332450Sz.hong@f5.com
22342450Sz.hong@f5.com nxt_free(text.start);
22352450Sz.hong@f5.com
22362450Sz.hong@f5.com if (nxt_slow_path(ret == NXT_ERROR)) {
22372450Sz.hong@f5.com goto fail;
22382450Sz.hong@f5.com }
22392450Sz.hong@f5.com }
22402450Sz.hong@f5.com
22412450Sz.hong@f5.com nxt_work_queue_add(&task->thread->engine->fast_work_queue,
22422450Sz.hong@f5.com nxt_router_conf_apply, task, tmcf, NULL);
22432450Sz.hong@f5.com return;
22442450Sz.hong@f5.com
22452450Sz.hong@f5.com fail:
22462450Sz.hong@f5.com
22472450Sz.hong@f5.com nxt_router_conf_error(task, tmcf);
22482450Sz.hong@f5.com }
22492450Sz.hong@f5.com
22502450Sz.hong@f5.com
22512450Sz.hong@f5.com static nxt_int_t
nxt_router_js_module_insert(nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * value)22522450Sz.hong@f5.com nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf,
22532450Sz.hong@f5.com nxt_conf_value_t *value)
22542450Sz.hong@f5.com {
22552450Sz.hong@f5.com nxt_router_js_module_t *js_module;
22562450Sz.hong@f5.com
22572450Sz.hong@f5.com js_module = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_js_module_t));
22582450Sz.hong@f5.com if (nxt_slow_path(js_module == NULL)) {
22592450Sz.hong@f5.com return NXT_ERROR;
22602450Sz.hong@f5.com }
22612450Sz.hong@f5.com
22622450Sz.hong@f5.com js_module->temp_conf = tmcf;
22632450Sz.hong@f5.com nxt_conf_get_string(value, &js_module->name);
22642450Sz.hong@f5.com
22652450Sz.hong@f5.com nxt_queue_insert_tail(&tmcf->js_modules, &js_module->link);
22662450Sz.hong@f5.com
22672450Sz.hong@f5.com return NXT_OK;
22682450Sz.hong@f5.com }
22692450Sz.hong@f5.com
22702450Sz.hong@f5.com #endif
22712450Sz.hong@f5.com
22722450Sz.hong@f5.com
22732450Sz.hong@f5.com static nxt_int_t
nxt_router_conf_process_static(nxt_task_t * task,nxt_router_conf_t * rtcf,nxt_conf_value_t * conf)22742450Sz.hong@f5.com nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf,
22751183Svbart@nginx.com nxt_conf_value_t *conf)
22761183Svbart@nginx.com {
22771183Svbart@nginx.com uint32_t next, i;
22781183Svbart@nginx.com nxt_mp_t *mp;
22791183Svbart@nginx.com nxt_str_t *type, exten, str, *s;
22801183Svbart@nginx.com nxt_int_t ret;
22812633Salx@kernel.org nxt_uint_t exts;
22821183Svbart@nginx.com nxt_conf_value_t *mtypes_conf, *ext_conf, *value;
22831183Svbart@nginx.com
22841183Svbart@nginx.com static nxt_str_t mtypes_path = nxt_string("/mime_types");
22851183Svbart@nginx.com
22861183Svbart@nginx.com mp = rtcf->mem_pool;
22871183Svbart@nginx.com
22881183Svbart@nginx.com ret = nxt_http_static_mtypes_init(mp, &rtcf->mtypes_hash);
22891183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
22901183Svbart@nginx.com return NXT_ERROR;
22911183Svbart@nginx.com }
22921183Svbart@nginx.com
22931183Svbart@nginx.com if (conf == NULL) {
22941183Svbart@nginx.com return NXT_OK;
22951183Svbart@nginx.com }
22961183Svbart@nginx.com
22971183Svbart@nginx.com mtypes_conf = nxt_conf_get_path(conf, &mtypes_path);
22981183Svbart@nginx.com
22991183Svbart@nginx.com if (mtypes_conf != NULL) {
23001183Svbart@nginx.com next = 0;
23011183Svbart@nginx.com
23021183Svbart@nginx.com for ( ;; ) {
23031183Svbart@nginx.com ext_conf = nxt_conf_next_object_member(mtypes_conf, &str, &next);
23041183Svbart@nginx.com
23051183Svbart@nginx.com if (ext_conf == NULL) {
23061183Svbart@nginx.com break;
23071183Svbart@nginx.com }
23081183Svbart@nginx.com
23091183Svbart@nginx.com type = nxt_str_dup(mp, NULL, &str);
23101183Svbart@nginx.com if (nxt_slow_path(type == NULL)) {
23111183Svbart@nginx.com return NXT_ERROR;
23121183Svbart@nginx.com }
23131183Svbart@nginx.com
23141183Svbart@nginx.com if (nxt_conf_type(ext_conf) == NXT_CONF_STRING) {
23151183Svbart@nginx.com s = nxt_conf_get_string_dup(ext_conf, mp, &exten);
23161183Svbart@nginx.com if (nxt_slow_path(s == NULL)) {
23172633Salx@kernel.org return NXT_ERROR;
23182633Salx@kernel.org }
23191183Svbart@nginx.com
23201183Svbart@nginx.com ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash,
23211183Svbart@nginx.com &exten, type);
23221183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
23231923Sz.hong@f5.com return NXT_ERROR;
23241183Svbart@nginx.com }
23251183Svbart@nginx.com
23261183Svbart@nginx.com continue;
23271183Svbart@nginx.com }
23281183Svbart@nginx.com
23291183Svbart@nginx.com exts = nxt_conf_array_elements_count(ext_conf);
23301183Svbart@nginx.com
23311183Svbart@nginx.com for (i = 0; i < exts; i++) {
23321183Svbart@nginx.com value = nxt_conf_get_array_element(ext_conf, i);
23331183Svbart@nginx.com
23341183Svbart@nginx.com s = nxt_conf_get_string_dup(value, mp, &exten);
23351183Svbart@nginx.com if (nxt_slow_path(s == NULL)) {
23362633Salx@kernel.org return NXT_ERROR;
23372633Salx@kernel.org }
23381183Svbart@nginx.com
23391183Svbart@nginx.com ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash,
23401183Svbart@nginx.com &exten, type);
23411183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
23421923Sz.hong@f5.com return NXT_ERROR;
23431183Svbart@nginx.com }
23441183Svbart@nginx.com }
23451183Svbart@nginx.com }
23461183Svbart@nginx.com }
23471183Svbart@nginx.com
23481183Svbart@nginx.com return NXT_OK;
23491183Svbart@nginx.com }
23501183Svbart@nginx.com
23511183Svbart@nginx.com
23521183Svbart@nginx.com static nxt_http_forward_t *
nxt_router_conf_forward(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * conf)23531183Svbart@nginx.com nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf)
23542133Sz.hong@f5.com {
23552133Sz.hong@f5.com nxt_int_t ret;
23561936So.canty@f5.com nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf;
23572133Sz.hong@f5.com nxt_conf_value_t *source_conf, *recursive_conf;
23582133Sz.hong@f5.com nxt_http_forward_t *forward;
23592133Sz.hong@f5.com nxt_http_route_addr_rule_t *source;
23602132Sz.hong@f5.com
23611936So.canty@f5.com static nxt_str_t header_path = nxt_string("/header");
23621936So.canty@f5.com static nxt_str_t client_ip_path = nxt_string("/client_ip");
23631936So.canty@f5.com static nxt_str_t protocol_path = nxt_string("/protocol");
23642133Sz.hong@f5.com static nxt_str_t source_path = nxt_string("/source");
23652133Sz.hong@f5.com static nxt_str_t recursive_path = nxt_string("/recursive");
23661936So.canty@f5.com
23671936So.canty@f5.com header_conf = nxt_conf_get_path(conf, &header_path);
23681936So.canty@f5.com
23692133Sz.hong@f5.com if (header_conf != NULL) {
23702133Sz.hong@f5.com client_ip_conf = nxt_conf_get_path(conf, &header_path);
23712133Sz.hong@f5.com protocol_conf = NULL;
23722133Sz.hong@f5.com
23732133Sz.hong@f5.com } else {
23742133Sz.hong@f5.com client_ip_conf = nxt_conf_get_path(conf, &client_ip_path);
23752133Sz.hong@f5.com protocol_conf = nxt_conf_get_path(conf, &protocol_path);
23762133Sz.hong@f5.com }
23772133Sz.hong@f5.com
23782133Sz.hong@f5.com source_conf = nxt_conf_get_path(conf, &source_path);
23792133Sz.hong@f5.com recursive_conf = nxt_conf_get_path(conf, &recursive_path);
23801936So.canty@f5.com
23811936So.canty@f5.com if (source_conf == NULL
23821936So.canty@f5.com || (protocol_conf == NULL && client_ip_conf == NULL))
23832133Sz.hong@f5.com {
23842133Sz.hong@f5.com return NULL;
23852133Sz.hong@f5.com }
23862133Sz.hong@f5.com
23871936So.canty@f5.com forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t));
23881936So.canty@f5.com if (nxt_slow_path(forward == NULL)) {
23892132Sz.hong@f5.com return NULL;
23902132Sz.hong@f5.com }
23912133Sz.hong@f5.com
23921936So.canty@f5.com source = nxt_http_route_addr_rule_create(task, mp, source_conf);
23931936So.canty@f5.com if (nxt_slow_path(source == NULL)) {
23941936So.canty@f5.com return NULL;
23951936So.canty@f5.com }
23962133Sz.hong@f5.com
23971936So.canty@f5.com forward->source = source;
23981936So.canty@f5.com
23992132Sz.hong@f5.com if (recursive_conf != NULL) {
24002132Sz.hong@f5.com forward->recursive = nxt_conf_get_boolean(recursive_conf);
24011936So.canty@f5.com }
24022132Sz.hong@f5.com
24031936So.canty@f5.com if (client_ip_conf != NULL) {
24041936So.canty@f5.com ret = nxt_router_conf_forward_header(mp, client_ip_conf,
24052133Sz.hong@f5.com &forward->client_ip);
24062133Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
24072133Sz.hong@f5.com return NULL;
24082133Sz.hong@f5.com }
24092133Sz.hong@f5.com }
24102133Sz.hong@f5.com
24112133Sz.hong@f5.com if (protocol_conf != NULL) {
24122133Sz.hong@f5.com ret = nxt_router_conf_forward_header(mp, protocol_conf,
24132133Sz.hong@f5.com &forward->protocol);
24142133Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) {
24152133Sz.hong@f5.com return NULL;
24162133Sz.hong@f5.com }
24172133Sz.hong@f5.com }
24182133Sz.hong@f5.com
24192133Sz.hong@f5.com return forward;
24202133Sz.hong@f5.com }
24212133Sz.hong@f5.com
24222133Sz.hong@f5.com
24232133Sz.hong@f5.com static nxt_int_t
nxt_router_conf_forward_header(nxt_mp_t * mp,nxt_conf_value_t * conf,nxt_http_forward_header_t * fh)24242133Sz.hong@f5.com nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf,
24252133Sz.hong@f5.com nxt_http_forward_header_t *fh)
24262133Sz.hong@f5.com {
24272133Sz.hong@f5.com char c;
24282133Sz.hong@f5.com size_t i;
24292633Salx@kernel.org uint32_t hash;
24302633Salx@kernel.org
24312633Salx@kernel.org fh->header = nxt_conf_get_string_dup(conf, mp, NULL);
24322633Salx@kernel.org if (nxt_slow_path(fh->header == NULL)) {
24332633Salx@kernel.org return NXT_ERROR;
24342133Sz.hong@f5.com }
24351936So.canty@f5.com
24361936So.canty@f5.com hash = NXT_HTTP_FIELD_HASH_INIT;
24371936So.canty@f5.com
24381936So.canty@f5.com for (i = 0; i < fh->header->length; i++) {
24391936So.canty@f5.com c = fh->header->start[i];
24402133Sz.hong@f5.com hash = nxt_http_field_hash_char(hash, nxt_lowcase(c));
24412133Sz.hong@f5.com }
24421936So.canty@f5.com
24431936So.canty@f5.com hash = nxt_http_field_hash_end(hash) & 0xFFFF;
24441936So.canty@f5.com
24451936So.canty@f5.com fh->header_hash = hash;
24461936So.canty@f5.com
24472133Sz.hong@f5.com return NXT_OK;
24481936So.canty@f5.com }
24491936So.canty@f5.com
24501936So.canty@f5.com
24511936So.canty@f5.com static nxt_app_t *
nxt_router_app_find(nxt_queue_t * queue,nxt_str_t * name)24521936So.canty@f5.com nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name)
2453133Sigor@sysoev.ru {
2454133Sigor@sysoev.ru nxt_app_t *app;
2455133Sigor@sysoev.ru
2456141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) {
2457141Smax.romanov@nginx.com
2458141Smax.romanov@nginx.com if (nxt_strstr_eq(name, &app->name)) {
2459133Sigor@sysoev.ru return app;
2460133Sigor@sysoev.ru }
2461133Sigor@sysoev.ru
2462133Sigor@sysoev.ru } nxt_queue_loop;
2463141Smax.romanov@nginx.com
2464141Smax.romanov@nginx.com return NULL;
2465133Sigor@sysoev.ru }
2466133Sigor@sysoev.ru
2467133Sigor@sysoev.ru
2468133Sigor@sysoev.ru static nxt_int_t
nxt_router_app_queue_init(nxt_task_t * task,nxt_port_t * port)2469133Sigor@sysoev.ru nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port)
24701555Smax.romanov@nginx.com {
24711555Smax.romanov@nginx.com void *mem;
24721555Smax.romanov@nginx.com nxt_int_t fd;
24731555Smax.romanov@nginx.com
24741555Smax.romanov@nginx.com fd = nxt_shm_open(task, sizeof(nxt_app_queue_t));
24751555Smax.romanov@nginx.com if (nxt_slow_path(fd == -1)) {
24761555Smax.romanov@nginx.com return NXT_ERROR;
24771555Smax.romanov@nginx.com }
24781555Smax.romanov@nginx.com
24791555Smax.romanov@nginx.com mem = nxt_mem_mmap(NULL, sizeof(nxt_app_queue_t),
24801555Smax.romanov@nginx.com PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
24811555Smax.romanov@nginx.com if (nxt_slow_path(mem == MAP_FAILED)) {
24821555Smax.romanov@nginx.com nxt_fd_close(fd);
24831555Smax.romanov@nginx.com
24841555Smax.romanov@nginx.com return NXT_ERROR;
24851555Smax.romanov@nginx.com }
24861555Smax.romanov@nginx.com
24871555Smax.romanov@nginx.com nxt_app_queue_init(mem);
24881555Smax.romanov@nginx.com
24891555Smax.romanov@nginx.com port->queue_fd = fd;
24901555Smax.romanov@nginx.com port->queue = mem;
24911555Smax.romanov@nginx.com
24921555Smax.romanov@nginx.com return NXT_OK;
24931555Smax.romanov@nginx.com }
24941555Smax.romanov@nginx.com
24951555Smax.romanov@nginx.com
24961555Smax.romanov@nginx.com static nxt_int_t
nxt_router_port_queue_init(nxt_task_t * task,nxt_port_t * port)24971555Smax.romanov@nginx.com nxt_router_port_queue_init(nxt_task_t *task, nxt_port_t *port)
24981555Smax.romanov@nginx.com {
24991555Smax.romanov@nginx.com void *mem;
25001555Smax.romanov@nginx.com nxt_int_t fd;
25011555Smax.romanov@nginx.com
25021555Smax.romanov@nginx.com fd = nxt_shm_open(task, sizeof(nxt_port_queue_t));
25031555Smax.romanov@nginx.com if (nxt_slow_path(fd == -1)) {
25041555Smax.romanov@nginx.com return NXT_ERROR;
25051555Smax.romanov@nginx.com }
25061555Smax.romanov@nginx.com
25071555Smax.romanov@nginx.com mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t),
25081555Smax.romanov@nginx.com PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
25091555Smax.romanov@nginx.com if (nxt_slow_path(mem == MAP_FAILED)) {
25101555Smax.romanov@nginx.com nxt_fd_close(fd);
25111555Smax.romanov@nginx.com
25121555Smax.romanov@nginx.com return NXT_ERROR;
25131555Smax.romanov@nginx.com }
25141555Smax.romanov@nginx.com
25151555Smax.romanov@nginx.com nxt_port_queue_init(mem);
25161555Smax.romanov@nginx.com
25171555Smax.romanov@nginx.com port->queue_fd = fd;
25181555Smax.romanov@nginx.com port->queue = mem;
25191555Smax.romanov@nginx.com
25201555Smax.romanov@nginx.com return NXT_OK;
25211555Smax.romanov@nginx.com }
25221555Smax.romanov@nginx.com
25231555Smax.romanov@nginx.com
25241555Smax.romanov@nginx.com static nxt_int_t
nxt_router_port_queue_map(nxt_task_t * task,nxt_port_t * port,nxt_fd_t fd)25251555Smax.romanov@nginx.com nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, nxt_fd_t fd)
25261555Smax.romanov@nginx.com {
25271555Smax.romanov@nginx.com void *mem;
25281555Smax.romanov@nginx.com
25291555Smax.romanov@nginx.com nxt_assert(fd != -1);
25301555Smax.romanov@nginx.com
25311555Smax.romanov@nginx.com mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t),
25321555Smax.romanov@nginx.com PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
25331555Smax.romanov@nginx.com if (nxt_slow_path(mem == MAP_FAILED)) {
25341555Smax.romanov@nginx.com
25351555Smax.romanov@nginx.com return NXT_ERROR;
25361555Smax.romanov@nginx.com }
25371555Smax.romanov@nginx.com
25381555Smax.romanov@nginx.com port->queue = mem;
25391555Smax.romanov@nginx.com
25401555Smax.romanov@nginx.com return NXT_OK;
25411555Smax.romanov@nginx.com }
25421555Smax.romanov@nginx.com
25431555Smax.romanov@nginx.com
25441555Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t nxt_router_apps_hash_proto nxt_aligned(64) = {
25451555Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT,
25461563Svbart@nginx.com nxt_router_apps_hash_test,
25471563Svbart@nginx.com nxt_mp_lvlhsh_alloc,
25481563Svbart@nginx.com nxt_mp_lvlhsh_free,
25491563Svbart@nginx.com };
25501563Svbart@nginx.com
25511563Svbart@nginx.com
25521563Svbart@nginx.com static nxt_int_t
nxt_router_apps_hash_test(nxt_lvlhsh_query_t * lhq,void * data)25531563Svbart@nginx.com nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
25541563Svbart@nginx.com {
25551563Svbart@nginx.com nxt_app_t *app;
25561563Svbart@nginx.com
25571563Svbart@nginx.com app = data;
25581563Svbart@nginx.com
25591563Svbart@nginx.com return nxt_strstr_eq(&lhq->key, &app->name) ? NXT_OK : NXT_DECLINED;
25601563Svbart@nginx.com }
25611563Svbart@nginx.com
25621563Svbart@nginx.com
25631563Svbart@nginx.com static nxt_int_t
nxt_router_apps_hash_add(nxt_router_conf_t * rtcf,nxt_app_t * app)25641563Svbart@nginx.com nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, nxt_app_t *app)
25651563Svbart@nginx.com {
25661563Svbart@nginx.com nxt_lvlhsh_query_t lhq;
25671563Svbart@nginx.com
25681563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(app->name.start, app->name.length);
25691563Svbart@nginx.com lhq.replace = 0;
25701563Svbart@nginx.com lhq.key = app->name;
25711563Svbart@nginx.com lhq.value = app;
25721563Svbart@nginx.com lhq.proto = &nxt_router_apps_hash_proto;
25731563Svbart@nginx.com lhq.pool = rtcf->mem_pool;
25741563Svbart@nginx.com
25751563Svbart@nginx.com switch (nxt_lvlhsh_insert(&rtcf->apps_hash, &lhq)) {
25761563Svbart@nginx.com
25771563Svbart@nginx.com case NXT_OK:
25781563Svbart@nginx.com return NXT_OK;
25791563Svbart@nginx.com
25801563Svbart@nginx.com case NXT_DECLINED:
25811563Svbart@nginx.com nxt_thread_log_alert("router app hash adding failed: "
25821563Svbart@nginx.com "\"%V\" is already in hash", &lhq.key);
25831563Svbart@nginx.com /* Fall through. */
25841563Svbart@nginx.com default:
25851563Svbart@nginx.com return NXT_ERROR;
25861563Svbart@nginx.com }
25871563Svbart@nginx.com }
25881563Svbart@nginx.com
25891563Svbart@nginx.com
25901563Svbart@nginx.com static nxt_app_t *
nxt_router_apps_hash_get(nxt_router_conf_t * rtcf,nxt_str_t * name)25911563Svbart@nginx.com nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, nxt_str_t *name)
25921563Svbart@nginx.com {
25931563Svbart@nginx.com nxt_lvlhsh_query_t lhq;
25941563Svbart@nginx.com
25951563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(name->start, name->length);
25961563Svbart@nginx.com lhq.key = *name;
25971563Svbart@nginx.com lhq.proto = &nxt_router_apps_hash_proto;
25981563Svbart@nginx.com
25991563Svbart@nginx.com if (nxt_lvlhsh_find(&rtcf->apps_hash, &lhq) != NXT_OK) {
26001563Svbart@nginx.com return NULL;
26011563Svbart@nginx.com }
26021563Svbart@nginx.com
26031563Svbart@nginx.com return lhq.value;
26041563Svbart@nginx.com }
26051563Svbart@nginx.com
26061563Svbart@nginx.com
26071563Svbart@nginx.com static void
nxt_router_apps_hash_use(nxt_task_t * task,nxt_router_conf_t * rtcf,int i)26081563Svbart@nginx.com nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, int i)
26091563Svbart@nginx.com {
26101563Svbart@nginx.com nxt_app_t *app;
26111563Svbart@nginx.com nxt_lvlhsh_each_t lhe;
26121563Svbart@nginx.com
26131563Svbart@nginx.com nxt_lvlhsh_each_init(&lhe, &nxt_router_apps_hash_proto);
26141563Svbart@nginx.com
26151563Svbart@nginx.com for ( ;; ) {
26161563Svbart@nginx.com app = nxt_lvlhsh_each(&rtcf->apps_hash, &lhe);
26171563Svbart@nginx.com
26181563Svbart@nginx.com if (app == NULL) {
26191563Svbart@nginx.com break;
26201563Svbart@nginx.com }
26211563Svbart@nginx.com
26221563Svbart@nginx.com nxt_router_app_use(task, app, i);
26231563Svbart@nginx.com }
26241563Svbart@nginx.com }
26251563Svbart@nginx.com
26261563Svbart@nginx.com
26271563Svbart@nginx.com typedef struct {
26281563Svbart@nginx.com nxt_app_t *app;
26291925Sz.hong@f5.com nxt_int_t target;
26301925Sz.hong@f5.com } nxt_http_app_conf_t;
26311925Sz.hong@f5.com
26321925Sz.hong@f5.com
26331925Sz.hong@f5.com nxt_int_t
nxt_router_application_init(nxt_router_conf_t * rtcf,nxt_str_t * name,nxt_str_t * target,nxt_http_action_t * action)26341563Svbart@nginx.com nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name,
26351563Svbart@nginx.com nxt_str_t *target, nxt_http_action_t *action)
26361925Sz.hong@f5.com {
26371925Sz.hong@f5.com nxt_app_t *app;
2638133Sigor@sysoev.ru nxt_str_t *targets;
26391925Sz.hong@f5.com nxt_uint_t i;
26401925Sz.hong@f5.com nxt_http_app_conf_t *conf;
26411925Sz.hong@f5.com
26421925Sz.hong@f5.com app = nxt_router_apps_hash_get(rtcf, name);
2643133Sigor@sysoev.ru if (app == NULL) {
26441563Svbart@nginx.com return NXT_DECLINED;
2645133Sigor@sysoev.ru }
26461563Svbart@nginx.com
2647133Sigor@sysoev.ru conf = nxt_mp_get(rtcf->mem_pool, sizeof(nxt_http_app_conf_t));
2648133Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) {
26491925Sz.hong@f5.com return NXT_ERROR;
26501925Sz.hong@f5.com }
26511925Sz.hong@f5.com
26521925Sz.hong@f5.com action->handler = nxt_http_application_handler;
26531925Sz.hong@f5.com action->u.conf = conf;
26541392Sigor@sysoev.ru
26551925Sz.hong@f5.com conf->app = app;
26561925Sz.hong@f5.com
26571925Sz.hong@f5.com if (target != NULL && target->length != 0) {
26581925Sz.hong@f5.com targets = app->targets;
26591925Sz.hong@f5.com
26601925Sz.hong@f5.com for (i = 0; !nxt_strstr_eq(target, &targets[i]); i++);
26611925Sz.hong@f5.com
26621925Sz.hong@f5.com conf->target = i;
26631925Sz.hong@f5.com
26641925Sz.hong@f5.com } else {
26651925Sz.hong@f5.com conf->target = 0;
26661925Sz.hong@f5.com }
26671925Sz.hong@f5.com
26681925Sz.hong@f5.com return NXT_OK;
26691563Svbart@nginx.com }
26701563Svbart@nginx.com
267153Sigor@sysoev.ru
267253Sigor@sysoev.ru static nxt_socket_conf_t *
nxt_router_socket_conf(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_str_t * name)267353Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
267453Sigor@sysoev.ru nxt_str_t *name)
2675359Sigor@sysoev.ru {
2676359Sigor@sysoev.ru size_t size;
267753Sigor@sysoev.ru nxt_int_t ret;
2678359Sigor@sysoev.ru nxt_bool_t wildcard;
2679359Sigor@sysoev.ru nxt_sockaddr_t *sa;
2680359Sigor@sysoev.ru nxt_socket_conf_t *skcf;
2681359Sigor@sysoev.ru nxt_listen_socket_t *ls;
2682359Sigor@sysoev.ru
2683359Sigor@sysoev.ru sa = nxt_sockaddr_parse(tmcf->mem_pool, name);
2684359Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) {
2685359Sigor@sysoev.ru nxt_alert(task, "invalid listener \"%V\"", name);
2686359Sigor@sysoev.ru return NULL;
2687564Svbart@nginx.com }
2688359Sigor@sysoev.ru
2689359Sigor@sysoev.ru sa->type = SOCK_STREAM;
2690359Sigor@sysoev.ru
2691359Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"",
2692359Sigor@sysoev.ru (size_t) sa->length, nxt_sockaddr_start(sa));
2693359Sigor@sysoev.ru
2694493Spluknet@nginx.com skcf = nxt_mp_zget(tmcf->router_conf->mem_pool, sizeof(nxt_socket_conf_t));
2695359Sigor@sysoev.ru if (nxt_slow_path(skcf == NULL)) {
2696591Sigor@sysoev.ru return NULL;
2697163Smax.romanov@nginx.com }
269853Sigor@sysoev.ru
269953Sigor@sysoev.ru size = nxt_sockaddr_size(sa);
270053Sigor@sysoev.ru
2701359Sigor@sysoev.ru ret = nxt_router_listen_socket_find(tmcf, skcf, sa);
2702359Sigor@sysoev.ru
2703359Sigor@sysoev.ru if (ret != NXT_OK) {
2704359Sigor@sysoev.ru
2705359Sigor@sysoev.ru ls = nxt_zalloc(sizeof(nxt_listen_socket_t) + size);
2706359Sigor@sysoev.ru if (nxt_slow_path(ls == NULL)) {
2707359Sigor@sysoev.ru return NULL;
2708359Sigor@sysoev.ru }
2709359Sigor@sysoev.ru
2710359Sigor@sysoev.ru skcf->listen = ls;
2711359Sigor@sysoev.ru
2712359Sigor@sysoev.ru ls->sockaddr = nxt_pointer_to(ls, sizeof(nxt_listen_socket_t));
2713359Sigor@sysoev.ru nxt_memcpy(ls->sockaddr, sa, size);
2714359Sigor@sysoev.ru
2715359Sigor@sysoev.ru nxt_listen_socket_remote_size(ls);
2716359Sigor@sysoev.ru
2717359Sigor@sysoev.ru ls->socket = -1;
2718359Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG;
2719359Sigor@sysoev.ru ls->flags = NXT_NONBLOCK;
2720359Sigor@sysoev.ru ls->read_after_accept = 1;
2721359Sigor@sysoev.ru }
2722359Sigor@sysoev.ru
2723359Sigor@sysoev.ru switch (sa->u.sockaddr.sa_family) {
2724359Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
2725359Sigor@sysoev.ru case AF_UNIX:
2726359Sigor@sysoev.ru wildcard = 0;
2727359Sigor@sysoev.ru break;
2728359Sigor@sysoev.ru #endif
2729359Sigor@sysoev.ru #if (NXT_INET6)
2730359Sigor@sysoev.ru case AF_INET6:
2731359Sigor@sysoev.ru wildcard = IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr);
2732359Sigor@sysoev.ru break;
2733359Sigor@sysoev.ru #endif
2734359Sigor@sysoev.ru case AF_INET:
2735359Sigor@sysoev.ru default:
2736359Sigor@sysoev.ru wildcard = (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY);
2737359Sigor@sysoev.ru break;
2738359Sigor@sysoev.ru }
2739359Sigor@sysoev.ru
2740359Sigor@sysoev.ru if (!wildcard) {
2741359Sigor@sysoev.ru skcf->sockaddr = nxt_mp_zget(tmcf->router_conf->mem_pool, size);
2742359Sigor@sysoev.ru if (nxt_slow_path(skcf->sockaddr == NULL)) {
2743591Sigor@sysoev.ru return NULL;
2744359Sigor@sysoev.ru }
2745359Sigor@sysoev.ru
2746359Sigor@sysoev.ru nxt_memcpy(skcf->sockaddr, sa, size);
2747359Sigor@sysoev.ru }
2748359Sigor@sysoev.ru
2749359Sigor@sysoev.ru return skcf;
2750163Smax.romanov@nginx.com }
2751163Smax.romanov@nginx.com
275253Sigor@sysoev.ru
275353Sigor@sysoev.ru static nxt_int_t
nxt_router_listen_socket_find(nxt_router_temp_conf_t * tmcf,nxt_socket_conf_t * nskcf,nxt_sockaddr_t * sa)275453Sigor@sysoev.ru nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf,
2755359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa)
2756359Sigor@sysoev.ru {
2757359Sigor@sysoev.ru nxt_router_t *router;
275853Sigor@sysoev.ru nxt_queue_link_t *qlk;
2759359Sigor@sysoev.ru nxt_socket_conf_t *skcf;
2760359Sigor@sysoev.ru
2761359Sigor@sysoev.ru router = tmcf->router_conf->router;
2762359Sigor@sysoev.ru
2763591Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->sockets);
2764359Sigor@sysoev.ru qlk != nxt_queue_tail(&router->sockets);
2765359Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
2766359Sigor@sysoev.ru {
2767359Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
276853Sigor@sysoev.ru
2769359Sigor@sysoev.ru if (nxt_sockaddr_cmp(skcf->listen->sockaddr, sa)) {
2770359Sigor@sysoev.ru nskcf->listen = skcf->listen;
2771359Sigor@sysoev.ru
2772359Sigor@sysoev.ru nxt_queue_remove(qlk);
2773359Sigor@sysoev.ru nxt_queue_insert_tail(&keeping_sockets, qlk);
2774359Sigor@sysoev.ru
27751509Sigor@sysoev.ru nxt_queue_insert_tail(&updating_sockets, &nskcf->link);
27761509Sigor@sysoev.ru
27771509Sigor@sysoev.ru return NXT_OK;
2778359Sigor@sysoev.ru }
2779359Sigor@sysoev.ru }
278053Sigor@sysoev.ru
278153Sigor@sysoev.ru nxt_queue_insert_tail(&pending_sockets, &nskcf->link);
278253Sigor@sysoev.ru
27831509Sigor@sysoev.ru return NXT_DECLINED;
2784359Sigor@sysoev.ru }
2785359Sigor@sysoev.ru
278653Sigor@sysoev.ru
278753Sigor@sysoev.ru static void
nxt_router_listen_socket_rpc_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_socket_conf_t * skcf)278853Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(nxt_task_t *task,
2789198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf)
2790198Sigor@sysoev.ru {
2791198Sigor@sysoev.ru size_t size;
2792198Sigor@sysoev.ru uint32_t stream;
2793358Sigor@sysoev.ru nxt_int_t ret;
2794198Sigor@sysoev.ru nxt_buf_t *b;
2795648Svbart@nginx.com nxt_port_t *main_port, *router_port;
2796198Sigor@sysoev.ru nxt_runtime_t *rt;
2797198Sigor@sysoev.ru nxt_socket_rpc_t *rpc;
2798198Sigor@sysoev.ru
2799198Sigor@sysoev.ru rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t));
2800198Sigor@sysoev.ru if (rpc == NULL) {
2801198Sigor@sysoev.ru goto fail;
2802198Sigor@sysoev.ru }
2803198Sigor@sysoev.ru
2804198Sigor@sysoev.ru rpc->socket_conf = skcf;
2805198Sigor@sysoev.ru rpc->temp_conf = tmcf;
2806198Sigor@sysoev.ru
2807198Sigor@sysoev.ru size = nxt_sockaddr_size(skcf->listen->sockaddr);
2808198Sigor@sysoev.ru
2809359Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0);
2810358Sigor@sysoev.ru if (b == NULL) {
2811358Sigor@sysoev.ru goto fail;
2812198Sigor@sysoev.ru }
2813198Sigor@sysoev.ru
2814198Sigor@sysoev.ru b->completion_handler = nxt_buf_dummy_completion;
2815198Sigor@sysoev.ru
28161940Sz.hong@f5.com b->mem.free = nxt_cpymem(b->mem.free, skcf->listen->sockaddr, size);
28171566Smax.romanov@nginx.com
2818359Sigor@sysoev.ru rt = task->thread->runtime;
2819198Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN];
2820198Sigor@sysoev.ru router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
2821240Sigor@sysoev.ru
2822198Sigor@sysoev.ru stream = nxt_port_rpc_register_handler(task, router_port,
2823198Sigor@sysoev.ru nxt_router_listen_socket_ready,
2824198Sigor@sysoev.ru nxt_router_listen_socket_error,
2825198Sigor@sysoev.ru main_port->pid, rpc);
2826198Sigor@sysoev.ru if (nxt_slow_path(stream == 0)) {
2827198Sigor@sysoev.ru goto fail;
2828645Svbart@nginx.com }
2829198Sigor@sysoev.ru
2830198Sigor@sysoev.ru ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1,
2831198Sigor@sysoev.ru stream, router_port->id, b);
2832648Svbart@nginx.com
2833648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
2834648Svbart@nginx.com nxt_port_rpc_cancel(task, router_port, stream);
2835648Svbart@nginx.com goto fail;
2836648Svbart@nginx.com }
2837648Svbart@nginx.com
2838648Svbart@nginx.com return;
2839198Sigor@sysoev.ru
2840198Sigor@sysoev.ru fail:
2841198Sigor@sysoev.ru
2842198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf);
2843198Sigor@sysoev.ru }
2844198Sigor@sysoev.ru
2845198Sigor@sysoev.ru
2846198Sigor@sysoev.ru static void
nxt_router_listen_socket_ready(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)2847198Sigor@sysoev.ru nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
2848198Sigor@sysoev.ru void *data)
2849198Sigor@sysoev.ru {
2850198Sigor@sysoev.ru nxt_int_t ret;
285153Sigor@sysoev.ru nxt_socket_t s;
2852359Sigor@sysoev.ru nxt_socket_rpc_t *rpc;
2853359Sigor@sysoev.ru
2854359Sigor@sysoev.ru rpc = data;
285553Sigor@sysoev.ru
2856198Sigor@sysoev.ru s = msg->fd[0];
2857198Sigor@sysoev.ru
28581558Smax.romanov@nginx.com ret = nxt_socket_nonblocking(task, s);
2859198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
2860198Sigor@sysoev.ru goto fail;
2861198Sigor@sysoev.ru }
2862198Sigor@sysoev.ru
286353Sigor@sysoev.ru nxt_socket_defer_accept(task, s, rpc->socket_conf->listen->sockaddr);
286453Sigor@sysoev.ru
2865359Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG);
2866198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
2867198Sigor@sysoev.ru goto fail;
2868198Sigor@sysoev.ru }
2869198Sigor@sysoev.ru
2870198Sigor@sysoev.ru rpc->socket_conf->listen->socket = s;
2871198Sigor@sysoev.ru
2872359Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue,
2873198Sigor@sysoev.ru nxt_router_conf_apply, task, rpc->temp_conf, NULL);
2874198Sigor@sysoev.ru
2875198Sigor@sysoev.ru return;
2876198Sigor@sysoev.ru
2877198Sigor@sysoev.ru fail:
2878148Sigor@sysoev.ru
2879148Sigor@sysoev.ru nxt_socket_close(task, s);
2880148Sigor@sysoev.ru
2881148Sigor@sysoev.ru nxt_router_conf_error(task, rpc->temp_conf);
2882148Sigor@sysoev.ru }
2883198Sigor@sysoev.ru
2884198Sigor@sysoev.ru
2885198Sigor@sysoev.ru static void
nxt_router_listen_socket_error(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)2886198Sigor@sysoev.ru nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
2887198Sigor@sysoev.ru void *data)
2888198Sigor@sysoev.ru {
2889198Sigor@sysoev.ru nxt_socket_rpc_t *rpc;
2890198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf;
2891955Svbart@nginx.com
2892955Svbart@nginx.com rpc = data;
2893955Svbart@nginx.com tmcf = rpc->temp_conf;
2894955Svbart@nginx.com
2895955Svbart@nginx.com #if 0
2896955Svbart@nginx.com u_char *p;
2897955Svbart@nginx.com size_t size;
2898198Sigor@sysoev.ru uint8_t error;
2899198Sigor@sysoev.ru nxt_buf_t *in, *out;
2900198Sigor@sysoev.ru nxt_sockaddr_t *sa;
2901198Sigor@sysoev.ru
2902198Sigor@sysoev.ru static nxt_str_t socket_errors[] = {
2903198Sigor@sysoev.ru nxt_string("ListenerSystem"),
2904198Sigor@sysoev.ru nxt_string("ListenerNoIPv6"),
2905198Sigor@sysoev.ru nxt_string("ListenerPort"),
2906198Sigor@sysoev.ru nxt_string("ListenerInUse"),
2907198Sigor@sysoev.ru nxt_string("ListenerNoAddress"),
2908198Sigor@sysoev.ru nxt_string("ListenerNoAccess"),
2909198Sigor@sysoev.ru nxt_string("ListenerPath"),
2910198Sigor@sysoev.ru };
2911198Sigor@sysoev.ru
2912198Sigor@sysoev.ru sa = rpc->socket_conf->listen->sockaddr;
2913198Sigor@sysoev.ru
2914359Sigor@sysoev.ru in = nxt_buf_chk_make_plain(tmcf->mem_pool, msg->buf, msg->size);
2915352Smax.romanov@nginx.com
2916352Smax.romanov@nginx.com if (nxt_slow_path(in == NULL)) {
2917352Smax.romanov@nginx.com return;
2918551Smax.romanov@nginx.com }
2919551Smax.romanov@nginx.com
2920551Smax.romanov@nginx.com p = in->mem.pos;
2921352Smax.romanov@nginx.com
2922198Sigor@sysoev.ru error = *p++;
2923198Sigor@sysoev.ru
2924198Sigor@sysoev.ru size = nxt_length("listen socket error: ")
2925198Sigor@sysoev.ru + nxt_length("{listener: \"\", code:\"\", message: \"\"}")
2926703Svbart@nginx.com + sa->length + socket_errors[error].length + (in->mem.free - p);
2927703Svbart@nginx.com
2928198Sigor@sysoev.ru out = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0);
2929198Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) {
2930198Sigor@sysoev.ru return;
2931198Sigor@sysoev.ru }
2932198Sigor@sysoev.ru
2933198Sigor@sysoev.ru out->mem.free = nxt_sprintf(out->mem.free, out->mem.end,
2934198Sigor@sysoev.ru "listen socket error: "
2935198Sigor@sysoev.ru "{listener: \"%*s\", code:\"%V\", message: \"%*s\"}",
2936198Sigor@sysoev.ru (size_t) sa->length, nxt_sockaddr_start(sa),
2937198Sigor@sysoev.ru &socket_errors[error], in->mem.free - p, p);
2938493Spluknet@nginx.com
2939198Sigor@sysoev.ru nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos);
2940198Sigor@sysoev.ru #endif
2941198Sigor@sysoev.ru
2942955Svbart@nginx.com nxt_router_conf_error(task, tmcf);
2943198Sigor@sysoev.ru }
2944198Sigor@sysoev.ru
294553Sigor@sysoev.ru
294653Sigor@sysoev.ru #if (NXT_TLS)
294753Sigor@sysoev.ru
2948774Svbart@nginx.com static void
nxt_router_tls_rpc_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)2949774Svbart@nginx.com nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
2950774Svbart@nginx.com void *data)
2951774Svbart@nginx.com {
2952774Svbart@nginx.com nxt_mp_t *mp;
2953774Svbart@nginx.com nxt_int_t ret;
29541828Sa.suvorov@f5.com nxt_tls_conf_t *tlscf;
29551828Sa.suvorov@f5.com nxt_router_tlssock_t *tls;
29561828Sa.suvorov@f5.com nxt_tls_bundle_conf_t *bundle;
29571885Sa.suvorov@f5.com nxt_router_temp_conf_t *tmcf;
29581828Sa.suvorov@f5.com
29591828Sa.suvorov@f5.com nxt_debug(task, "tls rpc handler");
2960774Svbart@nginx.com
2961774Svbart@nginx.com tls = data;
2962774Svbart@nginx.com tmcf = tls->temp_conf;
29631885Sa.suvorov@f5.com
29641885Sa.suvorov@f5.com if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
2965774Svbart@nginx.com goto fail;
2966774Svbart@nginx.com }
2967774Svbart@nginx.com
2968774Svbart@nginx.com mp = tmcf->router_conf->mem_pool;
2969774Svbart@nginx.com
2970774Svbart@nginx.com if (tls->socket_conf->tls == NULL) {
2971774Svbart@nginx.com tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t));
29722617Szelenkov@nginx.com if (nxt_slow_path(tlscf == NULL)) {
29731828Sa.suvorov@f5.com goto fail;
29741828Sa.suvorov@f5.com }
29751828Sa.suvorov@f5.com
29761828Sa.suvorov@f5.com tlscf->no_wait_shutdown = 1;
29771828Sa.suvorov@f5.com tls->socket_conf->tls = tlscf;
29781884Sa.suvorov@f5.com
29791885Sa.suvorov@f5.com } else {
29801828Sa.suvorov@f5.com tlscf = tls->socket_conf->tls;
29811828Sa.suvorov@f5.com }
29821885Sa.suvorov@f5.com
29831828Sa.suvorov@f5.com tls->tls_init->conf = tlscf;
29841828Sa.suvorov@f5.com
29851920Sa.suvorov@f5.com bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t));
29861920Sa.suvorov@f5.com if (nxt_slow_path(bundle == NULL)) {
29871828Sa.suvorov@f5.com goto fail;
29881828Sa.suvorov@f5.com }
2989774Svbart@nginx.com
2990774Svbart@nginx.com if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) {
2991774Svbart@nginx.com goto fail;
29921885Sa.suvorov@f5.com }
29931885Sa.suvorov@f5.com
29941885Sa.suvorov@f5.com bundle->chain_file = msg->fd[0];
29951885Sa.suvorov@f5.com bundle->next = tlscf->bundle;
29961828Sa.suvorov@f5.com tlscf->bundle = bundle;
29971828Sa.suvorov@f5.com
29981828Sa.suvorov@f5.com ret = task->thread->runtime->tls->server_init(task, mp, tls->tls_init,
29991828Sa.suvorov@f5.com tls->last);
30001920Sa.suvorov@f5.com if (nxt_slow_path(ret != NXT_OK)) {
30011920Sa.suvorov@f5.com goto fail;
3002774Svbart@nginx.com }
3003774Svbart@nginx.com
3004774Svbart@nginx.com nxt_work_queue_add(&task->thread->engine->fast_work_queue,
3005774Svbart@nginx.com nxt_router_conf_apply, task, tmcf, NULL);
3006774Svbart@nginx.com return;
3007774Svbart@nginx.com
3008774Svbart@nginx.com fail:
3009774Svbart@nginx.com
3010774Svbart@nginx.com nxt_router_conf_error(task, tmcf);
3011774Svbart@nginx.com }
3012774Svbart@nginx.com
3013774Svbart@nginx.com #endif
3014774Svbart@nginx.com
3015774Svbart@nginx.com
3016774Svbart@nginx.com static void
nxt_router_app_rpc_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_app_t * app)3017774Svbart@nginx.com nxt_router_app_rpc_create(nxt_task_t *task,
3018507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app)
3019507Smax.romanov@nginx.com {
3020507Smax.romanov@nginx.com size_t size;
3021507Smax.romanov@nginx.com uint32_t stream;
3022507Smax.romanov@nginx.com nxt_fd_t port_fd, queue_fd;
3023507Smax.romanov@nginx.com nxt_int_t ret;
30242014Smax.romanov@nginx.com nxt_buf_t *b;
3025648Svbart@nginx.com nxt_port_t *router_port, *dport;
3026507Smax.romanov@nginx.com nxt_runtime_t *rt;
30271998St.nateldemoura@f5.com nxt_app_rpc_t *rpc;
3028507Smax.romanov@nginx.com
3029507Smax.romanov@nginx.com rt = task->thread->runtime;
3030507Smax.romanov@nginx.com
30311998St.nateldemoura@f5.com dport = app->proto_port;
30321998St.nateldemoura@f5.com
30331998St.nateldemoura@f5.com if (dport == NULL) {
30341998St.nateldemoura@f5.com nxt_debug(task, "app '%V' prototype prefork", &app->name);
30351998St.nateldemoura@f5.com
30361998St.nateldemoura@f5.com size = app->name.length + 1 + app->conf.length;
30371998St.nateldemoura@f5.com
30381998St.nateldemoura@f5.com b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0);
30391998St.nateldemoura@f5.com if (nxt_slow_path(b == NULL)) {
30401998St.nateldemoura@f5.com goto fail;
30411998St.nateldemoura@f5.com }
30421998St.nateldemoura@f5.com
30431998St.nateldemoura@f5.com b->completion_handler = nxt_buf_dummy_completion;
30441998St.nateldemoura@f5.com
30451998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->name);
30461998St.nateldemoura@f5.com *b->mem.free++ = '\0';
30471998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->conf);
30481998St.nateldemoura@f5.com
30491998St.nateldemoura@f5.com dport = rt->port_by_type[NXT_PROCESS_MAIN];
30501998St.nateldemoura@f5.com
30511998St.nateldemoura@f5.com port_fd = app->shared_port->pair[0];
30521998St.nateldemoura@f5.com queue_fd = app->shared_port->queue_fd;
30532014Smax.romanov@nginx.com
30542014Smax.romanov@nginx.com } else {
30552014Smax.romanov@nginx.com nxt_debug(task, "app '%V' prefork", &app->name);
30561998St.nateldemoura@f5.com
30571998St.nateldemoura@f5.com b = NULL;
30581998St.nateldemoura@f5.com port_fd = -1;
30591998St.nateldemoura@f5.com queue_fd = -1;
30602014Smax.romanov@nginx.com }
30612014Smax.romanov@nginx.com
30621998St.nateldemoura@f5.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
30631998St.nateldemoura@f5.com
30641998St.nateldemoura@f5.com rpc = nxt_port_rpc_register_handler_ex(task, router_port,
30651998St.nateldemoura@f5.com nxt_router_app_prefork_ready,
30661998St.nateldemoura@f5.com nxt_router_app_prefork_error,
30671998St.nateldemoura@f5.com sizeof(nxt_app_rpc_t));
30681998St.nateldemoura@f5.com if (nxt_slow_path(rpc == NULL)) {
30691998St.nateldemoura@f5.com goto fail;
30701998St.nateldemoura@f5.com }
3071507Smax.romanov@nginx.com
3072507Smax.romanov@nginx.com rpc->app = app;
3073507Smax.romanov@nginx.com rpc->temp_conf = tmcf;
3074507Smax.romanov@nginx.com rpc->proto = (b != NULL);
3075507Smax.romanov@nginx.com
30761998St.nateldemoura@f5.com stream = nxt_port_rpc_ex_stream(rpc);
30771998St.nateldemoura@f5.com
30781998St.nateldemoura@f5.com ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS,
30791998St.nateldemoura@f5.com port_fd, queue_fd, stream, router_port->id, b);
30802014Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
30812014Smax.romanov@nginx.com nxt_port_rpc_cancel(task, router_port, stream);
3082648Svbart@nginx.com goto fail;
3083648Svbart@nginx.com }
3084648Svbart@nginx.com
3085648Svbart@nginx.com if (b == NULL) {
3086648Svbart@nginx.com nxt_port_rpc_ex_set_peer(task, router_port, rpc, dport->pid);
30871998St.nateldemoura@f5.com
30881998St.nateldemoura@f5.com app->pending_processes++;
30891998St.nateldemoura@f5.com }
30901998St.nateldemoura@f5.com
30911998St.nateldemoura@f5.com return;
3092507Smax.romanov@nginx.com
3093507Smax.romanov@nginx.com fail:
3094507Smax.romanov@nginx.com
3095507Smax.romanov@nginx.com nxt_router_conf_error(task, tmcf);
3096507Smax.romanov@nginx.com }
3097507Smax.romanov@nginx.com
3098507Smax.romanov@nginx.com
3099507Smax.romanov@nginx.com static void
nxt_router_app_prefork_ready(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)3100507Smax.romanov@nginx.com nxt_router_app_prefork_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
3101507Smax.romanov@nginx.com void *data)
3102507Smax.romanov@nginx.com {
3103507Smax.romanov@nginx.com nxt_app_t *app;
3104507Smax.romanov@nginx.com nxt_port_t *port;
3105507Smax.romanov@nginx.com nxt_app_rpc_t *rpc;
3106507Smax.romanov@nginx.com nxt_event_engine_t *engine;
3107507Smax.romanov@nginx.com
3108507Smax.romanov@nginx.com rpc = data;
3109507Smax.romanov@nginx.com app = rpc->app;
3110507Smax.romanov@nginx.com
3111507Smax.romanov@nginx.com port = msg->u.new_port;
3112507Smax.romanov@nginx.com
3113507Smax.romanov@nginx.com nxt_assert(port != NULL);
31141547Smax.romanov@nginx.com nxt_assert(port->id == 0);
31151547Smax.romanov@nginx.com
31161998St.nateldemoura@f5.com if (rpc->proto) {
31171998St.nateldemoura@f5.com nxt_assert(app->proto_port == NULL);
31181998St.nateldemoura@f5.com nxt_assert(port->type == NXT_PROCESS_PROTOTYPE);
31191998St.nateldemoura@f5.com
31201998St.nateldemoura@f5.com nxt_port_inc_use(port);
31211998St.nateldemoura@f5.com
31221998St.nateldemoura@f5.com app->proto_port = port;
31231998St.nateldemoura@f5.com port->app = app;
31241998St.nateldemoura@f5.com
31251998St.nateldemoura@f5.com nxt_router_app_rpc_create(task, rpc->temp_conf, app);
31261998St.nateldemoura@f5.com
31271998St.nateldemoura@f5.com return;
31281998St.nateldemoura@f5.com }
31291998St.nateldemoura@f5.com
31301998St.nateldemoura@f5.com nxt_assert(port->type == NXT_PROCESS_APP);
31311998St.nateldemoura@f5.com
31321547Smax.romanov@nginx.com port->app = app;
31331547Smax.romanov@nginx.com port->main_app_port = port;
3134507Smax.romanov@nginx.com
31351547Smax.romanov@nginx.com app->pending_processes--;
3136507Smax.romanov@nginx.com app->processes++;
3137507Smax.romanov@nginx.com app->idle_processes++;
3138507Smax.romanov@nginx.com
3139507Smax.romanov@nginx.com engine = task->thread->engine;
3140507Smax.romanov@nginx.com
3141507Smax.romanov@nginx.com nxt_queue_insert_tail(&app->ports, &port->app_link);
3142507Smax.romanov@nginx.com nxt_queue_insert_tail(&app->spare_ports, &port->idle_link);
3143507Smax.romanov@nginx.com
3144507Smax.romanov@nginx.com nxt_debug(task, "app '%V' move new port %PI:%d to spare_ports",
31451549Smax.romanov@nginx.com &app->name, port->pid, port->id);
31461549Smax.romanov@nginx.com
31471549Smax.romanov@nginx.com nxt_port_hash_add(&app->port_hash, port);
31481549Smax.romanov@nginx.com app->port_hash_count++;
31491547Smax.romanov@nginx.com
31501547Smax.romanov@nginx.com port->idle_start = 0;
3151507Smax.romanov@nginx.com
3152507Smax.romanov@nginx.com nxt_port_inc_use(port);
3153507Smax.romanov@nginx.com
3154507Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL);
3155507Smax.romanov@nginx.com
31562014Smax.romanov@nginx.com nxt_work_queue_add(&engine->fast_work_queue,
31571547Smax.romanov@nginx.com nxt_router_conf_apply, task, rpc->temp_conf, NULL);
3158507Smax.romanov@nginx.com }
3159507Smax.romanov@nginx.com
3160507Smax.romanov@nginx.com
3161507Smax.romanov@nginx.com static void
nxt_router_app_prefork_error(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)3162507Smax.romanov@nginx.com nxt_router_app_prefork_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
3163507Smax.romanov@nginx.com void *data)
3164507Smax.romanov@nginx.com {
3165507Smax.romanov@nginx.com nxt_app_t *app;
3166507Smax.romanov@nginx.com nxt_app_rpc_t *rpc;
3167507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf;
3168507Smax.romanov@nginx.com
3169507Smax.romanov@nginx.com rpc = data;
3170507Smax.romanov@nginx.com app = rpc->app;
3171507Smax.romanov@nginx.com tmcf = rpc->temp_conf;
3172507Smax.romanov@nginx.com
3173507Smax.romanov@nginx.com if (rpc->proto) {
3174507Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "failed to start prototype \"%V\"",
31751998St.nateldemoura@f5.com &app->name);
31761998St.nateldemoura@f5.com
31771998St.nateldemoura@f5.com } else {
31781998St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "failed to start application \"%V\"",
31791998St.nateldemoura@f5.com &app->name);
31801998St.nateldemoura@f5.com
31811998St.nateldemoura@f5.com app->pending_processes--;
31821998St.nateldemoura@f5.com }
31831998St.nateldemoura@f5.com
31841998St.nateldemoura@f5.com nxt_router_conf_error(task, tmcf);
3185507Smax.romanov@nginx.com }
3186507Smax.romanov@nginx.com
3187507Smax.romanov@nginx.com
3188507Smax.romanov@nginx.com static nxt_int_t
nxt_router_engines_create(nxt_task_t * task,nxt_router_t * router,nxt_router_temp_conf_t * tmcf,const nxt_event_interface_t * interface)3189507Smax.romanov@nginx.com nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router,
319053Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface)
319153Sigor@sysoev.ru {
319253Sigor@sysoev.ru nxt_int_t ret;
319353Sigor@sysoev.ru nxt_uint_t n, threads;
319453Sigor@sysoev.ru nxt_queue_link_t *qlk;
319553Sigor@sysoev.ru nxt_router_engine_conf_t *recf;
319653Sigor@sysoev.ru
319753Sigor@sysoev.ru threads = tmcf->router_conf->threads;
319853Sigor@sysoev.ru
3199591Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads,
320053Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t));
320153Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) {
320253Sigor@sysoev.ru return NXT_ERROR;
320353Sigor@sysoev.ru }
320453Sigor@sysoev.ru
320553Sigor@sysoev.ru n = 0;
320653Sigor@sysoev.ru
320753Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines);
320853Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines);
320953Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
321053Sigor@sysoev.ru {
321153Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines);
321253Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) {
321353Sigor@sysoev.ru return NXT_ERROR;
321453Sigor@sysoev.ru }
321553Sigor@sysoev.ru
321653Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0);
321753Sigor@sysoev.ru
3218115Sigor@sysoev.ru if (n < threads) {
321953Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_KEEP;
322053Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf);
3221315Sigor@sysoev.ru
3222115Sigor@sysoev.ru } else {
322353Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_DELETE;
322453Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf);
3225315Sigor@sysoev.ru }
3226115Sigor@sysoev.ru
322753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
322853Sigor@sysoev.ru return ret;
322953Sigor@sysoev.ru }
323053Sigor@sysoev.ru
323153Sigor@sysoev.ru n++;
323253Sigor@sysoev.ru }
323353Sigor@sysoev.ru
323453Sigor@sysoev.ru tmcf->new_threads = n;
323553Sigor@sysoev.ru
323653Sigor@sysoev.ru while (n < threads) {
323753Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines);
323853Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) {
323953Sigor@sysoev.ru return NXT_ERROR;
324053Sigor@sysoev.ru }
324153Sigor@sysoev.ru
324253Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_ADD;
324353Sigor@sysoev.ru
3244315Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0);
3245315Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) {
324653Sigor@sysoev.ru return NXT_ERROR;
324753Sigor@sysoev.ru }
324853Sigor@sysoev.ru
324953Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf);
325053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3251115Sigor@sysoev.ru return ret;
325253Sigor@sysoev.ru }
325353Sigor@sysoev.ru
325453Sigor@sysoev.ru n++;
325553Sigor@sysoev.ru }
325653Sigor@sysoev.ru
325753Sigor@sysoev.ru return NXT_OK;
325853Sigor@sysoev.ru }
325953Sigor@sysoev.ru
326053Sigor@sysoev.ru
326153Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_conf_create(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf)326253Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf,
326353Sigor@sysoev.ru nxt_router_engine_conf_t *recf)
3264115Sigor@sysoev.ru {
3265115Sigor@sysoev.ru nxt_int_t ret;
326653Sigor@sysoev.ru
3267359Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets,
326853Sigor@sysoev.ru nxt_router_listen_socket_create);
32691509Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3270154Sigor@sysoev.ru return ret;
3271115Sigor@sysoev.ru }
3272115Sigor@sysoev.ru
3273115Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets,
3274115Sigor@sysoev.ru nxt_router_listen_socket_create);
32751509Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3276154Sigor@sysoev.ru return ret;
327753Sigor@sysoev.ru }
327853Sigor@sysoev.ru
327953Sigor@sysoev.ru return ret;
328053Sigor@sysoev.ru }
3281115Sigor@sysoev.ru
328253Sigor@sysoev.ru
328353Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_conf_update(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf)328453Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf,
328553Sigor@sysoev.ru nxt_router_engine_conf_t *recf)
3286115Sigor@sysoev.ru {
3287115Sigor@sysoev.ru nxt_int_t ret;
328853Sigor@sysoev.ru
3289359Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets,
329053Sigor@sysoev.ru nxt_router_listen_socket_create);
32911509Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3292154Sigor@sysoev.ru return ret;
329353Sigor@sysoev.ru }
329453Sigor@sysoev.ru
329553Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets,
329653Sigor@sysoev.ru nxt_router_listen_socket_update);
32971509Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3298154Sigor@sysoev.ru return ret;
329953Sigor@sysoev.ru }
330053Sigor@sysoev.ru
330153Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets);
330253Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
33031509Sigor@sysoev.ru return ret;
3304115Sigor@sysoev.ru }
3305115Sigor@sysoev.ru
3306115Sigor@sysoev.ru return ret;
3307115Sigor@sysoev.ru }
3308115Sigor@sysoev.ru
330953Sigor@sysoev.ru
331053Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_conf_delete(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf)331153Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf,
331253Sigor@sysoev.ru nxt_router_engine_conf_t *recf)
3313115Sigor@sysoev.ru {
3314115Sigor@sysoev.ru nxt_int_t ret;
331553Sigor@sysoev.ru
331653Sigor@sysoev.ru ret = nxt_router_engine_quit(tmcf, recf);
331753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
3318313Sigor@sysoev.ru return ret;
3319313Sigor@sysoev.ru }
3320313Sigor@sysoev.ru
3321313Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &updating_sockets);
3322313Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
33231509Sigor@sysoev.ru return ret;
332453Sigor@sysoev.ru }
332553Sigor@sysoev.ru
332653Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets);
332753Sigor@sysoev.ru }
33281509Sigor@sysoev.ru
332953Sigor@sysoev.ru
333053Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_joints_create(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf,nxt_queue_t * sockets,nxt_work_handler_t handler)333153Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf,
333253Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets,
3333154Sigor@sysoev.ru nxt_work_handler_t handler)
3334154Sigor@sysoev.ru {
333553Sigor@sysoev.ru nxt_int_t ret;
333653Sigor@sysoev.ru nxt_joint_job_t *job;
33371394Sigor@sysoev.ru nxt_queue_link_t *qlk;
3338153Sigor@sysoev.ru nxt_socket_conf_t *skcf;
333953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint;
3340155Sigor@sysoev.ru
334153Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets);
334253Sigor@sysoev.ru qlk != nxt_queue_tail(sockets);
334353Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
334453Sigor@sysoev.ru {
334553Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t));
334653Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) {
3347154Sigor@sysoev.ru return NXT_ERROR;
3348153Sigor@sysoev.ru }
3349139Sigor@sysoev.ru
3350139Sigor@sysoev.ru job->work.next = recf->jobs;
3351139Sigor@sysoev.ru recf->jobs = &job->work;
3352154Sigor@sysoev.ru
3353154Sigor@sysoev.ru job->task = tmcf->engine->task;
3354154Sigor@sysoev.ru job->work.handler = handler;
3355153Sigor@sysoev.ru job->work.task = &job->task;
3356153Sigor@sysoev.ru job->work.obj = job;
3357153Sigor@sysoev.ru job->tmcf = tmcf;
3358153Sigor@sysoev.ru
3359153Sigor@sysoev.ru tmcf->count++;
336053Sigor@sysoev.ru
3361154Sigor@sysoev.ru joint = nxt_mp_alloc(tmcf->router_conf->mem_pool,
3362154Sigor@sysoev.ru sizeof(nxt_socket_conf_joint_t));
3363591Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) {
3364154Sigor@sysoev.ru return NXT_ERROR;
336553Sigor@sysoev.ru }
336653Sigor@sysoev.ru
336753Sigor@sysoev.ru job->work.data = joint;
336853Sigor@sysoev.ru
3369153Sigor@sysoev.ru ret = nxt_upstreams_joint_create(tmcf, &joint->upstreams);
337053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
33711394Sigor@sysoev.ru return ret;
33721394Sigor@sysoev.ru }
33731394Sigor@sysoev.ru
33741394Sigor@sysoev.ru joint->count = 1;
33751394Sigor@sysoev.ru
337653Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
3377155Sigor@sysoev.ru skcf->count++;
3378155Sigor@sysoev.ru joint->socket_conf = skcf;
3379155Sigor@sysoev.ru
3380155Sigor@sysoev.ru joint->engine = recf->engine;
3381155Sigor@sysoev.ru }
338288Smax.romanov@nginx.com
338353Sigor@sysoev.ru return NXT_OK;
338453Sigor@sysoev.ru }
338520Sigor@sysoev.ru
338620Sigor@sysoev.ru
338720Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_quit(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf)338820Sigor@sysoev.ru nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf,
338920Sigor@sysoev.ru nxt_router_engine_conf_t *recf)
3390313Sigor@sysoev.ru {
3391313Sigor@sysoev.ru nxt_joint_job_t *job;
3392313Sigor@sysoev.ru
3393313Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t));
3394313Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) {
3395313Sigor@sysoev.ru return NXT_ERROR;
3396313Sigor@sysoev.ru }
3397313Sigor@sysoev.ru
3398313Sigor@sysoev.ru job->work.next = recf->jobs;
3399313Sigor@sysoev.ru recf->jobs = &job->work;
3400313Sigor@sysoev.ru
3401313Sigor@sysoev.ru job->task = tmcf->engine->task;
3402313Sigor@sysoev.ru job->work.handler = nxt_router_worker_thread_quit;
3403313Sigor@sysoev.ru job->work.task = &job->task;
3404313Sigor@sysoev.ru job->work.obj = NULL;
3405313Sigor@sysoev.ru job->work.data = NULL;
3406313Sigor@sysoev.ru job->tmcf = NULL;
3407313Sigor@sysoev.ru
3408313Sigor@sysoev.ru return NXT_OK;
3409313Sigor@sysoev.ru }
3410313Sigor@sysoev.ru
3411313Sigor@sysoev.ru
3412313Sigor@sysoev.ru static nxt_int_t
nxt_router_engine_joints_delete(nxt_router_temp_conf_t * tmcf,nxt_router_engine_conf_t * recf,nxt_queue_t * sockets)3413313Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
3414313Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets)
3415139Sigor@sysoev.ru {
3416139Sigor@sysoev.ru nxt_joint_job_t *job;
341720Sigor@sysoev.ru nxt_queue_link_t *qlk;
3418153Sigor@sysoev.ru
341953Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets);
342020Sigor@sysoev.ru qlk != nxt_queue_tail(sockets);
342153Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
342253Sigor@sysoev.ru {
342353Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t));
342453Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) {
3425154Sigor@sysoev.ru return NXT_ERROR;
3426153Sigor@sysoev.ru }
3427139Sigor@sysoev.ru
3428139Sigor@sysoev.ru job->work.next = recf->jobs;
3429139Sigor@sysoev.ru recf->jobs = &job->work;
3430154Sigor@sysoev.ru
3431154Sigor@sysoev.ru job->task = tmcf->engine->task;
3432154Sigor@sysoev.ru job->work.handler = nxt_router_listen_socket_delete;
3433153Sigor@sysoev.ru job->work.task = &job->task;
3434153Sigor@sysoev.ru job->work.obj = job;
3435153Sigor@sysoev.ru job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
3436153Sigor@sysoev.ru job->tmcf = tmcf;
3437153Sigor@sysoev.ru
3438153Sigor@sysoev.ru tmcf->count++;
3439154Sigor@sysoev.ru }
3440154Sigor@sysoev.ru
344120Sigor@sysoev.ru return NXT_OK;
344220Sigor@sysoev.ru }
344353Sigor@sysoev.ru
344453Sigor@sysoev.ru
344520Sigor@sysoev.ru static nxt_int_t
nxt_router_threads_create(nxt_task_t * task,nxt_runtime_t * rt,nxt_router_temp_conf_t * tmcf)344620Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
344753Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf)
344853Sigor@sysoev.ru {
344953Sigor@sysoev.ru nxt_int_t ret;
345053Sigor@sysoev.ru nxt_uint_t i, threads;
345153Sigor@sysoev.ru nxt_router_engine_conf_t *recf;
345253Sigor@sysoev.ru
345353Sigor@sysoev.ru recf = tmcf->engines->elts;
345420Sigor@sysoev.ru threads = tmcf->router_conf->threads;
345553Sigor@sysoev.ru
3456591Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) {
345720Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine);
345853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
345953Sigor@sysoev.ru return ret;
346053Sigor@sysoev.ru }
346153Sigor@sysoev.ru }
346253Sigor@sysoev.ru
346320Sigor@sysoev.ru return NXT_OK;
346420Sigor@sysoev.ru }
346520Sigor@sysoev.ru
346620Sigor@sysoev.ru
346753Sigor@sysoev.ru static nxt_int_t
nxt_router_thread_create(nxt_task_t * task,nxt_runtime_t * rt,nxt_event_engine_t * engine)346853Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
346953Sigor@sysoev.ru nxt_event_engine_t *engine)
347053Sigor@sysoev.ru {
347153Sigor@sysoev.ru nxt_int_t ret;
347253Sigor@sysoev.ru nxt_thread_link_t *link;
347353Sigor@sysoev.ru nxt_thread_handle_t handle;
347453Sigor@sysoev.ru
347553Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t));
347653Sigor@sysoev.ru
347753Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) {
347853Sigor@sysoev.ru return NXT_ERROR;
347953Sigor@sysoev.ru }
348053Sigor@sysoev.ru
348153Sigor@sysoev.ru link->start = nxt_router_thread_start;
348253Sigor@sysoev.ru link->engine = engine;
348353Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler;
348453Sigor@sysoev.ru link->work.task = task;
348553Sigor@sysoev.ru link->work.data = link;
348653Sigor@sysoev.ru
348753Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link);
348853Sigor@sysoev.ru
348953Sigor@sysoev.ru ret = nxt_thread_create(&handle, link);
349053Sigor@sysoev.ru
349153Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
349253Sigor@sysoev.ru nxt_queue_remove(&engine->link);
349353Sigor@sysoev.ru }
349453Sigor@sysoev.ru
349553Sigor@sysoev.ru return ret;
349653Sigor@sysoev.ru }
349753Sigor@sysoev.ru
349853Sigor@sysoev.ru
349953Sigor@sysoev.ru static void
nxt_router_apps_sort(nxt_task_t * task,nxt_router_t * router,nxt_router_temp_conf_t * tmcf)350053Sigor@sysoev.ru nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router,
350153Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf)
3502343Smax.romanov@nginx.com {
3503343Smax.romanov@nginx.com nxt_app_t *app;
3504133Sigor@sysoev.ru
3505507Smax.romanov@nginx.com nxt_queue_each(app, &router->apps, nxt_app_t, link) {
3506141Smax.romanov@nginx.com
3507141Smax.romanov@nginx.com nxt_router_app_unlink(task, app);
3508133Sigor@sysoev.ru
3509753Smax.romanov@nginx.com } nxt_queue_loop;
3510343Smax.romanov@nginx.com
3511141Smax.romanov@nginx.com nxt_queue_add(&router->apps, &tmcf->previous);
3512133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps);
3513133Sigor@sysoev.ru }
3514133Sigor@sysoev.ru
3515133Sigor@sysoev.ru
3516133Sigor@sysoev.ru static void
nxt_router_engines_post(nxt_router_t * router,nxt_router_temp_conf_t * tmcf)3517133Sigor@sysoev.ru nxt_router_engines_post(nxt_router_t *router, nxt_router_temp_conf_t *tmcf)
3518133Sigor@sysoev.ru {
3519315Sigor@sysoev.ru nxt_uint_t n;
352053Sigor@sysoev.ru nxt_event_engine_t *engine;
352153Sigor@sysoev.ru nxt_router_engine_conf_t *recf;
3522315Sigor@sysoev.ru
352353Sigor@sysoev.ru recf = tmcf->engines->elts;
352453Sigor@sysoev.ru
352553Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) {
352653Sigor@sysoev.ru engine = recf->engine;
352753Sigor@sysoev.ru
3528315Sigor@sysoev.ru switch (recf->action) {
3529315Sigor@sysoev.ru
3530315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_KEEP:
3531315Sigor@sysoev.ru break;
3532315Sigor@sysoev.ru
3533315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_ADD:
3534315Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &engine->link0);
3535315Sigor@sysoev.ru break;
3536315Sigor@sysoev.ru
3537315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_DELETE:
3538315Sigor@sysoev.ru nxt_queue_remove(&engine->link0);
3539315Sigor@sysoev.ru break;
3540315Sigor@sysoev.ru }
3541315Sigor@sysoev.ru
3542315Sigor@sysoev.ru nxt_router_engine_post(engine, recf->jobs);
3543315Sigor@sysoev.ru
3544316Sigor@sysoev.ru recf++;
3545316Sigor@sysoev.ru }
354653Sigor@sysoev.ru }
354753Sigor@sysoev.ru
354853Sigor@sysoev.ru
354953Sigor@sysoev.ru static void
nxt_router_engine_post(nxt_event_engine_t * engine,nxt_work_t * jobs)355053Sigor@sysoev.ru nxt_router_engine_post(nxt_event_engine_t *engine, nxt_work_t *jobs)
355153Sigor@sysoev.ru {
3552315Sigor@sysoev.ru nxt_work_t *work, *next;
355353Sigor@sysoev.ru
3554154Sigor@sysoev.ru for (work = jobs; work != NULL; work = next) {
3555154Sigor@sysoev.ru next = work->next;
3556315Sigor@sysoev.ru work->next = NULL;
3557154Sigor@sysoev.ru
3558154Sigor@sysoev.ru nxt_event_engine_post(engine, work);
3559154Sigor@sysoev.ru }
3560315Sigor@sysoev.ru }
356153Sigor@sysoev.ru
356253Sigor@sysoev.ru
356353Sigor@sysoev.ru static nxt_port_handlers_t nxt_router_app_port_handlers = {
356453Sigor@sysoev.ru .rpc_error = nxt_port_rpc_handler,
3565320Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler,
35661547Smax.romanov@nginx.com .data = nxt_port_rpc_handler,
35671547Smax.romanov@nginx.com .oosm = nxt_router_oosm_handler,
35681547Smax.romanov@nginx.com .req_headers_ack = nxt_port_rpc_handler,
35691547Smax.romanov@nginx.com };
35701547Smax.romanov@nginx.com
357188Smax.romanov@nginx.com
357288Smax.romanov@nginx.com static void
nxt_router_thread_start(void * data)357388Smax.romanov@nginx.com nxt_router_thread_start(void *data)
357488Smax.romanov@nginx.com {
357553Sigor@sysoev.ru nxt_int_t ret;
357653Sigor@sysoev.ru nxt_port_t *port;
3577141Smax.romanov@nginx.com nxt_task_t *task;
3578141Smax.romanov@nginx.com nxt_work_t *work;
357988Smax.romanov@nginx.com nxt_thread_t *thread;
35801545Smax.romanov@nginx.com nxt_thread_link_t *link;
358153Sigor@sysoev.ru nxt_event_engine_t *engine;
358253Sigor@sysoev.ru
358353Sigor@sysoev.ru link = data;
358453Sigor@sysoev.ru engine = link->engine;
358553Sigor@sysoev.ru task = &engine->task;
358653Sigor@sysoev.ru
358788Smax.romanov@nginx.com thread = nxt_thread();
358853Sigor@sysoev.ru
358953Sigor@sysoev.ru nxt_event_engine_thread_adopt(engine);
359053Sigor@sysoev.ru
3591165Smax.romanov@nginx.com /* STUB */
3592165Smax.romanov@nginx.com thread->runtime = engine->task.thread->runtime;
359353Sigor@sysoev.ru
359453Sigor@sysoev.ru engine->task.thread = thread;
359553Sigor@sysoev.ru engine->task.log = thread->log;
359653Sigor@sysoev.ru thread->engine = engine;
359753Sigor@sysoev.ru thread->task = &engine->task;
359853Sigor@sysoev.ru #if 0
359963Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber;
3600326Svbart@nginx.com #endif
360153Sigor@sysoev.ru
3602326Svbart@nginx.com engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64);
360353Sigor@sysoev.ru if (nxt_slow_path(engine->mem_pool == NULL)) {
360463Sigor@sysoev.ru return;
3605337Sigor@sysoev.ru }
3606337Sigor@sysoev.ru
3607337Sigor@sysoev.ru port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid,
360853Sigor@sysoev.ru NXT_PROCESS_ROUTER);
3609197Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) {
3610197Smax.romanov@nginx.com return;
3611141Smax.romanov@nginx.com }
3612141Smax.romanov@nginx.com
3613141Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0);
3614141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
3615141Smax.romanov@nginx.com nxt_port_use(task, port, -1);
3616141Smax.romanov@nginx.com return;
3617343Smax.romanov@nginx.com }
3618141Smax.romanov@nginx.com
3619141Smax.romanov@nginx.com ret = nxt_router_port_queue_init(task, port);
3620141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
36211555Smax.romanov@nginx.com nxt_port_use(task, port, -1);
36221555Smax.romanov@nginx.com return;
36231555Smax.romanov@nginx.com }
36241555Smax.romanov@nginx.com
36251555Smax.romanov@nginx.com engine->port = port;
36261555Smax.romanov@nginx.com
3627141Smax.romanov@nginx.com nxt_port_enable(task, port, &nxt_router_app_port_handlers);
3628141Smax.romanov@nginx.com
3629320Smax.romanov@nginx.com work = nxt_zalloc(sizeof(nxt_work_t));
3630141Smax.romanov@nginx.com if (nxt_slow_path(work == NULL)) {
36311545Smax.romanov@nginx.com return;
36321545Smax.romanov@nginx.com }
36331545Smax.romanov@nginx.com
36341545Smax.romanov@nginx.com work->handler = nxt_router_rt_add_port;
36351545Smax.romanov@nginx.com work->task = link->work.task;
36361545Smax.romanov@nginx.com work->obj = work;
36371545Smax.romanov@nginx.com work->data = port;
36381545Smax.romanov@nginx.com
36391545Smax.romanov@nginx.com nxt_event_engine_post(link->work.task->thread->engine, work);
36401545Smax.romanov@nginx.com
36411545Smax.romanov@nginx.com nxt_event_engine_start(engine);
36421545Smax.romanov@nginx.com }
364353Sigor@sysoev.ru
364453Sigor@sysoev.ru
364553Sigor@sysoev.ru static void
nxt_router_rt_add_port(nxt_task_t * task,void * obj,void * data)364653Sigor@sysoev.ru nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data)
364753Sigor@sysoev.ru {
36481545Smax.romanov@nginx.com nxt_int_t res;
36491545Smax.romanov@nginx.com nxt_port_t *port;
36501545Smax.romanov@nginx.com nxt_runtime_t *rt;
36511545Smax.romanov@nginx.com
36521545Smax.romanov@nginx.com rt = task->thread->runtime;
36531545Smax.romanov@nginx.com port = data;
36541545Smax.romanov@nginx.com
36551545Smax.romanov@nginx.com nxt_free(obj);
36561545Smax.romanov@nginx.com
36571545Smax.romanov@nginx.com res = nxt_port_hash_add(&rt->ports, port);
36581545Smax.romanov@nginx.com
36591545Smax.romanov@nginx.com if (nxt_fast_path(res == NXT_OK)) {
36601545Smax.romanov@nginx.com nxt_port_use(task, port, 1);
36611545Smax.romanov@nginx.com }
36621545Smax.romanov@nginx.com }
36631545Smax.romanov@nginx.com
36641545Smax.romanov@nginx.com
36651545Smax.romanov@nginx.com static void
nxt_router_listen_socket_create(nxt_task_t * task,void * obj,void * data)36661545Smax.romanov@nginx.com nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data)
36671545Smax.romanov@nginx.com {
366853Sigor@sysoev.ru nxt_joint_job_t *job;
366953Sigor@sysoev.ru nxt_socket_conf_t *skcf;
3670153Sigor@sysoev.ru nxt_listen_event_t *lev;
3671359Sigor@sysoev.ru nxt_listen_socket_t *ls;
3672359Sigor@sysoev.ru nxt_thread_spinlock_t *lock;
367353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint;
3674359Sigor@sysoev.ru
367553Sigor@sysoev.ru job = obj;
367653Sigor@sysoev.ru joint = data;
3677153Sigor@sysoev.ru
367853Sigor@sysoev.ru nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link);
367953Sigor@sysoev.ru
3680159Sigor@sysoev.ru skcf = joint->socket_conf;
3681159Sigor@sysoev.ru ls = skcf->listen;
3682359Sigor@sysoev.ru
3683359Sigor@sysoev.ru lev = nxt_listen_event(task, ls);
3684359Sigor@sysoev.ru if (nxt_slow_path(lev == NULL)) {
3685359Sigor@sysoev.ru nxt_router_listen_socket_release(task, skcf);
3686359Sigor@sysoev.ru return;
3687359Sigor@sysoev.ru }
368853Sigor@sysoev.ru
368953Sigor@sysoev.ru lev->socket.data = joint;
369053Sigor@sysoev.ru
3691359Sigor@sysoev.ru lock = &skcf->router_conf->router->lock;
3692359Sigor@sysoev.ru
3693359Sigor@sysoev.ru nxt_thread_spin_lock(lock);
3694359Sigor@sysoev.ru ls->count++;
3695359Sigor@sysoev.ru nxt_thread_spin_unlock(lock);
3696359Sigor@sysoev.ru
3697359Sigor@sysoev.ru job->work.next = NULL;
3698139Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait;
3699153Sigor@sysoev.ru
3700153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work);
3701153Sigor@sysoev.ru }
3702153Sigor@sysoev.ru
370353Sigor@sysoev.ru
370453Sigor@sysoev.ru nxt_inline nxt_listen_event_t *
nxt_router_listen_event(nxt_queue_t * listen_connections,nxt_socket_conf_t * skcf)370553Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections,
370653Sigor@sysoev.ru nxt_socket_conf_t *skcf)
370753Sigor@sysoev.ru {
370853Sigor@sysoev.ru nxt_socket_t fd;
370953Sigor@sysoev.ru nxt_queue_link_t *qlk;
3710115Sigor@sysoev.ru nxt_listen_event_t *lev;
3711115Sigor@sysoev.ru
3712359Sigor@sysoev.ru fd = skcf->listen->socket;
3713359Sigor@sysoev.ru
3714359Sigor@sysoev.ru for (qlk = nxt_queue_first(listen_connections);
371553Sigor@sysoev.ru qlk != nxt_queue_tail(listen_connections);
3716115Sigor@sysoev.ru qlk = nxt_queue_next(qlk))
3717115Sigor@sysoev.ru {
3718115Sigor@sysoev.ru lev = nxt_queue_link_data(qlk, nxt_listen_event_t, link);
371953Sigor@sysoev.ru
3720359Sigor@sysoev.ru if (fd == lev->socket.fd) {
3721359Sigor@sysoev.ru return lev;
3722359Sigor@sysoev.ru }
3723359Sigor@sysoev.ru }
372453Sigor@sysoev.ru
372553Sigor@sysoev.ru return NULL;
372653Sigor@sysoev.ru }
372753Sigor@sysoev.ru
372853Sigor@sysoev.ru
372953Sigor@sysoev.ru static void
nxt_router_listen_socket_update(nxt_task_t * task,void * obj,void * data)373053Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data)
373153Sigor@sysoev.ru {
373253Sigor@sysoev.ru nxt_joint_job_t *job;
373353Sigor@sysoev.ru nxt_event_engine_t *engine;
3734153Sigor@sysoev.ru nxt_listen_event_t *lev;
373553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old;
3736359Sigor@sysoev.ru
373753Sigor@sysoev.ru job = obj;
373853Sigor@sysoev.ru joint = data;
3739153Sigor@sysoev.ru
374053Sigor@sysoev.ru engine = task->thread->engine;
374153Sigor@sysoev.ru
3742139Sigor@sysoev.ru nxt_queue_insert_tail(&engine->joints, &joint->link);
3743139Sigor@sysoev.ru
3744159Sigor@sysoev.ru lev = nxt_router_listen_event(&engine->listen_connections,
3745159Sigor@sysoev.ru joint->socket_conf);
3746359Sigor@sysoev.ru
3747359Sigor@sysoev.ru old = lev->socket.data;
3748359Sigor@sysoev.ru lev->socket.data = joint;
3749359Sigor@sysoev.ru lev->listen = joint->socket_conf->listen;
3750359Sigor@sysoev.ru
3751359Sigor@sysoev.ru job->work.next = NULL;
375253Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait;
3753153Sigor@sysoev.ru
3754153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work);
3755153Sigor@sysoev.ru
3756153Sigor@sysoev.ru /*
3757139Sigor@sysoev.ru * The task is allocated from configuration temporary
3758181Smax.romanov@nginx.com * memory pool so it can be freed after engine post operation.
3759181Smax.romanov@nginx.com */
3760181Smax.romanov@nginx.com
3761181Smax.romanov@nginx.com nxt_router_conf_release(&engine->task, old);
3762181Smax.romanov@nginx.com }
3763181Smax.romanov@nginx.com
376453Sigor@sysoev.ru
376553Sigor@sysoev.ru static void
nxt_router_listen_socket_delete(nxt_task_t * task,void * obj,void * data)376653Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data)
376753Sigor@sysoev.ru {
376853Sigor@sysoev.ru nxt_socket_conf_t *skcf;
376953Sigor@sysoev.ru nxt_listen_event_t *lev;
37701867Smax.romanov@nginx.com nxt_event_engine_t *engine;
37711867Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint;
37721867Smax.romanov@nginx.com
37731867Smax.romanov@nginx.com skcf = data;
37741867Smax.romanov@nginx.com
377553Sigor@sysoev.ru engine = task->thread->engine;
377653Sigor@sysoev.ru
3777139Sigor@sysoev.ru lev = nxt_router_listen_event(&engine->listen_connections, skcf);
3778139Sigor@sysoev.ru
3779359Sigor@sysoev.ru nxt_fd_event_delete(engine, &lev->socket);
3780359Sigor@sysoev.ru
3781359Sigor@sysoev.ru nxt_debug(task, "engine %p: listen socket delete: %d", engine,
378253Sigor@sysoev.ru lev->socket.fd);
3783163Smax.romanov@nginx.com
3784359Sigor@sysoev.ru joint = lev->socket.data;
3785359Sigor@sysoev.ru joint->close_job = obj;
37861867Smax.romanov@nginx.com
37871867Smax.romanov@nginx.com lev->timer.handler = nxt_router_listen_socket_close;
37881867Smax.romanov@nginx.com lev->timer.work_queue = &engine->fast_work_queue;
3789359Sigor@sysoev.ru
3790359Sigor@sysoev.ru nxt_timer_add(engine, &lev->timer, 0);
3791359Sigor@sysoev.ru }
3792359Sigor@sysoev.ru
379353Sigor@sysoev.ru
379453Sigor@sysoev.ru static void
nxt_router_worker_thread_quit(nxt_task_t * task,void * obj,void * data)379553Sigor@sysoev.ru nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, void *data)
379653Sigor@sysoev.ru {
3797313Sigor@sysoev.ru nxt_event_engine_t *engine;
3798313Sigor@sysoev.ru
3799313Sigor@sysoev.ru nxt_debug(task, "router worker thread quit");
3800313Sigor@sysoev.ru
3801313Sigor@sysoev.ru engine = task->thread->engine;
3802313Sigor@sysoev.ru
3803313Sigor@sysoev.ru engine->shutdown = 1;
3804313Sigor@sysoev.ru
3805313Sigor@sysoev.ru if (nxt_queue_is_empty(&engine->joints)) {
3806313Sigor@sysoev.ru nxt_thread_exit(task->thread);
3807313Sigor@sysoev.ru }
3808313Sigor@sysoev.ru }
3809313Sigor@sysoev.ru
3810313Sigor@sysoev.ru
3811313Sigor@sysoev.ru static void
nxt_router_listen_socket_close(nxt_task_t * task,void * obj,void * data)3812313Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data)
3813313Sigor@sysoev.ru {
381453Sigor@sysoev.ru nxt_timer_t *timer;
381553Sigor@sysoev.ru nxt_joint_job_t *job;
381653Sigor@sysoev.ru nxt_listen_event_t *lev;
38171867Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint;
3818359Sigor@sysoev.ru
381953Sigor@sysoev.ru timer = obj;
382053Sigor@sysoev.ru lev = nxt_timer_data(timer, nxt_listen_event_t, timer);
382153Sigor@sysoev.ru
3822359Sigor@sysoev.ru nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine,
382353Sigor@sysoev.ru lev->socket.fd);
3824163Smax.romanov@nginx.com
3825359Sigor@sysoev.ru nxt_queue_remove(&lev->link);
3826359Sigor@sysoev.ru
3827359Sigor@sysoev.ru joint = lev->socket.data;
3828359Sigor@sysoev.ru lev->socket.data = NULL;
3829683Sigor@sysoev.ru
3830683Sigor@sysoev.ru /* 'task' refers to lev->task and we cannot use after nxt_free() */
3831683Sigor@sysoev.ru task = &task->thread->engine->task;
38321881Smax.romanov@nginx.com
38331881Smax.romanov@nginx.com nxt_router_listen_socket_release(task, joint->socket_conf);
38341881Smax.romanov@nginx.com
38351881Smax.romanov@nginx.com job = joint->close_job;
38361881Smax.romanov@nginx.com job->work.next = NULL;
38371867Smax.romanov@nginx.com job->work.handler = nxt_router_conf_wait;
38381867Smax.romanov@nginx.com
38391867Smax.romanov@nginx.com nxt_event_engine_post(job->tmcf->engine, &job->work);
38401867Smax.romanov@nginx.com
38411867Smax.romanov@nginx.com nxt_router_listen_event_release(task, lev, joint);
38421867Smax.romanov@nginx.com }
3843683Sigor@sysoev.ru
384453Sigor@sysoev.ru
384553Sigor@sysoev.ru static void
nxt_router_listen_socket_release(nxt_task_t * task,nxt_socket_conf_t * skcf)384653Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf)
384753Sigor@sysoev.ru {
3848359Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
384953Sigor@sysoev.ru size_t size;
38502377Sa.clayton@nginx.com nxt_buf_t *b;
38512377Sa.clayton@nginx.com nxt_port_t *main_port;
38522377Sa.clayton@nginx.com nxt_runtime_t *rt;
38532377Sa.clayton@nginx.com nxt_sockaddr_t *sa;
38542377Sa.clayton@nginx.com #endif
38552377Sa.clayton@nginx.com nxt_listen_socket_t *ls;
38562377Sa.clayton@nginx.com nxt_thread_spinlock_t *lock;
3857359Sigor@sysoev.ru
385853Sigor@sysoev.ru ls = skcf->listen;
385953Sigor@sysoev.ru lock = &skcf->router_conf->router->lock;
3860359Sigor@sysoev.ru
3861118Sigor@sysoev.ru nxt_thread_spin_lock(lock);
386253Sigor@sysoev.ru
386353Sigor@sysoev.ru nxt_debug(task, "engine %p: listen socket release: ls->count %D",
386453Sigor@sysoev.ru task->thread->engine, ls->count);
3865359Sigor@sysoev.ru
3866359Sigor@sysoev.ru if (--ls->count != 0) {
3867359Sigor@sysoev.ru ls = NULL;
3868359Sigor@sysoev.ru }
3869359Sigor@sysoev.ru
387053Sigor@sysoev.ru nxt_thread_spin_unlock(lock);
387153Sigor@sysoev.ru
387253Sigor@sysoev.ru if (ls == NULL) {
387353Sigor@sysoev.ru return;
38742377Sa.clayton@nginx.com }
38752377Sa.clayton@nginx.com
38762377Sa.clayton@nginx.com nxt_socket_close(task, ls->socket);
38772377Sa.clayton@nginx.com
38782377Sa.clayton@nginx.com #if (NXT_HAVE_UNIX_DOMAIN)
38792377Sa.clayton@nginx.com sa = ls->sockaddr;
38802377Sa.clayton@nginx.com if (sa->u.sockaddr.sa_family != AF_UNIX
38812377Sa.clayton@nginx.com || sa->u.sockaddr_un.sun_path[0] == '\0')
38822377Sa.clayton@nginx.com {
38832377Sa.clayton@nginx.com goto out_free_ls;
38842377Sa.clayton@nginx.com }
38852377Sa.clayton@nginx.com
38862377Sa.clayton@nginx.com size = nxt_sockaddr_size(ls->sockaddr);
38872377Sa.clayton@nginx.com
38882377Sa.clayton@nginx.com b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0);
38892377Sa.clayton@nginx.com if (b == NULL) {
38902377Sa.clayton@nginx.com goto out_free_ls;
38912377Sa.clayton@nginx.com }
38922377Sa.clayton@nginx.com
38932377Sa.clayton@nginx.com b->mem.free = nxt_cpymem(b->mem.free, ls->sockaddr, size);
38942377Sa.clayton@nginx.com
38952377Sa.clayton@nginx.com rt = task->thread->runtime;
38962377Sa.clayton@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN];
38972377Sa.clayton@nginx.com
38982377Sa.clayton@nginx.com (void) nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET_UNLINK,
38992377Sa.clayton@nginx.com -1, 0, 0, b);
39002377Sa.clayton@nginx.com
39012377Sa.clayton@nginx.com out_free_ls:
39022377Sa.clayton@nginx.com #endif
39032377Sa.clayton@nginx.com nxt_free(ls);
39042377Sa.clayton@nginx.com }
39052377Sa.clayton@nginx.com
390653Sigor@sysoev.ru
390753Sigor@sysoev.ru void
nxt_router_listen_event_release(nxt_task_t * task,nxt_listen_event_t * lev,nxt_socket_conf_joint_t * joint)390853Sigor@sysoev.ru nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev,
3909683Sigor@sysoev.ru nxt_socket_conf_joint_t *joint)
3910683Sigor@sysoev.ru {
3911683Sigor@sysoev.ru nxt_event_engine_t *engine;
3912683Sigor@sysoev.ru
3913683Sigor@sysoev.ru nxt_debug(task, "listen event count: %D", lev->count);
3914683Sigor@sysoev.ru
3915683Sigor@sysoev.ru engine = task->thread->engine;
3916683Sigor@sysoev.ru
39171541Smax.romanov@nginx.com if (--lev->count == 0) {
39181541Smax.romanov@nginx.com if (lev->next != NULL) {
3919683Sigor@sysoev.ru nxt_sockaddr_cache_free(engine, lev->next);
39201535Smax.romanov@nginx.com
39211541Smax.romanov@nginx.com nxt_conn_free(task, lev->next);
39221541Smax.romanov@nginx.com }
39231535Smax.romanov@nginx.com
39241535Smax.romanov@nginx.com nxt_free(lev);
39251535Smax.romanov@nginx.com }
3926683Sigor@sysoev.ru
3927683Sigor@sysoev.ru if (joint != NULL) {
3928683Sigor@sysoev.ru nxt_router_conf_release(task, joint);
3929683Sigor@sysoev.ru }
3930683Sigor@sysoev.ru
3931683Sigor@sysoev.ru if (engine->shutdown && nxt_queue_is_empty(&engine->joints)) {
3932683Sigor@sysoev.ru nxt_thread_exit(task->thread);
3933683Sigor@sysoev.ru }
3934683Sigor@sysoev.ru }
3935683Sigor@sysoev.ru
3936683Sigor@sysoev.ru
3937683Sigor@sysoev.ru void
nxt_router_conf_release(nxt_task_t * task,nxt_socket_conf_joint_t * joint)3938683Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint)
3939683Sigor@sysoev.ru {
394053Sigor@sysoev.ru nxt_socket_conf_t *skcf;
394153Sigor@sysoev.ru nxt_router_conf_t *rtcf;
394253Sigor@sysoev.ru nxt_thread_spinlock_t *lock;
394353Sigor@sysoev.ru
394453Sigor@sysoev.ru nxt_debug(task, "conf joint %p count: %D", joint, joint->count);
394553Sigor@sysoev.ru
3946163Smax.romanov@nginx.com if (--joint->count != 0) {
394753Sigor@sysoev.ru return;
394853Sigor@sysoev.ru }
394953Sigor@sysoev.ru
395053Sigor@sysoev.ru nxt_queue_remove(&joint->link);
395153Sigor@sysoev.ru
395253Sigor@sysoev.ru /*
395353Sigor@sysoev.ru * The joint content can not be safely used after the critical
3954530Sigor@sysoev.ru * section protected by the spinlock because its memory pool may
3955530Sigor@sysoev.ru * be already destroyed by another thread.
3956530Sigor@sysoev.ru */
3957530Sigor@sysoev.ru skcf = joint->socket_conf;
3958530Sigor@sysoev.ru rtcf = skcf->router_conf;
395953Sigor@sysoev.ru lock = &rtcf->router->lock;
396053Sigor@sysoev.ru
396153Sigor@sysoev.ru nxt_thread_spin_lock(lock);
396253Sigor@sysoev.ru
396353Sigor@sysoev.ru nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count,
396453Sigor@sysoev.ru rtcf, rtcf->count);
3965163Smax.romanov@nginx.com
3966163Smax.romanov@nginx.com if (--skcf->count != 0) {
3967163Smax.romanov@nginx.com skcf = NULL;
396853Sigor@sysoev.ru rtcf = NULL;
3969952Sigor@sysoev.ru
397053Sigor@sysoev.ru } else {
397153Sigor@sysoev.ru nxt_queue_remove(&skcf->link);
397253Sigor@sysoev.ru
397353Sigor@sysoev.ru if (--rtcf->count != 0) {
397453Sigor@sysoev.ru rtcf = NULL;
397553Sigor@sysoev.ru }
397653Sigor@sysoev.ru }
397753Sigor@sysoev.ru
397853Sigor@sysoev.ru nxt_thread_spin_unlock(lock);
397953Sigor@sysoev.ru
398053Sigor@sysoev.ru #if (NXT_TLS)
398153Sigor@sysoev.ru if (skcf != NULL && skcf->tls != NULL) {
3982952Sigor@sysoev.ru task->thread->runtime->tls->server_free(task, skcf->tls);
39831563Svbart@nginx.com }
39841563Svbart@nginx.com #endif
39851563Svbart@nginx.com
3986952Sigor@sysoev.ru /* TODO remove engine->port */
3987952Sigor@sysoev.ru
3988141Smax.romanov@nginx.com if (rtcf != NULL) {
3989141Smax.romanov@nginx.com nxt_debug(task, "old router conf is destroyed");
399053Sigor@sysoev.ru
3991115Sigor@sysoev.ru nxt_router_apps_hash_use(task, rtcf, -1);
3992131Smax.romanov@nginx.com
39931563Svbart@nginx.com nxt_router_access_log_release(task, lock, rtcf->access_log);
3994964Sigor@sysoev.ru
3995630Svbart@nginx.com nxt_tstr_state_release(rtcf->tstr_state);
3996630Svbart@nginx.com
39972318Sz.hong@f5.com nxt_mp_thread_adopt(rtcf->mem_pool);
39982318Sz.hong@f5.com
3999131Smax.romanov@nginx.com nxt_mp_destroy(rtcf->mem_pool);
4000131Smax.romanov@nginx.com }
400165Sigor@sysoev.ru }
400253Sigor@sysoev.ru
400353Sigor@sysoev.ru
400453Sigor@sysoev.ru static void
nxt_router_thread_exit_handler(nxt_task_t * task,void * obj,void * data)400553Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data)
400653Sigor@sysoev.ru {
400753Sigor@sysoev.ru nxt_port_t *port;
400853Sigor@sysoev.ru nxt_thread_link_t *link;
4009141Smax.romanov@nginx.com nxt_event_engine_t *engine;
401053Sigor@sysoev.ru nxt_thread_handle_t handle;
401153Sigor@sysoev.ru
401253Sigor@sysoev.ru handle = (nxt_thread_handle_t) (uintptr_t) obj;
401353Sigor@sysoev.ru link = data;
40141810Smax.romanov@nginx.com
401553Sigor@sysoev.ru nxt_thread_wait(handle);
401653Sigor@sysoev.ru
401753Sigor@sysoev.ru engine = link->engine;
401853Sigor@sysoev.ru
401953Sigor@sysoev.ru nxt_queue_remove(&engine->link);
402053Sigor@sysoev.ru
402153Sigor@sysoev.ru port = engine->port;
402253Sigor@sysoev.ru
4023141Smax.romanov@nginx.com // TODO notify all apps
4024141Smax.romanov@nginx.com
4025141Smax.romanov@nginx.com port->engine = task->thread->engine;
4026141Smax.romanov@nginx.com nxt_mp_thread_adopt(port->mem_pool);
4027343Smax.romanov@nginx.com nxt_port_use(task, port, -1);
4028163Smax.romanov@nginx.com
4029343Smax.romanov@nginx.com nxt_mp_thread_adopt(engine->mem_pool);
4030163Smax.romanov@nginx.com nxt_mp_destroy(engine->mem_pool);
4031163Smax.romanov@nginx.com
403263Sigor@sysoev.ru nxt_event_engine_free(engine);
403353Sigor@sysoev.ru
403453Sigor@sysoev.ru nxt_free(link);
403553Sigor@sysoev.ru }
403653Sigor@sysoev.ru
403753Sigor@sysoev.ru
403853Sigor@sysoev.ru static void
nxt_router_response_ready_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)403953Sigor@sysoev.ru nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
404053Sigor@sysoev.ru void *data)
4041318Smax.romanov@nginx.com {
4042318Smax.romanov@nginx.com size_t b_size, count;
404388Smax.romanov@nginx.com nxt_int_t ret;
40441661Smax.romanov@nginx.com nxt_app_t *app;
40451123Smax.romanov@nginx.com nxt_buf_t *b, *next;
40461547Smax.romanov@nginx.com nxt_port_t *app_port;
40471269Sigor@sysoev.ru nxt_unit_field_t *f;
40481131Smax.romanov@nginx.com nxt_http_field_t *field;
40491123Smax.romanov@nginx.com nxt_http_request_t *r;
40501123Smax.romanov@nginx.com nxt_unit_response_t *resp;
40511123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data;
40521123Smax.romanov@nginx.com
40531123Smax.romanov@nginx.com req_rpc_data = data;
405488Smax.romanov@nginx.com
40551123Smax.romanov@nginx.com r = req_rpc_data->request;
405688Smax.romanov@nginx.com if (nxt_slow_path(r == NULL)) {
40571123Smax.romanov@nginx.com return;
40581007Salexander.borisov@nginx.com }
4059570Smax.romanov@nginx.com
4060570Smax.romanov@nginx.com if (r->error) {
4061425Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, req_rpc_data);
40621007Salexander.borisov@nginx.com return;
40631123Smax.romanov@nginx.com }
4064608Sigor@sysoev.ru
4065608Sigor@sysoev.ru app = req_rpc_data->app;
4066608Sigor@sysoev.ru nxt_assert(app != NULL);
40671547Smax.romanov@nginx.com
40681547Smax.romanov@nginx.com if (msg->port_msg.type == _NXT_PORT_MSG_REQ_HEADERS_ACK) {
40691547Smax.romanov@nginx.com nxt_router_req_headers_ack_handler(task, msg, req_rpc_data);
40701547Smax.romanov@nginx.com
40711547Smax.romanov@nginx.com return;
40721547Smax.romanov@nginx.com }
40731547Smax.romanov@nginx.com
40741547Smax.romanov@nginx.com b = (msg->size == 0) ? NULL : msg->buf;
40751547Smax.romanov@nginx.com
40761547Smax.romanov@nginx.com if (msg->port_msg.last != 0) {
40771547Smax.romanov@nginx.com nxt_debug(task, "router data create last buf");
407888Smax.romanov@nginx.com
407988Smax.romanov@nginx.com nxt_buf_chain_add(&b, nxt_http_buf_last(r));
408088Smax.romanov@nginx.com
40811007Salexander.borisov@nginx.com req_rpc_data->rpc_cancel = 0;
4082167Smax.romanov@nginx.com
40831547Smax.romanov@nginx.com if (req_rpc_data->apr_action == NXT_APR_REQUEST_FAILED) {
40841780Smax.romanov@nginx.com req_rpc_data->apr_action = NXT_APR_GOT_RESPONSE;
40851780Smax.romanov@nginx.com }
40861780Smax.romanov@nginx.com
40871780Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, req_rpc_data);
40881547Smax.romanov@nginx.com
40891123Smax.romanov@nginx.com } else {
4090425Smax.romanov@nginx.com if (app->timeout != 0) {
4091425Smax.romanov@nginx.com r->timer.handler = nxt_router_app_timeout;
40921547Smax.romanov@nginx.com r->timer_data = req_rpc_data;
40931007Salexander.borisov@nginx.com nxt_timer_add(task->thread->engine, &r->timer, app->timeout);
40941123Smax.romanov@nginx.com }
40951547Smax.romanov@nginx.com }
4096425Smax.romanov@nginx.com
409788Smax.romanov@nginx.com if (b == NULL) {
409888Smax.romanov@nginx.com return;
409988Smax.romanov@nginx.com }
410088Smax.romanov@nginx.com
410188Smax.romanov@nginx.com if (msg->buf == b) {
410288Smax.romanov@nginx.com /* Disable instant buffer completion/re-using by port. */
4103206Smax.romanov@nginx.com msg->buf = NULL;
4104206Smax.romanov@nginx.com }
4105206Smax.romanov@nginx.com
4106206Smax.romanov@nginx.com if (r->header_sent) {
4107194Smax.romanov@nginx.com nxt_buf_chain_add(&r->out, b);
4108431Sigor@sysoev.ru nxt_http_request_send_body(task, r, NULL);
4109431Sigor@sysoev.ru
4110431Sigor@sysoev.ru } else {
4111277Sigor@sysoev.ru b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0;
411288Smax.romanov@nginx.com
41131661Smax.romanov@nginx.com if (nxt_slow_path(b_size < sizeof(nxt_unit_response_t))) {
41141661Smax.romanov@nginx.com nxt_alert(task, "response buffer too small: %z", b_size);
41151661Smax.romanov@nginx.com goto fail;
41161661Smax.romanov@nginx.com }
4117743Smax.romanov@nginx.com
4118743Smax.romanov@nginx.com resp = (void *) b->mem.pos;
4119743Smax.romanov@nginx.com count = (b_size - sizeof(nxt_unit_response_t))
4120743Smax.romanov@nginx.com / sizeof(nxt_unit_field_t);
41211661Smax.romanov@nginx.com
41221661Smax.romanov@nginx.com if (nxt_slow_path(count < resp->fields_count)) {
41231661Smax.romanov@nginx.com nxt_alert(task, "response buffer too small for fields count: %D",
41241661Smax.romanov@nginx.com resp->fields_count);
41251661Smax.romanov@nginx.com goto fail;
41261661Smax.romanov@nginx.com }
4127743Smax.romanov@nginx.com
4128743Smax.romanov@nginx.com field = NULL;
4129743Smax.romanov@nginx.com
41301126Smax.romanov@nginx.com for (f = resp->fields; f < resp->fields + resp->fields_count; f++) {
41311126Smax.romanov@nginx.com if (f->skip) {
4132743Smax.romanov@nginx.com continue;
41331126Smax.romanov@nginx.com }
41341126Smax.romanov@nginx.com
41351126Smax.romanov@nginx.com field = nxt_list_add(r->resp.fields);
41361126Smax.romanov@nginx.com
41371007Salexander.borisov@nginx.com if (nxt_slow_path(field == NULL)) {
4138743Smax.romanov@nginx.com goto fail;
4139743Smax.romanov@nginx.com }
4140743Smax.romanov@nginx.com
4141743Smax.romanov@nginx.com field->hash = f->hash;
4142743Smax.romanov@nginx.com field->skip = 0;
4143743Smax.romanov@nginx.com field->hopbyhop = 0;
41441126Smax.romanov@nginx.com
41451270Sigor@sysoev.ru field->name_length = f->name_length;
4146743Smax.romanov@nginx.com field->value_length = f->value_length;
4147743Smax.romanov@nginx.com field->name = nxt_unit_sptr_get(&f->name);
4148743Smax.romanov@nginx.com field->value = nxt_unit_sptr_get(&f->value);
4149743Smax.romanov@nginx.com
4150743Smax.romanov@nginx.com ret = nxt_http_field_process(field, &nxt_response_fields_hash, r);
4151743Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) {
41521126Smax.romanov@nginx.com goto fail;
41531126Smax.romanov@nginx.com }
41541126Smax.romanov@nginx.com
41551126Smax.romanov@nginx.com nxt_debug(task, "header%s: %*s: %*s",
41561126Smax.romanov@nginx.com (field->skip ? " skipped" : ""),
41571126Smax.romanov@nginx.com (size_t) field->name_length, field->name,
41581126Smax.romanov@nginx.com (size_t) field->value_length, field->value);
4159743Smax.romanov@nginx.com
4160743Smax.romanov@nginx.com if (field->skip) {
41611126Smax.romanov@nginx.com r->resp.fields->last->nelts--;
41621126Smax.romanov@nginx.com }
41631126Smax.romanov@nginx.com }
41641126Smax.romanov@nginx.com
4165743Smax.romanov@nginx.com r->status = resp->status;
41661007Salexander.borisov@nginx.com
4167743Smax.romanov@nginx.com if (resp->piggyback_content_length != 0) {
4168743Smax.romanov@nginx.com b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content);
4169743Smax.romanov@nginx.com b->mem.free = b->mem.pos + resp->piggyback_content_length;
4170743Smax.romanov@nginx.com
4171743Smax.romanov@nginx.com } else {
4172743Smax.romanov@nginx.com b->mem.pos = b->mem.free;
4173743Smax.romanov@nginx.com }
4174743Smax.romanov@nginx.com
4175743Smax.romanov@nginx.com if (nxt_buf_mem_used_size(&b->mem) == 0) {
4176743Smax.romanov@nginx.com next = b->next;
4177435Sigor@sysoev.ru b->next = NULL;
41781269Sigor@sysoev.ru
41791269Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue,
41801269Sigor@sysoev.ru b->completion_handler, task, b, b->parent);
4181435Sigor@sysoev.ru
4182435Sigor@sysoev.ru b = next;
4183507Smax.romanov@nginx.com }
41841269Sigor@sysoev.ru
4185520Smax.romanov@nginx.com if (b != NULL) {
4186520Smax.romanov@nginx.com nxt_buf_chain_add(&r->out, b);
4187520Smax.romanov@nginx.com }
4188431Sigor@sysoev.ru
4189431Sigor@sysoev.ru nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL);
4190431Sigor@sysoev.ru
41911270Sigor@sysoev.ru if (r->websocket_handshake
41921127Smax.romanov@nginx.com && r->status == NXT_HTTP_SWITCHING_PROTOCOLS)
41931131Smax.romanov@nginx.com {
41941131Smax.romanov@nginx.com app_port = req_rpc_data->app_port;
41951131Smax.romanov@nginx.com if (nxt_slow_path(app_port == NULL)) {
41961547Smax.romanov@nginx.com goto fail;
41971131Smax.romanov@nginx.com }
41981131Smax.romanov@nginx.com
41991131Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
42001131Smax.romanov@nginx.com
42011547Smax.romanov@nginx.com app_port->main_app_port->active_websockets++;
42021547Smax.romanov@nginx.com
42031547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
42041547Smax.romanov@nginx.com
42051547Smax.romanov@nginx.com nxt_router_app_port_release(task, app, app_port, NXT_APR_UPGRADE);
42061131Smax.romanov@nginx.com req_rpc_data->apr_action = NXT_APR_CLOSE;
42071978Smax.romanov@nginx.com
42081547Smax.romanov@nginx.com nxt_debug(task, "stream #%uD upgrade", req_rpc_data->stream);
42091547Smax.romanov@nginx.com
42101547Smax.romanov@nginx.com r->state = &nxt_http_websocket;
42111131Smax.romanov@nginx.com
42121131Smax.romanov@nginx.com } else {
42131131Smax.romanov@nginx.com r->state = &nxt_http_request_send_state;
42141131Smax.romanov@nginx.com }
42151131Smax.romanov@nginx.com }
42161131Smax.romanov@nginx.com
4217431Sigor@sysoev.ru return;
4218431Sigor@sysoev.ru
4219431Sigor@sysoev.ru fail:
4220431Sigor@sysoev.ru
4221431Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE);
4222431Sigor@sysoev.ru
4223615Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, req_rpc_data);
4224615Smax.romanov@nginx.com }
42251123Smax.romanov@nginx.com
4226431Sigor@sysoev.ru
4227431Sigor@sysoev.ru static void
nxt_router_req_headers_ack_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg,nxt_request_rpc_data_t * req_rpc_data)4228431Sigor@sysoev.ru nxt_router_req_headers_ack_handler(nxt_task_t *task,
42291547Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data)
42301547Smax.romanov@nginx.com {
42311547Smax.romanov@nginx.com int res;
42321547Smax.romanov@nginx.com nxt_app_t *app;
42331555Smax.romanov@nginx.com nxt_buf_t *b;
42341547Smax.romanov@nginx.com nxt_bool_t start_process, unlinked;
42351698Smax.romanov@nginx.com nxt_port_t *app_port, *main_app_port, *idle_port;
42361561Smax.romanov@nginx.com nxt_queue_link_t *idle_lnk;
42371547Smax.romanov@nginx.com nxt_http_request_t *r;
42381547Smax.romanov@nginx.com
42391547Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: got ack from %PI:%d",
42401547Smax.romanov@nginx.com req_rpc_data->stream,
42411547Smax.romanov@nginx.com msg->port_msg.pid, msg->port_msg.reply_port);
42421547Smax.romanov@nginx.com
42431547Smax.romanov@nginx.com nxt_port_rpc_ex_set_peer(task, msg->port, req_rpc_data,
42441547Smax.romanov@nginx.com msg->port_msg.pid);
42451547Smax.romanov@nginx.com
42461547Smax.romanov@nginx.com app = req_rpc_data->app;
42471547Smax.romanov@nginx.com r = req_rpc_data->request;
42481547Smax.romanov@nginx.com
42491561Smax.romanov@nginx.com start_process = 0;
42501547Smax.romanov@nginx.com unlinked = 0;
42511547Smax.romanov@nginx.com
42521561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
42531547Smax.romanov@nginx.com
42541547Smax.romanov@nginx.com if (r->app_link.next != NULL) {
42551547Smax.romanov@nginx.com nxt_queue_remove(&r->app_link);
42561561Smax.romanov@nginx.com r->app_link.next = NULL;
42571561Smax.romanov@nginx.com
42581561Smax.romanov@nginx.com unlinked = 1;
42591561Smax.romanov@nginx.com }
42601561Smax.romanov@nginx.com
42611561Smax.romanov@nginx.com app_port = nxt_port_hash_find(&app->port_hash, msg->port_msg.pid,
42621561Smax.romanov@nginx.com msg->port_msg.reply_port);
42631547Smax.romanov@nginx.com if (nxt_slow_path(app_port == NULL)) {
42641547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
42651547Smax.romanov@nginx.com
42661547Smax.romanov@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
42671547Smax.romanov@nginx.com
42681547Smax.romanov@nginx.com if (unlinked) {
42691547Smax.romanov@nginx.com nxt_mp_release(r->mem_pool);
42701561Smax.romanov@nginx.com }
42711561Smax.romanov@nginx.com
42721561Smax.romanov@nginx.com return;
42731561Smax.romanov@nginx.com }
42741547Smax.romanov@nginx.com
42751547Smax.romanov@nginx.com main_app_port = app_port->main_app_port;
42761547Smax.romanov@nginx.com
42771547Smax.romanov@nginx.com if (nxt_queue_chk_remove(&main_app_port->idle_link)) {
42781547Smax.romanov@nginx.com app->idle_processes--;
42791547Smax.romanov@nginx.com
42801547Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d out of %s (ack)",
42811547Smax.romanov@nginx.com &app->name, main_app_port->pid, main_app_port->id,
42821549Smax.romanov@nginx.com (main_app_port->idle_start ? "idle_ports" : "spare_ports"));
42831549Smax.romanov@nginx.com
42841549Smax.romanov@nginx.com /* Check port was in 'spare_ports' using idle_start field. */
42851549Smax.romanov@nginx.com if (main_app_port->idle_start == 0
42861547Smax.romanov@nginx.com && app->idle_processes >= app->spare_processes)
42871547Smax.romanov@nginx.com {
42881547Smax.romanov@nginx.com /*
42891547Smax.romanov@nginx.com * If there is a vacant space in spare ports,
42901547Smax.romanov@nginx.com * move the last idle to spare_ports.
42911547Smax.romanov@nginx.com */
42921547Smax.romanov@nginx.com nxt_assert(!nxt_queue_is_empty(&app->idle_ports));
42931547Smax.romanov@nginx.com
42941547Smax.romanov@nginx.com idle_lnk = nxt_queue_last(&app->idle_ports);
42951547Smax.romanov@nginx.com idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link);
42961547Smax.romanov@nginx.com nxt_queue_remove(idle_lnk);
42971547Smax.romanov@nginx.com
42981547Smax.romanov@nginx.com nxt_queue_insert_tail(&app->spare_ports, idle_lnk);
42991547Smax.romanov@nginx.com
43001547Smax.romanov@nginx.com idle_port->idle_start = 0;
43011547Smax.romanov@nginx.com
43021547Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d from idle_ports "
43031549Smax.romanov@nginx.com "to spare_ports",
43041549Smax.romanov@nginx.com &app->name, idle_port->pid, idle_port->id);
43051549Smax.romanov@nginx.com }
43061549Smax.romanov@nginx.com
43071547Smax.romanov@nginx.com if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) {
43081547Smax.romanov@nginx.com app->pending_processes++;
43091547Smax.romanov@nginx.com start_process = 1;
43101547Smax.romanov@nginx.com }
43111547Smax.romanov@nginx.com }
43121547Smax.romanov@nginx.com
43131547Smax.romanov@nginx.com main_app_port->active_requests++;
43141547Smax.romanov@nginx.com
43151547Smax.romanov@nginx.com nxt_port_inc_use(app_port);
43161547Smax.romanov@nginx.com
43171547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
43181547Smax.romanov@nginx.com
43191547Smax.romanov@nginx.com if (unlinked) {
43201547Smax.romanov@nginx.com nxt_mp_release(r->mem_pool);
43211561Smax.romanov@nginx.com }
43221561Smax.romanov@nginx.com
43231561Smax.romanov@nginx.com if (start_process) {
43241561Smax.romanov@nginx.com nxt_router_start_app_process(task, app);
43251547Smax.romanov@nginx.com }
43261547Smax.romanov@nginx.com
43271547Smax.romanov@nginx.com nxt_port_use(task, req_rpc_data->app_port, -1);
43281547Smax.romanov@nginx.com
43291547Smax.romanov@nginx.com req_rpc_data->app_port = app_port;
43301547Smax.romanov@nginx.com
43311547Smax.romanov@nginx.com b = req_rpc_data->msg_info.buf;
43321547Smax.romanov@nginx.com
43331698Smax.romanov@nginx.com if (b != NULL) {
43341698Smax.romanov@nginx.com /* First buffer is already sent. Start from second. */
43351698Smax.romanov@nginx.com b = b->next;
43361698Smax.romanov@nginx.com
43371698Smax.romanov@nginx.com req_rpc_data->msg_info.buf->next = NULL;
43381829Smax.romanov@nginx.com }
43391829Smax.romanov@nginx.com
43401698Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) {
43411698Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: send body fd %d", req_rpc_data->stream,
43421698Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd);
43431555Smax.romanov@nginx.com
43441555Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1) {
43451555Smax.romanov@nginx.com lseek(req_rpc_data->msg_info.body_fd, 0, SEEK_SET);
43461698Smax.romanov@nginx.com }
43471698Smax.romanov@nginx.com
43481698Smax.romanov@nginx.com res = nxt_port_socket_write(task, app_port, NXT_PORT_MSG_REQ_BODY,
43491555Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd,
43501555Smax.romanov@nginx.com req_rpc_data->stream,
43511555Smax.romanov@nginx.com task->thread->engine->port->id, b);
43521555Smax.romanov@nginx.com
43531698Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) {
43541555Smax.romanov@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
43551555Smax.romanov@nginx.com }
43561555Smax.romanov@nginx.com }
43571555Smax.romanov@nginx.com
43581555Smax.romanov@nginx.com if (app->timeout != 0) {
43591555Smax.romanov@nginx.com r->timer.handler = nxt_router_app_timeout;
43601547Smax.romanov@nginx.com r->timer_data = req_rpc_data;
43611547Smax.romanov@nginx.com nxt_timer_add(task->thread->engine, &r->timer, app->timeout);
43621547Smax.romanov@nginx.com }
43631547Smax.romanov@nginx.com }
43641547Smax.romanov@nginx.com
43651547Smax.romanov@nginx.com
43661547Smax.romanov@nginx.com static const nxt_http_request_state_t nxt_http_request_send_state
43671547Smax.romanov@nginx.com nxt_aligned(64) =
4368431Sigor@sysoev.ru {
4369431Sigor@sysoev.ru .error_handler = nxt_http_request_error_handler,
4370431Sigor@sysoev.ru };
4371943Sigor@sysoev.ru
4372431Sigor@sysoev.ru
4373431Sigor@sysoev.ru static void
nxt_http_request_send_body(nxt_task_t * task,void * obj,void * data)4374431Sigor@sysoev.ru nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data)
4375431Sigor@sysoev.ru {
4376431Sigor@sysoev.ru nxt_buf_t *out;
4377431Sigor@sysoev.ru nxt_http_request_t *r;
4378431Sigor@sysoev.ru
4379431Sigor@sysoev.ru r = obj;
4380431Sigor@sysoev.ru
4381431Sigor@sysoev.ru out = r->out;
4382431Sigor@sysoev.ru
4383431Sigor@sysoev.ru if (out != NULL) {
4384431Sigor@sysoev.ru r->out = NULL;
4385431Sigor@sysoev.ru nxt_http_request_send(task, r, out);
4386431Sigor@sysoev.ru }
4387431Sigor@sysoev.ru }
438888Smax.romanov@nginx.com
438988Smax.romanov@nginx.com
439088Smax.romanov@nginx.com static void
nxt_router_response_error_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)4391277Sigor@sysoev.ru nxt_router_response_error_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
4392318Smax.romanov@nginx.com void *data)
4393318Smax.romanov@nginx.com {
4394318Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data;
4395318Smax.romanov@nginx.com
43961123Smax.romanov@nginx.com req_rpc_data = data;
43971123Smax.romanov@nginx.com
43981123Smax.romanov@nginx.com req_rpc_data->rpc_cancel = 0;
43991123Smax.romanov@nginx.com
44001547Smax.romanov@nginx.com /* TODO cancel message and return if cancelled. */
44011547Smax.romanov@nginx.com // nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream);
44021547Smax.romanov@nginx.com
44031547Smax.romanov@nginx.com if (req_rpc_data->request != NULL) {
4404425Smax.romanov@nginx.com nxt_http_request_error(task, req_rpc_data->request,
44051123Smax.romanov@nginx.com NXT_HTTP_SERVICE_UNAVAILABLE);
44061123Smax.romanov@nginx.com }
4407616Smax.romanov@nginx.com
4408616Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, req_rpc_data);
4409318Smax.romanov@nginx.com }
44101123Smax.romanov@nginx.com
4411318Smax.romanov@nginx.com
4412318Smax.romanov@nginx.com static void
nxt_router_app_port_ready(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)4413318Smax.romanov@nginx.com nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
4414141Smax.romanov@nginx.com void *data)
4415343Smax.romanov@nginx.com {
4416343Smax.romanov@nginx.com uint32_t n;
4417192Smax.romanov@nginx.com nxt_app_t *app;
44181998St.nateldemoura@f5.com nxt_bool_t start_process, restarted;
44191926Smax.romanov@nginx.com nxt_port_t *port;
44201998St.nateldemoura@f5.com nxt_app_joint_t *app_joint;
44211926Smax.romanov@nginx.com nxt_app_joint_rpc_t *app_joint_rpc;
44221926Smax.romanov@nginx.com
44231926Smax.romanov@nginx.com nxt_assert(data != NULL);
44241926Smax.romanov@nginx.com
44251926Smax.romanov@nginx.com app_joint_rpc = data;
44261926Smax.romanov@nginx.com app_joint = app_joint_rpc->app_joint;
44271926Smax.romanov@nginx.com port = msg->u.new_port;
44281926Smax.romanov@nginx.com
4429347Smax.romanov@nginx.com nxt_assert(app_joint != NULL);
4430343Smax.romanov@nginx.com nxt_assert(port != NULL);
4431753Smax.romanov@nginx.com nxt_assert(port->id == 0);
4432343Smax.romanov@nginx.com
44331547Smax.romanov@nginx.com app = app_joint->app;
4434343Smax.romanov@nginx.com
4435753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app_joint, -1);
4436753Smax.romanov@nginx.com
4437753Smax.romanov@nginx.com if (nxt_slow_path(app == NULL)) {
4438753Smax.romanov@nginx.com nxt_debug(task, "new port ready for released app, send QUIT");
4439753Smax.romanov@nginx.com
4440753Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL);
4441753Smax.romanov@nginx.com
4442753Smax.romanov@nginx.com return;
4443753Smax.romanov@nginx.com }
4444753Smax.romanov@nginx.com
4445753Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
4446753Smax.romanov@nginx.com
4447343Smax.romanov@nginx.com restarted = (app->generation != app_joint_rpc->generation);
4448343Smax.romanov@nginx.com
44491998St.nateldemoura@f5.com if (app_joint_rpc->proto) {
44501998St.nateldemoura@f5.com nxt_assert(app->proto_port == NULL);
44511998St.nateldemoura@f5.com nxt_assert(port->type == NXT_PROCESS_PROTOTYPE);
44521998St.nateldemoura@f5.com
44531998St.nateldemoura@f5.com n = app->proto_port_requests;
44541998St.nateldemoura@f5.com app->proto_port_requests = 0;
44551998St.nateldemoura@f5.com
44561998St.nateldemoura@f5.com if (nxt_slow_path(restarted)) {
44571998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex);
44581998St.nateldemoura@f5.com
44591998St.nateldemoura@f5.com nxt_debug(task, "proto port ready for restarted app, send QUIT");
44601998St.nateldemoura@f5.com
44611998St.nateldemoura@f5.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0,
44621998St.nateldemoura@f5.com NULL);
44631998St.nateldemoura@f5.com
44641998St.nateldemoura@f5.com } else {
44651998St.nateldemoura@f5.com port->app = app;
44661998St.nateldemoura@f5.com app->proto_port = port;
44671998St.nateldemoura@f5.com
44681998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex);
44691998St.nateldemoura@f5.com
44701998St.nateldemoura@f5.com nxt_port_use(task, port, 1);
44711998St.nateldemoura@f5.com }
44721998St.nateldemoura@f5.com
44731998St.nateldemoura@f5.com port = task->thread->runtime->port_by_type[NXT_PROCESS_ROUTER];
44741998St.nateldemoura@f5.com
44751998St.nateldemoura@f5.com while (n > 0) {
44761998St.nateldemoura@f5.com nxt_router_app_use(task, app, 1);
44771998St.nateldemoura@f5.com
44781998St.nateldemoura@f5.com nxt_router_start_app_process_handler(task, port, app);
44791998St.nateldemoura@f5.com
44801998St.nateldemoura@f5.com n--;
44811998St.nateldemoura@f5.com }
44821998St.nateldemoura@f5.com
44831998St.nateldemoura@f5.com return;
44841998St.nateldemoura@f5.com }
44851998St.nateldemoura@f5.com
44861998St.nateldemoura@f5.com nxt_assert(port->type == NXT_PROCESS_APP);
44871998St.nateldemoura@f5.com nxt_assert(app->pending_processes != 0);
44881998St.nateldemoura@f5.com
4489507Smax.romanov@nginx.com app->pending_processes--;
4490507Smax.romanov@nginx.com
4491507Smax.romanov@nginx.com if (nxt_slow_path(restarted)) {
44921926Smax.romanov@nginx.com nxt_debug(task, "new port ready for restarted app, send QUIT");
44931998St.nateldemoura@f5.com
44941926Smax.romanov@nginx.com start_process = !task->thread->engine->shutdown
44951926Smax.romanov@nginx.com && nxt_router_app_can_start(app)
44961926Smax.romanov@nginx.com && nxt_router_app_need_start(app);
44971926Smax.romanov@nginx.com
44981926Smax.romanov@nginx.com if (start_process) {
44991926Smax.romanov@nginx.com app->pending_processes++;
45001926Smax.romanov@nginx.com }
45011926Smax.romanov@nginx.com
45021926Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
45031926Smax.romanov@nginx.com
45041926Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL);
45051926Smax.romanov@nginx.com
45061926Smax.romanov@nginx.com if (start_process) {
45071926Smax.romanov@nginx.com nxt_router_start_app_process(task, app);
45081926Smax.romanov@nginx.com }
45091926Smax.romanov@nginx.com
45101926Smax.romanov@nginx.com return;
45111926Smax.romanov@nginx.com }
45121926Smax.romanov@nginx.com
45131926Smax.romanov@nginx.com port->app = app;
45141926Smax.romanov@nginx.com port->main_app_port = port;
45151926Smax.romanov@nginx.com
45161926Smax.romanov@nginx.com app->processes++;
45171926Smax.romanov@nginx.com nxt_port_hash_add(&app->port_hash, port);
4518507Smax.romanov@nginx.com app->port_hash_count++;
45191547Smax.romanov@nginx.com
45201547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4521343Smax.romanov@nginx.com
4522343Smax.romanov@nginx.com nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d",
4523343Smax.romanov@nginx.com &app->name, port->pid, app->processes, app->pending_processes);
4524507Smax.romanov@nginx.com
4525507Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL);
4526343Smax.romanov@nginx.com
45272014Smax.romanov@nginx.com nxt_router_app_port_release(task, app, port, NXT_APR_NEW_PORT);
45281547Smax.romanov@nginx.com }
45291978Smax.romanov@nginx.com
4530192Smax.romanov@nginx.com
4531192Smax.romanov@nginx.com static void
nxt_router_app_port_error(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)4532192Smax.romanov@nginx.com nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
4533192Smax.romanov@nginx.com void *data)
4534343Smax.romanov@nginx.com {
4535343Smax.romanov@nginx.com nxt_app_t *app;
4536192Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
45371926Smax.romanov@nginx.com nxt_queue_link_t *link;
45381926Smax.romanov@nginx.com nxt_http_request_t *r;
45391926Smax.romanov@nginx.com nxt_app_joint_rpc_t *app_joint_rpc;
45401926Smax.romanov@nginx.com
45411926Smax.romanov@nginx.com nxt_assert(data != NULL);
45421926Smax.romanov@nginx.com
45431926Smax.romanov@nginx.com app_joint_rpc = data;
45441926Smax.romanov@nginx.com app_joint = app_joint_rpc->app_joint;
45451926Smax.romanov@nginx.com
45461926Smax.romanov@nginx.com nxt_assert(app_joint != NULL);
4547753Smax.romanov@nginx.com
4548753Smax.romanov@nginx.com app = app_joint->app;
4549753Smax.romanov@nginx.com
4550753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app_joint, -1);
4551753Smax.romanov@nginx.com
4552753Smax.romanov@nginx.com if (nxt_slow_path(app == NULL)) {
4553753Smax.romanov@nginx.com nxt_debug(task, "start error for released app");
4554753Smax.romanov@nginx.com
4555753Smax.romanov@nginx.com return;
4556753Smax.romanov@nginx.com }
4557753Smax.romanov@nginx.com
4558753Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p start error", &app->name, app);
4559343Smax.romanov@nginx.com
4560343Smax.romanov@nginx.com link = NULL;
4561343Smax.romanov@nginx.com
45621561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
45631561Smax.romanov@nginx.com
4564343Smax.romanov@nginx.com nxt_assert(app->pending_processes != 0);
4565343Smax.romanov@nginx.com
4566507Smax.romanov@nginx.com app->pending_processes--;
4567507Smax.romanov@nginx.com
4568507Smax.romanov@nginx.com if (app->processes == 0 && !nxt_queue_is_empty(&app->ack_waiting_req)) {
4569318Smax.romanov@nginx.com link = nxt_queue_first(&app->ack_waiting_req);
45701561Smax.romanov@nginx.com
45711561Smax.romanov@nginx.com nxt_queue_remove(link);
45721561Smax.romanov@nginx.com link->next = NULL;
45731561Smax.romanov@nginx.com }
45741561Smax.romanov@nginx.com
45751561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
45761561Smax.romanov@nginx.com
4577343Smax.romanov@nginx.com while (link != NULL) {
4578343Smax.romanov@nginx.com r = nxt_container_of(link, nxt_http_request_t, app_link);
45791561Smax.romanov@nginx.com
45801561Smax.romanov@nginx.com nxt_event_engine_post(r->engine, &r->err_work);
45811561Smax.romanov@nginx.com
45821561Smax.romanov@nginx.com link = NULL;
45831561Smax.romanov@nginx.com
45841561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
45851561Smax.romanov@nginx.com
45861561Smax.romanov@nginx.com if (app->processes == 0 && app->pending_processes == 0
45871561Smax.romanov@nginx.com && !nxt_queue_is_empty(&app->ack_waiting_req))
45881561Smax.romanov@nginx.com {
45891561Smax.romanov@nginx.com link = nxt_queue_first(&app->ack_waiting_req);
45901561Smax.romanov@nginx.com
45911561Smax.romanov@nginx.com nxt_queue_remove(link);
45921561Smax.romanov@nginx.com link->next = NULL;
45931561Smax.romanov@nginx.com }
45941561Smax.romanov@nginx.com
45951561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
45961561Smax.romanov@nginx.com }
45971561Smax.romanov@nginx.com }
45981561Smax.romanov@nginx.com
4599192Smax.romanov@nginx.com
4600192Smax.romanov@nginx.com nxt_inline nxt_port_t *
nxt_router_app_get_port_for_quit(nxt_task_t * task,nxt_app_t * app)4601192Smax.romanov@nginx.com nxt_router_app_get_port_for_quit(nxt_task_t *task, nxt_app_t *app)
4602507Smax.romanov@nginx.com {
46031549Smax.romanov@nginx.com nxt_port_t *port;
4604141Smax.romanov@nginx.com
4605343Smax.romanov@nginx.com port = NULL;
4606141Smax.romanov@nginx.com
4607141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
4608141Smax.romanov@nginx.com
4609141Smax.romanov@nginx.com nxt_queue_each(port, &app->ports, nxt_port_t, app_link) {
4610141Smax.romanov@nginx.com
4611343Smax.romanov@nginx.com /* Caller is responsible to decrease port use count. */
4612343Smax.romanov@nginx.com nxt_queue_chk_remove(&port->app_link);
4613507Smax.romanov@nginx.com
4614507Smax.romanov@nginx.com if (nxt_queue_chk_remove(&port->idle_link)) {
4615507Smax.romanov@nginx.com app->idle_processes--;
4616507Smax.romanov@nginx.com
4617507Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d out of %s for quit",
46181549Smax.romanov@nginx.com &app->name, port->pid, port->id,
46191549Smax.romanov@nginx.com (port->idle_start ? "idle_ports" : "spare_ports"));
46201549Smax.romanov@nginx.com }
46211549Smax.romanov@nginx.com
4622507Smax.romanov@nginx.com nxt_port_hash_remove(&app->port_hash, port);
4623507Smax.romanov@nginx.com app->port_hash_count--;
46241547Smax.romanov@nginx.com
46251547Smax.romanov@nginx.com port->app = NULL;
46261547Smax.romanov@nginx.com app->processes--;
4627507Smax.romanov@nginx.com
4628507Smax.romanov@nginx.com break;
4629343Smax.romanov@nginx.com
4630343Smax.romanov@nginx.com } nxt_queue_loop;
4631343Smax.romanov@nginx.com
4632343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4633141Smax.romanov@nginx.com
4634141Smax.romanov@nginx.com return port;
4635141Smax.romanov@nginx.com }
4636141Smax.romanov@nginx.com
4637141Smax.romanov@nginx.com
4638141Smax.romanov@nginx.com static void
nxt_router_app_use(nxt_task_t * task,nxt_app_t * app,int i)4639141Smax.romanov@nginx.com nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i)
4640141Smax.romanov@nginx.com {
46411563Svbart@nginx.com int c;
46421563Svbart@nginx.com
46431563Svbart@nginx.com c = nxt_atomic_fetch_add(&app->use_count, i);
46441563Svbart@nginx.com
46451563Svbart@nginx.com if (i < 0 && c == -i) {
46461563Svbart@nginx.com
46471563Svbart@nginx.com if (task->thread->engine != app->engine) {
46481563Svbart@nginx.com nxt_event_engine_post(app->engine, &app->joint->free_app_work);
46491563Svbart@nginx.com
46501563Svbart@nginx.com } else {
46511563Svbart@nginx.com nxt_router_free_app(task, app->joint, NULL);
46521563Svbart@nginx.com }
46531563Svbart@nginx.com }
46541563Svbart@nginx.com }
46551563Svbart@nginx.com
46561563Svbart@nginx.com
46571563Svbart@nginx.com static void
nxt_router_app_unlink(nxt_task_t * task,nxt_app_t * app)46581563Svbart@nginx.com nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app)
46591563Svbart@nginx.com {
4660753Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p unlink", &app->name, app);
4661507Smax.romanov@nginx.com
4662753Smax.romanov@nginx.com nxt_queue_remove(&app->link);
4663507Smax.romanov@nginx.com
4664507Smax.romanov@nginx.com nxt_router_app_use(task, app, -1);
4665507Smax.romanov@nginx.com }
4666753Smax.romanov@nginx.com
4667507Smax.romanov@nginx.com
4668507Smax.romanov@nginx.com static void
nxt_router_app_port_release(nxt_task_t * task,nxt_app_t * app,nxt_port_t * port,nxt_apr_action_t action)4669507Smax.romanov@nginx.com nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, nxt_port_t *port,
4670507Smax.romanov@nginx.com nxt_apr_action_t action)
46711978Smax.romanov@nginx.com {
46721123Smax.romanov@nginx.com int inc_use;
4673343Smax.romanov@nginx.com uint32_t got_response, dec_requests;
46741547Smax.romanov@nginx.com nxt_bool_t adjust_idle_timer;
46751547Smax.romanov@nginx.com nxt_port_t *main_app_port;
46761980Smax.romanov@nginx.com
46771547Smax.romanov@nginx.com nxt_assert(port != NULL);
4678343Smax.romanov@nginx.com
4679343Smax.romanov@nginx.com inc_use = 0;
4680343Smax.romanov@nginx.com got_response = 0;
46811123Smax.romanov@nginx.com dec_requests = 0;
46821123Smax.romanov@nginx.com
46831547Smax.romanov@nginx.com switch (action) {
46841123Smax.romanov@nginx.com case NXT_APR_NEW_PORT:
46851123Smax.romanov@nginx.com break;
46861123Smax.romanov@nginx.com case NXT_APR_REQUEST_FAILED:
46871123Smax.romanov@nginx.com dec_requests = 1;
46881123Smax.romanov@nginx.com inc_use = -1;
46891547Smax.romanov@nginx.com break;
46901123Smax.romanov@nginx.com case NXT_APR_GOT_RESPONSE:
46911123Smax.romanov@nginx.com got_response = 1;
46921123Smax.romanov@nginx.com inc_use = -1;
46931123Smax.romanov@nginx.com break;
46941123Smax.romanov@nginx.com case NXT_APR_UPGRADE:
46951123Smax.romanov@nginx.com got_response = 1;
46961131Smax.romanov@nginx.com break;
46971131Smax.romanov@nginx.com case NXT_APR_CLOSE:
46981131Smax.romanov@nginx.com inc_use = -1;
46991123Smax.romanov@nginx.com break;
47001123Smax.romanov@nginx.com }
47011123Smax.romanov@nginx.com
47021123Smax.romanov@nginx.com nxt_debug(task, "app '%V' release port %PI:%d: %d %d", &app->name,
47031123Smax.romanov@nginx.com port->pid, port->id,
47041547Smax.romanov@nginx.com (int) inc_use, (int) got_response);
47051547Smax.romanov@nginx.com
47061547Smax.romanov@nginx.com if (port->id == NXT_SHARED_PORT_ID) {
47071547Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
47081926Smax.romanov@nginx.com
47091547Smax.romanov@nginx.com app->active_requests -= got_response + dec_requests;
47101547Smax.romanov@nginx.com
47111547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
47121547Smax.romanov@nginx.com
47131547Smax.romanov@nginx.com goto adjust_use;
47141547Smax.romanov@nginx.com }
47151547Smax.romanov@nginx.com
47161547Smax.romanov@nginx.com main_app_port = port->main_app_port;
47171547Smax.romanov@nginx.com
47181547Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
47191547Smax.romanov@nginx.com
4720343Smax.romanov@nginx.com main_app_port->active_requests -= got_response + dec_requests;
4721343Smax.romanov@nginx.com app->active_requests -= got_response + dec_requests;
47221547Smax.romanov@nginx.com
47231547Smax.romanov@nginx.com if (main_app_port->pair[1] != -1 && main_app_port->app_link.next == NULL) {
47241547Smax.romanov@nginx.com nxt_queue_insert_tail(&app->ports, &main_app_port->app_link);
47251980Smax.romanov@nginx.com
47261980Smax.romanov@nginx.com nxt_port_inc_use(main_app_port);
47271980Smax.romanov@nginx.com }
47281980Smax.romanov@nginx.com
4729507Smax.romanov@nginx.com adjust_idle_timer = 0;
4730507Smax.romanov@nginx.com
4731507Smax.romanov@nginx.com if (main_app_port->pair[1] != -1
4732507Smax.romanov@nginx.com && main_app_port->active_requests == 0
47331980Smax.romanov@nginx.com && main_app_port->active_websockets == 0
47341547Smax.romanov@nginx.com && main_app_port->idle_link.next == NULL)
47351547Smax.romanov@nginx.com {
47361547Smax.romanov@nginx.com if (app->idle_processes == app->spare_processes
47371131Smax.romanov@nginx.com && app->adjust_idle_work.data == NULL)
4738507Smax.romanov@nginx.com {
4739507Smax.romanov@nginx.com adjust_idle_timer = 1;
4740507Smax.romanov@nginx.com app->adjust_idle_work.data = app;
4741507Smax.romanov@nginx.com app->adjust_idle_work.next = NULL;
4742507Smax.romanov@nginx.com }
4743507Smax.romanov@nginx.com
4744507Smax.romanov@nginx.com if (app->idle_processes < app->spare_processes) {
4745507Smax.romanov@nginx.com nxt_queue_insert_tail(&app->spare_ports, &main_app_port->idle_link);
4746507Smax.romanov@nginx.com
47471547Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d to spare_ports",
4748507Smax.romanov@nginx.com &app->name, main_app_port->pid, main_app_port->id);
47491549Smax.romanov@nginx.com } else {
47501549Smax.romanov@nginx.com nxt_queue_insert_tail(&app->idle_ports, &main_app_port->idle_link);
4751507Smax.romanov@nginx.com
47521547Smax.romanov@nginx.com main_app_port->idle_start = task->thread->engine->timers.now;
47531547Smax.romanov@nginx.com
47541547Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d to idle_ports",
47551549Smax.romanov@nginx.com &app->name, main_app_port->pid, main_app_port->id);
47561549Smax.romanov@nginx.com }
47571549Smax.romanov@nginx.com
4758507Smax.romanov@nginx.com app->idle_processes++;
4759507Smax.romanov@nginx.com }
4760507Smax.romanov@nginx.com
4761507Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4762507Smax.romanov@nginx.com
4763343Smax.romanov@nginx.com if (adjust_idle_timer) {
4764343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1);
4765507Smax.romanov@nginx.com nxt_event_engine_post(app->engine, &app->adjust_idle_work);
4766507Smax.romanov@nginx.com }
4767507Smax.romanov@nginx.com
4768507Smax.romanov@nginx.com /* ? */
4769507Smax.romanov@nginx.com if (main_app_port->pair[1] == -1) {
4770343Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p port %p already closed (pid %PI dead?)",
47711547Smax.romanov@nginx.com &app->name, app, main_app_port, main_app_port->pid);
4772343Smax.romanov@nginx.com
47731547Smax.romanov@nginx.com goto adjust_use;
4774343Smax.romanov@nginx.com }
4775343Smax.romanov@nginx.com
4776163Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p requests queue is empty, keep the port",
4777163Smax.romanov@nginx.com &app->name, app);
4778167Smax.romanov@nginx.com
4779167Smax.romanov@nginx.com adjust_use:
4780141Smax.romanov@nginx.com
4781343Smax.romanov@nginx.com nxt_port_use(task, port, inc_use);
4782343Smax.romanov@nginx.com }
47831123Smax.romanov@nginx.com
4784141Smax.romanov@nginx.com
4785141Smax.romanov@nginx.com void
nxt_router_app_port_close(nxt_task_t * task,nxt_port_t * port)4786141Smax.romanov@nginx.com nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port)
4787343Smax.romanov@nginx.com {
4788343Smax.romanov@nginx.com nxt_app_t *app;
4789141Smax.romanov@nginx.com nxt_bool_t unchain, start_process;
4790507Smax.romanov@nginx.com nxt_port_t *idle_port;
4791507Smax.romanov@nginx.com nxt_queue_link_t *idle_lnk;
4792507Smax.romanov@nginx.com
4793507Smax.romanov@nginx.com app = port->app;
4794141Smax.romanov@nginx.com
4795141Smax.romanov@nginx.com nxt_assert(app != NULL);
4796343Smax.romanov@nginx.com
4797343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
4798141Smax.romanov@nginx.com
4799141Smax.romanov@nginx.com if (port == app->proto_port) {
4800141Smax.romanov@nginx.com app->proto_port = NULL;
48011998St.nateldemoura@f5.com port->app = NULL;
48021998St.nateldemoura@f5.com
48031998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex);
48041998St.nateldemoura@f5.com
48051998St.nateldemoura@f5.com nxt_debug(task, "app '%V' prototype pid %PI closed", &app->name,
48061998St.nateldemoura@f5.com port->pid);
48071998St.nateldemoura@f5.com
48081998St.nateldemoura@f5.com nxt_port_use(task, port, -1);
48091998St.nateldemoura@f5.com
48101998St.nateldemoura@f5.com return;
48111998St.nateldemoura@f5.com }
48121998St.nateldemoura@f5.com
48131998St.nateldemoura@f5.com nxt_port_hash_remove(&app->port_hash, port);
48141998St.nateldemoura@f5.com app->port_hash_count--;
48151547Smax.romanov@nginx.com
48161547Smax.romanov@nginx.com if (port->id != 0) {
48171547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
48181547Smax.romanov@nginx.com
48191547Smax.romanov@nginx.com nxt_debug(task, "app '%V' port (%PI, %d) closed", &app->name,
48201547Smax.romanov@nginx.com port->pid, port->id);
48211547Smax.romanov@nginx.com
48221547Smax.romanov@nginx.com return;
48231547Smax.romanov@nginx.com }
48241547Smax.romanov@nginx.com
48251547Smax.romanov@nginx.com unchain = nxt_queue_chk_remove(&port->app_link);
48261547Smax.romanov@nginx.com
4827507Smax.romanov@nginx.com if (nxt_queue_chk_remove(&port->idle_link)) {
4828507Smax.romanov@nginx.com app->idle_processes--;
4829507Smax.romanov@nginx.com
4830507Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d out of %s before close",
4831507Smax.romanov@nginx.com &app->name, port->pid, port->id,
48321549Smax.romanov@nginx.com (port->idle_start ? "idle_ports" : "spare_ports"));
48331549Smax.romanov@nginx.com
48341549Smax.romanov@nginx.com if (port->idle_start == 0
48351549Smax.romanov@nginx.com && app->idle_processes >= app->spare_processes)
4836507Smax.romanov@nginx.com {
4837507Smax.romanov@nginx.com nxt_assert(!nxt_queue_is_empty(&app->idle_ports));
4838507Smax.romanov@nginx.com
4839507Smax.romanov@nginx.com idle_lnk = nxt_queue_last(&app->idle_ports);
4840507Smax.romanov@nginx.com idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link);
4841507Smax.romanov@nginx.com nxt_queue_remove(idle_lnk);
4842507Smax.romanov@nginx.com
4843507Smax.romanov@nginx.com nxt_queue_insert_tail(&app->spare_ports, idle_lnk);
4844507Smax.romanov@nginx.com
4845507Smax.romanov@nginx.com idle_port->idle_start = 0;
4846507Smax.romanov@nginx.com
4847507Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d from idle_ports "
48481549Smax.romanov@nginx.com "to spare_ports",
48491549Smax.romanov@nginx.com &app->name, idle_port->pid, idle_port->id);
48501549Smax.romanov@nginx.com }
48511549Smax.romanov@nginx.com }
4852507Smax.romanov@nginx.com
4853343Smax.romanov@nginx.com app->processes--;
4854343Smax.romanov@nginx.com
4855507Smax.romanov@nginx.com start_process = !task->thread->engine->shutdown
4856507Smax.romanov@nginx.com && nxt_router_app_can_start(app)
4857753Smax.romanov@nginx.com && nxt_router_app_need_start(app);
4858507Smax.romanov@nginx.com
48591547Smax.romanov@nginx.com if (start_process) {
4860507Smax.romanov@nginx.com app->pending_processes++;
4861507Smax.romanov@nginx.com }
4862507Smax.romanov@nginx.com
4863163Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4864141Smax.romanov@nginx.com
4865141Smax.romanov@nginx.com nxt_debug(task, "app '%V' pid %PI closed", &app->name, port->pid);
4866163Smax.romanov@nginx.com
4867507Smax.romanov@nginx.com if (unchain) {
4868343Smax.romanov@nginx.com nxt_port_use(task, port, -1);
4869343Smax.romanov@nginx.com }
4870343Smax.romanov@nginx.com
4871163Smax.romanov@nginx.com if (start_process) {
4872163Smax.romanov@nginx.com nxt_router_start_app_process(task, app);
4873507Smax.romanov@nginx.com }
4874507Smax.romanov@nginx.com }
4875507Smax.romanov@nginx.com
4876507Smax.romanov@nginx.com
4877507Smax.romanov@nginx.com static void
nxt_router_adjust_idle_timer(nxt_task_t * task,void * obj,void * data)4878507Smax.romanov@nginx.com nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data)
4879507Smax.romanov@nginx.com {
4880507Smax.romanov@nginx.com nxt_app_t *app;
4881507Smax.romanov@nginx.com nxt_bool_t queued;
4882507Smax.romanov@nginx.com nxt_port_t *port;
4883507Smax.romanov@nginx.com nxt_msec_t timeout, threshold;
4884507Smax.romanov@nginx.com nxt_queue_link_t *lnk;
4885507Smax.romanov@nginx.com nxt_event_engine_t *engine;
4886507Smax.romanov@nginx.com
4887507Smax.romanov@nginx.com app = obj;
4888507Smax.romanov@nginx.com queued = (data == app);
4889507Smax.romanov@nginx.com
4890507Smax.romanov@nginx.com nxt_debug(task, "nxt_router_adjust_idle_timer: app \"%V\", queued %b",
4891507Smax.romanov@nginx.com &app->name, queued);
4892507Smax.romanov@nginx.com
4893507Smax.romanov@nginx.com engine = task->thread->engine;
4894507Smax.romanov@nginx.com
4895507Smax.romanov@nginx.com nxt_assert(app->engine == engine);
4896507Smax.romanov@nginx.com
4897507Smax.romanov@nginx.com threshold = engine->timers.now + app->joint->idle_timer.bias;
4898507Smax.romanov@nginx.com timeout = 0;
4899811Svbart@nginx.com
4900507Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
4901507Smax.romanov@nginx.com
4902507Smax.romanov@nginx.com if (queued) {
4903507Smax.romanov@nginx.com app->adjust_idle_work.data = NULL;
4904507Smax.romanov@nginx.com }
4905507Smax.romanov@nginx.com
4906343Smax.romanov@nginx.com nxt_debug(task, "app '%V' idle_processes %d, spare_processes %d",
4907507Smax.romanov@nginx.com &app->name,
49081547Smax.romanov@nginx.com (int) app->idle_processes, (int) app->spare_processes);
49091547Smax.romanov@nginx.com
49101547Smax.romanov@nginx.com while (app->idle_processes > app->spare_processes) {
49111547Smax.romanov@nginx.com
4912507Smax.romanov@nginx.com nxt_assert(!nxt_queue_is_empty(&app->idle_ports));
4913507Smax.romanov@nginx.com
4914551Smax.romanov@nginx.com lnk = nxt_queue_first(&app->idle_ports);
4915507Smax.romanov@nginx.com port = nxt_queue_link_data(lnk, nxt_port_t, idle_link);
4916507Smax.romanov@nginx.com
4917507Smax.romanov@nginx.com timeout = port->idle_start + app->idle_timeout;
4918507Smax.romanov@nginx.com
4919507Smax.romanov@nginx.com nxt_debug(task, "app '%V' pid %PI, start %M, timeout %M, threshold %M",
4920507Smax.romanov@nginx.com &app->name, port->pid,
49211547Smax.romanov@nginx.com port->idle_start, timeout, threshold);
49221547Smax.romanov@nginx.com
49231547Smax.romanov@nginx.com if (timeout > threshold) {
49241547Smax.romanov@nginx.com break;
4925507Smax.romanov@nginx.com }
4926507Smax.romanov@nginx.com
4927507Smax.romanov@nginx.com nxt_queue_remove(lnk);
4928507Smax.romanov@nginx.com lnk->next = NULL;
4929507Smax.romanov@nginx.com
4930507Smax.romanov@nginx.com nxt_debug(task, "app '%V' move port %PI:%d out of idle_ports (timeout)",
4931507Smax.romanov@nginx.com &app->name, port->pid, port->id);
49321549Smax.romanov@nginx.com
49331549Smax.romanov@nginx.com nxt_queue_chk_remove(&port->app_link);
49341549Smax.romanov@nginx.com
4935507Smax.romanov@nginx.com nxt_port_hash_remove(&app->port_hash, port);
4936507Smax.romanov@nginx.com app->port_hash_count--;
49371547Smax.romanov@nginx.com
49381547Smax.romanov@nginx.com app->idle_processes--;
49391547Smax.romanov@nginx.com app->processes--;
4940507Smax.romanov@nginx.com port->app = NULL;
4941507Smax.romanov@nginx.com
4942507Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4943507Smax.romanov@nginx.com
4944507Smax.romanov@nginx.com nxt_debug(task, "app '%V' send QUIT to idle port %PI",
4945507Smax.romanov@nginx.com &app->name, port->pid);
4946507Smax.romanov@nginx.com
4947507Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL);
4948507Smax.romanov@nginx.com
4949507Smax.romanov@nginx.com nxt_port_use(task, port, -1);
4950507Smax.romanov@nginx.com
4951507Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
4952507Smax.romanov@nginx.com }
4953507Smax.romanov@nginx.com
4954507Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
4955507Smax.romanov@nginx.com
4956507Smax.romanov@nginx.com if (timeout > threshold) {
4957507Smax.romanov@nginx.com nxt_timer_add(engine, &app->joint->idle_timer, timeout - threshold);
4958507Smax.romanov@nginx.com
4959753Smax.romanov@nginx.com } else {
4960507Smax.romanov@nginx.com nxt_timer_disable(engine, &app->joint->idle_timer);
4961507Smax.romanov@nginx.com }
4962753Smax.romanov@nginx.com
4963507Smax.romanov@nginx.com if (queued) {
4964507Smax.romanov@nginx.com nxt_router_app_use(task, app, -1);
4965507Smax.romanov@nginx.com }
4966507Smax.romanov@nginx.com }
4967507Smax.romanov@nginx.com
4968507Smax.romanov@nginx.com
4969507Smax.romanov@nginx.com static void
nxt_router_app_idle_timeout(nxt_task_t * task,void * obj,void * data)4970507Smax.romanov@nginx.com nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, void *data)
4971507Smax.romanov@nginx.com {
4972507Smax.romanov@nginx.com nxt_timer_t *timer;
4973507Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
4974753Smax.romanov@nginx.com
4975753Smax.romanov@nginx.com timer = obj;
4976507Smax.romanov@nginx.com app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer);
4977507Smax.romanov@nginx.com
4978753Smax.romanov@nginx.com if (nxt_fast_path(app_joint->app != NULL)) {
4979753Smax.romanov@nginx.com nxt_router_adjust_idle_timer(task, app_joint->app, NULL);
4980753Smax.romanov@nginx.com }
4981753Smax.romanov@nginx.com }
4982753Smax.romanov@nginx.com
4983753Smax.romanov@nginx.com
4984753Smax.romanov@nginx.com static void
nxt_router_app_joint_release_handler(nxt_task_t * task,void * obj,void * data)4985753Smax.romanov@nginx.com nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, void *data)
4986753Smax.romanov@nginx.com {
4987753Smax.romanov@nginx.com nxt_timer_t *timer;
4988753Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
4989753Smax.romanov@nginx.com
4990753Smax.romanov@nginx.com timer = obj;
4991753Smax.romanov@nginx.com app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer);
4992753Smax.romanov@nginx.com
4993753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app_joint, -1);
4994753Smax.romanov@nginx.com }
4995753Smax.romanov@nginx.com
4996507Smax.romanov@nginx.com
4997507Smax.romanov@nginx.com static void
nxt_router_free_app(nxt_task_t * task,void * obj,void * data)4998507Smax.romanov@nginx.com nxt_router_free_app(nxt_task_t *task, void *obj, void *data)
4999507Smax.romanov@nginx.com {
5000753Smax.romanov@nginx.com nxt_app_t *app;
5001507Smax.romanov@nginx.com nxt_port_t *port, *proto_port;
5002753Smax.romanov@nginx.com nxt_app_joint_t *app_joint;
50031998St.nateldemoura@f5.com
5004753Smax.romanov@nginx.com app_joint = obj;
5005753Smax.romanov@nginx.com app = app_joint->app;
5006753Smax.romanov@nginx.com
5007753Smax.romanov@nginx.com for ( ;; ) {
5008753Smax.romanov@nginx.com port = nxt_router_app_get_port_for_quit(task, app);
5009753Smax.romanov@nginx.com if (port == NULL) {
50101549Smax.romanov@nginx.com break;
5011753Smax.romanov@nginx.com }
5012753Smax.romanov@nginx.com
5013753Smax.romanov@nginx.com nxt_port_use(task, port, -1);
5014753Smax.romanov@nginx.com }
5015753Smax.romanov@nginx.com
5016753Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
5017753Smax.romanov@nginx.com
50181658Smax.romanov@nginx.com for ( ;; ) {
50191658Smax.romanov@nginx.com port = nxt_port_hash_retrieve(&app->port_hash);
50201658Smax.romanov@nginx.com if (port == NULL) {
50211658Smax.romanov@nginx.com break;
50221658Smax.romanov@nginx.com }
50231658Smax.romanov@nginx.com
50241658Smax.romanov@nginx.com app->port_hash_count--;
50251658Smax.romanov@nginx.com
50261658Smax.romanov@nginx.com port->app = NULL;
50271658Smax.romanov@nginx.com
50281658Smax.romanov@nginx.com nxt_port_close(task, port);
50291658Smax.romanov@nginx.com
50301658Smax.romanov@nginx.com nxt_port_use(task, port, -1);
50311658Smax.romanov@nginx.com }
50321658Smax.romanov@nginx.com
50331658Smax.romanov@nginx.com proto_port = app->proto_port;
50341658Smax.romanov@nginx.com
50351998St.nateldemoura@f5.com if (proto_port != NULL) {
50361998St.nateldemoura@f5.com nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name,
50371998St.nateldemoura@f5.com proto_port->pid);
50381998St.nateldemoura@f5.com
50391998St.nateldemoura@f5.com app->proto_port = NULL;
50401998St.nateldemoura@f5.com proto_port->app = NULL;
50411998St.nateldemoura@f5.com }
50421998St.nateldemoura@f5.com
50431998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex);
50441998St.nateldemoura@f5.com
50451658Smax.romanov@nginx.com if (proto_port != NULL) {
50461658Smax.romanov@nginx.com nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT,
50471998St.nateldemoura@f5.com -1, 0, 0, NULL);
50481998St.nateldemoura@f5.com
50491998St.nateldemoura@f5.com nxt_port_close(task, proto_port);
50501998St.nateldemoura@f5.com
50511998St.nateldemoura@f5.com nxt_port_use(task, proto_port, -1);
50521998St.nateldemoura@f5.com }
50531998St.nateldemoura@f5.com
50541998St.nateldemoura@f5.com nxt_assert(app->proto_port == NULL);
50551998St.nateldemoura@f5.com nxt_assert(app->processes == 0);
50561998St.nateldemoura@f5.com nxt_assert(app->active_requests == 0);
5057753Smax.romanov@nginx.com nxt_assert(app->port_hash_count == 0);
50581547Smax.romanov@nginx.com nxt_assert(app->idle_processes == 0);
50591547Smax.romanov@nginx.com nxt_assert(nxt_queue_is_empty(&app->ports));
5060753Smax.romanov@nginx.com nxt_assert(nxt_queue_is_empty(&app->spare_ports));
5061753Smax.romanov@nginx.com nxt_assert(nxt_queue_is_empty(&app->idle_ports));
5062753Smax.romanov@nginx.com
5063753Smax.romanov@nginx.com nxt_port_mmaps_destroy(&app->outgoing, 1);
5064753Smax.romanov@nginx.com
50651547Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->outgoing.mutex);
50661547Smax.romanov@nginx.com
50671547Smax.romanov@nginx.com if (app->shared_port != NULL) {
50681547Smax.romanov@nginx.com app->shared_port->app = NULL;
50691547Smax.romanov@nginx.com nxt_port_close(task, app->shared_port);
50701547Smax.romanov@nginx.com nxt_port_use(task, app->shared_port, -1);
50711547Smax.romanov@nginx.com
50721547Smax.romanov@nginx.com app->shared_port = NULL;
50731926Smax.romanov@nginx.com }
50741926Smax.romanov@nginx.com
50751547Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->mutex);
50761547Smax.romanov@nginx.com nxt_mp_destroy(app->mem_pool);
5077753Smax.romanov@nginx.com
50781473Svbart@nginx.com app_joint->app = NULL;
5079753Smax.romanov@nginx.com
5080753Smax.romanov@nginx.com if (nxt_timer_delete(task->thread->engine, &app_joint->idle_timer)) {
5081753Smax.romanov@nginx.com app_joint->idle_timer.handler = nxt_router_app_joint_release_handler;
5082753Smax.romanov@nginx.com nxt_timer_add(task->thread->engine, &app_joint->idle_timer, 0);
5083753Smax.romanov@nginx.com
5084753Smax.romanov@nginx.com } else {
5085753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app_joint, -1);
5086753Smax.romanov@nginx.com }
5087753Smax.romanov@nginx.com }
5088753Smax.romanov@nginx.com
5089141Smax.romanov@nginx.com
5090141Smax.romanov@nginx.com static void
nxt_router_app_port_get(nxt_task_t * task,nxt_app_t * app,nxt_request_rpc_data_t * req_rpc_data)5091141Smax.romanov@nginx.com nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app,
5092427Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data)
50931547Smax.romanov@nginx.com {
50941547Smax.romanov@nginx.com nxt_bool_t start_process;
5095141Smax.romanov@nginx.com nxt_port_t *port;
50961561Smax.romanov@nginx.com nxt_http_request_t *r;
50971561Smax.romanov@nginx.com
50981561Smax.romanov@nginx.com start_process = 0;
50991547Smax.romanov@nginx.com
51001547Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex);
5101427Smax.romanov@nginx.com
5102427Smax.romanov@nginx.com port = app->shared_port;
5103427Smax.romanov@nginx.com nxt_port_inc_use(port);
51041547Smax.romanov@nginx.com
51051547Smax.romanov@nginx.com app->active_requests++;
51061547Smax.romanov@nginx.com
51071547Smax.romanov@nginx.com if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) {
51081547Smax.romanov@nginx.com app->pending_processes++;
51091547Smax.romanov@nginx.com start_process = 1;
51101547Smax.romanov@nginx.com }
51111547Smax.romanov@nginx.com
51121547Smax.romanov@nginx.com r = req_rpc_data->request;
5113427Smax.romanov@nginx.com
51141561Smax.romanov@nginx.com /*
51151561Smax.romanov@nginx.com * Put request into application-wide list to be able to cancel request
51161561Smax.romanov@nginx.com * if something goes wrong with application processes.
51171561Smax.romanov@nginx.com */
51181561Smax.romanov@nginx.com nxt_queue_insert_tail(&app->ack_waiting_req, &r->app_link);
51191561Smax.romanov@nginx.com
51201561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex);
51211561Smax.romanov@nginx.com
5122427Smax.romanov@nginx.com /*
5123427Smax.romanov@nginx.com * Retain request memory pool while request is linked in ack_waiting_req
51241561Smax.romanov@nginx.com * to guarantee request structure memory is accessble.
51251561Smax.romanov@nginx.com */
51261561Smax.romanov@nginx.com nxt_mp_retain(r->mem_pool);
51271561Smax.romanov@nginx.com
51281561Smax.romanov@nginx.com req_rpc_data->app_port = port;
51291561Smax.romanov@nginx.com req_rpc_data->apr_action = NXT_APR_REQUEST_FAILED;
51301547Smax.romanov@nginx.com
51311547Smax.romanov@nginx.com if (start_process) {
51321547Smax.romanov@nginx.com nxt_router_start_app_process(task, app);
51331547Smax.romanov@nginx.com }
51341547Smax.romanov@nginx.com }
51351547Smax.romanov@nginx.com
5136427Smax.romanov@nginx.com
5137427Smax.romanov@nginx.com void
nxt_router_process_http_request(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)5138427Smax.romanov@nginx.com nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r,
5139431Sigor@sysoev.ru nxt_http_action_t *action)
51401007Salexander.borisov@nginx.com {
51411925Sz.hong@f5.com nxt_event_engine_t *engine;
514253Sigor@sysoev.ru nxt_http_app_conf_t *conf;
51431123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data;
51441925Sz.hong@f5.com
51451123Smax.romanov@nginx.com conf = action->u.conf;
5146431Sigor@sysoev.ru engine = task->thread->engine;
51471925Sz.hong@f5.com
514888Smax.romanov@nginx.com r->app_target = conf->target;
514988Smax.romanov@nginx.com
51501925Sz.hong@f5.com req_rpc_data = nxt_port_rpc_register_handler_ex(task, engine->port,
51511925Sz.hong@f5.com nxt_router_response_ready_handler,
51521123Smax.romanov@nginx.com nxt_router_response_error_handler,
5153318Smax.romanov@nginx.com sizeof(nxt_request_rpc_data_t));
5154318Smax.romanov@nginx.com if (nxt_slow_path(req_rpc_data == NULL)) {
51551123Smax.romanov@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
51561123Smax.romanov@nginx.com return;
5157431Sigor@sysoev.ru }
5158141Smax.romanov@nginx.com
515988Smax.romanov@nginx.com /*
516088Smax.romanov@nginx.com * At this point we have request req_rpc_data allocated and registered
51611402Smax.romanov@nginx.com * in port handlers. Need to fixup request memory pool. Counterpart
51621402Smax.romanov@nginx.com * release will be called via following call chain:
51631402Smax.romanov@nginx.com * nxt_request_rpc_data_unlink() ->
51641402Smax.romanov@nginx.com * nxt_router_http_request_release_post() ->
51651402Smax.romanov@nginx.com * nxt_router_http_request_release()
51661547Smax.romanov@nginx.com */
51671402Smax.romanov@nginx.com nxt_mp_retain(r->mem_pool);
51681402Smax.romanov@nginx.com
51691402Smax.romanov@nginx.com r->timer.task = &engine->task;
51701402Smax.romanov@nginx.com r->timer.work_queue = &engine->fast_work_queue;
51711402Smax.romanov@nginx.com r->timer.log = engine->task.log;
51721402Smax.romanov@nginx.com r->timer.bias = NXT_TIMER_DEFAULT_BIAS;
51731402Smax.romanov@nginx.com
51741402Smax.romanov@nginx.com r->engine = engine;
51751402Smax.romanov@nginx.com r->err_work.handler = nxt_router_http_request_error;
51761561Smax.romanov@nginx.com r->err_work.task = task;
51771561Smax.romanov@nginx.com r->err_work.obj = r;
51781561Smax.romanov@nginx.com
51791561Smax.romanov@nginx.com req_rpc_data->stream = nxt_port_rpc_ex_stream(req_rpc_data);
51801561Smax.romanov@nginx.com req_rpc_data->app = conf->app;
51811123Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1;
51821925Sz.hong@f5.com req_rpc_data->rpc_cancel = 1;
51831547Smax.romanov@nginx.com
51841547Smax.romanov@nginx.com nxt_router_app_use(task, conf->app, 1);
5185425Smax.romanov@nginx.com
51861925Sz.hong@f5.com req_rpc_data->request = r;
5187425Smax.romanov@nginx.com r->req_rpc_data = req_rpc_data;
51881123Smax.romanov@nginx.com
51891131Smax.romanov@nginx.com if (r->last != NULL) {
51901123Smax.romanov@nginx.com r->last->completion_handler = nxt_router_http_request_done;
51911547Smax.romanov@nginx.com }
51921547Smax.romanov@nginx.com
51931547Smax.romanov@nginx.com nxt_router_app_port_get(task, conf->app, req_rpc_data);
51941547Smax.romanov@nginx.com nxt_router_app_prepare_request(task, req_rpc_data);
51951925Sz.hong@f5.com }
51961547Smax.romanov@nginx.com
51971547Smax.romanov@nginx.com
51981547Smax.romanov@nginx.com static void
nxt_router_http_request_error(nxt_task_t * task,void * obj,void * data)51991547Smax.romanov@nginx.com nxt_router_http_request_error(nxt_task_t *task, void *obj, void *data)
52001547Smax.romanov@nginx.com {
52011561Smax.romanov@nginx.com nxt_http_request_t *r;
52021561Smax.romanov@nginx.com
52031561Smax.romanov@nginx.com r = obj;
52041561Smax.romanov@nginx.com
52051561Smax.romanov@nginx.com nxt_debug(task, "router http request error (rpc_data %p)", r->req_rpc_data);
52061561Smax.romanov@nginx.com
52071561Smax.romanov@nginx.com nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE);
52081561Smax.romanov@nginx.com
52091561Smax.romanov@nginx.com if (r->req_rpc_data != NULL) {
52101561Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, r->req_rpc_data);
52111561Smax.romanov@nginx.com }
52121561Smax.romanov@nginx.com
52131561Smax.romanov@nginx.com nxt_mp_release(r->mem_pool);
52141561Smax.romanov@nginx.com }
52151561Smax.romanov@nginx.com
52161561Smax.romanov@nginx.com
52171561Smax.romanov@nginx.com static void
nxt_router_http_request_done(nxt_task_t * task,void * obj,void * data)52181561Smax.romanov@nginx.com nxt_router_http_request_done(nxt_task_t *task, void *obj, void *data)
52191561Smax.romanov@nginx.com {
52201547Smax.romanov@nginx.com nxt_http_request_t *r;
52211547Smax.romanov@nginx.com
52221547Smax.romanov@nginx.com r = data;
52231547Smax.romanov@nginx.com
52241547Smax.romanov@nginx.com nxt_debug(task, "router http request done (rpc_data %p)", r->req_rpc_data);
52251547Smax.romanov@nginx.com
52261547Smax.romanov@nginx.com if (r->req_rpc_data != NULL) {
52271547Smax.romanov@nginx.com nxt_request_rpc_data_unlink(task, r->req_rpc_data);
52281561Smax.romanov@nginx.com }
52291547Smax.romanov@nginx.com
52301547Smax.romanov@nginx.com nxt_http_request_close_handler(task, r, r->proto.any);
52311547Smax.romanov@nginx.com }
52321547Smax.romanov@nginx.com
5233167Smax.romanov@nginx.com
5234167Smax.romanov@nginx.com static void
nxt_router_app_prepare_request(nxt_task_t * task,nxt_request_rpc_data_t * req_rpc_data)5235167Smax.romanov@nginx.com nxt_router_app_prepare_request(nxt_task_t *task,
5236167Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data)
52371123Smax.romanov@nginx.com {
52381547Smax.romanov@nginx.com nxt_app_t *app;
5239167Smax.romanov@nginx.com nxt_buf_t *buf, *body;
52401547Smax.romanov@nginx.com nxt_int_t res;
52411547Smax.romanov@nginx.com nxt_port_t *port, *reply_port;
52421123Smax.romanov@nginx.com
52431545Smax.romanov@nginx.com int notify;
52441547Smax.romanov@nginx.com struct {
52451555Smax.romanov@nginx.com nxt_port_msg_t pm;
52461555Smax.romanov@nginx.com nxt_port_mmap_msg_t mm;
52471555Smax.romanov@nginx.com } msg;
52481555Smax.romanov@nginx.com
52491555Smax.romanov@nginx.com
52501555Smax.romanov@nginx.com app = req_rpc_data->app;
52511555Smax.romanov@nginx.com
52521547Smax.romanov@nginx.com nxt_assert(app != NULL);
52531547Smax.romanov@nginx.com
52541547Smax.romanov@nginx.com port = req_rpc_data->app_port;
52551547Smax.romanov@nginx.com
52561547Smax.romanov@nginx.com nxt_assert(port != NULL);
52571547Smax.romanov@nginx.com nxt_assert(port->queue != NULL);
52581547Smax.romanov@nginx.com
52591555Smax.romanov@nginx.com reply_port = task->thread->engine->port;
52601547Smax.romanov@nginx.com
52611547Smax.romanov@nginx.com buf = nxt_router_prepare_msg(task, req_rpc_data->request, app,
52621547Smax.romanov@nginx.com nxt_app_msg_prefix[app->type]);
52631547Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) {
52641547Smax.romanov@nginx.com nxt_alert(task, "stream #%uD, app '%V': failed to prepare app message",
5265743Smax.romanov@nginx.com req_rpc_data->stream, &app->name);
52661547Smax.romanov@nginx.com
52671547Smax.romanov@nginx.com nxt_http_request_error(task, req_rpc_data->request,
52681547Smax.romanov@nginx.com NXT_HTTP_INTERNAL_SERVER_ERROR);
52691547Smax.romanov@nginx.com
52701547Smax.romanov@nginx.com return;
52711547Smax.romanov@nginx.com }
52721547Smax.romanov@nginx.com
5273122Smax.romanov@nginx.com nxt_debug(task, "about to send %O bytes buffer to app process port %d",
527488Smax.romanov@nginx.com nxt_buf_used_size(buf),
5275507Smax.romanov@nginx.com port->socket.fd);
5276743Smax.romanov@nginx.com
5277743Smax.romanov@nginx.com req_rpc_data->msg_info.buf = buf;
527888Smax.romanov@nginx.com
52791547Smax.romanov@nginx.com body = req_rpc_data->request->body;
52801547Smax.romanov@nginx.com
52811547Smax.romanov@nginx.com if (body != NULL && nxt_buf_is_file(body)) {
52821547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = body->file->fd;
52831547Smax.romanov@nginx.com
52841547Smax.romanov@nginx.com body->file->fd = -1;
52851547Smax.romanov@nginx.com
52861547Smax.romanov@nginx.com } else {
52871547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1;
52881547Smax.romanov@nginx.com }
52891547Smax.romanov@nginx.com
52901547Smax.romanov@nginx.com msg.pm.stream = req_rpc_data->stream;
52911547Smax.romanov@nginx.com msg.pm.pid = reply_port->pid;
52921555Smax.romanov@nginx.com msg.pm.reply_port = reply_port->id;
52931555Smax.romanov@nginx.com msg.pm.type = NXT_PORT_MSG_REQ_HEADERS;
52941555Smax.romanov@nginx.com msg.pm.last = 0;
52951555Smax.romanov@nginx.com msg.pm.mmap = 1;
52961555Smax.romanov@nginx.com msg.pm.nf = 0;
52971555Smax.romanov@nginx.com msg.pm.mf = 0;
52981555Smax.romanov@nginx.com
52991555Smax.romanov@nginx.com nxt_port_mmap_handler_t *mmap_handler = buf->parent;
53001555Smax.romanov@nginx.com nxt_port_mmap_header_t *hdr = mmap_handler->hdr;
53011555Smax.romanov@nginx.com
53021555Smax.romanov@nginx.com msg.mm.mmap_id = hdr->id;
53031555Smax.romanov@nginx.com msg.mm.chunk_id = nxt_port_mmap_chunk_id(hdr, buf->mem.pos);
53041555Smax.romanov@nginx.com msg.mm.size = nxt_buf_used_size(buf);
53051555Smax.romanov@nginx.com
53061555Smax.romanov@nginx.com res = nxt_app_queue_send(port->queue, &msg, sizeof(msg),
53071555Smax.romanov@nginx.com req_rpc_data->stream, ¬ify,
53081555Smax.romanov@nginx.com &req_rpc_data->msg_info.tracking_cookie);
53091555Smax.romanov@nginx.com if (nxt_fast_path(res == NXT_OK)) {
53101555Smax.romanov@nginx.com if (notify != 0) {
53111555Smax.romanov@nginx.com (void) nxt_port_socket_write(task, port,
53121555Smax.romanov@nginx.com NXT_PORT_MSG_READ_QUEUE,
53131555Smax.romanov@nginx.com -1, req_rpc_data->stream,
53141555Smax.romanov@nginx.com reply_port->id, NULL);
53151555Smax.romanov@nginx.com
53161555Smax.romanov@nginx.com } else {
53171555Smax.romanov@nginx.com nxt_debug(task, "queue is not empty");
53181555Smax.romanov@nginx.com }
53191555Smax.romanov@nginx.com
53201555Smax.romanov@nginx.com buf->is_port_mmap_sent = 1;
53211555Smax.romanov@nginx.com buf->mem.pos = buf->mem.free;
53221615Smax.romanov@nginx.com
53231615Smax.romanov@nginx.com } else {
53241615Smax.romanov@nginx.com nxt_alert(task, "stream #%uD, app '%V': failed to send app message",
53251555Smax.romanov@nginx.com req_rpc_data->stream, &app->name);
53261547Smax.romanov@nginx.com
53271547Smax.romanov@nginx.com nxt_http_request_error(task, req_rpc_data->request,
53281547Smax.romanov@nginx.com NXT_HTTP_INTERNAL_SERVER_ERROR);
53291547Smax.romanov@nginx.com }
53301547Smax.romanov@nginx.com }
53311547Smax.romanov@nginx.com
533253Sigor@sysoev.ru
533353Sigor@sysoev.ru struct nxt_fields_iter_s {
533453Sigor@sysoev.ru nxt_list_part_t *part;
5335743Smax.romanov@nginx.com nxt_http_field_t *field;
5336743Smax.romanov@nginx.com };
5337743Smax.romanov@nginx.com
5338743Smax.romanov@nginx.com typedef struct nxt_fields_iter_s nxt_fields_iter_t;
5339743Smax.romanov@nginx.com
5340743Smax.romanov@nginx.com
5341743Smax.romanov@nginx.com static nxt_http_field_t *
nxt_fields_part_first(nxt_list_part_t * part,nxt_fields_iter_t * i)5342743Smax.romanov@nginx.com nxt_fields_part_first(nxt_list_part_t *part, nxt_fields_iter_t *i)
5343743Smax.romanov@nginx.com {
5344743Smax.romanov@nginx.com if (part == NULL) {
5345216Sigor@sysoev.ru return NULL;
5346743Smax.romanov@nginx.com }
5347743Smax.romanov@nginx.com
5348216Sigor@sysoev.ru while (part->nelts == 0) {
5349216Sigor@sysoev.ru part = part->next;
5350743Smax.romanov@nginx.com if (part == NULL) {
5351743Smax.romanov@nginx.com return NULL;
5352743Smax.romanov@nginx.com }
5353743Smax.romanov@nginx.com }
5354743Smax.romanov@nginx.com
5355216Sigor@sysoev.ru i->part = part;
5356216Sigor@sysoev.ru i->field = nxt_list_data(i->part);
5357743Smax.romanov@nginx.com
5358743Smax.romanov@nginx.com return i->field;
5359743Smax.romanov@nginx.com }
5360743Smax.romanov@nginx.com
5361743Smax.romanov@nginx.com
5362743Smax.romanov@nginx.com static nxt_http_field_t *
nxt_fields_first(nxt_list_t * fields,nxt_fields_iter_t * i)5363743Smax.romanov@nginx.com nxt_fields_first(nxt_list_t *fields, nxt_fields_iter_t *i)
5364743Smax.romanov@nginx.com {
5365743Smax.romanov@nginx.com return nxt_fields_part_first(nxt_list_part(fields), i);
5366743Smax.romanov@nginx.com }
5367743Smax.romanov@nginx.com
5368743Smax.romanov@nginx.com
5369743Smax.romanov@nginx.com static nxt_http_field_t *
nxt_fields_next(nxt_fields_iter_t * i)5370743Smax.romanov@nginx.com nxt_fields_next(nxt_fields_iter_t *i)
5371743Smax.romanov@nginx.com {
5372743Smax.romanov@nginx.com nxt_http_field_t *end = nxt_list_data(i->part);
5373743Smax.romanov@nginx.com
5374743Smax.romanov@nginx.com end += i->part->nelts;
5375743Smax.romanov@nginx.com i->field++;
5376743Smax.romanov@nginx.com
5377743Smax.romanov@nginx.com if (i->field < end) {
5378743Smax.romanov@nginx.com return i->field;
5379743Smax.romanov@nginx.com }
5380743Smax.romanov@nginx.com
5381216Sigor@sysoev.ru return nxt_fields_part_first(i->part->next, i);
5382216Sigor@sysoev.ru }
5383743Smax.romanov@nginx.com
5384216Sigor@sysoev.ru
5385216Sigor@sysoev.ru static nxt_buf_t *
nxt_router_prepare_msg(nxt_task_t * task,nxt_http_request_t * r,nxt_app_t * app,const nxt_str_t * prefix)5386216Sigor@sysoev.ru nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r,
5387743Smax.romanov@nginx.com nxt_app_t *app, const nxt_str_t *prefix)
53881007Salexander.borisov@nginx.com {
53891547Smax.romanov@nginx.com void *target_pos, *query_pos;
5390216Sigor@sysoev.ru u_char *pos, *end, *p, c;
53911007Salexander.borisov@nginx.com size_t fields_count, req_size, size, free_size;
53921007Salexander.borisov@nginx.com size_t copy_size;
53931007Salexander.borisov@nginx.com nxt_off_t content_length;
53941007Salexander.borisov@nginx.com nxt_buf_t *b, *buf, *out, **tail;
53951007Salexander.borisov@nginx.com nxt_http_field_t *field, *dup;
53961007Salexander.borisov@nginx.com nxt_unit_field_t *dst_field;
53971007Salexander.borisov@nginx.com nxt_fields_iter_t iter, dup_iter;
53981007Salexander.borisov@nginx.com nxt_unit_request_t *req;
53991007Salexander.borisov@nginx.com
54001007Salexander.borisov@nginx.com req_size = sizeof(nxt_unit_request_t)
5401216Sigor@sysoev.ru + r->method->length + 1
5402743Smax.romanov@nginx.com + r->version.length + 1
54031007Salexander.borisov@nginx.com + r->remote->address_length + 1
54041007Salexander.borisov@nginx.com + r->local->address_length + 1
54052374Sa.clayton@nginx.com + nxt_sockaddr_port_length(r->local) + 1
54062374Sa.clayton@nginx.com + r->server_name.length + 1
54072371Sa.clayton@nginx.com + r->target.length + 1
54081007Salexander.borisov@nginx.com + (r->path->start != r->target.start ? r->path->length + 1 : 0);
54091007Salexander.borisov@nginx.com
54101007Salexander.borisov@nginx.com content_length = r->content_length_n < 0 ? 0 : r->content_length_n;
54111007Salexander.borisov@nginx.com fields_count = 0;
54121007Salexander.borisov@nginx.com
5413743Smax.romanov@nginx.com nxt_list_each(field, r->fields) {
5414743Smax.romanov@nginx.com fields_count++;
54151007Salexander.borisov@nginx.com
5416743Smax.romanov@nginx.com req_size += field->name_length + prefix->length + 1
5417743Smax.romanov@nginx.com + field->value_length + 1;
5418743Smax.romanov@nginx.com } nxt_list_loop;
5419743Smax.romanov@nginx.com
5420743Smax.romanov@nginx.com req_size += fields_count * sizeof(nxt_unit_field_t);
5421743Smax.romanov@nginx.com
5422743Smax.romanov@nginx.com if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) {
5423743Smax.romanov@nginx.com nxt_alert(task, "headers to big to fit in shared memory (%d)",
5424743Smax.romanov@nginx.com (int) req_size);
5425743Smax.romanov@nginx.com
5426743Smax.romanov@nginx.com return NULL;
5427743Smax.romanov@nginx.com }
5428743Smax.romanov@nginx.com
5429743Smax.romanov@nginx.com out = nxt_port_mmap_get_buf(task, &app->outgoing,
5430743Smax.romanov@nginx.com nxt_min(req_size + content_length, PORT_MMAP_DATA_SIZE));
54311547Smax.romanov@nginx.com if (nxt_slow_path(out == NULL)) {
54321007Salexander.borisov@nginx.com return NULL;
5433743Smax.romanov@nginx.com }
5434743Smax.romanov@nginx.com
5435743Smax.romanov@nginx.com req = (nxt_unit_request_t *) out->mem.free;
5436743Smax.romanov@nginx.com out->mem.free += req_size;
5437743Smax.romanov@nginx.com
5438743Smax.romanov@nginx.com req->app_target = r->app_target;
5439743Smax.romanov@nginx.com
54401473Svbart@nginx.com req->content_length = content_length;
54411473Svbart@nginx.com
54421007Salexander.borisov@nginx.com p = (u_char *) (req->fields + fields_count);
5443743Smax.romanov@nginx.com
5444743Smax.romanov@nginx.com nxt_debug(task, "fields_count=%d", (int) fields_count);
5445743Smax.romanov@nginx.com
5446743Smax.romanov@nginx.com req->method_length = r->method->length;
5447743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->method, p);
54481007Salexander.borisov@nginx.com p = nxt_cpymem(p, r->method->start, r->method->length);
5449743Smax.romanov@nginx.com *p++ = '\0';
54501007Salexander.borisov@nginx.com
5451743Smax.romanov@nginx.com req->version_length = r->version.length;
5452743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->version, p);
54531007Salexander.borisov@nginx.com p = nxt_cpymem(p, r->version.start, r->version.length);
5454743Smax.romanov@nginx.com *p++ = '\0';
54551007Salexander.borisov@nginx.com
5456743Smax.romanov@nginx.com req->remote_length = r->remote->address_length;
5457743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->remote, p);
54581007Salexander.borisov@nginx.com p = nxt_cpymem(p, nxt_sockaddr_address(r->remote),
5459743Smax.romanov@nginx.com r->remote->address_length);
54601007Salexander.borisov@nginx.com *p++ = '\0';
54611007Salexander.borisov@nginx.com
5462743Smax.romanov@nginx.com req->local_addr_length = r->local->address_length;
5463743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->local_addr, p);
54642208Sa.clayton@nginx.com p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length);
54652208Sa.clayton@nginx.com *p++ = '\0';
54661007Salexander.borisov@nginx.com
5467743Smax.romanov@nginx.com req->local_port_length = nxt_sockaddr_port_length(r->local);
5468743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->local_port, p);
54692230Sa.clayton@nginx.com p = nxt_cpymem(p, nxt_sockaddr_port(r->local),
54702230Sa.clayton@nginx.com nxt_sockaddr_port_length(r->local));
54712230Sa.clayton@nginx.com *p++ = '\0';
54722230Sa.clayton@nginx.com
54732230Sa.clayton@nginx.com req->tls = r->tls;
54742230Sa.clayton@nginx.com req->websocket_handshake = r->websocket_handshake;
54752133Sz.hong@f5.com
54761131Smax.romanov@nginx.com req->server_name_length = r->server_name.length;
54771011Smax.romanov@nginx.com nxt_unit_sptr_set(&req->server_name, p);
54781007Salexander.borisov@nginx.com p = nxt_cpymem(p, r->server_name.start, r->server_name.length);
5479967Svbart@nginx.com *p++ = '\0';
54801007Salexander.borisov@nginx.com
5481967Svbart@nginx.com target_pos = p;
5482967Svbart@nginx.com req->target_length = (uint32_t) r->target.length;
5483743Smax.romanov@nginx.com nxt_unit_sptr_set(&req->target, p);
54841007Salexander.borisov@nginx.com p = nxt_cpymem(p, r->target.start, r->target.length);
5485743Smax.romanov@nginx.com *p++ = '\0';
54861007Salexander.borisov@nginx.com
5487743Smax.romanov@nginx.com req->path_length = (uint32_t) r->path->length;
5488743Smax.romanov@nginx.com if (r->path->start == r->target.start) {
54891007Salexander.borisov@nginx.com nxt_unit_sptr_set(&req->path, target_pos);
54901007Salexander.borisov@nginx.com
5491743Smax.romanov@nginx.com } else {
5492277Sigor@sysoev.ru nxt_unit_sptr_set(&req->path, p);
5493216Sigor@sysoev.ru p = nxt_cpymem(p, r->path->start, r->path->length);
5494743Smax.romanov@nginx.com *p++ = '\0';
54951007Salexander.borisov@nginx.com }
5496743Smax.romanov@nginx.com
5497305Smax.romanov@nginx.com req->query_length = (uint32_t) r->args->length;
5498216Sigor@sysoev.ru if (r->args->start != NULL) {
54991990Sz.hong@f5.com query_pos = nxt_pointer_to(target_pos,
55001990Sz.hong@f5.com r->args->start - r->target.start);
5501743Smax.romanov@nginx.com
55021007Salexander.borisov@nginx.com nxt_unit_sptr_set(&req->query, query_pos);
5503743Smax.romanov@nginx.com
5504743Smax.romanov@nginx.com } else {
5505277Sigor@sysoev.ru req->query.offset = 0;
5506216Sigor@sysoev.ru }
5507743Smax.romanov@nginx.com
5508216Sigor@sysoev.ru req->content_length_field = NXT_UNIT_NONE_FIELD;
5509216Sigor@sysoev.ru req->content_type_field = NXT_UNIT_NONE_FIELD;
5510743Smax.romanov@nginx.com req->cookie_field = NXT_UNIT_NONE_FIELD;
5511743Smax.romanov@nginx.com req->authorization_field = NXT_UNIT_NONE_FIELD;
5512743Smax.romanov@nginx.com
55131733Svbart@nginx.com dst_field = req->fields;
5514743Smax.romanov@nginx.com
5515743Smax.romanov@nginx.com for (field = nxt_fields_first(r->fields, &iter);
5516743Smax.romanov@nginx.com field != NULL;
55171007Salexander.borisov@nginx.com field = nxt_fields_next(&iter))
5518743Smax.romanov@nginx.com {
5519743Smax.romanov@nginx.com if (field->skip) {
5520743Smax.romanov@nginx.com continue;
5521743Smax.romanov@nginx.com }
5522743Smax.romanov@nginx.com
5523743Smax.romanov@nginx.com dst_field->hash = field->hash;
5524743Smax.romanov@nginx.com dst_field->skip = 0;
5525743Smax.romanov@nginx.com dst_field->name_length = field->name_length + prefix->length;
5526743Smax.romanov@nginx.com dst_field->value_length = field->value_length;
5527743Smax.romanov@nginx.com
5528743Smax.romanov@nginx.com if (field == r->content_length) {
5529743Smax.romanov@nginx.com req->content_length_field = dst_field - req->fields;
55301007Salexander.borisov@nginx.com
5531743Smax.romanov@nginx.com } else if (field == r->content_type) {
5532743Smax.romanov@nginx.com req->content_type_field = dst_field - req->fields;
55331007Salexander.borisov@nginx.com
5534743Smax.romanov@nginx.com } else if (field == r->cookie) {
5535743Smax.romanov@nginx.com req->cookie_field = dst_field - req->fields;
55361007Salexander.borisov@nginx.com
5537743Smax.romanov@nginx.com } else if (field == r->authorization) {
55381733Svbart@nginx.com req->authorization_field = dst_field - req->fields;
55391733Svbart@nginx.com }
55401733Svbart@nginx.com
5541743Smax.romanov@nginx.com nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p",
5542743Smax.romanov@nginx.com (int) field->hash, (int) field->skip,
5543743Smax.romanov@nginx.com (int) field->name_length, field->name,
5544743Smax.romanov@nginx.com (int) field->value_length, field->value);
5545743Smax.romanov@nginx.com
5546743Smax.romanov@nginx.com if (prefix->length != 0) {
5547743Smax.romanov@nginx.com nxt_unit_sptr_set(&dst_field->name, p);
5548743Smax.romanov@nginx.com p = nxt_cpymem(p, prefix->start, prefix->length);
5549743Smax.romanov@nginx.com
5550743Smax.romanov@nginx.com end = field->name + field->name_length;
5551743Smax.romanov@nginx.com for (pos = field->name; pos < end; pos++) {
5552743Smax.romanov@nginx.com c = *pos;
5553743Smax.romanov@nginx.com
5554743Smax.romanov@nginx.com if (c >= 'a' && c <= 'z') {
5555743Smax.romanov@nginx.com *p++ = (c & ~0x20);
5556743Smax.romanov@nginx.com continue;
5557743Smax.romanov@nginx.com }
5558743Smax.romanov@nginx.com
5559743Smax.romanov@nginx.com if (c == '-') {
5560743Smax.romanov@nginx.com *p++ = '_';
5561743Smax.romanov@nginx.com continue;
5562743Smax.romanov@nginx.com }
5563743Smax.romanov@nginx.com
5564743Smax.romanov@nginx.com *p++ = c;
5565743Smax.romanov@nginx.com }
5566743Smax.romanov@nginx.com
5567743Smax.romanov@nginx.com } else {
5568743Smax.romanov@nginx.com nxt_unit_sptr_set(&dst_field->name, p);
5569743Smax.romanov@nginx.com p = nxt_cpymem(p, field->name, field->name_length);
5570743Smax.romanov@nginx.com }
5571743Smax.romanov@nginx.com
5572743Smax.romanov@nginx.com *p++ = '\0';
5573743Smax.romanov@nginx.com
5574743Smax.romanov@nginx.com nxt_unit_sptr_set(&dst_field->value, p);
5575743Smax.romanov@nginx.com p = nxt_cpymem(p, field->value, field->value_length);
5576743Smax.romanov@nginx.com
5577743Smax.romanov@nginx.com if (prefix->length != 0) {
5578743Smax.romanov@nginx.com dup_iter = iter;
5579743Smax.romanov@nginx.com
5580743Smax.romanov@nginx.com for (dup = nxt_fields_next(&dup_iter);
5581743Smax.romanov@nginx.com dup != NULL;
5582743Smax.romanov@nginx.com dup = nxt_fields_next(&dup_iter))
5583743Smax.romanov@nginx.com {
5584743Smax.romanov@nginx.com if (dup->name_length != field->name_length
5585743Smax.romanov@nginx.com || dup->skip
5586743Smax.romanov@nginx.com || dup->hash != field->hash
5587743Smax.romanov@nginx.com || nxt_memcasecmp(dup->name, field->name, dup->name_length))
5588743Smax.romanov@nginx.com {
5589743Smax.romanov@nginx.com continue;
5590743Smax.romanov@nginx.com }
5591743Smax.romanov@nginx.com
5592743Smax.romanov@nginx.com p = nxt_cpymem(p, ", ", 2);
5593743Smax.romanov@nginx.com p = nxt_cpymem(p, dup->value, dup->value_length);
5594743Smax.romanov@nginx.com
5595743Smax.romanov@nginx.com dst_field->value_length += 2 + dup->value_length;
5596743Smax.romanov@nginx.com
5597743Smax.romanov@nginx.com dup->skip = 1;
5598743Smax.romanov@nginx.com }
5599743Smax.romanov@nginx.com }
5600743Smax.romanov@nginx.com
5601743Smax.romanov@nginx.com *p++ = '\0';
5602743Smax.romanov@nginx.com
5603743Smax.romanov@nginx.com dst_field++;
5604743Smax.romanov@nginx.com }
5605743Smax.romanov@nginx.com
5606743Smax.romanov@nginx.com req->fields_count = (uint32_t) (dst_field - req->fields);
5607743Smax.romanov@nginx.com
56081007Salexander.borisov@nginx.com nxt_unit_sptr_set(&req->preread_content, out->mem.free);
5609743Smax.romanov@nginx.com
5610743Smax.romanov@nginx.com buf = out;
5611743Smax.romanov@nginx.com tail = &buf->next;
5612743Smax.romanov@nginx.com
5613743Smax.romanov@nginx.com for (b = r->body; b != NULL; b = b->next) {
5614216Sigor@sysoev.ru size = nxt_buf_mem_used_size(&b->mem);
56151007Salexander.borisov@nginx.com pos = b->mem.pos;
5616743Smax.romanov@nginx.com
5617743Smax.romanov@nginx.com while (size > 0) {
5618743Smax.romanov@nginx.com if (buf == NULL) {
5619743Smax.romanov@nginx.com free_size = nxt_min(size, PORT_MMAP_DATA_SIZE);
5620743Smax.romanov@nginx.com
5621743Smax.romanov@nginx.com buf = nxt_port_mmap_get_buf(task, &app->outgoing, free_size);
5622743Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) {
56231547Smax.romanov@nginx.com while (out != NULL) {
5624743Smax.romanov@nginx.com buf = out->next;
5625743Smax.romanov@nginx.com out->next = NULL;
5626743Smax.romanov@nginx.com out->completion_handler(task, out, out->parent);
56271269Sigor@sysoev.ru out = buf;
5628743Smax.romanov@nginx.com }
5629743Smax.romanov@nginx.com return NULL;
5630743Smax.romanov@nginx.com }
5631743Smax.romanov@nginx.com
5632743Smax.romanov@nginx.com *tail = buf;
5633743Smax.romanov@nginx.com tail = &buf->next;
5634743Smax.romanov@nginx.com
5635743Smax.romanov@nginx.com } else {
5636743Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&buf->mem);
5637743Smax.romanov@nginx.com if (free_size < size
5638743Smax.romanov@nginx.com && nxt_port_mmap_increase_buf(task, buf, size, 1)
5639743Smax.romanov@nginx.com == NXT_OK)
5640743Smax.romanov@nginx.com {
5641743Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&buf->mem);
5642743Smax.romanov@nginx.com }
5643743Smax.romanov@nginx.com }
5644743Smax.romanov@nginx.com
5645743Smax.romanov@nginx.com if (free_size > 0) {
5646743Smax.romanov@nginx.com copy_size = nxt_min(free_size, size);
5647743Smax.romanov@nginx.com
5648743Smax.romanov@nginx.com buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size);
5649743Smax.romanov@nginx.com
5650743Smax.romanov@nginx.com size -= copy_size;
5651743Smax.romanov@nginx.com pos += copy_size;
5652743Smax.romanov@nginx.com
5653743Smax.romanov@nginx.com if (size == 0) {
5654743Smax.romanov@nginx.com break;
5655743Smax.romanov@nginx.com }
5656743Smax.romanov@nginx.com }
5657743Smax.romanov@nginx.com
5658743Smax.romanov@nginx.com buf = NULL;
5659743Smax.romanov@nginx.com }
5660743Smax.romanov@nginx.com }
5661743Smax.romanov@nginx.com
5662216Sigor@sysoev.ru return out;
5663216Sigor@sysoev.ru }
5664743Smax.romanov@nginx.com
5665584Salexander.borisov@nginx.com
5666584Salexander.borisov@nginx.com static void
nxt_router_app_timeout(nxt_task_t * task,void * obj,void * data)5667584Salexander.borisov@nginx.com nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data)
566853Sigor@sysoev.ru {
5669318Smax.romanov@nginx.com nxt_timer_t *timer;
5670318Smax.romanov@nginx.com nxt_http_request_t *r;
5671615Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data;
56721007Salexander.borisov@nginx.com
56731123Smax.romanov@nginx.com timer = obj;
5674318Smax.romanov@nginx.com
5675318Smax.romanov@nginx.com nxt_debug(task, "router app timeout");
5676318Smax.romanov@nginx.com
5677318Smax.romanov@nginx.com r = nxt_timer_data(timer, nxt_http_request_t, timer);
5678318Smax.romanov@nginx.com req_rpc_data = r->timer_data;
56791007Salexander.borisov@nginx.com
56801123Smax.romanov@nginx.com nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE);
5681615Smax.romanov@nginx.com
56821007Salexander.borisov@nginx.com nxt_request_rpc_data_unlink(task, req_rpc_data);
5683615Smax.romanov@nginx.com }
56841123Smax.romanov@nginx.com
5685318Smax.romanov@nginx.com
56861007Salexander.borisov@nginx.com static void
nxt_router_http_request_release_post(nxt_task_t * task,nxt_http_request_t * r)56871007Salexander.borisov@nginx.com nxt_router_http_request_release_post(nxt_task_t *task, nxt_http_request_t *r)
56881547Smax.romanov@nginx.com {
56891547Smax.romanov@nginx.com r->timer.handler = nxt_router_http_request_release;
56901007Salexander.borisov@nginx.com nxt_timer_add(task->thread->engine, &r->timer, 0);
56911007Salexander.borisov@nginx.com }
56921007Salexander.borisov@nginx.com
56931007Salexander.borisov@nginx.com
56941007Salexander.borisov@nginx.com static void
nxt_router_http_request_release(nxt_task_t * task,void * obj,void * data)56951007Salexander.borisov@nginx.com nxt_router_http_request_release(nxt_task_t *task, void *obj, void *data)
56961007Salexander.borisov@nginx.com {
56971007Salexander.borisov@nginx.com nxt_http_request_t *r;
56981007Salexander.borisov@nginx.com
56991007Salexander.borisov@nginx.com nxt_debug(task, "http request pool release");
57001007Salexander.borisov@nginx.com
57011547Smax.romanov@nginx.com r = nxt_timer_data(obj, nxt_http_request_t, timer);
57021007Salexander.borisov@nginx.com
57031007Salexander.borisov@nginx.com nxt_mp_release(r->mem_pool);
57041007Salexander.borisov@nginx.com }
57051007Salexander.borisov@nginx.com
57061007Salexander.borisov@nginx.com
57071321Smax.romanov@nginx.com static void
nxt_router_oosm_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)57081321Smax.romanov@nginx.com nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
57091321Smax.romanov@nginx.com {
57101321Smax.romanov@nginx.com size_t mi;
57111321Smax.romanov@nginx.com uint32_t i;
57121321Smax.romanov@nginx.com nxt_bool_t ack;
57131321Smax.romanov@nginx.com nxt_process_t *process;
57141321Smax.romanov@nginx.com nxt_free_map_t *m;
57151321Smax.romanov@nginx.com nxt_port_mmap_handler_t *mmap_handler;
57161321Smax.romanov@nginx.com
57171754Smax.romanov@nginx.com nxt_debug(task, "oosm in %PI", msg->port_msg.pid);
57181321Smax.romanov@nginx.com
57191321Smax.romanov@nginx.com process = nxt_runtime_process_find(task->thread->runtime,
57201321Smax.romanov@nginx.com msg->port_msg.pid);
57211321Smax.romanov@nginx.com if (nxt_slow_path(process == NULL)) {
57221321Smax.romanov@nginx.com return;
57231321Smax.romanov@nginx.com }
57241321Smax.romanov@nginx.com
57251321Smax.romanov@nginx.com ack = 0;
57261321Smax.romanov@nginx.com
57271321Smax.romanov@nginx.com /*
57281321Smax.romanov@nginx.com * To mitigate possible racing condition (when OOSM message received
57291321Smax.romanov@nginx.com * after some of the memory was already freed), need to try to find
57301321Smax.romanov@nginx.com * first free segment in shared memory and send ACK if found.
57311321Smax.romanov@nginx.com */
57321321Smax.romanov@nginx.com
57331321Smax.romanov@nginx.com nxt_thread_mutex_lock(&process->incoming.mutex);
57341321Smax.romanov@nginx.com
57351321Smax.romanov@nginx.com for (i = 0; i < process->incoming.size; i++) {
57361321Smax.romanov@nginx.com mmap_handler = process->incoming.elts[i].mmap_handler;
57371321Smax.romanov@nginx.com
57381754Smax.romanov@nginx.com if (nxt_slow_path(mmap_handler == NULL)) {
57391754Smax.romanov@nginx.com continue;
57401754Smax.romanov@nginx.com }
57411754Smax.romanov@nginx.com
57421754Smax.romanov@nginx.com m = mmap_handler->hdr->free_map;
57431754Smax.romanov@nginx.com
57441754Smax.romanov@nginx.com for (mi = 0; mi < MAX_FREE_IDX; mi++) {
57451321Smax.romanov@nginx.com if (m[mi] != 0) {
57461321Smax.romanov@nginx.com ack = 1;
57471321Smax.romanov@nginx.com
57481321Smax.romanov@nginx.com nxt_debug(task, "oosm: already free #%uD %uz = 0x%08xA",
57491321Smax.romanov@nginx.com i, mi, m[mi]);
57501321Smax.romanov@nginx.com
57511321Smax.romanov@nginx.com break;
57521321Smax.romanov@nginx.com }
57531321Smax.romanov@nginx.com }
57541321Smax.romanov@nginx.com }
57551321Smax.romanov@nginx.com
57561321Smax.romanov@nginx.com nxt_thread_mutex_unlock(&process->incoming.mutex);
57571321Smax.romanov@nginx.com
57581321Smax.romanov@nginx.com if (ack) {
57591321Smax.romanov@nginx.com nxt_process_broadcast_shm_ack(task, process);
57601321Smax.romanov@nginx.com }
57611662Smax.romanov@nginx.com }
57621321Smax.romanov@nginx.com
57631321Smax.romanov@nginx.com
57641545Smax.romanov@nginx.com static void
nxt_router_get_mmap_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)57651545Smax.romanov@nginx.com nxt_router_get_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
57661545Smax.romanov@nginx.com {
57671546Smax.romanov@nginx.com nxt_fd_t fd;
57681546Smax.romanov@nginx.com nxt_port_t *port;
57691546Smax.romanov@nginx.com nxt_runtime_t *rt;
57701546Smax.romanov@nginx.com nxt_port_mmaps_t *mmaps;
57711546Smax.romanov@nginx.com nxt_port_msg_get_mmap_t *get_mmap_msg;
57721546Smax.romanov@nginx.com nxt_port_mmap_handler_t *mmap_handler;
57731546Smax.romanov@nginx.com
57741546Smax.romanov@nginx.com rt = task->thread->runtime;
57751546Smax.romanov@nginx.com
57761546Smax.romanov@nginx.com port = nxt_runtime_port_find(rt, msg->port_msg.pid,
57771546Smax.romanov@nginx.com msg->port_msg.reply_port);
57781546Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) {
57791546Smax.romanov@nginx.com nxt_alert(task, "get_mmap_handler: reply_port %PI:%d not found",
57801546Smax.romanov@nginx.com msg->port_msg.pid, msg->port_msg.reply_port);
57811546Smax.romanov@nginx.com
57821546Smax.romanov@nginx.com return;
57831546Smax.romanov@nginx.com }
57841546Smax.romanov@nginx.com
57851546Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_used_size(msg->buf)
57861546Smax.romanov@nginx.com < (int) sizeof(nxt_port_msg_get_mmap_t)))
57871546Smax.romanov@nginx.com {
57881546Smax.romanov@nginx.com nxt_alert(task, "get_mmap_handler: message buffer too small (%d)",
57891546Smax.romanov@nginx.com (int) nxt_buf_used_size(msg->buf));
57901546Smax.romanov@nginx.com
57911546Smax.romanov@nginx.com return;
57921546Smax.romanov@nginx.com }
57931546Smax.romanov@nginx.com
57941546Smax.romanov@nginx.com get_mmap_msg = (nxt_port_msg_get_mmap_t *) msg->buf->mem.pos;
57951546Smax.romanov@nginx.com
57961546Smax.romanov@nginx.com nxt_assert(port->type == NXT_PROCESS_APP);
57971546Smax.romanov@nginx.com
57981546Smax.romanov@nginx.com if (nxt_slow_path(port->app == NULL)) {
57991546Smax.romanov@nginx.com nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d",
58001547Smax.romanov@nginx.com port->pid, port->id);
58011547Smax.romanov@nginx.com
58021547Smax.romanov@nginx.com // FIXME
58031547Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
58041547Smax.romanov@nginx.com -1, msg->port_msg.stream, 0, NULL);
58051547Smax.romanov@nginx.com
58061547Smax.romanov@nginx.com return;
58071547Smax.romanov@nginx.com }
58081547Smax.romanov@nginx.com
58091547Smax.romanov@nginx.com mmaps = &port->app->outgoing;
58101547Smax.romanov@nginx.com nxt_thread_mutex_lock(&mmaps->mutex);
58111547Smax.romanov@nginx.com
58121546Smax.romanov@nginx.com if (nxt_slow_path(get_mmap_msg->id >= mmaps->size)) {
58131546Smax.romanov@nginx.com nxt_thread_mutex_unlock(&mmaps->mutex);
58141546Smax.romanov@nginx.com
58151546Smax.romanov@nginx.com nxt_alert(task, "get_mmap_handler: mmap id is too big (%d)",
58161546Smax.romanov@nginx.com (int) get_mmap_msg->id);
58171546Smax.romanov@nginx.com
58181546Smax.romanov@nginx.com // FIXME
58191546Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
58201547Smax.romanov@nginx.com -1, msg->port_msg.stream, 0, NULL);
58211547Smax.romanov@nginx.com return;
58221547Smax.romanov@nginx.com }
58231546Smax.romanov@nginx.com
58241546Smax.romanov@nginx.com mmap_handler = mmaps->elts[get_mmap_msg->id].mmap_handler;
58251546Smax.romanov@nginx.com
58261546Smax.romanov@nginx.com fd = mmap_handler->fd;
58271546Smax.romanov@nginx.com
58281546Smax.romanov@nginx.com nxt_thread_mutex_unlock(&mmaps->mutex);
58291546Smax.romanov@nginx.com
58301546Smax.romanov@nginx.com nxt_debug(task, "get mmap %PI:%d found",
58311546Smax.romanov@nginx.com msg->port_msg.pid, (int) get_mmap_msg->id);
58321546Smax.romanov@nginx.com
58331546Smax.romanov@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, NULL);
58341546Smax.romanov@nginx.com }
58351546Smax.romanov@nginx.com
58361546Smax.romanov@nginx.com
58371546Smax.romanov@nginx.com static void
nxt_router_get_port_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)58381546Smax.romanov@nginx.com nxt_router_get_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
58391546Smax.romanov@nginx.com {
58401545Smax.romanov@nginx.com nxt_port_t *port, *reply_port;
58411545Smax.romanov@nginx.com nxt_runtime_t *rt;
58421545Smax.romanov@nginx.com nxt_port_msg_get_port_t *get_port_msg;
58431545Smax.romanov@nginx.com
58441545Smax.romanov@nginx.com rt = task->thread->runtime;
58451545Smax.romanov@nginx.com
58461545Smax.romanov@nginx.com reply_port = nxt_runtime_port_find(rt, msg->port_msg.pid,
58471545Smax.romanov@nginx.com msg->port_msg.reply_port);
58481545Smax.romanov@nginx.com if (nxt_slow_path(reply_port == NULL)) {
58491545Smax.romanov@nginx.com nxt_alert(task, "get_port_handler: reply_port %PI:%d not found",
58501545Smax.romanov@nginx.com msg->port_msg.pid, msg->port_msg.reply_port);
58511545Smax.romanov@nginx.com
58521545Smax.romanov@nginx.com return;
58531545Smax.romanov@nginx.com }
58541545Smax.romanov@nginx.com
58551545Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_used_size(msg->buf)
58561545Smax.romanov@nginx.com < (int) sizeof(nxt_port_msg_get_port_t)))
58571545Smax.romanov@nginx.com {
58581545Smax.romanov@nginx.com nxt_alert(task, "get_port_handler: message buffer too small (%d)",
58591545Smax.romanov@nginx.com (int) nxt_buf_used_size(msg->buf));
58601545Smax.romanov@nginx.com
58611545Smax.romanov@nginx.com return;
58621545Smax.romanov@nginx.com }
58631545Smax.romanov@nginx.com
58641545Smax.romanov@nginx.com get_port_msg = (nxt_port_msg_get_port_t *) msg->buf->mem.pos;
58651545Smax.romanov@nginx.com
58661545Smax.romanov@nginx.com port = nxt_runtime_port_find(rt, get_port_msg->pid, get_port_msg->id);
58671545Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) {
58681545Smax.romanov@nginx.com nxt_alert(task, "get_port_handler: port %PI:%d not found",
58691545Smax.romanov@nginx.com get_port_msg->pid, get_port_msg->id);
58701545Smax.romanov@nginx.com
58711545Smax.romanov@nginx.com return;
58721545Smax.romanov@nginx.com }
58731545Smax.romanov@nginx.com
58741545Smax.romanov@nginx.com nxt_debug(task, "get port %PI:%d found", get_port_msg->pid,
58751545Smax.romanov@nginx.com get_port_msg->id);
58761545Smax.romanov@nginx.com
58771545Smax.romanov@nginx.com (void) nxt_port_send_port(task, reply_port, port, msg->port_msg.stream);
58781545Smax.romanov@nginx.com }
58791545Smax.romanov@nginx.com