xref: /unit/src/nxt_router.c (revision 313)
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 {
13133Sigor@sysoev.ru     nxt_str_t  type;
14133Sigor@sysoev.ru     uint32_t   workers;
15133Sigor@sysoev.ru } nxt_router_app_conf_t;
16133Sigor@sysoev.ru 
17133Sigor@sysoev.ru 
18133Sigor@sysoev.ru typedef struct {
19133Sigor@sysoev.ru     nxt_str_t  application;
20115Sigor@sysoev.ru } nxt_router_listener_conf_t;
21115Sigor@sysoev.ru 
22115Sigor@sysoev.ru 
23167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t;
24141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t;
25141Smax.romanov@nginx.com 
26141Smax.romanov@nginx.com struct nxt_start_worker_s {
27141Smax.romanov@nginx.com     nxt_app_t              *app;
28167Smax.romanov@nginx.com     nxt_req_app_link_t     *ra;
29141Smax.romanov@nginx.com 
30141Smax.romanov@nginx.com     nxt_work_t             work;
31141Smax.romanov@nginx.com };
32141Smax.romanov@nginx.com 
33141Smax.romanov@nginx.com 
34167Smax.romanov@nginx.com struct nxt_req_app_link_s {
35167Smax.romanov@nginx.com     nxt_req_id_t         req_id;
36167Smax.romanov@nginx.com     nxt_port_t           *app_port;
37167Smax.romanov@nginx.com     nxt_port_t           *reply_port;
38167Smax.romanov@nginx.com     nxt_app_parse_ctx_t  *ap;
39167Smax.romanov@nginx.com     nxt_req_conn_link_t  *rc;
40167Smax.romanov@nginx.com 
41167Smax.romanov@nginx.com     nxt_queue_link_t     link; /* for nxt_app_t.requests */
42167Smax.romanov@nginx.com 
43167Smax.romanov@nginx.com     nxt_mp_t             *mem_pool;
44167Smax.romanov@nginx.com     nxt_work_t           work;
45167Smax.romanov@nginx.com };
46167Smax.romanov@nginx.com 
47167Smax.romanov@nginx.com 
48198Sigor@sysoev.ru typedef struct {
49198Sigor@sysoev.ru     nxt_socket_conf_t       *socket_conf;
50198Sigor@sysoev.ru     nxt_router_temp_conf_t  *temp_conf;
51198Sigor@sysoev.ru } nxt_socket_rpc_t;
52198Sigor@sysoev.ru 
53198Sigor@sysoev.ru 
54139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
55198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
56198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task,
57139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
58139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task,
59139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
60139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task,
61193Smax.romanov@nginx.com     nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
6253Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router,
6353Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
6453Sigor@sysoev.ru 
65115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
66115Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
67133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
68133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf,
69133Sigor@sysoev.ru     nxt_str_t *name);
70198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task,
71198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf);
72198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task,
73198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
74198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task,
75198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
7665Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp,
7765Sigor@sysoev.ru     nxt_sockaddr_t *sa);
7853Sigor@sysoev.ru 
7953Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task,
8053Sigor@sysoev.ru     nxt_router_t *router, nxt_router_temp_conf_t *tmcf,
8153Sigor@sysoev.ru     const nxt_event_interface_t *interface);
82115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf,
83115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
84115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf,
85115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
86115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf,
87115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
88115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets);
89154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf,
90154Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets,
91154Sigor@sysoev.ru     nxt_work_handler_t handler);
92*313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf,
93*313Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
94139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
95139Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets);
9653Sigor@sysoev.ru 
9753Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
9853Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
9953Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
10053Sigor@sysoev.ru     nxt_event_engine_t *engine);
101133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router,
102133Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
10353Sigor@sysoev.ru 
10453Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf);
105154Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf);
106277Sigor@sysoev.ru static void nxt_router_app_data_handler(nxt_task_t *task,
107277Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
10853Sigor@sysoev.ru 
10953Sigor@sysoev.ru static void nxt_router_thread_start(void *data);
11053Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj,
11153Sigor@sysoev.ru     void *data);
11253Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj,
11353Sigor@sysoev.ru     void *data);
11453Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj,
11553Sigor@sysoev.ru     void *data);
116*313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj,
117*313Sigor@sysoev.ru     void *data);
11853Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj,
11953Sigor@sysoev.ru     void *data);
12053Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task,
12153Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
12253Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj,
12353Sigor@sysoev.ru     void *data);
12453Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task,
12553Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
12653Sigor@sysoev.ru 
127167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj,
128167Smax.romanov@nginx.com     void *data);
129167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app);
130167Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t req_id);
131141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj,
132141Smax.romanov@nginx.com     void *data);
133141Smax.romanov@nginx.com 
13453Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data);
13553Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj,
13653Sigor@sysoev.ru     void *data);
137206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj,
138206Smax.romanov@nginx.com     void *data);
13988Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task,
14088Smax.romanov@nginx.com     nxt_conn_t *c, nxt_app_parse_ctx_t *ap);
141141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task,
142167Smax.romanov@nginx.com     nxt_req_app_link_t *ra, nxt_port_t *port);
143216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
144216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
145216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
146216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
147216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
148216Sigor@sysoev.ru     nxt_app_wmsg_t *wmsg);
14988Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data);
15053Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data);
15153Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data);
15253Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data);
15353Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data);
15462Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data);
15520Sigor@sysoev.ru 
156141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code,
157141Smax.romanov@nginx.com     const char* fmt, ...);
158141Smax.romanov@nginx.com 
159119Smax.romanov@nginx.com static nxt_router_t  *nxt_router;
16020Sigor@sysoev.ru 
161216Sigor@sysoev.ru 
162216Sigor@sysoev.ru static nxt_app_prepare_msg_t  nxt_app_prepare_msg[] = {
163216Sigor@sysoev.ru     nxt_python_prepare_msg,
164216Sigor@sysoev.ru     nxt_php_prepare_msg,
165216Sigor@sysoev.ru     nxt_go_prepare_msg,
166216Sigor@sysoev.ru };
167216Sigor@sysoev.ru 
168216Sigor@sysoev.ru 
16920Sigor@sysoev.ru nxt_int_t
170141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data)
17120Sigor@sysoev.ru {
172141Smax.romanov@nginx.com     nxt_int_t      ret;
173141Smax.romanov@nginx.com     nxt_router_t   *router;
174141Smax.romanov@nginx.com     nxt_runtime_t  *rt;
175141Smax.romanov@nginx.com 
176141Smax.romanov@nginx.com     rt = task->thread->runtime;
17753Sigor@sysoev.ru 
17888Smax.romanov@nginx.com     ret = nxt_app_http_init(task, rt);
17988Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
18088Smax.romanov@nginx.com         return ret;
18188Smax.romanov@nginx.com     }
18288Smax.romanov@nginx.com 
18353Sigor@sysoev.ru     router = nxt_zalloc(sizeof(nxt_router_t));
18453Sigor@sysoev.ru     if (nxt_slow_path(router == NULL)) {
18553Sigor@sysoev.ru         return NXT_ERROR;
18653Sigor@sysoev.ru     }
18753Sigor@sysoev.ru 
18853Sigor@sysoev.ru     nxt_queue_init(&router->engines);
18953Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
190133Sigor@sysoev.ru     nxt_queue_init(&router->apps);
19153Sigor@sysoev.ru 
192119Smax.romanov@nginx.com     nxt_router = router;
193119Smax.romanov@nginx.com 
194115Sigor@sysoev.ru     return NXT_OK;
195115Sigor@sysoev.ru }
196115Sigor@sysoev.ru 
197115Sigor@sysoev.ru 
198167Smax.romanov@nginx.com static nxt_start_worker_t *
199192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra)
200167Smax.romanov@nginx.com {
201240Sigor@sysoev.ru     nxt_port_t          *main_port;
202167Smax.romanov@nginx.com     nxt_runtime_t       *rt;
203167Smax.romanov@nginx.com     nxt_start_worker_t  *sw;
204167Smax.romanov@nginx.com 
205192Smax.romanov@nginx.com     sw = nxt_zalloc(sizeof(nxt_start_worker_t));
206167Smax.romanov@nginx.com 
207167Smax.romanov@nginx.com     if (nxt_slow_path(sw == NULL)) {
208167Smax.romanov@nginx.com         return NULL;
209167Smax.romanov@nginx.com     }
210167Smax.romanov@nginx.com 
211167Smax.romanov@nginx.com     sw->app = app;
212167Smax.romanov@nginx.com     sw->ra = ra;
213167Smax.romanov@nginx.com 
214192Smax.romanov@nginx.com     nxt_debug(task, "sw %p create, request #%uxD, app '%V' %p", sw,
215167Smax.romanov@nginx.com                     ra->req_id, &app->name, app);
216167Smax.romanov@nginx.com 
217167Smax.romanov@nginx.com     rt = task->thread->runtime;
218240Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MAIN];
219167Smax.romanov@nginx.com 
220167Smax.romanov@nginx.com     sw->work.handler = nxt_router_send_sw_request;
221240Sigor@sysoev.ru     sw->work.task = &main_port->engine->task;
222167Smax.romanov@nginx.com     sw->work.obj = sw;
223167Smax.romanov@nginx.com     sw->work.data = task->thread->engine;
224167Smax.romanov@nginx.com     sw->work.next = NULL;
225167Smax.romanov@nginx.com 
226240Sigor@sysoev.ru     if (task->thread->engine != main_port->engine) {
227240Sigor@sysoev.ru         nxt_debug(task, "sw %p post send to main engine %p", sw,
228240Sigor@sysoev.ru                   main_port->engine);
229240Sigor@sysoev.ru 
230240Sigor@sysoev.ru         nxt_event_engine_post(main_port->engine, &sw->work);
231167Smax.romanov@nginx.com 
232167Smax.romanov@nginx.com     } else {
233167Smax.romanov@nginx.com         nxt_router_send_sw_request(task, sw, sw->work.data);
234167Smax.romanov@nginx.com     }
235167Smax.romanov@nginx.com 
236167Smax.romanov@nginx.com     return sw;
237167Smax.romanov@nginx.com }
238167Smax.romanov@nginx.com 
239167Smax.romanov@nginx.com 
240192Smax.romanov@nginx.com nxt_inline void
241192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw)
242141Smax.romanov@nginx.com {
243192Smax.romanov@nginx.com     nxt_debug(task, "sw %p release", sw);
244192Smax.romanov@nginx.com 
245192Smax.romanov@nginx.com     nxt_free(sw);
246141Smax.romanov@nginx.com }
247141Smax.romanov@nginx.com 
248141Smax.romanov@nginx.com 
249167Smax.romanov@nginx.com static nxt_req_app_link_t *
250167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc)
251167Smax.romanov@nginx.com {
252167Smax.romanov@nginx.com     nxt_mp_t            *mp;
253167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
254167Smax.romanov@nginx.com 
255167Smax.romanov@nginx.com     mp = rc->conn->mem_pool;
256167Smax.romanov@nginx.com 
257167Smax.romanov@nginx.com     ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t));
258167Smax.romanov@nginx.com 
259167Smax.romanov@nginx.com     if (nxt_slow_path(ra == NULL)) {
260167Smax.romanov@nginx.com         return NULL;
261167Smax.romanov@nginx.com     }
262167Smax.romanov@nginx.com 
263275Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD create", rc->req_id);
264167Smax.romanov@nginx.com 
265167Smax.romanov@nginx.com     nxt_memzero(ra, sizeof(nxt_req_app_link_t));
266167Smax.romanov@nginx.com 
267167Smax.romanov@nginx.com     ra->req_id = rc->req_id;
268167Smax.romanov@nginx.com     ra->app_port = NULL;
269167Smax.romanov@nginx.com     ra->rc = rc;
270167Smax.romanov@nginx.com 
271167Smax.romanov@nginx.com     ra->mem_pool = mp;
272167Smax.romanov@nginx.com 
273167Smax.romanov@nginx.com     ra->work.handler = NULL;
274167Smax.romanov@nginx.com     ra->work.task = &task->thread->engine->task;
275167Smax.romanov@nginx.com     ra->work.obj = ra;
276167Smax.romanov@nginx.com     ra->work.data = task->thread->engine;
277167Smax.romanov@nginx.com 
278167Smax.romanov@nginx.com     return ra;
279167Smax.romanov@nginx.com }
280167Smax.romanov@nginx.com 
281167Smax.romanov@nginx.com 
282167Smax.romanov@nginx.com static void
283167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data)
284167Smax.romanov@nginx.com {
285167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
286167Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
287167Smax.romanov@nginx.com 
288167Smax.romanov@nginx.com     ra = obj;
289167Smax.romanov@nginx.com     engine = data;
290167Smax.romanov@nginx.com 
291167Smax.romanov@nginx.com     if (task->thread->engine != engine) {
292167Smax.romanov@nginx.com         ra->work.handler = nxt_router_ra_release;
293167Smax.romanov@nginx.com         ra->work.task = &engine->task;
294167Smax.romanov@nginx.com         ra->work.next = NULL;
295167Smax.romanov@nginx.com 
296167Smax.romanov@nginx.com         nxt_debug(task, "ra #%uxD post release to %p", ra->req_id, engine);
297167Smax.romanov@nginx.com 
298167Smax.romanov@nginx.com         nxt_event_engine_post(engine, &ra->work);
299167Smax.romanov@nginx.com 
300167Smax.romanov@nginx.com         return;
301167Smax.romanov@nginx.com     }
302167Smax.romanov@nginx.com 
303167Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD release", ra->req_id);
304167Smax.romanov@nginx.com 
305167Smax.romanov@nginx.com     if (ra->app_port != NULL) {
306167Smax.romanov@nginx.com 
307264Smax.romanov@nginx.com         nxt_router_app_release_port(task, ra->app_port, ra->app_port->app);
308264Smax.romanov@nginx.com 
309264Smax.romanov@nginx.com #if 0
310264Smax.romanov@nginx.com         /* Uncomment to hold app port until complete response received. */
311167Smax.romanov@nginx.com         if (ra->rc->conn != NULL) {
312167Smax.romanov@nginx.com             ra->rc->app_port = ra->app_port;
313167Smax.romanov@nginx.com 
314167Smax.romanov@nginx.com         } else {
315167Smax.romanov@nginx.com             nxt_router_app_release_port(task, ra->app_port, ra->app_port->app);
316167Smax.romanov@nginx.com         }
317264Smax.romanov@nginx.com #endif
318167Smax.romanov@nginx.com     }
319167Smax.romanov@nginx.com 
320167Smax.romanov@nginx.com     nxt_mp_release(ra->mem_pool, ra);
321167Smax.romanov@nginx.com }
322167Smax.romanov@nginx.com 
323167Smax.romanov@nginx.com 
324141Smax.romanov@nginx.com void
325141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
326141Smax.romanov@nginx.com {
327141Smax.romanov@nginx.com     nxt_port_new_port_handler(task, msg);
328141Smax.romanov@nginx.com 
329192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
330141Smax.romanov@nginx.com         return;
331141Smax.romanov@nginx.com     }
332141Smax.romanov@nginx.com 
333192Smax.romanov@nginx.com     if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) {
334192Smax.romanov@nginx.com         msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
335141Smax.romanov@nginx.com     }
336192Smax.romanov@nginx.com 
337192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
338141Smax.romanov@nginx.com }
339141Smax.romanov@nginx.com 
340141Smax.romanov@nginx.com 
341139Sigor@sysoev.ru void
342139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
343115Sigor@sysoev.ru {
344139Sigor@sysoev.ru     size_t                  dump_size;
345198Sigor@sysoev.ru     nxt_int_t               ret;
346139Sigor@sysoev.ru     nxt_buf_t               *b;
347139Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
348139Sigor@sysoev.ru 
349139Sigor@sysoev.ru     b = msg->buf;
350139Sigor@sysoev.ru 
351139Sigor@sysoev.ru     dump_size = nxt_buf_used_size(b);
352139Sigor@sysoev.ru 
353139Sigor@sysoev.ru     if (dump_size > 300) {
354139Sigor@sysoev.ru         dump_size = 300;
35553Sigor@sysoev.ru     }
35653Sigor@sysoev.ru 
357139Sigor@sysoev.ru     nxt_debug(task, "router conf data (%z): %*s",
358139Sigor@sysoev.ru               msg->size, dump_size, b->mem.pos);
359139Sigor@sysoev.ru 
360139Sigor@sysoev.ru     tmcf = nxt_router_temp_conf(task);
361139Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
362139Sigor@sysoev.ru         return;
36353Sigor@sysoev.ru     }
36453Sigor@sysoev.ru 
365139Sigor@sysoev.ru     tmcf->conf->router = nxt_router;
366139Sigor@sysoev.ru     tmcf->stream = msg->port_msg.stream;
367139Sigor@sysoev.ru     tmcf->port = nxt_runtime_port_find(task->thread->runtime,
368198Sigor@sysoev.ru                                        msg->port_msg.pid,
369198Sigor@sysoev.ru                                        msg->port_msg.reply_port);
370198Sigor@sysoev.ru 
371198Sigor@sysoev.ru     ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free);
372198Sigor@sysoev.ru 
373198Sigor@sysoev.ru     if (nxt_fast_path(ret == NXT_OK)) {
374198Sigor@sysoev.ru         nxt_router_conf_apply(task, tmcf, NULL);
375198Sigor@sysoev.ru 
376198Sigor@sysoev.ru     } else {
377198Sigor@sysoev.ru         nxt_router_conf_error(task, tmcf);
378139Sigor@sysoev.ru     }
37953Sigor@sysoev.ru }
38053Sigor@sysoev.ru 
38153Sigor@sysoev.ru 
382192Smax.romanov@nginx.com void
383192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
384192Smax.romanov@nginx.com {
385192Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, msg);
386192Smax.romanov@nginx.com 
387192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
388192Smax.romanov@nginx.com         return;
389192Smax.romanov@nginx.com     }
390192Smax.romanov@nginx.com 
391192Smax.romanov@nginx.com     msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
392192Smax.romanov@nginx.com 
393192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
394192Smax.romanov@nginx.com }
395192Smax.romanov@nginx.com 
396192Smax.romanov@nginx.com 
39753Sigor@sysoev.ru static nxt_router_temp_conf_t *
398139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task)
39953Sigor@sysoev.ru {
40065Sigor@sysoev.ru     nxt_mp_t                *mp, *tmp;
40153Sigor@sysoev.ru     nxt_router_conf_t       *rtcf;
40253Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
40353Sigor@sysoev.ru 
40465Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
40553Sigor@sysoev.ru     if (nxt_slow_path(mp == NULL)) {
40653Sigor@sysoev.ru         return NULL;
40753Sigor@sysoev.ru     }
40853Sigor@sysoev.ru 
40965Sigor@sysoev.ru     rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t));
41053Sigor@sysoev.ru     if (nxt_slow_path(rtcf == NULL)) {
41153Sigor@sysoev.ru         goto fail;
41253Sigor@sysoev.ru     }
41353Sigor@sysoev.ru 
41453Sigor@sysoev.ru     rtcf->mem_pool = mp;
41553Sigor@sysoev.ru 
41665Sigor@sysoev.ru     tmp = nxt_mp_create(1024, 128, 256, 32);
41753Sigor@sysoev.ru     if (nxt_slow_path(tmp == NULL)) {
41853Sigor@sysoev.ru         goto fail;
41953Sigor@sysoev.ru     }
42053Sigor@sysoev.ru 
42165Sigor@sysoev.ru     tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t));
42253Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
42353Sigor@sysoev.ru         goto temp_fail;
42453Sigor@sysoev.ru     }
42553Sigor@sysoev.ru 
42653Sigor@sysoev.ru     tmcf->mem_pool = tmp;
42753Sigor@sysoev.ru     tmcf->conf = rtcf;
428139Sigor@sysoev.ru     tmcf->count = 1;
429139Sigor@sysoev.ru     tmcf->engine = task->thread->engine;
43053Sigor@sysoev.ru 
43153Sigor@sysoev.ru     tmcf->engines = nxt_array_create(tmcf->mem_pool, 4,
43253Sigor@sysoev.ru                                      sizeof(nxt_router_engine_conf_t));
43353Sigor@sysoev.ru     if (nxt_slow_path(tmcf->engines == NULL)) {
43453Sigor@sysoev.ru         goto temp_fail;
43553Sigor@sysoev.ru     }
43653Sigor@sysoev.ru 
43753Sigor@sysoev.ru     nxt_queue_init(&tmcf->deleting);
43853Sigor@sysoev.ru     nxt_queue_init(&tmcf->keeping);
43953Sigor@sysoev.ru     nxt_queue_init(&tmcf->updating);
44053Sigor@sysoev.ru     nxt_queue_init(&tmcf->pending);
44153Sigor@sysoev.ru     nxt_queue_init(&tmcf->creating);
442133Sigor@sysoev.ru     nxt_queue_init(&tmcf->apps);
443133Sigor@sysoev.ru     nxt_queue_init(&tmcf->previous);
44453Sigor@sysoev.ru 
44553Sigor@sysoev.ru     return tmcf;
44653Sigor@sysoev.ru 
44753Sigor@sysoev.ru temp_fail:
44853Sigor@sysoev.ru 
44965Sigor@sysoev.ru     nxt_mp_destroy(tmp);
45053Sigor@sysoev.ru 
45153Sigor@sysoev.ru fail:
45253Sigor@sysoev.ru 
45365Sigor@sysoev.ru     nxt_mp_destroy(mp);
45453Sigor@sysoev.ru 
45553Sigor@sysoev.ru     return NULL;
45653Sigor@sysoev.ru }
45753Sigor@sysoev.ru 
45853Sigor@sysoev.ru 
459198Sigor@sysoev.ru static void
460198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
461139Sigor@sysoev.ru {
462139Sigor@sysoev.ru     nxt_int_t                    ret;
463139Sigor@sysoev.ru     nxt_router_t                 *router;
464139Sigor@sysoev.ru     nxt_runtime_t                *rt;
465198Sigor@sysoev.ru     nxt_queue_link_t             *qlk;
466198Sigor@sysoev.ru     nxt_socket_conf_t            *skcf;
467198Sigor@sysoev.ru     nxt_router_temp_conf_t       *tmcf;
468139Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
469139Sigor@sysoev.ru 
470198Sigor@sysoev.ru     tmcf = obj;
471198Sigor@sysoev.ru 
472198Sigor@sysoev.ru     qlk = nxt_queue_first(&tmcf->pending);
473198Sigor@sysoev.ru 
474198Sigor@sysoev.ru     if (qlk != nxt_queue_tail(&tmcf->pending)) {
475198Sigor@sysoev.ru         nxt_queue_remove(qlk);
476198Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->creating, qlk);
477198Sigor@sysoev.ru 
478198Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
479198Sigor@sysoev.ru 
480198Sigor@sysoev.ru         nxt_router_listen_socket_rpc_create(task, tmcf, skcf);
481198Sigor@sysoev.ru 
482198Sigor@sysoev.ru         return;
483139Sigor@sysoev.ru     }
484139Sigor@sysoev.ru 
485139Sigor@sysoev.ru     rt = task->thread->runtime;
486139Sigor@sysoev.ru 
487139Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
488139Sigor@sysoev.ru 
489198Sigor@sysoev.ru     router = tmcf->conf->router;
490198Sigor@sysoev.ru 
491139Sigor@sysoev.ru     ret = nxt_router_engines_create(task, router, tmcf, interface);
492139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
493198Sigor@sysoev.ru         goto fail;
494139Sigor@sysoev.ru     }
495139Sigor@sysoev.ru 
496139Sigor@sysoev.ru     ret = nxt_router_threads_create(task, rt, tmcf);
497139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
498198Sigor@sysoev.ru         goto fail;
499139Sigor@sysoev.ru     }
500139Sigor@sysoev.ru 
501139Sigor@sysoev.ru     nxt_router_apps_sort(router, tmcf);
502139Sigor@sysoev.ru 
503139Sigor@sysoev.ru     nxt_router_engines_post(tmcf);
504139Sigor@sysoev.ru 
505139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->updating);
506139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->creating);
507139Sigor@sysoev.ru 
508198Sigor@sysoev.ru     nxt_router_conf_ready(task, tmcf);
509198Sigor@sysoev.ru 
510198Sigor@sysoev.ru     return;
511198Sigor@sysoev.ru 
512198Sigor@sysoev.ru fail:
513198Sigor@sysoev.ru 
514198Sigor@sysoev.ru     nxt_router_conf_error(task, tmcf);
515198Sigor@sysoev.ru 
516198Sigor@sysoev.ru     return;
517139Sigor@sysoev.ru }
518139Sigor@sysoev.ru 
519139Sigor@sysoev.ru 
520139Sigor@sysoev.ru static void
521139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data)
522139Sigor@sysoev.ru {
523153Sigor@sysoev.ru     nxt_joint_job_t  *job;
524153Sigor@sysoev.ru 
525153Sigor@sysoev.ru     job = obj;
526153Sigor@sysoev.ru 
527198Sigor@sysoev.ru     nxt_router_conf_ready(task, job->tmcf);
528139Sigor@sysoev.ru }
529139Sigor@sysoev.ru 
530139Sigor@sysoev.ru 
531139Sigor@sysoev.ru static void
532198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
533139Sigor@sysoev.ru {
534139Sigor@sysoev.ru     nxt_debug(task, "temp conf count:%D", tmcf->count);
535139Sigor@sysoev.ru 
536139Sigor@sysoev.ru     if (--tmcf->count == 0) {
537193Smax.romanov@nginx.com         nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST);
538139Sigor@sysoev.ru     }
539139Sigor@sysoev.ru }
540139Sigor@sysoev.ru 
541139Sigor@sysoev.ru 
542139Sigor@sysoev.ru static void
543139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
544139Sigor@sysoev.ru {
545148Sigor@sysoev.ru     nxt_socket_t       s;
546149Sigor@sysoev.ru     nxt_router_t       *router;
547148Sigor@sysoev.ru     nxt_queue_link_t   *qlk;
548148Sigor@sysoev.ru     nxt_socket_conf_t  *skcf;
549148Sigor@sysoev.ru 
550198Sigor@sysoev.ru     nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf");
551198Sigor@sysoev.ru 
552148Sigor@sysoev.ru     for (qlk = nxt_queue_first(&tmcf->creating);
553148Sigor@sysoev.ru          qlk != nxt_queue_tail(&tmcf->creating);
554148Sigor@sysoev.ru          qlk = nxt_queue_next(qlk))
555148Sigor@sysoev.ru     {
556148Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
557148Sigor@sysoev.ru         s = skcf->listen.socket;
558148Sigor@sysoev.ru 
559148Sigor@sysoev.ru         if (s != -1) {
560148Sigor@sysoev.ru             nxt_socket_close(task, s);
561148Sigor@sysoev.ru         }
562148Sigor@sysoev.ru 
563148Sigor@sysoev.ru         nxt_free(skcf->socket);
564148Sigor@sysoev.ru     }
565148Sigor@sysoev.ru 
566149Sigor@sysoev.ru     router = tmcf->conf->router;
567149Sigor@sysoev.ru 
568149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->keeping);
569149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->deleting);
570149Sigor@sysoev.ru 
571148Sigor@sysoev.ru     // TODO: new engines and threads
572148Sigor@sysoev.ru 
573139Sigor@sysoev.ru     nxt_mp_destroy(tmcf->conf->mem_pool);
574139Sigor@sysoev.ru 
575193Smax.romanov@nginx.com     nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR);
576139Sigor@sysoev.ru }
577139Sigor@sysoev.ru 
578139Sigor@sysoev.ru 
579139Sigor@sysoev.ru static void
580139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
581193Smax.romanov@nginx.com     nxt_port_msg_type_t type)
582139Sigor@sysoev.ru {
583193Smax.romanov@nginx.com     nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL);
584139Sigor@sysoev.ru }
585139Sigor@sysoev.ru 
586139Sigor@sysoev.ru 
587115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_conf[] = {
588115Sigor@sysoev.ru     {
589133Sigor@sysoev.ru         nxt_string("listeners_threads"),
590115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
591115Sigor@sysoev.ru         offsetof(nxt_router_conf_t, threads),
592115Sigor@sysoev.ru     },
593115Sigor@sysoev.ru };
594115Sigor@sysoev.ru 
595115Sigor@sysoev.ru 
596133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_app_conf[] = {
597115Sigor@sysoev.ru     {
598133Sigor@sysoev.ru         nxt_string("type"),
599115Sigor@sysoev.ru         NXT_CONF_MAP_STR,
600133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, type),
601115Sigor@sysoev.ru     },
602115Sigor@sysoev.ru 
603115Sigor@sysoev.ru     {
604133Sigor@sysoev.ru         nxt_string("workers"),
605115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
606133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, workers),
607133Sigor@sysoev.ru     },
608133Sigor@sysoev.ru };
609133Sigor@sysoev.ru 
610133Sigor@sysoev.ru 
611133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_listener_conf[] = {
612133Sigor@sysoev.ru     {
613133Sigor@sysoev.ru         nxt_string("application"),
614133Sigor@sysoev.ru         NXT_CONF_MAP_STR,
615133Sigor@sysoev.ru         offsetof(nxt_router_listener_conf_t, application),
616115Sigor@sysoev.ru     },
617115Sigor@sysoev.ru };
618115Sigor@sysoev.ru 
619115Sigor@sysoev.ru 
620115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_http_conf[] = {
621115Sigor@sysoev.ru     {
622115Sigor@sysoev.ru         nxt_string("header_buffer_size"),
623115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
624115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_buffer_size),
625115Sigor@sysoev.ru     },
626115Sigor@sysoev.ru 
627115Sigor@sysoev.ru     {
628115Sigor@sysoev.ru         nxt_string("large_header_buffer_size"),
629115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
630115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, large_header_buffer_size),
631115Sigor@sysoev.ru     },
632115Sigor@sysoev.ru 
633115Sigor@sysoev.ru     {
634206Smax.romanov@nginx.com         nxt_string("large_header_buffers"),
635206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
636206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, large_header_buffers),
637206Smax.romanov@nginx.com     },
638206Smax.romanov@nginx.com 
639206Smax.romanov@nginx.com     {
640206Smax.romanov@nginx.com         nxt_string("body_buffer_size"),
641206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
642206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_buffer_size),
643206Smax.romanov@nginx.com     },
644206Smax.romanov@nginx.com 
645206Smax.romanov@nginx.com     {
646206Smax.romanov@nginx.com         nxt_string("max_body_size"),
647206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
648206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, max_body_size),
649206Smax.romanov@nginx.com     },
650206Smax.romanov@nginx.com 
651206Smax.romanov@nginx.com     {
652115Sigor@sysoev.ru         nxt_string("header_read_timeout"),
653115Sigor@sysoev.ru         NXT_CONF_MAP_MSEC,
654115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_read_timeout),
655115Sigor@sysoev.ru     },
656206Smax.romanov@nginx.com 
657206Smax.romanov@nginx.com     {
658206Smax.romanov@nginx.com         nxt_string("body_read_timeout"),
659206Smax.romanov@nginx.com         NXT_CONF_MAP_MSEC,
660206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_read_timeout),
661206Smax.romanov@nginx.com     },
662115Sigor@sysoev.ru };
663115Sigor@sysoev.ru 
664115Sigor@sysoev.ru 
66553Sigor@sysoev.ru static nxt_int_t
666115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
667115Sigor@sysoev.ru     u_char *start, u_char *end)
66853Sigor@sysoev.ru {
669133Sigor@sysoev.ru     u_char                      *p;
670133Sigor@sysoev.ru     size_t                      size;
671115Sigor@sysoev.ru     nxt_mp_t                    *mp;
672115Sigor@sysoev.ru     uint32_t                    next;
673115Sigor@sysoev.ru     nxt_int_t                   ret;
674115Sigor@sysoev.ru     nxt_str_t                   name;
675133Sigor@sysoev.ru     nxt_app_t                   *app, *prev;
676133Sigor@sysoev.ru     nxt_app_type_t              type;
677115Sigor@sysoev.ru     nxt_sockaddr_t              *sa;
678133Sigor@sysoev.ru     nxt_conf_value_t            *conf, *http;
679133Sigor@sysoev.ru     nxt_conf_value_t            *applications, *application;
680133Sigor@sysoev.ru     nxt_conf_value_t            *listeners, *listener;
681115Sigor@sysoev.ru     nxt_socket_conf_t           *skcf;
682216Sigor@sysoev.ru     nxt_app_lang_module_t       *lang;
683133Sigor@sysoev.ru     nxt_router_app_conf_t       apcf;
684115Sigor@sysoev.ru     nxt_router_listener_conf_t  lscf;
685115Sigor@sysoev.ru 
686115Sigor@sysoev.ru     static nxt_str_t  http_path = nxt_string("/http");
687133Sigor@sysoev.ru     static nxt_str_t  applications_path = nxt_string("/applications");
688115Sigor@sysoev.ru     static nxt_str_t  listeners_path = nxt_string("/listeners");
689115Sigor@sysoev.ru 
690208Svbart@nginx.com     conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
691115Sigor@sysoev.ru     if (conf == NULL) {
692115Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "configuration parsing error");
693115Sigor@sysoev.ru         return NXT_ERROR;
694115Sigor@sysoev.ru     }
695115Sigor@sysoev.ru 
696213Svbart@nginx.com     mp = tmcf->conf->mem_pool;
697213Svbart@nginx.com 
698213Svbart@nginx.com     ret = nxt_conf_map_object(mp, conf, nxt_router_conf,
699136Svbart@nginx.com                               nxt_nitems(nxt_router_conf), tmcf->conf);
700115Sigor@sysoev.ru     if (ret != NXT_OK) {
701133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "root map error");
702115Sigor@sysoev.ru         return NXT_ERROR;
703115Sigor@sysoev.ru     }
704115Sigor@sysoev.ru 
705117Sigor@sysoev.ru     if (tmcf->conf->threads == 0) {
706117Sigor@sysoev.ru         tmcf->conf->threads = nxt_ncpu;
707117Sigor@sysoev.ru     }
708117Sigor@sysoev.ru 
709133Sigor@sysoev.ru     applications = nxt_conf_get_path(conf, &applications_path);
710133Sigor@sysoev.ru     if (applications == NULL) {
711133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block");
712115Sigor@sysoev.ru         return NXT_ERROR;
713115Sigor@sysoev.ru     }
714115Sigor@sysoev.ru 
715133Sigor@sysoev.ru     next = 0;
716133Sigor@sysoev.ru 
717133Sigor@sysoev.ru     for ( ;; ) {
718133Sigor@sysoev.ru         application = nxt_conf_next_object_member(applications, &name, &next);
719133Sigor@sysoev.ru         if (application == NULL) {
720133Sigor@sysoev.ru             break;
721133Sigor@sysoev.ru         }
722133Sigor@sysoev.ru 
723133Sigor@sysoev.ru         nxt_debug(task, "application \"%V\"", &name);
724133Sigor@sysoev.ru 
725144Smax.romanov@nginx.com         size = nxt_conf_json_length(application, NULL);
726144Smax.romanov@nginx.com 
727144Smax.romanov@nginx.com         app = nxt_malloc(sizeof(nxt_app_t) + name.length + size);
728133Sigor@sysoev.ru         if (app == NULL) {
729133Sigor@sysoev.ru             goto fail;
730133Sigor@sysoev.ru         }
731133Sigor@sysoev.ru 
732144Smax.romanov@nginx.com         nxt_memzero(app, sizeof(nxt_app_t));
733144Smax.romanov@nginx.com 
734144Smax.romanov@nginx.com         app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t));
735144Smax.romanov@nginx.com         app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length);
736133Sigor@sysoev.ru 
737133Sigor@sysoev.ru         p = nxt_conf_json_print(app->conf.start, application, NULL);
738133Sigor@sysoev.ru         app->conf.length = p - app->conf.start;
739133Sigor@sysoev.ru 
740144Smax.romanov@nginx.com         nxt_assert(app->conf.length <= size);
741144Smax.romanov@nginx.com 
742133Sigor@sysoev.ru         nxt_debug(task, "application conf \"%V\"", &app->conf);
743133Sigor@sysoev.ru 
744133Sigor@sysoev.ru         prev = nxt_router_app_find(&tmcf->conf->router->apps, &name);
745133Sigor@sysoev.ru 
746133Sigor@sysoev.ru         if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) {
747133Sigor@sysoev.ru             nxt_free(app);
748133Sigor@sysoev.ru 
749133Sigor@sysoev.ru             nxt_queue_remove(&prev->link);
750133Sigor@sysoev.ru             nxt_queue_insert_tail(&tmcf->previous, &prev->link);
751133Sigor@sysoev.ru             continue;
752133Sigor@sysoev.ru         }
753133Sigor@sysoev.ru 
754263Smax.romanov@nginx.com         apcf.workers = 1;
755263Smax.romanov@nginx.com 
756213Svbart@nginx.com         ret = nxt_conf_map_object(mp, application, nxt_router_app_conf,
757136Svbart@nginx.com                                   nxt_nitems(nxt_router_app_conf), &apcf);
758133Sigor@sysoev.ru         if (ret != NXT_OK) {
759133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "application map error");
760133Sigor@sysoev.ru             goto app_fail;
761133Sigor@sysoev.ru         }
762115Sigor@sysoev.ru 
763133Sigor@sysoev.ru         nxt_debug(task, "application type: %V", &apcf.type);
764133Sigor@sysoev.ru         nxt_debug(task, "application workers: %D", apcf.workers);
765133Sigor@sysoev.ru 
766216Sigor@sysoev.ru         lang = nxt_app_lang_module(task->thread->runtime, &apcf.type);
767216Sigor@sysoev.ru 
768216Sigor@sysoev.ru         if (lang == NULL) {
769141Smax.romanov@nginx.com             nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
770141Smax.romanov@nginx.com                     &apcf.type);
771141Smax.romanov@nginx.com             goto app_fail;
772141Smax.romanov@nginx.com         }
773141Smax.romanov@nginx.com 
774216Sigor@sysoev.ru         nxt_debug(task, "application language module: \"%s\"", lang->file);
775216Sigor@sysoev.ru 
776216Sigor@sysoev.ru         type = nxt_app_parse_type(&lang->type);
777216Sigor@sysoev.ru 
778216Sigor@sysoev.ru         if (type == NXT_APP_UNKNOWN) {
779216Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
780216Sigor@sysoev.ru                     &lang->type);
781216Sigor@sysoev.ru             goto app_fail;
782216Sigor@sysoev.ru         }
783216Sigor@sysoev.ru 
784216Sigor@sysoev.ru         if (nxt_app_prepare_msg[type] == NULL) {
785133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"",
786216Sigor@sysoev.ru                     &lang->type);
787133Sigor@sysoev.ru             goto app_fail;
788133Sigor@sysoev.ru         }
789133Sigor@sysoev.ru 
790133Sigor@sysoev.ru         ret = nxt_thread_mutex_create(&app->mutex);
791133Sigor@sysoev.ru         if (ret != NXT_OK) {
792133Sigor@sysoev.ru             goto app_fail;
793133Sigor@sysoev.ru         }
794133Sigor@sysoev.ru 
795141Smax.romanov@nginx.com         nxt_queue_init(&app->ports);
796141Smax.romanov@nginx.com         nxt_queue_init(&app->requests);
797141Smax.romanov@nginx.com 
798144Smax.romanov@nginx.com         app->name.length = name.length;
799144Smax.romanov@nginx.com         nxt_memcpy(app->name.start, name.start, name.length);
800144Smax.romanov@nginx.com 
801133Sigor@sysoev.ru         app->type = type;
802133Sigor@sysoev.ru         app->max_workers = apcf.workers;
803133Sigor@sysoev.ru         app->live = 1;
804216Sigor@sysoev.ru         app->prepare_msg = nxt_app_prepare_msg[type];
805133Sigor@sysoev.ru 
806133Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->apps, &app->link);
807133Sigor@sysoev.ru     }
808133Sigor@sysoev.ru 
809133Sigor@sysoev.ru     http = nxt_conf_get_path(conf, &http_path);
810133Sigor@sysoev.ru #if 0
811133Sigor@sysoev.ru     if (http == NULL) {
812133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"http\" block");
813133Sigor@sysoev.ru         return NXT_ERROR;
814133Sigor@sysoev.ru     }
815133Sigor@sysoev.ru #endif
816133Sigor@sysoev.ru 
817133Sigor@sysoev.ru     listeners = nxt_conf_get_path(conf, &listeners_path);
818115Sigor@sysoev.ru     if (listeners == NULL) {
819133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block");
820115Sigor@sysoev.ru         return NXT_ERROR;
821115Sigor@sysoev.ru     }
82253Sigor@sysoev.ru 
823133Sigor@sysoev.ru     next = 0;
82453Sigor@sysoev.ru 
825115Sigor@sysoev.ru     for ( ;; ) {
826115Sigor@sysoev.ru         listener = nxt_conf_next_object_member(listeners, &name, &next);
827115Sigor@sysoev.ru         if (listener == NULL) {
828115Sigor@sysoev.ru             break;
829115Sigor@sysoev.ru         }
83053Sigor@sysoev.ru 
831115Sigor@sysoev.ru         sa = nxt_sockaddr_parse(mp, &name);
832115Sigor@sysoev.ru         if (sa == NULL) {
833115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name);
834133Sigor@sysoev.ru             goto fail;
835115Sigor@sysoev.ru         }
836115Sigor@sysoev.ru 
837115Sigor@sysoev.ru         sa->type = SOCK_STREAM;
838115Sigor@sysoev.ru 
839115Sigor@sysoev.ru         nxt_debug(task, "router listener: \"%*s\"",
840115Sigor@sysoev.ru                   sa->length, nxt_sockaddr_start(sa));
84153Sigor@sysoev.ru 
842115Sigor@sysoev.ru         skcf = nxt_router_socket_conf(task, mp, sa);
843115Sigor@sysoev.ru         if (skcf == NULL) {
844133Sigor@sysoev.ru             goto fail;
845115Sigor@sysoev.ru         }
84653Sigor@sysoev.ru 
847213Svbart@nginx.com         ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf,
848136Svbart@nginx.com                                   nxt_nitems(nxt_router_listener_conf), &lscf);
849115Sigor@sysoev.ru         if (ret != NXT_OK) {
850115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "listener map error");
851133Sigor@sysoev.ru             goto fail;
852115Sigor@sysoev.ru         }
85353Sigor@sysoev.ru 
854133Sigor@sysoev.ru         nxt_debug(task, "application: %V", &lscf.application);
855133Sigor@sysoev.ru 
856133Sigor@sysoev.ru         // STUB, default values if http block is not defined.
857133Sigor@sysoev.ru         skcf->header_buffer_size = 2048;
858133Sigor@sysoev.ru         skcf->large_header_buffer_size = 8192;
859206Smax.romanov@nginx.com         skcf->large_header_buffers = 4;
860206Smax.romanov@nginx.com         skcf->body_buffer_size = 16 * 1024;
861206Smax.romanov@nginx.com         skcf->max_body_size = 2 * 1024 * 1024;
862133Sigor@sysoev.ru         skcf->header_read_timeout = 5000;
863206Smax.romanov@nginx.com         skcf->body_read_timeout = 5000;
86453Sigor@sysoev.ru 
865133Sigor@sysoev.ru         if (http != NULL) {
866213Svbart@nginx.com             ret = nxt_conf_map_object(mp, http, nxt_router_http_conf,
867136Svbart@nginx.com                                       nxt_nitems(nxt_router_http_conf), skcf);
868133Sigor@sysoev.ru             if (ret != NXT_OK) {
869133Sigor@sysoev.ru                 nxt_log(task, NXT_LOG_CRIT, "http map error");
870133Sigor@sysoev.ru                 goto fail;
871133Sigor@sysoev.ru             }
872115Sigor@sysoev.ru         }
873115Sigor@sysoev.ru 
874115Sigor@sysoev.ru         skcf->listen.handler = nxt_router_conn_init;
875115Sigor@sysoev.ru         skcf->router_conf = tmcf->conf;
876160Sigor@sysoev.ru         skcf->router_conf->count++;
877133Sigor@sysoev.ru         skcf->application = nxt_router_listener_application(tmcf,
878133Sigor@sysoev.ru                                                             &lscf.application);
879115Sigor@sysoev.ru 
880115Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->pending, &skcf->link);
881115Sigor@sysoev.ru     }
88253Sigor@sysoev.ru 
883198Sigor@sysoev.ru     nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf);
884198Sigor@sysoev.ru 
88553Sigor@sysoev.ru     return NXT_OK;
886133Sigor@sysoev.ru 
887133Sigor@sysoev.ru app_fail:
888133Sigor@sysoev.ru 
889133Sigor@sysoev.ru     nxt_free(app);
890133Sigor@sysoev.ru 
891133Sigor@sysoev.ru fail:
892133Sigor@sysoev.ru 
893141Smax.romanov@nginx.com     nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
894141Smax.romanov@nginx.com 
895141Smax.romanov@nginx.com         nxt_queue_remove(&app->link);
896133Sigor@sysoev.ru         nxt_thread_mutex_destroy(&app->mutex);
897133Sigor@sysoev.ru         nxt_free(app);
898141Smax.romanov@nginx.com 
899141Smax.romanov@nginx.com     } nxt_queue_loop;
900133Sigor@sysoev.ru 
901133Sigor@sysoev.ru     return NXT_ERROR;
902133Sigor@sysoev.ru }
903133Sigor@sysoev.ru 
904133Sigor@sysoev.ru 
905133Sigor@sysoev.ru static nxt_app_t *
906133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name)
907133Sigor@sysoev.ru {
908141Smax.romanov@nginx.com     nxt_app_t  *app;
909141Smax.romanov@nginx.com 
910141Smax.romanov@nginx.com     nxt_queue_each(app, queue, nxt_app_t, link) {
911133Sigor@sysoev.ru 
912133Sigor@sysoev.ru         if (nxt_strstr_eq(name, &app->name)) {
913133Sigor@sysoev.ru             return app;
914133Sigor@sysoev.ru         }
915141Smax.romanov@nginx.com 
916141Smax.romanov@nginx.com     } nxt_queue_loop;
917133Sigor@sysoev.ru 
918133Sigor@sysoev.ru     return NULL;
919133Sigor@sysoev.ru }
920133Sigor@sysoev.ru 
921133Sigor@sysoev.ru 
922133Sigor@sysoev.ru static nxt_app_t *
923133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name)
924133Sigor@sysoev.ru {
925133Sigor@sysoev.ru     nxt_app_t  *app;
926133Sigor@sysoev.ru 
927133Sigor@sysoev.ru     app = nxt_router_app_find(&tmcf->apps, name);
928133Sigor@sysoev.ru 
929133Sigor@sysoev.ru     if (app == NULL) {
930134Sigor@sysoev.ru         app = nxt_router_app_find(&tmcf->previous, name);
931133Sigor@sysoev.ru     }
932133Sigor@sysoev.ru 
933133Sigor@sysoev.ru     return app;
93453Sigor@sysoev.ru }
93553Sigor@sysoev.ru 
93653Sigor@sysoev.ru 
93753Sigor@sysoev.ru static nxt_socket_conf_t *
93865Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa)
93953Sigor@sysoev.ru {
940163Smax.romanov@nginx.com     nxt_socket_conf_t  *skcf;
941163Smax.romanov@nginx.com 
942163Smax.romanov@nginx.com     skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t));
943163Smax.romanov@nginx.com     if (nxt_slow_path(skcf == NULL)) {
94453Sigor@sysoev.ru         return NULL;
94553Sigor@sysoev.ru     }
946