xref: /unit/src/nxt_router.c (revision 198)
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 
48*198Sigor@sysoev.ru typedef struct {
49*198Sigor@sysoev.ru     nxt_socket_conf_t       *socket_conf;
50*198Sigor@sysoev.ru     nxt_router_temp_conf_t  *temp_conf;
51*198Sigor@sysoev.ru } nxt_socket_rpc_t;
52*198Sigor@sysoev.ru 
53*198Sigor@sysoev.ru 
54139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
55*198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
56*198Sigor@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);
70*198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task,
71*198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf);
72*198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task,
73*198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
74*198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task,
75*198Sigor@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);
92139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
93139Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets);
9453Sigor@sysoev.ru 
9553Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
9653Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
9753Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
9853Sigor@sysoev.ru     nxt_event_engine_t *engine);
99133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router,
100133Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
10153Sigor@sysoev.ru 
10253Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf);
103154Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf);
10453Sigor@sysoev.ru 
10553Sigor@sysoev.ru static void nxt_router_thread_start(void *data);
10653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj,
10753Sigor@sysoev.ru     void *data);
10853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj,
10953Sigor@sysoev.ru     void *data);
11053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj,
11153Sigor@sysoev.ru     void *data);
11253Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj,
11353Sigor@sysoev.ru     void *data);
11453Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task,
11553Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
11653Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj,
11753Sigor@sysoev.ru     void *data);
11853Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task,
11953Sigor@sysoev.ru     nxt_socket_conf_joint_t *joint);
12053Sigor@sysoev.ru 
121167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj,
122167Smax.romanov@nginx.com     void *data);
123167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app);
124167Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t req_id);
125141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj,
126141Smax.romanov@nginx.com     void *data);
127141Smax.romanov@nginx.com 
12853Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data);
12953Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj,
13053Sigor@sysoev.ru     void *data);
13188Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task,
13288Smax.romanov@nginx.com     nxt_conn_t *c, nxt_app_parse_ctx_t *ap);
133141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task,
134167Smax.romanov@nginx.com     nxt_req_app_link_t *ra, nxt_port_t *port);
13588Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data);
13653Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data);
13753Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data);
13853Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data);
13953Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data);
14062Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data);
14120Sigor@sysoev.ru 
142141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code,
143141Smax.romanov@nginx.com     const char* fmt, ...);
144141Smax.romanov@nginx.com 
145119Smax.romanov@nginx.com static nxt_router_t  *nxt_router;
14620Sigor@sysoev.ru 
14720Sigor@sysoev.ru nxt_int_t
148141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data)
14920Sigor@sysoev.ru {
150141Smax.romanov@nginx.com     nxt_int_t      ret;
151141Smax.romanov@nginx.com     nxt_router_t   *router;
152141Smax.romanov@nginx.com     nxt_runtime_t  *rt;
153141Smax.romanov@nginx.com 
154141Smax.romanov@nginx.com     rt = task->thread->runtime;
15553Sigor@sysoev.ru 
15688Smax.romanov@nginx.com     ret = nxt_app_http_init(task, rt);
15788Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
15888Smax.romanov@nginx.com         return ret;
15988Smax.romanov@nginx.com     }
16088Smax.romanov@nginx.com 
16153Sigor@sysoev.ru     router = nxt_zalloc(sizeof(nxt_router_t));
16253Sigor@sysoev.ru     if (nxt_slow_path(router == NULL)) {
16353Sigor@sysoev.ru         return NXT_ERROR;
16453Sigor@sysoev.ru     }
16553Sigor@sysoev.ru 
16653Sigor@sysoev.ru     nxt_queue_init(&router->engines);
16753Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
168133Sigor@sysoev.ru     nxt_queue_init(&router->apps);
16953Sigor@sysoev.ru 
170119Smax.romanov@nginx.com     nxt_router = router;
171119Smax.romanov@nginx.com 
172115Sigor@sysoev.ru     return NXT_OK;
173115Sigor@sysoev.ru }
174115Sigor@sysoev.ru 
175115Sigor@sysoev.ru 
176167Smax.romanov@nginx.com static nxt_start_worker_t *
177192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra)
178167Smax.romanov@nginx.com {
179167Smax.romanov@nginx.com     nxt_port_t          *master_port;
180167Smax.romanov@nginx.com     nxt_runtime_t       *rt;
181167Smax.romanov@nginx.com     nxt_start_worker_t  *sw;
182167Smax.romanov@nginx.com 
183192Smax.romanov@nginx.com     sw = nxt_zalloc(sizeof(nxt_start_worker_t));
184167Smax.romanov@nginx.com 
185167Smax.romanov@nginx.com     if (nxt_slow_path(sw == NULL)) {
186167Smax.romanov@nginx.com         return NULL;
187167Smax.romanov@nginx.com     }
188167Smax.romanov@nginx.com 
189167Smax.romanov@nginx.com     sw->app = app;
190167Smax.romanov@nginx.com     sw->ra = ra;
191167Smax.romanov@nginx.com 
192192Smax.romanov@nginx.com     nxt_debug(task, "sw %p create, request #%uxD, app '%V' %p", sw,
193167Smax.romanov@nginx.com                     ra->req_id, &app->name, app);
194167Smax.romanov@nginx.com 
195167Smax.romanov@nginx.com     rt = task->thread->runtime;
196167Smax.romanov@nginx.com     master_port = rt->port_by_type[NXT_PROCESS_MASTER];
197167Smax.romanov@nginx.com 
198167Smax.romanov@nginx.com     sw->work.handler = nxt_router_send_sw_request;
199167Smax.romanov@nginx.com     sw->work.task = &master_port->engine->task;
200167Smax.romanov@nginx.com     sw->work.obj = sw;
201167Smax.romanov@nginx.com     sw->work.data = task->thread->engine;
202167Smax.romanov@nginx.com     sw->work.next = NULL;
203167Smax.romanov@nginx.com 
204167Smax.romanov@nginx.com     if (task->thread->engine != master_port->engine) {
205192Smax.romanov@nginx.com         nxt_debug(task, "sw %p post send to master engine %p", sw,
206167Smax.romanov@nginx.com                   master_port->engine);
207167Smax.romanov@nginx.com 
208167Smax.romanov@nginx.com         nxt_event_engine_post(master_port->engine, &sw->work);
209167Smax.romanov@nginx.com 
210167Smax.romanov@nginx.com     } else {
211167Smax.romanov@nginx.com         nxt_router_send_sw_request(task, sw, sw->work.data);
212167Smax.romanov@nginx.com     }
213167Smax.romanov@nginx.com 
214167Smax.romanov@nginx.com     return sw;
215167Smax.romanov@nginx.com }
216167Smax.romanov@nginx.com 
217167Smax.romanov@nginx.com 
218192Smax.romanov@nginx.com nxt_inline void
219192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw)
220141Smax.romanov@nginx.com {
221192Smax.romanov@nginx.com     nxt_debug(task, "sw %p release", sw);
222192Smax.romanov@nginx.com 
223192Smax.romanov@nginx.com     nxt_free(sw);
224141Smax.romanov@nginx.com }
225141Smax.romanov@nginx.com 
226141Smax.romanov@nginx.com 
227167Smax.romanov@nginx.com static nxt_req_app_link_t *
228167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc)
229167Smax.romanov@nginx.com {
230167Smax.romanov@nginx.com     nxt_mp_t            *mp;
231167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
232167Smax.romanov@nginx.com 
233167Smax.romanov@nginx.com     mp = rc->conn->mem_pool;
234167Smax.romanov@nginx.com 
235167Smax.romanov@nginx.com     ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t));
236167Smax.romanov@nginx.com 
237167Smax.romanov@nginx.com     if (nxt_slow_path(ra == NULL)) {
238167Smax.romanov@nginx.com         return NULL;
239167Smax.romanov@nginx.com     }
240167Smax.romanov@nginx.com 
241167Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD create", ra->req_id);
242167Smax.romanov@nginx.com 
243167Smax.romanov@nginx.com     nxt_memzero(ra, sizeof(nxt_req_app_link_t));
244167Smax.romanov@nginx.com 
245167Smax.romanov@nginx.com     ra->req_id = rc->req_id;
246167Smax.romanov@nginx.com     ra->app_port = NULL;
247167Smax.romanov@nginx.com     ra->rc = rc;
248167Smax.romanov@nginx.com 
249167Smax.romanov@nginx.com     ra->mem_pool = mp;
250167Smax.romanov@nginx.com 
251167Smax.romanov@nginx.com     ra->work.handler = NULL;
252167Smax.romanov@nginx.com     ra->work.task = &task->thread->engine->task;
253167Smax.romanov@nginx.com     ra->work.obj = ra;
254167Smax.romanov@nginx.com     ra->work.data = task->thread->engine;
255167Smax.romanov@nginx.com 
256167Smax.romanov@nginx.com     return ra;
257167Smax.romanov@nginx.com }
258167Smax.romanov@nginx.com 
259167Smax.romanov@nginx.com 
260167Smax.romanov@nginx.com static void
261167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data)
262167Smax.romanov@nginx.com {
263167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
264167Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
265167Smax.romanov@nginx.com 
266167Smax.romanov@nginx.com     ra = obj;
267167Smax.romanov@nginx.com     engine = data;
268167Smax.romanov@nginx.com 
269167Smax.romanov@nginx.com     if (task->thread->engine != engine) {
270167Smax.romanov@nginx.com         ra->work.handler = nxt_router_ra_release;
271167Smax.romanov@nginx.com         ra->work.task = &engine->task;
272167Smax.romanov@nginx.com         ra->work.next = NULL;
273167Smax.romanov@nginx.com 
274167Smax.romanov@nginx.com         nxt_debug(task, "ra #%uxD post release to %p", ra->req_id, engine);
275167Smax.romanov@nginx.com 
276167Smax.romanov@nginx.com         nxt_event_engine_post(engine, &ra->work);
277167Smax.romanov@nginx.com 
278167Smax.romanov@nginx.com         return;
279167Smax.romanov@nginx.com     }
280167Smax.romanov@nginx.com 
281167Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD release", ra->req_id);
282167Smax.romanov@nginx.com 
283167Smax.romanov@nginx.com     if (ra->app_port != NULL) {
284167Smax.romanov@nginx.com 
285167Smax.romanov@nginx.com         if (ra->rc->conn != NULL) {
286167Smax.romanov@nginx.com             ra->rc->app_port = ra->app_port;
287167Smax.romanov@nginx.com 
288167Smax.romanov@nginx.com         } else {
289167Smax.romanov@nginx.com             nxt_router_app_release_port(task, ra->app_port, ra->app_port->app);
290167Smax.romanov@nginx.com         }
291167Smax.romanov@nginx.com     }
292167Smax.romanov@nginx.com 
293167Smax.romanov@nginx.com     nxt_mp_release(ra->mem_pool, ra);
294167Smax.romanov@nginx.com }
295167Smax.romanov@nginx.com 
296167Smax.romanov@nginx.com 
297141Smax.romanov@nginx.com void
298141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
299141Smax.romanov@nginx.com {
300141Smax.romanov@nginx.com     nxt_port_new_port_handler(task, msg);
301141Smax.romanov@nginx.com 
302192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
303141Smax.romanov@nginx.com         return;
304141Smax.romanov@nginx.com     }
305141Smax.romanov@nginx.com 
306192Smax.romanov@nginx.com     if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) {
307192Smax.romanov@nginx.com         msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
308141Smax.romanov@nginx.com     }
309192Smax.romanov@nginx.com 
310192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
311141Smax.romanov@nginx.com }
312141Smax.romanov@nginx.com 
313141Smax.romanov@nginx.com 
314139Sigor@sysoev.ru void
315139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
316115Sigor@sysoev.ru {
317139Sigor@sysoev.ru     size_t                  dump_size;
318*198Sigor@sysoev.ru     nxt_int_t               ret;
319139Sigor@sysoev.ru     nxt_buf_t               *b;
320139Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
321139Sigor@sysoev.ru 
322139Sigor@sysoev.ru     b = msg->buf;
323139Sigor@sysoev.ru 
324139Sigor@sysoev.ru     dump_size = nxt_buf_used_size(b);
325139Sigor@sysoev.ru 
326139Sigor@sysoev.ru     if (dump_size > 300) {
327139Sigor@sysoev.ru         dump_size = 300;
32853Sigor@sysoev.ru     }
32953Sigor@sysoev.ru 
330139Sigor@sysoev.ru     nxt_debug(task, "router conf data (%z): %*s",
331139Sigor@sysoev.ru               msg->size, dump_size, b->mem.pos);
332139Sigor@sysoev.ru 
333139Sigor@sysoev.ru     tmcf = nxt_router_temp_conf(task);
334139Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
335139Sigor@sysoev.ru         return;
33653Sigor@sysoev.ru     }
33753Sigor@sysoev.ru 
338139Sigor@sysoev.ru     tmcf->conf->router = nxt_router;
339139Sigor@sysoev.ru     tmcf->stream = msg->port_msg.stream;
340139Sigor@sysoev.ru     tmcf->port = nxt_runtime_port_find(task->thread->runtime,
341*198Sigor@sysoev.ru                                        msg->port_msg.pid,
342*198Sigor@sysoev.ru                                        msg->port_msg.reply_port);
343*198Sigor@sysoev.ru 
344*198Sigor@sysoev.ru     ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free);
345*198Sigor@sysoev.ru 
346*198Sigor@sysoev.ru     if (nxt_fast_path(ret == NXT_OK)) {
347*198Sigor@sysoev.ru         nxt_router_conf_apply(task, tmcf, NULL);
348*198Sigor@sysoev.ru 
349*198Sigor@sysoev.ru     } else {
350*198Sigor@sysoev.ru         nxt_router_conf_error(task, tmcf);
351139Sigor@sysoev.ru     }
35253Sigor@sysoev.ru }
35353Sigor@sysoev.ru 
35453Sigor@sysoev.ru 
355192Smax.romanov@nginx.com void
356192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
357192Smax.romanov@nginx.com {
358192Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, msg);
359192Smax.romanov@nginx.com 
360192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
361192Smax.romanov@nginx.com         return;
362192Smax.romanov@nginx.com     }
363192Smax.romanov@nginx.com 
364192Smax.romanov@nginx.com     msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
365192Smax.romanov@nginx.com 
366192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
367192Smax.romanov@nginx.com }
368192Smax.romanov@nginx.com 
369192Smax.romanov@nginx.com 
37053Sigor@sysoev.ru static nxt_router_temp_conf_t *
371139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task)
37253Sigor@sysoev.ru {
37365Sigor@sysoev.ru     nxt_mp_t                *mp, *tmp;
37453Sigor@sysoev.ru     nxt_router_conf_t       *rtcf;
37553Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
37653Sigor@sysoev.ru 
37765Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
37853Sigor@sysoev.ru     if (nxt_slow_path(mp == NULL)) {
37953Sigor@sysoev.ru         return NULL;
38053Sigor@sysoev.ru     }
38153Sigor@sysoev.ru 
38265Sigor@sysoev.ru     rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t));
38353Sigor@sysoev.ru     if (nxt_slow_path(rtcf == NULL)) {
38453Sigor@sysoev.ru         goto fail;
38553Sigor@sysoev.ru     }
38653Sigor@sysoev.ru 
38753Sigor@sysoev.ru     rtcf->mem_pool = mp;
38853Sigor@sysoev.ru 
38965Sigor@sysoev.ru     tmp = nxt_mp_create(1024, 128, 256, 32);
39053Sigor@sysoev.ru     if (nxt_slow_path(tmp == NULL)) {
39153Sigor@sysoev.ru         goto fail;
39253Sigor@sysoev.ru     }
39353Sigor@sysoev.ru 
39465Sigor@sysoev.ru     tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t));
39553Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
39653Sigor@sysoev.ru         goto temp_fail;
39753Sigor@sysoev.ru     }
39853Sigor@sysoev.ru 
39953Sigor@sysoev.ru     tmcf->mem_pool = tmp;
40053Sigor@sysoev.ru     tmcf->conf = rtcf;
401139Sigor@sysoev.ru     tmcf->count = 1;
402139Sigor@sysoev.ru     tmcf->engine = task->thread->engine;
40353Sigor@sysoev.ru 
40453Sigor@sysoev.ru     tmcf->engines = nxt_array_create(tmcf->mem_pool, 4,
40553Sigor@sysoev.ru                                      sizeof(nxt_router_engine_conf_t));
40653Sigor@sysoev.ru     if (nxt_slow_path(tmcf->engines == NULL)) {
40753Sigor@sysoev.ru         goto temp_fail;
40853Sigor@sysoev.ru     }
40953Sigor@sysoev.ru 
41053Sigor@sysoev.ru     nxt_queue_init(&tmcf->deleting);
41153Sigor@sysoev.ru     nxt_queue_init(&tmcf->keeping);
41253Sigor@sysoev.ru     nxt_queue_init(&tmcf->updating);
41353Sigor@sysoev.ru     nxt_queue_init(&tmcf->pending);
41453Sigor@sysoev.ru     nxt_queue_init(&tmcf->creating);
415133Sigor@sysoev.ru     nxt_queue_init(&tmcf->apps);
416133Sigor@sysoev.ru     nxt_queue_init(&tmcf->previous);
41753Sigor@sysoev.ru 
41853Sigor@sysoev.ru     return tmcf;
41953Sigor@sysoev.ru 
42053Sigor@sysoev.ru temp_fail:
42153Sigor@sysoev.ru 
42265Sigor@sysoev.ru     nxt_mp_destroy(tmp);
42353Sigor@sysoev.ru 
42453Sigor@sysoev.ru fail:
42553Sigor@sysoev.ru 
42665Sigor@sysoev.ru     nxt_mp_destroy(mp);
42753Sigor@sysoev.ru 
42853Sigor@sysoev.ru     return NULL;
42953Sigor@sysoev.ru }
43053Sigor@sysoev.ru 
43153Sigor@sysoev.ru 
432*198Sigor@sysoev.ru static void
433*198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
434139Sigor@sysoev.ru {
435139Sigor@sysoev.ru     nxt_int_t                    ret;
436139Sigor@sysoev.ru     nxt_router_t                 *router;
437139Sigor@sysoev.ru     nxt_runtime_t                *rt;
438*198Sigor@sysoev.ru     nxt_queue_link_t             *qlk;
439*198Sigor@sysoev.ru     nxt_socket_conf_t            *skcf;
440*198Sigor@sysoev.ru     nxt_router_temp_conf_t       *tmcf;
441139Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
442139Sigor@sysoev.ru 
443*198Sigor@sysoev.ru     tmcf = obj;
444*198Sigor@sysoev.ru 
445*198Sigor@sysoev.ru     qlk = nxt_queue_first(&tmcf->pending);
446*198Sigor@sysoev.ru 
447*198Sigor@sysoev.ru     if (qlk != nxt_queue_tail(&tmcf->pending)) {
448*198Sigor@sysoev.ru         nxt_queue_remove(qlk);
449*198Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->creating, qlk);
450*198Sigor@sysoev.ru 
451*198Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
452*198Sigor@sysoev.ru 
453*198Sigor@sysoev.ru         nxt_router_listen_socket_rpc_create(task, tmcf, skcf);
454*198Sigor@sysoev.ru 
455*198Sigor@sysoev.ru         return;
456139Sigor@sysoev.ru     }
457139Sigor@sysoev.ru 
458139Sigor@sysoev.ru     rt = task->thread->runtime;
459139Sigor@sysoev.ru 
460139Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
461139Sigor@sysoev.ru 
462*198Sigor@sysoev.ru     router = tmcf->conf->router;
463*198Sigor@sysoev.ru 
464139Sigor@sysoev.ru     ret = nxt_router_engines_create(task, router, tmcf, interface);
465139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
466*198Sigor@sysoev.ru         goto fail;
467139Sigor@sysoev.ru     }
468139Sigor@sysoev.ru 
469139Sigor@sysoev.ru     ret = nxt_router_threads_create(task, rt, tmcf);
470139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
471*198Sigor@sysoev.ru         goto fail;
472139Sigor@sysoev.ru     }
473139Sigor@sysoev.ru 
474139Sigor@sysoev.ru     nxt_router_apps_sort(router, tmcf);
475139Sigor@sysoev.ru 
476139Sigor@sysoev.ru     nxt_router_engines_post(tmcf);
477139Sigor@sysoev.ru 
478139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->updating);
479139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->creating);
480139Sigor@sysoev.ru 
481*198Sigor@sysoev.ru     nxt_router_conf_ready(task, tmcf);
482*198Sigor@sysoev.ru 
483*198Sigor@sysoev.ru     return;
484*198Sigor@sysoev.ru 
485*198Sigor@sysoev.ru fail:
486*198Sigor@sysoev.ru 
487*198Sigor@sysoev.ru     nxt_router_conf_error(task, tmcf);
488*198Sigor@sysoev.ru 
489*198Sigor@sysoev.ru     return;
490139Sigor@sysoev.ru }
491139Sigor@sysoev.ru 
492139Sigor@sysoev.ru 
493139Sigor@sysoev.ru static void
494139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data)
495139Sigor@sysoev.ru {
496153Sigor@sysoev.ru     nxt_joint_job_t  *job;
497153Sigor@sysoev.ru 
498153Sigor@sysoev.ru     job = obj;
499153Sigor@sysoev.ru 
500*198Sigor@sysoev.ru     nxt_router_conf_ready(task, job->tmcf);
501139Sigor@sysoev.ru }
502139Sigor@sysoev.ru 
503139Sigor@sysoev.ru 
504139Sigor@sysoev.ru static void
505*198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
506139Sigor@sysoev.ru {
507139Sigor@sysoev.ru     nxt_debug(task, "temp conf count:%D", tmcf->count);
508139Sigor@sysoev.ru 
509139Sigor@sysoev.ru     if (--tmcf->count == 0) {
510193Smax.romanov@nginx.com         nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST);
511139Sigor@sysoev.ru     }
512139Sigor@sysoev.ru }
513139Sigor@sysoev.ru 
514139Sigor@sysoev.ru 
515139Sigor@sysoev.ru static void
516139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
517139Sigor@sysoev.ru {
518148Sigor@sysoev.ru     nxt_socket_t       s;
519149Sigor@sysoev.ru     nxt_router_t       *router;
520148Sigor@sysoev.ru     nxt_queue_link_t   *qlk;
521148Sigor@sysoev.ru     nxt_socket_conf_t  *skcf;
522148Sigor@sysoev.ru 
523*198Sigor@sysoev.ru     nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf");
524*198Sigor@sysoev.ru 
525148Sigor@sysoev.ru     for (qlk = nxt_queue_first(&tmcf->creating);
526148Sigor@sysoev.ru          qlk != nxt_queue_tail(&tmcf->creating);
527148Sigor@sysoev.ru          qlk = nxt_queue_next(qlk))
528148Sigor@sysoev.ru     {
529148Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
530148Sigor@sysoev.ru         s = skcf->listen.socket;
531148Sigor@sysoev.ru 
532148Sigor@sysoev.ru         if (s != -1) {
533148Sigor@sysoev.ru             nxt_socket_close(task, s);
534148Sigor@sysoev.ru         }
535148Sigor@sysoev.ru 
536148Sigor@sysoev.ru         nxt_free(skcf->socket);
537148Sigor@sysoev.ru     }
538148Sigor@sysoev.ru 
539149Sigor@sysoev.ru     router = tmcf->conf->router;
540149Sigor@sysoev.ru 
541149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->keeping);
542149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->deleting);
543149Sigor@sysoev.ru 
544148Sigor@sysoev.ru     // TODO: new engines and threads
545148Sigor@sysoev.ru 
546139Sigor@sysoev.ru     nxt_mp_destroy(tmcf->conf->mem_pool);
547139Sigor@sysoev.ru 
548193Smax.romanov@nginx.com     nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR);
549139Sigor@sysoev.ru }
550139Sigor@sysoev.ru 
551139Sigor@sysoev.ru 
552139Sigor@sysoev.ru static void
553139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
554193Smax.romanov@nginx.com     nxt_port_msg_type_t type)
555139Sigor@sysoev.ru {
556193Smax.romanov@nginx.com     nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL);
557139Sigor@sysoev.ru }
558139Sigor@sysoev.ru 
559139Sigor@sysoev.ru 
560115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_conf[] = {
561115Sigor@sysoev.ru     {
562133Sigor@sysoev.ru         nxt_string("listeners_threads"),
563115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
564115Sigor@sysoev.ru         offsetof(nxt_router_conf_t, threads),
565115Sigor@sysoev.ru     },
566115Sigor@sysoev.ru };
567115Sigor@sysoev.ru 
568115Sigor@sysoev.ru 
569133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_app_conf[] = {
570115Sigor@sysoev.ru     {
571133Sigor@sysoev.ru         nxt_string("type"),
572115Sigor@sysoev.ru         NXT_CONF_MAP_STR,
573133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, type),
574115Sigor@sysoev.ru     },
575115Sigor@sysoev.ru 
576115Sigor@sysoev.ru     {
577133Sigor@sysoev.ru         nxt_string("workers"),
578115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
579133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, workers),
580133Sigor@sysoev.ru     },
581133Sigor@sysoev.ru };
582133Sigor@sysoev.ru 
583133Sigor@sysoev.ru 
584133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_listener_conf[] = {
585133Sigor@sysoev.ru     {
586133Sigor@sysoev.ru         nxt_string("application"),
587133Sigor@sysoev.ru         NXT_CONF_MAP_STR,
588133Sigor@sysoev.ru         offsetof(nxt_router_listener_conf_t, application),
589115Sigor@sysoev.ru     },
590115Sigor@sysoev.ru };
591115Sigor@sysoev.ru 
592115Sigor@sysoev.ru 
593115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_http_conf[] = {
594115Sigor@sysoev.ru     {
595115Sigor@sysoev.ru         nxt_string("header_buffer_size"),
596115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
597115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_buffer_size),
598115Sigor@sysoev.ru     },
599115Sigor@sysoev.ru 
600115Sigor@sysoev.ru     {
601115Sigor@sysoev.ru         nxt_string("large_header_buffer_size"),
602115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
603115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, large_header_buffer_size),
604115Sigor@sysoev.ru     },
605115Sigor@sysoev.ru 
606115Sigor@sysoev.ru     {
607115Sigor@sysoev.ru         nxt_string("header_read_timeout"),
608115Sigor@sysoev.ru         NXT_CONF_MAP_MSEC,
609115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_read_timeout),
610115Sigor@sysoev.ru     },
611115Sigor@sysoev.ru };
612115Sigor@sysoev.ru 
613115Sigor@sysoev.ru 
61453Sigor@sysoev.ru static nxt_int_t
615115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
616115Sigor@sysoev.ru     u_char *start, u_char *end)
61753Sigor@sysoev.ru {
618133Sigor@sysoev.ru     u_char                      *p;
619133Sigor@sysoev.ru     size_t                      size;
620115Sigor@sysoev.ru     nxt_mp_t                    *mp;
621115Sigor@sysoev.ru     uint32_t                    next;
622115Sigor@sysoev.ru     nxt_int_t                   ret;
623115Sigor@sysoev.ru     nxt_str_t                   name;
624133Sigor@sysoev.ru     nxt_app_t                   *app, *prev;
625133Sigor@sysoev.ru     nxt_app_type_t              type;
626115Sigor@sysoev.ru     nxt_sockaddr_t              *sa;
627133Sigor@sysoev.ru     nxt_conf_value_t            *conf, *http;
628133Sigor@sysoev.ru     nxt_conf_value_t            *applications, *application;
629133Sigor@sysoev.ru     nxt_conf_value_t            *listeners, *listener;
630115Sigor@sysoev.ru     nxt_socket_conf_t           *skcf;
631133Sigor@sysoev.ru     nxt_router_app_conf_t       apcf;
632115Sigor@sysoev.ru     nxt_router_listener_conf_t  lscf;
633115Sigor@sysoev.ru 
634115Sigor@sysoev.ru     static nxt_str_t  http_path = nxt_string("/http");
635133Sigor@sysoev.ru     static nxt_str_t  applications_path = nxt_string("/applications");
636115Sigor@sysoev.ru     static nxt_str_t  listeners_path = nxt_string("/listeners");
637115Sigor@sysoev.ru 
638115Sigor@sysoev.ru     conf = nxt_conf_json_parse(tmcf->mem_pool, start, end);
639115Sigor@sysoev.ru     if (conf == NULL) {
640115Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "configuration parsing error");
641115Sigor@sysoev.ru         return NXT_ERROR;
642115Sigor@sysoev.ru     }
643115Sigor@sysoev.ru 
644136Svbart@nginx.com     ret = nxt_conf_map_object(conf, nxt_router_conf,
645136Svbart@nginx.com                               nxt_nitems(nxt_router_conf), tmcf->conf);
646115Sigor@sysoev.ru     if (ret != NXT_OK) {
647133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "root map error");
648115Sigor@sysoev.ru         return NXT_ERROR;
649115Sigor@sysoev.ru     }
650115Sigor@sysoev.ru 
651117Sigor@sysoev.ru     if (tmcf->conf->threads == 0) {
652117Sigor@sysoev.ru         tmcf->conf->threads = nxt_ncpu;
653117Sigor@sysoev.ru     }
654117Sigor@sysoev.ru 
655133Sigor@sysoev.ru     applications = nxt_conf_get_path(conf, &applications_path);
656133Sigor@sysoev.ru     if (applications == NULL) {
657133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block");
658115Sigor@sysoev.ru         return NXT_ERROR;
659115Sigor@sysoev.ru     }
660115Sigor@sysoev.ru 
661133Sigor@sysoev.ru     next = 0;
662133Sigor@sysoev.ru 
663133Sigor@sysoev.ru     for ( ;; ) {
664133Sigor@sysoev.ru         application = nxt_conf_next_object_member(applications, &name, &next);
665133Sigor@sysoev.ru         if (application == NULL) {
666133Sigor@sysoev.ru             break;
667133Sigor@sysoev.ru         }
668133Sigor@sysoev.ru 
669133Sigor@sysoev.ru         nxt_debug(task, "application \"%V\"", &name);
670133Sigor@sysoev.ru 
671144Smax.romanov@nginx.com         size = nxt_conf_json_length(application, NULL);
672144Smax.romanov@nginx.com 
673144Smax.romanov@nginx.com         app = nxt_malloc(sizeof(nxt_app_t) + name.length + size);
674133Sigor@sysoev.ru         if (app == NULL) {
675133Sigor@sysoev.ru             goto fail;
676133Sigor@sysoev.ru         }
677133Sigor@sysoev.ru 
678144Smax.romanov@nginx.com         nxt_memzero(app, sizeof(nxt_app_t));
679144Smax.romanov@nginx.com 
680144Smax.romanov@nginx.com         app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t));
681144Smax.romanov@nginx.com         app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length);
682133Sigor@sysoev.ru 
683133Sigor@sysoev.ru         p = nxt_conf_json_print(app->conf.start, application, NULL);
684133Sigor@sysoev.ru         app->conf.length = p - app->conf.start;
685133Sigor@sysoev.ru 
686144Smax.romanov@nginx.com         nxt_assert(app->conf.length <= size);
687144Smax.romanov@nginx.com 
688133Sigor@sysoev.ru         nxt_debug(task, "application conf \"%V\"", &app->conf);
689133Sigor@sysoev.ru 
690133Sigor@sysoev.ru         prev = nxt_router_app_find(&tmcf->conf->router->apps, &name);
691133Sigor@sysoev.ru 
692133Sigor@sysoev.ru         if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) {
693133Sigor@sysoev.ru             nxt_free(app);
694133Sigor@sysoev.ru 
695133Sigor@sysoev.ru             nxt_queue_remove(&prev->link);
696133Sigor@sysoev.ru             nxt_queue_insert_tail(&tmcf->previous, &prev->link);
697133Sigor@sysoev.ru             continue;
698133Sigor@sysoev.ru         }
699133Sigor@sysoev.ru 
700136Svbart@nginx.com         ret = nxt_conf_map_object(application, nxt_router_app_conf,
701136Svbart@nginx.com                                   nxt_nitems(nxt_router_app_conf), &apcf);
702133Sigor@sysoev.ru         if (ret != NXT_OK) {
703133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "application map error");
704133Sigor@sysoev.ru             goto app_fail;
705133Sigor@sysoev.ru         }
706115Sigor@sysoev.ru 
707133Sigor@sysoev.ru         nxt_debug(task, "application type: %V", &apcf.type);
708133Sigor@sysoev.ru         nxt_debug(task, "application workers: %D", apcf.workers);
709133Sigor@sysoev.ru 
710141Smax.romanov@nginx.com         type = nxt_app_parse_type(&apcf.type);
711141Smax.romanov@nginx.com 
712141Smax.romanov@nginx.com         if (type == NXT_APP_UNKNOWN) {
713141Smax.romanov@nginx.com             nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
714141Smax.romanov@nginx.com                     &apcf.type);
715141Smax.romanov@nginx.com             goto app_fail;
716141Smax.romanov@nginx.com         }
717141Smax.romanov@nginx.com 
718141Smax.romanov@nginx.com         if (nxt_app_modules[type] == NULL) {
719133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"",
720133Sigor@sysoev.ru                     &apcf.type);
721133Sigor@sysoev.ru             goto app_fail;
722133Sigor@sysoev.ru         }
723133Sigor@sysoev.ru 
724133Sigor@sysoev.ru         ret = nxt_thread_mutex_create(&app->mutex);
725133Sigor@sysoev.ru         if (ret != NXT_OK) {
726133Sigor@sysoev.ru             goto app_fail;
727133Sigor@sysoev.ru         }
728133Sigor@sysoev.ru 
729141Smax.romanov@nginx.com         nxt_queue_init(&app->ports);
730141Smax.romanov@nginx.com         nxt_queue_init(&app->requests);
731141Smax.romanov@nginx.com 
732144Smax.romanov@nginx.com         app->name.length = name.length;
733144Smax.romanov@nginx.com         nxt_memcpy(app->name.start, name.start, name.length);
734144Smax.romanov@nginx.com 
735133Sigor@sysoev.ru         app->type = type;
736133Sigor@sysoev.ru         app->max_workers = apcf.workers;
737133Sigor@sysoev.ru         app->live = 1;
738141Smax.romanov@nginx.com         app->module = nxt_app_modules[type];
739133Sigor@sysoev.ru 
740133Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->apps, &app->link);
741133Sigor@sysoev.ru     }
742133Sigor@sysoev.ru 
743133Sigor@sysoev.ru     http = nxt_conf_get_path(conf, &http_path);
744133Sigor@sysoev.ru #if 0
745133Sigor@sysoev.ru     if (http == NULL) {
746133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"http\" block");
747133Sigor@sysoev.ru         return NXT_ERROR;
748133Sigor@sysoev.ru     }
749133Sigor@sysoev.ru #endif
750133Sigor@sysoev.ru 
751133Sigor@sysoev.ru     listeners = nxt_conf_get_path(conf, &listeners_path);
752115Sigor@sysoev.ru     if (listeners == NULL) {
753133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block");
754115Sigor@sysoev.ru         return NXT_ERROR;
755115Sigor@sysoev.ru     }
75653Sigor@sysoev.ru 
757133Sigor@sysoev.ru     next = 0;
75853Sigor@sysoev.ru 
759133Sigor@sysoev.ru     mp = tmcf->conf->mem_pool;
760115Sigor@sysoev.ru 
761115Sigor@sysoev.ru     for ( ;; ) {
762115Sigor@sysoev.ru         listener = nxt_conf_next_object_member(listeners, &name, &next);
763115Sigor@sysoev.ru         if (listener == NULL) {
764115Sigor@sysoev.ru             break;
765115Sigor@sysoev.ru         }
76653Sigor@sysoev.ru 
767115Sigor@sysoev.ru         sa = nxt_sockaddr_parse(mp, &name);
768115Sigor@sysoev.ru         if (sa == NULL) {
769115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name);
770133Sigor@sysoev.ru             goto fail;
771115Sigor@sysoev.ru         }
772115Sigor@sysoev.ru 
773115Sigor@sysoev.ru         sa->type = SOCK_STREAM;
774115Sigor@sysoev.ru 
775115Sigor@sysoev.ru         nxt_debug(task, "router listener: \"%*s\"",
776115Sigor@sysoev.ru                   sa->length, nxt_sockaddr_start(sa));
77753Sigor@sysoev.ru 
778115Sigor@sysoev.ru         skcf = nxt_router_socket_conf(task, mp, sa);
779115Sigor@sysoev.ru         if (skcf == NULL) {
780133Sigor@sysoev.ru             goto fail;
781115Sigor@sysoev.ru         }
78253Sigor@sysoev.ru 
783136Svbart@nginx.com         ret = nxt_conf_map_object(listener, nxt_router_listener_conf,
784136Svbart@nginx.com                                   nxt_nitems(nxt_router_listener_conf), &lscf);
785115Sigor@sysoev.ru         if (ret != NXT_OK) {
786115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "listener map error");
787133Sigor@sysoev.ru             goto fail;
788115Sigor@sysoev.ru         }
78953Sigor@sysoev.ru 
790133Sigor@sysoev.ru         nxt_debug(task, "application: %V", &lscf.application);
791133Sigor@sysoev.ru 
792133Sigor@sysoev.ru         // STUB, default values if http block is not defined.
793133Sigor@sysoev.ru         skcf->header_buffer_size = 2048;
794133Sigor@sysoev.ru         skcf->large_header_buffer_size = 8192;
795133Sigor@sysoev.ru         skcf->header_read_timeout = 5000;
79653Sigor@sysoev.ru 
797133Sigor@sysoev.ru         if (http != NULL) {
798136Svbart@nginx.com             ret = nxt_conf_map_object(http, nxt_router_http_conf,
799136Svbart@nginx.com                                       nxt_nitems(nxt_router_http_conf), skcf);
800133Sigor@sysoev.ru             if (ret != NXT_OK) {
801133Sigor@sysoev.ru                 nxt_log(task, NXT_LOG_CRIT, "http map error");
802133Sigor@sysoev.ru                 goto fail;
803133Sigor@sysoev.ru             }
804115Sigor@sysoev.ru         }
805115Sigor@sysoev.ru 
806115Sigor@sysoev.ru         skcf->listen.handler = nxt_router_conn_init;
807115Sigor@sysoev.ru         skcf->router_conf = tmcf->conf;
808160Sigor@sysoev.ru         skcf->router_conf->count++;
809133Sigor@sysoev.ru         skcf->application = nxt_router_listener_application(tmcf,
810133Sigor@sysoev.ru                                                             &lscf.application);
811115Sigor@sysoev.ru 
812115Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->pending, &skcf->link);
813115Sigor@sysoev.ru     }
81453Sigor@sysoev.ru 
815*198Sigor@sysoev.ru     nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf);
816*198Sigor@sysoev.ru 
81753Sigor@sysoev.ru     return NXT_OK;
818133Sigor@sysoev.ru 
819133Sigor@sysoev.ru app_fail:
820133Sigor@sysoev.ru 
821133Sigor@sysoev.ru     nxt_free(app);
822133Sigor@sysoev.ru 
823133Sigor@sysoev.ru fail:
824133Sigor@sysoev.ru 
825141Smax.romanov@nginx.com     nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
826141Smax.romanov@nginx.com 
827141Smax.romanov@nginx.com         nxt_queue_remove(&app->link);
828133Sigor@sysoev.ru         nxt_thread_mutex_destroy(&app->mutex);
829133Sigor@sysoev.ru         nxt_free(app);
830141Smax.romanov@nginx.com 
831141Smax.romanov@nginx.com     } nxt_queue_loop;
832133Sigor@sysoev.ru 
833133Sigor@sysoev.ru     return NXT_ERROR;
834133Sigor@sysoev.ru }
835133Sigor@sysoev.ru 
836133Sigor@sysoev.ru 
837133Sigor@sysoev.ru static nxt_app_t *
838133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name)
839133Sigor@sysoev.ru {
840141Smax.romanov@nginx.com     nxt_app_t  *app;
841141Smax.romanov@nginx.com 
842141Smax.romanov@nginx.com     nxt_queue_each(app, queue, nxt_app_t, link) {
843133Sigor@sysoev.ru 
844133Sigor@sysoev.ru         if (nxt_strstr_eq(name, &app->name)) {
845133Sigor@sysoev.ru             return app;
846133Sigor@sysoev.ru         }
847141Smax.romanov@nginx.com 
848141Smax.romanov@nginx.com     } nxt_queue_loop;
849133Sigor@sysoev.ru 
850133Sigor@sysoev.ru     return NULL;
851133Sigor@sysoev.ru }
852133Sigor@sysoev.ru 
853133Sigor@sysoev.ru 
854133Sigor@sysoev.ru static nxt_app_t *
855133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name)
856133Sigor@sysoev.ru {
857133Sigor@sysoev.ru     nxt_app_t  *app;
858133Sigor@sysoev.ru 
859133Sigor@sysoev.ru     app = nxt_router_app_find(&tmcf->apps, name);
860133Sigor@sysoev.ru 
861133Sigor@sysoev.ru     if (app == NULL) {
862134Sigor@sysoev.ru         app = nxt_router_app_find(&tmcf->previous, name);
863133Sigor@sysoev.ru     }
864133Sigor@sysoev.ru 
865133Sigor@sysoev.ru     return app;
86653Sigor@sysoev.ru }
86753Sigor@sysoev.ru 
86853Sigor@sysoev.ru 
86953Sigor@sysoev.ru static nxt_socket_conf_t *
87065Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa)
87153Sigor@sysoev.ru {
872163Smax.romanov@nginx.com     nxt_socket_conf_t  *skcf;
873163Smax.romanov@nginx.com 
874163Smax.romanov@nginx.com     skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t));
875163Smax.romanov@nginx.com     if (nxt_slow_path(skcf == NULL)) {
87653Sigor@sysoev.ru         return NULL;
87753Sigor@sysoev.ru     }
87853Sigor@sysoev.ru 
879163Smax.romanov@nginx.com     skcf->sockaddr = sa;
880163Smax.romanov@nginx.com 
881163Smax.romanov@nginx.com     skcf->listen.sockaddr = sa;
882163Smax.romanov@nginx.com     skcf->listen.socklen = sa->socklen;
883163Smax.romanov@nginx.com     skcf->listen.address_length = sa->length;
884163Smax.romanov@nginx.com 
885163Smax.romanov@nginx.com     skcf->listen.socket = -1;
886163Smax.romanov@nginx.com     skcf->listen.backlog = NXT_LISTEN_BACKLOG;
887163Smax.romanov@nginx.com     skcf->listen.flags = NXT_NONBLOCK;
888163Smax.romanov@nginx.com     skcf->listen.read_after_accept = 1;
889163Smax.romanov@nginx.com 
890163Smax.romanov@nginx.com     return skcf;
89153Sigor@sysoev.ru }
89253Sigor@sysoev.ru 
89353Sigor@sysoev.ru 
89453Sigor@sysoev.ru static void
89553Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router,
89653Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf)
89753Sigor@sysoev.ru {
89853Sigor@sysoev.ru     nxt_queue_link_t   *nqlk, *oqlk, *next;
89953Sigor@sysoev.ru     nxt_socket_conf_t  *nskcf, *oskcf;
90053Sigor@sysoev.ru 
90153Sigor@sysoev.ru     for (nqlk = nxt_queue_first(&tmcf->pending);
90253Sigor@sysoev.ru          nqlk != nxt_queue_tail(&tmcf->pending);
90353Sigor@sysoev.ru          nqlk = next)
90453Sigor@sysoev.ru     {
90553Sigor@sysoev.ru         next = nxt_queue_next(nqlk);
90653Sigor@sysoev.ru         nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link);
90753Sigor@sysoev.ru 
90853Sigor@sysoev.ru         for (oqlk = nxt_queue_first(&router->sockets);
90953Sigor@sysoev.ru              oqlk != nxt_queue_tail(&router->sockets);
91053Sigor@sysoev.ru              oqlk = nxt_queue_next(oqlk))
91153Sigor@sysoev.ru         {
91253Sigor@sysoev.ru             oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link);
91353Sigor@sysoev.ru 
914115Sigor@sysoev.ru             if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) {
915115Sigor@sysoev.ru                 nskcf->socket = oskcf->socket;
916115Sigor@sysoev.ru                 nskcf->listen.socket = oskcf->listen.socket;
917115Sigor@sysoev.ru 
91853Sigor@sysoev.ru                 nxt_queue_remove(oqlk);
91953Sigor@sysoev.ru                 nxt_queue_insert_tail(&tmcf->keeping, oqlk);
92053Sigor@sysoev.ru 
92153Sigor@sysoev.ru                 nxt_queue_remove(nqlk);
92253Sigor@sysoev.ru                 nxt_queue_insert_tail(&tmcf->updating, nqlk);
92353Sigor@sysoev.ru 
92453Sigor@sysoev.ru                 break;
92553Sigor@sysoev.ru             }
92653Sigor@sysoev.ru         }
92753Sigor@sysoev.ru     }
92853Sigor@sysoev.ru 
92953Sigor@sysoev.ru     nxt_queue_add(&tmcf->deleting, &router->sockets);
930115Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
93153Sigor@sysoev.ru }
93253Sigor@sysoev.ru 
93353Sigor@sysoev.ru 
934*198Sigor@sysoev.ru static void
935*198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(nxt_task_t *task,
936*198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf)
937*198Sigor@sysoev.ru {
938*198Sigor@sysoev.ru     uint32_t          stream;
939*198Sigor@sysoev.ru     nxt_buf_t         *b;
940*198Sigor@sysoev.ru     nxt_port_t        *main_port, *router_port;
941*198Sigor@sysoev.ru     nxt_runtime_t     *rt;
942*198Sigor@sysoev.ru     nxt_socket_rpc_t  *rpc;
943*198Sigor@sysoev.ru 
944*198Sigor@sysoev.ru     rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t));
945*198Sigor@sysoev.ru     if (rpc == NULL) {
946*198Sigor@sysoev.ru         goto fail;
947*198Sigor@sysoev.ru     }
948*198Sigor@sysoev.ru 
949*198Sigor@sysoev.ru     rpc->socket_conf = skcf;
950*198Sigor@sysoev.ru     rpc->temp_conf = tmcf;
951*198Sigor@sysoev.ru 
952*198Sigor@sysoev.ru     b = nxt_buf_mem_alloc(tmcf->mem_pool, skcf->sockaddr->sockaddr_size, 0);
953*198Sigor@sysoev.ru     if (b == NULL) {
954*198Sigor@sysoev.ru         goto fail;
955*198Sigor@sysoev.ru     }
956*198Sigor@sysoev.ru 
957*198Sigor@sysoev.ru     b->mem.free = nxt_cpymem(b->mem.free, skcf->sockaddr,
958*198Sigor@sysoev.ru                              skcf->sockaddr->sockaddr_size);
959*198Sigor@sysoev.ru 
960*198Sigor@sysoev.ru     rt = task->thread->runtime;
961*198Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MASTER];
962*198Sigor@sysoev.ru     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
963*198Sigor@sysoev.ru 
964*198Sigor@sysoev.ru     stream = nxt_port_rpc_register_handler(task, router_port,
965*198Sigor@sysoev.ru                                            nxt_router_listen_socket_ready,
966*198Sigor@sysoev.ru                                            nxt_router_listen_socket_error,
967*198Sigor@sysoev.ru                                            main_port->pid, rpc);
968*198Sigor@sysoev.ru     if (stream == 0) {
969*198Sigor@sysoev.ru         goto fail;
970*198Sigor@sysoev.ru     }
971*198Sigor@sysoev.ru 
972*198Sigor@sysoev.ru     nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1,
973*198Sigor@sysoev.ru                           stream, router_port->id,