xref: /unit/src/nxt_router.c (revision 318)
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>
1020Sigor@sysoev.ru 
1120Sigor@sysoev.ru 
12115Sigor@sysoev.ru typedef struct {
13*318Smax.romanov@nginx.com     nxt_str_t         type;
14*318Smax.romanov@nginx.com     uint32_t          workers;
15*318Smax.romanov@nginx.com     nxt_msec_t        timeout;
16*318Smax.romanov@nginx.com     uint32_t          requests;
17*318Smax.romanov@nginx.com     nxt_conf_value_t  *limits_value;
18133Sigor@sysoev.ru } nxt_router_app_conf_t;
19133Sigor@sysoev.ru 
20133Sigor@sysoev.ru 
21133Sigor@sysoev.ru typedef struct {
22133Sigor@sysoev.ru     nxt_str_t  application;
23115Sigor@sysoev.ru } nxt_router_listener_conf_t;
24115Sigor@sysoev.ru 
25115Sigor@sysoev.ru 
26167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t;
27141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t;
28141Smax.romanov@nginx.com 
29141Smax.romanov@nginx.com struct nxt_start_worker_s {
30141Smax.romanov@nginx.com     nxt_app_t              *app;
31167Smax.romanov@nginx.com     nxt_req_app_link_t     *ra;
32141Smax.romanov@nginx.com 
33141Smax.romanov@nginx.com     nxt_work_t             work;
34141Smax.romanov@nginx.com };
35141Smax.romanov@nginx.com 
36141Smax.romanov@nginx.com 
37*318Smax.romanov@nginx.com typedef struct {
38*318Smax.romanov@nginx.com     uint32_t             stream;
39*318Smax.romanov@nginx.com     nxt_conn_t           *conn;
40*318Smax.romanov@nginx.com     nxt_port_t           *app_port;
41*318Smax.romanov@nginx.com     nxt_req_app_link_t   *ra;
42*318Smax.romanov@nginx.com 
43*318Smax.romanov@nginx.com     nxt_queue_link_t     link;     /* for nxt_conn_t.requests */
44*318Smax.romanov@nginx.com } nxt_req_conn_link_t;
45*318Smax.romanov@nginx.com 
46*318Smax.romanov@nginx.com 
47167Smax.romanov@nginx.com struct nxt_req_app_link_s {
48*318Smax.romanov@nginx.com     uint32_t             stream;
49167Smax.romanov@nginx.com     nxt_port_t           *app_port;
50*318Smax.romanov@nginx.com     nxt_pid_t            app_pid;
51167Smax.romanov@nginx.com     nxt_port_t           *reply_port;
52167Smax.romanov@nginx.com     nxt_app_parse_ctx_t  *ap;
53167Smax.romanov@nginx.com     nxt_req_conn_link_t  *rc;
54167Smax.romanov@nginx.com 
55167Smax.romanov@nginx.com     nxt_queue_link_t     link; /* for nxt_app_t.requests */
56167Smax.romanov@nginx.com 
57167Smax.romanov@nginx.com     nxt_mp_t             *mem_pool;
58167Smax.romanov@nginx.com     nxt_work_t           work;
59167Smax.romanov@nginx.com };
60167Smax.romanov@nginx.com 
61167Smax.romanov@nginx.com 
62198Sigor@sysoev.ru typedef struct {
63198Sigor@sysoev.ru     nxt_socket_conf_t       *socket_conf;
64198Sigor@sysoev.ru     nxt_router_temp_conf_t  *temp_conf;
65198Sigor@sysoev.ru } nxt_socket_rpc_t;
66198Sigor@sysoev.ru 
67198Sigor@sysoev.ru 
68*318Smax.romanov@nginx.com typedef struct {
69*318Smax.romanov@nginx.com     nxt_mp_t             *mem_pool;
70*318Smax.romanov@nginx.com     nxt_port_recv_msg_t  msg;
71*318Smax.romanov@nginx.com     nxt_work_t           work;
72*318Smax.romanov@nginx.com } nxt_remove_pid_msg_t;
73*318Smax.romanov@nginx.com 
74*318Smax.romanov@nginx.com 
75*318Smax.romanov@nginx.com static void nxt_router_worker_remove_pid_handler(nxt_task_t *task, void *obj,
76*318Smax.romanov@nginx.com     void *data);
77*318Smax.romanov@nginx.com static void nxt_router_worker_remove_pid_done(nxt_task_t *task, void *obj,
78*318Smax.romanov@nginx.com     void *data);
79*318Smax.romanov@nginx.com 
80139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
81198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
82198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task,
83139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
84139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task,
85139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
86139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task,
87193Smax.romanov@nginx.com     nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
8853Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router,
8953Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
9053Sigor@sysoev.ru 
91115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
92115Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
93133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
94133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf,
95133Sigor@sysoev.ru     nxt_str_t *name);
96198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task,
97198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf);
98198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task,
99198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
100198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task,
101198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
10265Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp,
10365Sigor@sysoev.ru     nxt_sockaddr_t *sa);
10453Sigor@sysoev.ru 
10553Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task,
10653Sigor@sysoev.ru     nxt_router_t *router, nxt_router_temp_conf_t *tmcf,
10753Sigor@sysoev.ru     const nxt_event_interface_t *interface);
108115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf,
109115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
110115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf,
111115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
112115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf,
113115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
114115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets);
115154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf,
116154Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets,
117154Sigor@sysoev.ru     nxt_work_handler_t handler);
118313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf,
119313Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
120139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
121139Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets);
12253Sigor@sysoev.ru 
12353Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
12453Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
12553Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
12653Sigor@sysoev.ru     nxt_event_engine_t *engine);
127133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router,
128133Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
12953Sigor@sysoev.ru 
130315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router,
131315Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
132315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine,
133315Sigor@sysoev.ru     nxt_work_t *jobs);
13453Sigor@sysoev.ru 
13553Sigor@sysoev.ru static void nxt_router_thread_start(void *data);
13653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj,
13753Sigor@sysoev.ru     void *data);
13853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj,
13953Sigor@sysoev.ru     void *data);
14053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj,
14153Sigor@sysoev.ru     void *data);
142313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj,
143313Sigor@sysoev.ru     void *data);
14453Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj,
14553Sigor@sysoev.ru     void *data);
14653Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task,
14753Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
14853Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj,
14953Sigor@sysoev.ru     void *data);
15053Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task,
15153Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
15253Sigor@sysoev.ru 
153167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj,
154167Smax.romanov@nginx.com     void *data);
155167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app);
156*318Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t stream);
157141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj,
158141Smax.romanov@nginx.com     void *data);
159141Smax.romanov@nginx.com 
16053Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data);
16153Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj,
16253Sigor@sysoev.ru     void *data);
163206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj,
164206Smax.romanov@nginx.com     void *data);
16588Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task,
16688Smax.romanov@nginx.com     nxt_conn_t *c, nxt_app_parse_ctx_t *ap);
167141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task,
168167Smax.romanov@nginx.com     nxt_req_app_link_t *ra, nxt_port_t *port);
169216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
170216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
171216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
172216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
173216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
174216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
17588Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data);
17653Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data);
17753Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data);
17853Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data);
17953Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data);
180*318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data);
18162Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data);
18220Sigor@sysoev.ru 
183141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code,
184141Smax.romanov@nginx.com     const char* fmt, ...);
185141Smax.romanov@nginx.com 
186119Smax.romanov@nginx.com static nxt_router_t  *nxt_router;
18720Sigor@sysoev.ru 
188216Sigor@sysoev.ru 
189216Sigor@sysoev.ru static nxt_app_prepare_msg_t  nxt_app_prepare_msg[] = {
190216Sigor@sysoev.ru     nxt_python_prepare_msg,
191216Sigor@sysoev.ru     nxt_php_prepare_msg,
192216Sigor@sysoev.ru     nxt_go_prepare_msg,
193216Sigor@sysoev.ru };
194216Sigor@sysoev.ru 
195216Sigor@sysoev.ru 
19620Sigor@sysoev.ru nxt_int_t
197141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data)
19820Sigor@sysoev.ru {
199141Smax.romanov@nginx.com     nxt_int_t      ret;
200141Smax.romanov@nginx.com     nxt_router_t   *router;
201141Smax.romanov@nginx.com     nxt_runtime_t  *rt;
202141Smax.romanov@nginx.com 
203141Smax.romanov@nginx.com     rt = task->thread->runtime;
20453Sigor@sysoev.ru 
20588Smax.romanov@nginx.com     ret = nxt_app_http_init(task, rt);
20688Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
20788Smax.romanov@nginx.com         return ret;
20888Smax.romanov@nginx.com     }
20988Smax.romanov@nginx.com 
21053Sigor@sysoev.ru     router = nxt_zalloc(sizeof(nxt_router_t));
21153Sigor@sysoev.ru     if (nxt_slow_path(router == NULL)) {
21253Sigor@sysoev.ru         return NXT_ERROR;
21353Sigor@sysoev.ru     }
21453Sigor@sysoev.ru 
21553Sigor@sysoev.ru     nxt_queue_init(&router->engines);
21653Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
217133Sigor@sysoev.ru     nxt_queue_init(&router->apps);
21853Sigor@sysoev.ru 
219119Smax.romanov@nginx.com     nxt_router = router;
220119Smax.romanov@nginx.com 
221115Sigor@sysoev.ru     return NXT_OK;
222115Sigor@sysoev.ru }
223115Sigor@sysoev.ru 
224115Sigor@sysoev.ru 
225167Smax.romanov@nginx.com static nxt_start_worker_t *
226192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra)
227167Smax.romanov@nginx.com {
228240Sigor@sysoev.ru     nxt_port_t          *main_port;
229167Smax.romanov@nginx.com     nxt_runtime_t       *rt;
230167Smax.romanov@nginx.com     nxt_start_worker_t  *sw;
231167Smax.romanov@nginx.com 
232192Smax.romanov@nginx.com     sw = nxt_zalloc(sizeof(nxt_start_worker_t));
233167Smax.romanov@nginx.com 
234167Smax.romanov@nginx.com     if (nxt_slow_path(sw == NULL)) {
235167Smax.romanov@nginx.com         return NULL;
236167Smax.romanov@nginx.com     }
237167Smax.romanov@nginx.com 
238167Smax.romanov@nginx.com     sw->app = app;
239167Smax.romanov@nginx.com     sw->ra = ra;
240167Smax.romanov@nginx.com 
241*318Smax.romanov@nginx.com     nxt_debug(task, "sw %p create, stream #%uD, app '%V' %p", sw,
242*318Smax.romanov@nginx.com                     ra->stream, &app->name, app);
243167Smax.romanov@nginx.com 
244167Smax.romanov@nginx.com     rt = task->thread->runtime;
245240Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MAIN];
246167Smax.romanov@nginx.com 
247167Smax.romanov@nginx.com     sw->work.handler = nxt_router_send_sw_request;
248240Sigor@sysoev.ru     sw->work.task = &main_port->engine->task;
249167Smax.romanov@nginx.com     sw->work.obj = sw;
250167Smax.romanov@nginx.com     sw->work.data = task->thread->engine;
251167Smax.romanov@nginx.com     sw->work.next = NULL;
252167Smax.romanov@nginx.com 
253240Sigor@sysoev.ru     if (task->thread->engine != main_port->engine) {
254240Sigor@sysoev.ru         nxt_debug(task, "sw %p post send to main engine %p", sw,
255240Sigor@sysoev.ru                   main_port->engine);
256240Sigor@sysoev.ru 
257240Sigor@sysoev.ru         nxt_event_engine_post(main_port->engine, &sw->work);
258167Smax.romanov@nginx.com 
259167Smax.romanov@nginx.com     } else {
260167Smax.romanov@nginx.com         nxt_router_send_sw_request(task, sw, sw->work.data);
261167Smax.romanov@nginx.com     }
262167Smax.romanov@nginx.com 
263167Smax.romanov@nginx.com     return sw;
264167Smax.romanov@nginx.com }
265167Smax.romanov@nginx.com 
266167Smax.romanov@nginx.com 
267192Smax.romanov@nginx.com nxt_inline void
268192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw)
269141Smax.romanov@nginx.com {
270192Smax.romanov@nginx.com     nxt_debug(task, "sw %p release", sw);
271192Smax.romanov@nginx.com 
272192Smax.romanov@nginx.com     nxt_free(sw);
273141Smax.romanov@nginx.com }
274141Smax.romanov@nginx.com 
275141Smax.romanov@nginx.com 
276*318Smax.romanov@nginx.com nxt_inline void
277*318Smax.romanov@nginx.com nxt_router_rc_unlink(nxt_req_conn_link_t *rc)
278*318Smax.romanov@nginx.com {
279*318Smax.romanov@nginx.com     nxt_queue_remove(&rc->link);
280*318Smax.romanov@nginx.com 
281*318Smax.romanov@nginx.com     if (rc->ra != NULL) {
282*318Smax.romanov@nginx.com         rc->ra->rc = NULL;
283*318Smax.romanov@nginx.com         rc->ra = NULL;
284*318Smax.romanov@nginx.com     }
285*318Smax.romanov@nginx.com 
286*318Smax.romanov@nginx.com     rc->conn = NULL;
287*318Smax.romanov@nginx.com }
288*318Smax.romanov@nginx.com 
289*318Smax.romanov@nginx.com 
290167Smax.romanov@nginx.com static nxt_req_app_link_t *
291167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc)
292167Smax.romanov@nginx.com {
293167Smax.romanov@nginx.com     nxt_mp_t            *mp;
294*318Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
295167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
296167Smax.romanov@nginx.com 
297167Smax.romanov@nginx.com     mp = rc->conn->mem_pool;
298*318Smax.romanov@nginx.com     engine = task->thread->engine;
299167Smax.romanov@nginx.com 
300167Smax.romanov@nginx.com     ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t));
301167Smax.romanov@nginx.com 
302167Smax.romanov@nginx.com     if (nxt_slow_path(ra == NULL)) {
303167Smax.romanov@nginx.com         return NULL;
304167Smax.romanov@nginx.com     }
305167Smax.romanov@nginx.com 
306*318Smax.romanov@nginx.com     nxt_debug(task, "ra stream #%uD create", rc->stream);
307167Smax.romanov@nginx.com 
308167Smax.romanov@nginx.com     nxt_memzero(ra, sizeof(nxt_req_app_link_t));
309167Smax.romanov@nginx.com 
310*318Smax.romanov@nginx.com     ra->stream = rc->stream;
311*318Smax.romanov@nginx.com     ra->app_pid = -1;
312167Smax.romanov@nginx.com     ra->rc = rc;
313*318Smax.romanov@nginx.com     rc->ra = ra;
314*318Smax.romanov@nginx.com     ra->reply_port = engine->port;
315167Smax.romanov@nginx.com 
316167Smax.romanov@nginx.com     ra->mem_pool = mp;
317167Smax.romanov@nginx.com 
318167Smax.romanov@nginx.com     ra->work.handler = NULL;
319*318Smax.romanov@nginx.com     ra->work.task = &engine->task;
320167Smax.romanov@nginx.com     ra->work.obj = ra;
321*318Smax.romanov@nginx.com     ra->work.data = engine;
322167Smax.romanov@nginx.com 
323167Smax.romanov@nginx.com     return ra;
324167Smax.romanov@nginx.com }
325167Smax.romanov@nginx.com 
326167Smax.romanov@nginx.com 
327167Smax.romanov@nginx.com static void
328167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data)
329167Smax.romanov@nginx.com {
330*318Smax.romanov@nginx.com     nxt_port_t          *app_port;
331*318Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
332*318Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
333*318Smax.romanov@nginx.com 
334*318Smax.romanov@nginx.com     ra = obj;
335*318Smax.romanov@nginx.com     engine = data;
336*318Smax.romanov@nginx.com 
337*318Smax.romanov@nginx.com     if (ra->app_port != NULL) {
338*318Smax.romanov@nginx.com 
339*318Smax.romanov@nginx.com         app_port = ra->app_port;
340*318Smax.romanov@nginx.com         ra->app_port = NULL;
341*318Smax.romanov@nginx.com 
342*318Smax.romanov@nginx.com         if (task->thread->engine != engine) {
343*318Smax.romanov@nginx.com             ra->app_pid = app_port->pid;
344*318Smax.romanov@nginx.com         }
345*318Smax.romanov@nginx.com 
346*318Smax.romanov@nginx.com         nxt_router_app_release_port(task, app_port, app_port->app);
347*318Smax.romanov@nginx.com 
348*318Smax.romanov@nginx.com #if 0
349*318Smax.romanov@nginx.com         /* Uncomment to hold app port until complete response received. */
350*318Smax.romanov@nginx.com         if (ra->rc != NULL) {
351*318Smax.romanov@nginx.com             ra->rc->app_port = ra->app_port;
352*318Smax.romanov@nginx.com 
353*318Smax.romanov@nginx.com         } else {
354*318Smax.romanov@nginx.com             nxt_router_app_release_port(task, ra->app_port, ra->app_port->app);
355*318Smax.romanov@nginx.com         }
356*318Smax.romanov@nginx.com #endif
357*318Smax.romanov@nginx.com     }
358*318Smax.romanov@nginx.com 
359*318Smax.romanov@nginx.com     if (task->thread->engine != engine) {
360*318Smax.romanov@nginx.com         ra->work.handler = nxt_router_ra_release;
361*318Smax.romanov@nginx.com         ra->work.task = &engine->task;
362*318Smax.romanov@nginx.com         ra->work.next = NULL;
363*318Smax.romanov@nginx.com 
364*318Smax.romanov@nginx.com         nxt_debug(task, "ra stream #%uD post release to %p",
365*318Smax.romanov@nginx.com                   ra->stream, engine);
366*318Smax.romanov@nginx.com 
367*318Smax.romanov@nginx.com         nxt_event_engine_post(engine, &ra->work);
368*318Smax.romanov@nginx.com 
369*318Smax.romanov@nginx.com         return;
370*318Smax.romanov@nginx.com     }
371*318Smax.romanov@nginx.com 
372*318Smax.romanov@nginx.com     if (ra->rc != NULL && ra->app_pid != -1) {
373*318Smax.romanov@nginx.com         nxt_port_rpc_ex_set_peer(task, engine->port, ra->rc, ra->app_pid);
374*318Smax.romanov@nginx.com     }
375*318Smax.romanov@nginx.com 
376*318Smax.romanov@nginx.com     nxt_debug(task, "ra stream #%uD release", ra->stream);
377*318Smax.romanov@nginx.com 
378*318Smax.romanov@nginx.com     nxt_mp_release(ra->mem_pool, ra);
379*318Smax.romanov@nginx.com }
380*318Smax.romanov@nginx.com 
381*318Smax.romanov@nginx.com 
382*318Smax.romanov@nginx.com static void
383*318Smax.romanov@nginx.com nxt_router_ra_abort(nxt_task_t *task, void *obj, void *data)
384*318Smax.romanov@nginx.com {
385*318Smax.romanov@nginx.com     nxt_conn_t          *c;
386167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
387167Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
388167Smax.romanov@nginx.com 
389167Smax.romanov@nginx.com     ra = obj;
390167Smax.romanov@nginx.com     engine = data;
391167Smax.romanov@nginx.com 
392167Smax.romanov@nginx.com     if (task->thread->engine != engine) {
393*318Smax.romanov@nginx.com         ra->work.handler = nxt_router_ra_abort;
394167Smax.romanov@nginx.com         ra->work.task = &engine->task;
395167Smax.romanov@nginx.com         ra->work.next = NULL;
396167Smax.romanov@nginx.com 
397*318Smax.romanov@nginx.com         nxt_debug(task, "ra stream #%uD post abort to %p", ra->stream, engine);
398167Smax.romanov@nginx.com 
399167Smax.romanov@nginx.com         nxt_event_engine_post(engine, &ra->work);
400167Smax.romanov@nginx.com 
401167Smax.romanov@nginx.com         return;
402167Smax.romanov@nginx.com     }
403167Smax.romanov@nginx.com 
404*318Smax.romanov@nginx.com     nxt_debug(task, "ra stream #%uD abort", ra->stream);
405*318Smax.romanov@nginx.com 
406*318Smax.romanov@nginx.com     if (ra->rc != NULL) {
407*318Smax.romanov@nginx.com         c = ra->rc->conn;
408*318Smax.romanov@nginx.com 
409*318Smax.romanov@nginx.com         nxt_router_gen_error(task, c, 500,
410*318Smax.romanov@nginx.com                              "Failed to start application worker");
411167Smax.romanov@nginx.com     }
412167Smax.romanov@nginx.com 
413167Smax.romanov@nginx.com     nxt_mp_release(ra->mem_pool, ra);
414167Smax.romanov@nginx.com }
415167Smax.romanov@nginx.com 
416167Smax.romanov@nginx.com 
417141Smax.romanov@nginx.com void
418141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
419141Smax.romanov@nginx.com {
420141Smax.romanov@nginx.com     nxt_port_new_port_handler(task, msg);
421141Smax.romanov@nginx.com 
422192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
423141Smax.romanov@nginx.com         return;
424141Smax.romanov@nginx.com     }
425141Smax.romanov@nginx.com 
426192Smax.romanov@nginx.com     if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) {
427192Smax.romanov@nginx.com         msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
428141Smax.romanov@nginx.com     }
429192Smax.romanov@nginx.com 
430192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
431141Smax.romanov@nginx.com }
432141Smax.romanov@nginx.com 
433141Smax.romanov@nginx.com 
434139Sigor@sysoev.ru void
435139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
436115Sigor@sysoev.ru {
437139Sigor@sysoev.ru     size_t                  dump_size;
438198Sigor@sysoev.ru     nxt_int_t               ret;
439139Sigor@sysoev.ru     nxt_buf_t               *b;
440139Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
441139Sigor@sysoev.ru 
442139Sigor@sysoev.ru     b = msg->buf;
443139Sigor@sysoev.ru 
444139Sigor@sysoev.ru     dump_size = nxt_buf_used_size(b);
445139Sigor@sysoev.ru 
446139Sigor@sysoev.ru     if (dump_size > 300) {
447139Sigor@sysoev.ru         dump_size = 300;
44853Sigor@sysoev.ru     }
44953Sigor@sysoev.ru 
450139Sigor@sysoev.ru     nxt_debug(task, "router conf data (%z): %*s",
451139Sigor@sysoev.ru               msg->size, dump_size, b->mem.pos);
452139Sigor@sysoev.ru 
453139Sigor@sysoev.ru     tmcf = nxt_router_temp_conf(task);
454139Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
455139Sigor@sysoev.ru         return;
45653Sigor@sysoev.ru     }
45753Sigor@sysoev.ru 
458139Sigor@sysoev.ru     tmcf->conf->router = nxt_router;
459139Sigor@sysoev.ru     tmcf->stream = msg->port_msg.stream;
460139Sigor@sysoev.ru     tmcf->port = nxt_runtime_port_find(task->thread->runtime,
461198Sigor@sysoev.ru                                        msg->port_msg.pid,
462198Sigor@sysoev.ru                                        msg->port_msg.reply_port);
463198Sigor@sysoev.ru 
464198Sigor@sysoev.ru     ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free);
465198Sigor@sysoev.ru 
466198Sigor@sysoev.ru     if (nxt_fast_path(ret == NXT_OK)) {
467198Sigor@sysoev.ru         nxt_router_conf_apply(task, tmcf, NULL);
468198Sigor@sysoev.ru 
469198Sigor@sysoev.ru     } else {
470198Sigor@sysoev.ru         nxt_router_conf_error(task, tmcf);
471139Sigor@sysoev.ru     }
47253Sigor@sysoev.ru }
47353Sigor@sysoev.ru 
47453Sigor@sysoev.ru 
475192Smax.romanov@nginx.com void
476192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
477192Smax.romanov@nginx.com {
478*318Smax.romanov@nginx.com     nxt_mp_t              *mp;
479*318Smax.romanov@nginx.com     nxt_buf_t             *buf;
480*318Smax.romanov@nginx.com     nxt_event_engine_t    *engine;
481*318Smax.romanov@nginx.com     nxt_remove_pid_msg_t  *rp;
482*318Smax.romanov@nginx.com 
483192Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, msg);
484192Smax.romanov@nginx.com 
485192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
486192Smax.romanov@nginx.com         return;
487192Smax.romanov@nginx.com     }
488192Smax.romanov@nginx.com 
489*318Smax.romanov@nginx.com     mp = nxt_mp_create(1024, 128, 256, 32);
490*318Smax.romanov@nginx.com 
491*318Smax.romanov@nginx.com     buf = nxt_buf_mem_alloc(mp, nxt_buf_used_size(msg->buf), 0);
492*318Smax.romanov@nginx.com     buf->mem.free = nxt_cpymem(buf->mem.free, msg->buf->mem.pos,
493*318Smax.romanov@nginx.com                                nxt_buf_used_size(msg->buf));
494*318Smax.romanov@nginx.com 
495*318Smax.romanov@nginx.com     nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0)
496*318Smax.romanov@nginx.com     {
497*318Smax.romanov@nginx.com         rp = nxt_mp_retain(mp, sizeof(nxt_remove_pid_msg_t));
498*318Smax.romanov@nginx.com 
499*318Smax.romanov@nginx.com         rp->mem_pool = mp;
500*318Smax.romanov@nginx.com 
501*318Smax.romanov@nginx.com         rp->msg.fd = msg->fd;
502*318Smax.romanov@nginx.com         rp->msg.buf = buf;
503*318Smax.romanov@nginx.com         rp->msg.port = engine->port;
504*318Smax.romanov@nginx.com         rp->msg.port_msg = msg->port_msg;
505*318Smax.romanov@nginx.com         rp->msg.size = msg->size;
506*318Smax.romanov@nginx.com         rp->msg.new_port = NULL;
507*318Smax.romanov@nginx.com 
508*318Smax.romanov@nginx.com         rp->work.handler = nxt_router_worker_remove_pid_handler;
509*318Smax.romanov@nginx.com         rp->work.task = &engine->task;
510*318Smax.romanov@nginx.com         rp->work.obj = rp;
511*318Smax.romanov@nginx.com         rp->work.data = task->thread->engine;
512*318Smax.romanov@nginx.com         rp->work.next = NULL;
513*318Smax.romanov@nginx.com 
514*318Smax.romanov@nginx.com         nxt_event_engine_post(engine, &rp->work);
515*318Smax.romanov@nginx.com     }
516*318Smax.romanov@nginx.com     nxt_queue_loop;
517*318Smax.romanov@nginx.com 
518192Smax.romanov@nginx.com     msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
519192Smax.romanov@nginx.com 
520192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
521192Smax.romanov@nginx.com }
522192Smax.romanov@nginx.com 
523192Smax.romanov@nginx.com 
524*318Smax.romanov@nginx.com static void
525*318Smax.romanov@nginx.com nxt_router_worker_remove_pid_handler(nxt_task_t *task, void *obj, void *data)
526*318Smax.romanov@nginx.com {
527*318Smax.romanov@nginx.com     nxt_event_engine_t    *engine;
528*318Smax.romanov@nginx.com     nxt_remove_pid_msg_t  *rp;
529*318Smax.romanov@nginx.com 
530*318Smax.romanov@nginx.com     rp = obj;
531*318Smax.romanov@nginx.com 
532*318Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, &rp->msg);
533*318Smax.romanov@nginx.com 
534*318Smax.romanov@nginx.com     engine = rp->work.data;
535*318Smax.romanov@nginx.com 
536*318Smax.romanov@nginx.com     rp->work.handler = nxt_router_worker_remove_pid_done;
537*318Smax.romanov@nginx.com     rp->work.task = &engine->task;
538*318Smax.romanov@nginx.com     rp->work.next = NULL;
539*318Smax.romanov@nginx.com 
540*318Smax.romanov@nginx.com     nxt_event_engine_post(engine, &rp->work);
541*318Smax.romanov@nginx.com }
542*318Smax.romanov@nginx.com 
543*318Smax.romanov@nginx.com 
544*318Smax.romanov@nginx.com static void
545*318Smax.romanov@nginx.com nxt_router_worker_remove_pid_done(nxt_task_t *task, void *obj, void *data)
546*318Smax.romanov@nginx.com {
547*318Smax.romanov@nginx.com     nxt_remove_pid_msg_t  *rp;
548*318Smax.romanov@nginx.com 
549*318Smax.romanov@nginx.com     rp = obj;
550*318Smax.romanov@nginx.com 
551*318Smax.romanov@nginx.com     nxt_mp_release(rp->mem_pool, rp);
552*318Smax.romanov@nginx.com }
553*318Smax.romanov@nginx.com 
554*318Smax.romanov@nginx.com 
55553Sigor@sysoev.ru static nxt_router_temp_conf_t *
556139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task)
55753Sigor@sysoev.ru {
55865Sigor@sysoev.ru     nxt_mp_t                *mp, *tmp;
55953Sigor@sysoev.ru     nxt_router_conf_t       *rtcf;
56053Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
56153Sigor@sysoev.ru 
56265Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
56353Sigor@sysoev.ru     if (nxt_slow_path(mp == NULL)) {
56453Sigor@sysoev.ru         return NULL;
56553Sigor@sysoev.ru     }
56653Sigor@sysoev.ru 
56765Sigor@sysoev.ru     rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t));
56853Sigor@sysoev.ru     if (nxt_slow_path(rtcf == NULL)) {
56953Sigor@sysoev.ru         goto fail;
57053Sigor@sysoev.ru     }
57153Sigor@sysoev.ru 
57253Sigor@sysoev.ru     rtcf->mem_pool = mp;
57353Sigor@sysoev.ru 
57465Sigor@sysoev.ru     tmp = nxt_mp_create(1024, 128, 256, 32);
57553Sigor@sysoev.ru     if (nxt_slow_path(tmp == NULL)) {
57653Sigor@sysoev.ru         goto fail;
57753Sigor@sysoev.ru     }
57853Sigor@sysoev.ru 
57965Sigor@sysoev.ru     tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t));
58053Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
58153Sigor@sysoev.ru         goto temp_fail;
58253Sigor@sysoev.ru     }
58353Sigor@sysoev.ru 
58453Sigor@sysoev.ru     tmcf->mem_pool = tmp;
58553Sigor@sysoev.ru     tmcf->conf = rtcf;
586139Sigor@sysoev.ru     tmcf->count = 1;
587139Sigor@sysoev.ru     tmcf->engine = task->thread->engine;
58853Sigor@sysoev.ru 
58953Sigor@sysoev.ru     tmcf->engines = nxt_array_create(tmcf->mem_pool, 4,
59053Sigor@sysoev.ru                                      sizeof(nxt_router_engine_conf_t));
59153Sigor@sysoev.ru     if (nxt_slow_path(tmcf->engines == NULL)) {
59253Sigor@sysoev.ru         goto temp_fail;
59353Sigor@sysoev.ru     }
59453Sigor@sysoev.ru 
59553Sigor@sysoev.ru     nxt_queue_init(&tmcf->deleting);
59653Sigor@sysoev.ru     nxt_queue_init(&tmcf->keeping);
59753Sigor@sysoev.ru     nxt_queue_init(&tmcf->updating);
59853Sigor@sysoev.ru     nxt_queue_init(&tmcf->pending);
59953Sigor@sysoev.ru     nxt_queue_init(&tmcf->creating);
600133Sigor@sysoev.ru     nxt_queue_init(&tmcf->apps);
601133Sigor@sysoev.ru     nxt_queue_init(&tmcf->previous);
60253Sigor@sysoev.ru 
60353Sigor@sysoev.ru     return tmcf;
60453Sigor@sysoev.ru 
60553Sigor@sysoev.ru temp_fail:
60653Sigor@sysoev.ru 
60765Sigor@sysoev.ru     nxt_mp_destroy(tmp);
60853Sigor@sysoev.ru 
60953Sigor@sysoev.ru fail:
61053Sigor@sysoev.ru 
61165Sigor@sysoev.ru     nxt_mp_destroy(mp);
61253Sigor@sysoev.ru 
61353Sigor@sysoev.ru     return NULL;
61453Sigor@sysoev.ru }
61553Sigor@sysoev.ru 
61653Sigor@sysoev.ru 
617198Sigor@sysoev.ru static void
618198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
619139Sigor@sysoev.ru {
620139Sigor@sysoev.ru     nxt_int_t                    ret;
621139Sigor@sysoev.ru     nxt_router_t                 *router;
622139Sigor@sysoev.ru     nxt_runtime_t                *rt;
623198Sigor@sysoev.ru     nxt_queue_link_t             *qlk;
624198Sigor@sysoev.ru     nxt_socket_conf_t            *skcf;
625198Sigor@sysoev.ru     nxt_router_temp_conf_t       *tmcf;
626139Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
627139Sigor@sysoev.ru 
628198Sigor@sysoev.ru     tmcf = obj;
629198Sigor@sysoev.ru 
630198Sigor@sysoev.ru     qlk = nxt_queue_first(&tmcf->pending);
631198Sigor@sysoev.ru 
632198Sigor@sysoev.ru     if (qlk != nxt_queue_tail(&tmcf->pending)) {
633198Sigor@sysoev.ru         nxt_queue_remove(qlk);
634198Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->creating, qlk);
635198Sigor@sysoev.ru 
636198Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
637198Sigor@sysoev.ru 
638198Sigor@sysoev.ru         nxt_router_listen_socket_rpc_create(task, tmcf, skcf);
639198Sigor@sysoev.ru 
640198Sigor@sysoev.ru         return;
641139Sigor@sysoev.ru     }
642139Sigor@sysoev.ru 
643139Sigor@sysoev.ru     rt = task->thread->runtime;
644139Sigor@sysoev.ru 
645139Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
646139Sigor@sysoev.ru 
647198Sigor@sysoev.ru     router = tmcf->conf->router;
648198Sigor@sysoev.ru 
649139Sigor@sysoev.ru     ret = nxt_router_engines_create(task, router, tmcf, interface);
650139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
651198Sigor@sysoev.ru         goto fail;
652139Sigor@sysoev.ru     }
653139Sigor@sysoev.ru 
654139Sigor@sysoev.ru     ret = nxt_router_threads_create(task, rt, tmcf);
655139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
656198Sigor@sysoev.ru         goto fail;
657139Sigor@sysoev.ru     }
658139Sigor@sysoev.ru 
659139Sigor@sysoev.ru     nxt_router_apps_sort(router, tmcf);
660139Sigor@sysoev.ru 
661315Sigor@sysoev.ru     nxt_router_engines_post(router, tmcf);
662139Sigor@sysoev.ru 
663139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->updating);
664139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->creating);
665139Sigor@sysoev.ru 
666198Sigor@sysoev.ru     nxt_router_conf_ready(task, tmcf);
667198Sigor@sysoev.ru 
668198Sigor@sysoev.ru     return;
669198Sigor@sysoev.ru 
670198Sigor@sysoev.ru fail:
671198Sigor@sysoev.ru 
672198Sigor@sysoev.ru     nxt_router_conf_error(task, tmcf);
673198Sigor@sysoev.ru 
674198Sigor@sysoev.ru     return;
675139Sigor@sysoev.ru }
676139Sigor@sysoev.ru 
677139Sigor@sysoev.ru 
678139Sigor@sysoev.ru static void
679139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data)
680139Sigor@sysoev.ru {
681153Sigor@sysoev.ru     nxt_joint_job_t  *job;
682153Sigor@sysoev.ru 
683153Sigor@sysoev.ru     job = obj;
684153Sigor@sysoev.ru 
685198Sigor@sysoev.ru     nxt_router_conf_ready(task, job->tmcf);
686139Sigor@sysoev.ru }
687139Sigor@sysoev.ru 
688139Sigor@sysoev.ru 
689139Sigor@sysoev.ru static void
690198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
691139Sigor@sysoev.ru {
692139Sigor@sysoev.ru     nxt_debug(task, "temp conf count:%D", tmcf->count);
693139Sigor@sysoev.ru 
694139Sigor@sysoev.ru     if (--tmcf->count == 0) {
695193Smax.romanov@nginx.com         nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST);
696139Sigor@sysoev.ru     }
697139Sigor@sysoev.ru }
698139Sigor@sysoev.ru 
699139Sigor@sysoev.ru 
700139Sigor@sysoev.ru static void
701139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
702139Sigor@sysoev.ru {
703148Sigor@sysoev.ru     nxt_socket_t       s;
704149Sigor@sysoev.ru     nxt_router_t       *router;
705148Sigor@sysoev.ru     nxt_queue_link_t   *qlk;
706148Sigor@sysoev.ru     nxt_socket_conf_t  *skcf;
707148Sigor@sysoev.ru 
708198Sigor@sysoev.ru     nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf");
709198Sigor@sysoev.ru 
710148Sigor@sysoev.ru     for (qlk = nxt_queue_first(&tmcf->creating);
711148Sigor@sysoev.ru          qlk != nxt_queue_tail(&tmcf->creating);
712148Sigor@sysoev.ru          qlk = nxt_queue_next(qlk))
713148Sigor@sysoev.ru     {
714148Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
715148Sigor@sysoev.ru         s = skcf->listen.socket;
716148Sigor@sysoev.ru 
717148Sigor@sysoev.ru         if (s != -1) {
718148Sigor@sysoev.ru             nxt_socket_close(task, s);
719148Sigor@sysoev.ru         }
720148Sigor@sysoev.ru 
721148Sigor@sysoev.ru         nxt_free(skcf->socket);
722148Sigor@sysoev.ru     }
723148Sigor@sysoev.ru 
724149Sigor@sysoev.ru     router = tmcf->conf->router;
725149Sigor@sysoev.ru 
726149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->keeping);
727149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->deleting);
728149Sigor@sysoev.ru 
729148Sigor@sysoev.ru     // TODO: new engines and threads
730148Sigor@sysoev.ru 
731139Sigor@sysoev.ru     nxt_mp_destroy(tmcf->conf->mem_pool);
732139Sigor@sysoev.ru 
733193Smax.romanov@nginx.com     nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR);
734139Sigor@sysoev.ru }
735139Sigor@sysoev.ru 
736139Sigor@sysoev.ru 
737139Sigor@sysoev.ru static void
738139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
739193Smax.romanov@nginx.com     nxt_port_msg_type_t type)
740139Sigor@sysoev.ru {
741193Smax.romanov@nginx.com     nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL);
742139Sigor@sysoev.ru }
743139Sigor@sysoev.ru 
744139Sigor@sysoev.ru 
745115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_conf[] = {
746115Sigor@sysoev.ru     {
747133Sigor@sysoev.ru         nxt_string("listeners_threads"),
748115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
749115Sigor@sysoev.ru         offsetof(nxt_router_conf_t, threads),
750115Sigor@sysoev.ru     },
751115Sigor@sysoev.ru };
752115Sigor@sysoev.ru 
753115Sigor@sysoev.ru 
754133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_app_conf[] = {
755115Sigor@sysoev.ru     {
756133Sigor@sysoev.ru         nxt_string("type"),
757115Sigor@sysoev.ru         NXT_CONF_MAP_STR,
758133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, type),
759115Sigor@sysoev.ru     },
760115Sigor@sysoev.ru 
761115Sigor@sysoev.ru     {
762133Sigor@sysoev.ru         nxt_string("workers"),
763115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
764133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, workers),
765133Sigor@sysoev.ru     },
766*318Smax.romanov@nginx.com 
767*318Smax.romanov@nginx.com     {
768*318Smax.romanov@nginx.com         nxt_string("limits"),
769*318Smax.romanov@nginx.com         NXT_CONF_MAP_PTR,
770*318Smax.romanov@nginx.com         offsetof(nxt_router_app_conf_t, limits_value),
771*318Smax.romanov@nginx.com     },
772*318Smax.romanov@nginx.com };
773*318Smax.romanov@nginx.com 
774*318Smax.romanov@nginx.com 
775*318Smax.romanov@nginx.com static nxt_conf_map_t  nxt_router_app_limits_conf[] = {
776*318Smax.romanov@nginx.com     {
777*318Smax.romanov@nginx.com         nxt_string("timeout"),
778*318Smax.romanov@nginx.com         NXT_CONF_MAP_MSEC,
779*318Smax.romanov@nginx.com         offsetof(nxt_router_app_conf_t, timeout),
780*318Smax.romanov@nginx.com     },
781*318Smax.romanov@nginx.com 
782*318Smax.romanov@nginx.com     {
783*318Smax.romanov@nginx.com         nxt_string("requests"),
784*318Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
785*318Smax.romanov@nginx.com         offsetof(nxt_router_app_conf_t, requests),
786*318Smax.romanov@nginx.com     },
787133Sigor@sysoev.ru };
788133Sigor@sysoev.ru 
789133Sigor@sysoev.ru 
790133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_listener_conf[] = {
791133Sigor@sysoev.ru     {
792133Sigor@sysoev.ru         nxt_string("application"),
793133Sigor@sysoev.ru         NXT_CONF_MAP_STR,
794133Sigor@sysoev.ru         offsetof(nxt_router_listener_conf_t, application),
795115Sigor@sysoev.ru     },
796115Sigor@sysoev.ru };
797115Sigor@sysoev.ru 
798115Sigor@sysoev.ru 
799115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_http_conf[] = {
800115Sigor@sysoev.ru     {
801115Sigor@sysoev.ru         nxt_string("header_buffer_size"),
802115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
803115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_buffer_size),
804115Sigor@sysoev.ru     },
805115Sigor@sysoev.ru 
806115Sigor@sysoev.ru     {
807115Sigor@sysoev.ru         nxt_string("large_header_buffer_size"),
808115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
809115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, large_header_buffer_size),
810115Sigor@sysoev.ru     },
811115Sigor@sysoev.ru 
812115Sigor@sysoev.ru     {
813206Smax.romanov@nginx.com         nxt_string("large_header_buffers"),
814206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
815206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, large_header_buffers),
816206Smax.romanov@nginx.com     },
817206Smax.romanov@nginx.com 
818206Smax.romanov@nginx.com     {
819206Smax.romanov@nginx.com         nxt_string("body_buffer_size"),
820206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
821206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_buffer_size),
822206Smax.romanov@nginx.com     },
823206Smax.romanov@nginx.com 
824206Smax.romanov@nginx.com     {
825206Smax.romanov@nginx.com         nxt_string("max_body_size"),
826206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
827206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, max_body_size),
828206Smax.romanov@nginx.com     },
829206Smax.romanov@nginx.com 
830206Smax.romanov@nginx.com     {
831115Sigor@sysoev.ru         nxt_string("header_read_timeout"),
832115Sigor@sysoev.ru         NXT_CONF_MAP_MSEC,
833115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_read_timeout),
834115Sigor@sysoev.ru     },
835206Smax.romanov@nginx.com 
836206Smax.romanov@nginx.com     {
837206Smax.romanov@nginx.com         nxt_string("body_read_timeout"),
838206Smax.romanov@nginx.com         NXT_CONF_MAP_MSEC,
839206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_read_timeout),
840206Smax.romanov@nginx.com     },
841115Sigor@sysoev.ru };
842115Sigor@sysoev.ru 
843115Sigor@sysoev.ru 
84453Sigor@sysoev.ru static nxt_int_t
845115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
846115Sigor@sysoev.ru     u_char *start, u_char *end)
84753Sigor@sysoev.ru {
848133Sigor@sysoev.ru     u_char                      *p;
849133Sigor@sysoev.ru     size_t                      size;
850115Sigor@sysoev.ru     nxt_mp_t                    *mp;
851115Sigor@sysoev.ru     uint32_t                    next;
852115Sigor@sysoev.ru     nxt_int_t                   ret;
853115Sigor@sysoev.ru     nxt_str_t                   name;
854133Sigor@sysoev.ru     nxt_app_t                   *app, *prev;
855133Sigor@sysoev.ru     nxt_app_type_t              type;
856115Sigor@sysoev.ru     nxt_sockaddr_t              *sa;
857133Sigor@sysoev.ru     nxt_conf_value_t            *conf, *http;
858133Sigor@sysoev.ru     nxt_conf_value_t            *applications, *application;
859133Sigor@sysoev.ru     nxt_conf_value_t            *listeners, *listener;
860115Sigor@sysoev.ru     nxt_socket_conf_t           *skcf;
861216Sigor@sysoev.ru     nxt_app_lang_module_t       *lang;
862133Sigor@sysoev.ru     nxt_router_app_conf_t       apcf;
863115Sigor@sysoev.ru     nxt_router_listener_conf_t  lscf;
864115Sigor@sysoev.ru 
865115Sigor@sysoev.ru     static nxt_str_t  http_path = nxt_string("/http");
866133Sigor@sysoev.ru     static nxt_str_t  applications_path = nxt_string("/applications");
867115Sigor@sysoev.ru     static nxt_str_t  listeners_path = nxt_string("/listeners");
868115Sigor@sysoev.ru 
869208Svbart@nginx.com     conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
870115Sigor@sysoev.ru     if (conf == NULL) {
871115Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "configuration parsing error");
872115Sigor@sysoev.ru         return NXT_ERROR;
873115Sigor@sysoev.ru     }
874115Sigor@sysoev.ru 
875213Svbart@nginx.com     mp = tmcf->conf->mem_pool;
876213Svbart@nginx.com 
877213Svbart@nginx.com     ret = nxt_conf_map_object(mp, conf, nxt_router_conf,
878136Svbart@nginx.com                               nxt_nitems(nxt_router_conf), tmcf->conf);
879115Sigor@sysoev.ru     if (ret != NXT_OK) {
880133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "root map error");
881115Sigor@sysoev.ru         return NXT_ERROR;
882115Sigor@sysoev.ru     }
883115Sigor@sysoev.ru 
884117Sigor@sysoev.ru     if (tmcf->conf->threads == 0) {
885117Sigor@sysoev.ru         tmcf->conf->threads = nxt_ncpu;
886117Sigor@sysoev.ru     }
887117Sigor@sysoev.ru 
888133Sigor@sysoev.ru     applications = nxt_conf_get_path(conf, &applications_path);
889133Sigor@sysoev.ru     if (applications == NULL) {
890133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block");
891115Sigor@sysoev.ru         return NXT_ERROR;
892115Sigor@sysoev.ru     }
893115Sigor@sysoev.ru 
894133Sigor@sysoev.ru     next = 0;
895133Sigor@sysoev.ru 
896133Sigor@sysoev.ru     for ( ;; ) {
897133Sigor@sysoev.ru         application = nxt_conf_next_object_member(applications, &name, &next);
898133Sigor@sysoev.ru         if (application == NULL) {
899133Sigor@sysoev.ru             break;
900133Sigor@sysoev.ru         }
901133Sigor@sysoev.ru 
902133Sigor@sysoev.ru         nxt_debug(task, "application \"%V\"", &name);
903133Sigor@sysoev.ru 
904144Smax.romanov@nginx.com         size = nxt_conf_json_length(application, NULL);
905144Smax.romanov@nginx.com 
906144Smax.romanov@nginx.com         app = nxt_malloc(sizeof(nxt_app_t) + name.length + size);
907133Sigor@sysoev.ru         if (app == NULL) {
908133Sigor@sysoev.ru             goto fail;
909133Sigor@sysoev.ru         }
910133Sigor@sysoev.ru 
911144Smax.romanov@nginx.com         nxt_memzero(app, sizeof(nxt_app_t));
912144Smax.romanov@nginx.com 
913144Smax.romanov@nginx.com         app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t));
914144Smax.romanov@nginx.com         app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length);
915133Sigor@sysoev.ru 
916133Sigor@sysoev.ru         p = nxt_conf_json_print(app->conf.start, application, NULL);
917133Sigor@sysoev.ru         app->conf.length = p - app->conf.start;
918133Sigor@sysoev.ru 
919144Smax.romanov@nginx.com         nxt_assert(app->conf.length <= size);
920144Smax.romanov@nginx.com 
921133Sigor@sysoev.ru         nxt_debug(task, "application conf \"%V\"", &app->conf);
922133Sigor@sysoev.ru 
923133Sigor@sysoev.ru         prev = nxt_router_app_find(&tmcf->conf->router->apps, &name);
924133Sigor@sysoev.ru 
925133Sigor@sysoev.ru         if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) {
926133Sigor@sysoev.ru             nxt_free(app);
927133Sigor@sysoev.ru 
928133Sigor@sysoev.ru             nxt_queue_remove(&prev->link);
929133Sigor@sysoev.ru             nxt_queue_insert_tail(&tmcf->previous, &prev->link);
930133Sigor@sysoev.ru             continue;
931133Sigor@sysoev.ru         }
932133Sigor@sysoev.ru 
933263Smax.romanov@nginx.com         apcf.workers = 1;
934*318Smax.romanov@nginx.com         apcf.timeout = 0;
935*318Smax.romanov@nginx.com         apcf.requests = 0;
936*318Smax.romanov@nginx.com         apcf.limits_value = NULL;
937263Smax.romanov@nginx.com 
938213Svbart@nginx.com         ret = nxt_conf_map_object(mp, application, nxt_router_app_conf,
939136Svbart@nginx.com                                   nxt_nitems(nxt_router_app_conf), &apcf);
940133Sigor@sysoev.ru         if (ret != NXT_OK) {
941133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "application map error");
942133Sigor@sysoev.ru             goto app_fail;
943133Sigor@sysoev.ru         }
944115Sigor@sysoev.ru 
945*318Smax.romanov@nginx.com         if (apcf.limits_value != NULL) {
946*318Smax.romanov@nginx.com 
947*318Smax.romanov@nginx.com             if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) {
948*318Smax.romanov@nginx.com                 nxt_log(task, NXT_LOG_CRIT, "application limits is not object");
949*318Smax.romanov@nginx.com                 goto app_fail;
950*318Smax.romanov@nginx.com             }
951*318Smax.romanov@nginx.com 
952*318Smax.romanov@nginx.com             ret = nxt_conf_map_object(mp, apcf.limits_value,
953*318Smax.romanov@nginx.com                                       nxt_router_app_limits_conf,
954*318Smax.romanov@nginx.com                                       nxt_nitems(nxt_router_app_limits_conf),
955*318Smax.romanov@nginx.com                                       &apcf);
956*318Smax.romanov@nginx.com             if (ret != NXT_OK) {
957*318Smax.romanov@nginx.com                 nxt_log(task, NXT_LOG_CRIT, "application limits map error");
958*318Smax.romanov@nginx.com                 goto app_fail;
959*318Smax.romanov@nginx.com             }
960*318Smax.romanov@nginx.com         }
961*318Smax.romanov@nginx.com 
962133Sigor@sysoev.ru         nxt_debug(task, "application type: %V", &apcf.type);
963133Sigor@sysoev.ru         nxt_debug(task, "application workers: %D", apcf.workers);
964*318Smax.romanov@nginx.com         nxt_debug(task, "application timeout: %D", apcf.timeout);
965*318Smax.romanov@nginx.com         nxt_debug(task, "application requests: %D", apcf.requests);
966133Sigor@sysoev.ru 
967216Sigor@sysoev.ru         lang = nxt_app_lang_module(task->thread->runtime, &apcf.type);
968