xref: /unit/src/nxt_router.c (revision 206)
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);
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);
131*206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj,
132*206Smax.romanov@nginx.com     void *data);
13388Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task,
13488Smax.romanov@nginx.com     nxt_conn_t *c, nxt_app_parse_ctx_t *ap);
135141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task,
136167Smax.romanov@nginx.com     nxt_req_app_link_t *ra, nxt_port_t *port);
13788Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data);
13853Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data);
13953Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data);
14053Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data);
14153Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data);
14262Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data);
14320Sigor@sysoev.ru 
144141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code,
145141Smax.romanov@nginx.com     const char* fmt, ...);
146141Smax.romanov@nginx.com 
147119Smax.romanov@nginx.com static nxt_router_t  *nxt_router;
14820Sigor@sysoev.ru 
14920Sigor@sysoev.ru nxt_int_t
150141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data)
15120Sigor@sysoev.ru {
152141Smax.romanov@nginx.com     nxt_int_t      ret;
153141Smax.romanov@nginx.com     nxt_router_t   *router;
154141Smax.romanov@nginx.com     nxt_runtime_t  *rt;
155141Smax.romanov@nginx.com 
156141Smax.romanov@nginx.com     rt = task->thread->runtime;
15753Sigor@sysoev.ru 
15888Smax.romanov@nginx.com     ret = nxt_app_http_init(task, rt);
15988Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
16088Smax.romanov@nginx.com         return ret;
16188Smax.romanov@nginx.com     }
16288Smax.romanov@nginx.com 
16353Sigor@sysoev.ru     router = nxt_zalloc(sizeof(nxt_router_t));
16453Sigor@sysoev.ru     if (nxt_slow_path(router == NULL)) {
16553Sigor@sysoev.ru         return NXT_ERROR;
16653Sigor@sysoev.ru     }
16753Sigor@sysoev.ru 
16853Sigor@sysoev.ru     nxt_queue_init(&router->engines);
16953Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
170133Sigor@sysoev.ru     nxt_queue_init(&router->apps);
17153Sigor@sysoev.ru 
172119Smax.romanov@nginx.com     nxt_router = router;
173119Smax.romanov@nginx.com 
174115Sigor@sysoev.ru     return NXT_OK;
175115Sigor@sysoev.ru }
176115Sigor@sysoev.ru 
177115Sigor@sysoev.ru 
178167Smax.romanov@nginx.com static nxt_start_worker_t *
179192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra)
180167Smax.romanov@nginx.com {
181167Smax.romanov@nginx.com     nxt_port_t          *master_port;
182167Smax.romanov@nginx.com     nxt_runtime_t       *rt;
183167Smax.romanov@nginx.com     nxt_start_worker_t  *sw;
184167Smax.romanov@nginx.com 
185192Smax.romanov@nginx.com     sw = nxt_zalloc(sizeof(nxt_start_worker_t));
186167Smax.romanov@nginx.com 
187167Smax.romanov@nginx.com     if (nxt_slow_path(sw == NULL)) {
188167Smax.romanov@nginx.com         return NULL;
189167Smax.romanov@nginx.com     }
190167Smax.romanov@nginx.com 
191167Smax.romanov@nginx.com     sw->app = app;
192167Smax.romanov@nginx.com     sw->ra = ra;
193167Smax.romanov@nginx.com 
194192Smax.romanov@nginx.com     nxt_debug(task, "sw %p create, request #%uxD, app '%V' %p", sw,
195167Smax.romanov@nginx.com                     ra->req_id, &app->name, app);
196167Smax.romanov@nginx.com 
197167Smax.romanov@nginx.com     rt = task->thread->runtime;
198167Smax.romanov@nginx.com     master_port = rt->port_by_type[NXT_PROCESS_MASTER];
199167Smax.romanov@nginx.com 
200167Smax.romanov@nginx.com     sw->work.handler = nxt_router_send_sw_request;
201167Smax.romanov@nginx.com     sw->work.task = &master_port->engine->task;
202167Smax.romanov@nginx.com     sw->work.obj = sw;
203167Smax.romanov@nginx.com     sw->work.data = task->thread->engine;
204167Smax.romanov@nginx.com     sw->work.next = NULL;
205167Smax.romanov@nginx.com 
206167Smax.romanov@nginx.com     if (task->thread->engine != master_port->engine) {
207192Smax.romanov@nginx.com         nxt_debug(task, "sw %p post send to master engine %p", sw,
208167Smax.romanov@nginx.com                   master_port->engine);
209167Smax.romanov@nginx.com 
210167Smax.romanov@nginx.com         nxt_event_engine_post(master_port->engine, &sw->work);
211167Smax.romanov@nginx.com 
212167Smax.romanov@nginx.com     } else {
213167Smax.romanov@nginx.com         nxt_router_send_sw_request(task, sw, sw->work.data);
214167Smax.romanov@nginx.com     }
215167Smax.romanov@nginx.com 
216167Smax.romanov@nginx.com     return sw;
217167Smax.romanov@nginx.com }
218167Smax.romanov@nginx.com 
219167Smax.romanov@nginx.com 
220192Smax.romanov@nginx.com nxt_inline void
221192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw)
222141Smax.romanov@nginx.com {
223192Smax.romanov@nginx.com     nxt_debug(task, "sw %p release", sw);
224192Smax.romanov@nginx.com 
225192Smax.romanov@nginx.com     nxt_free(sw);
226141Smax.romanov@nginx.com }
227141Smax.romanov@nginx.com 
228141Smax.romanov@nginx.com 
229167Smax.romanov@nginx.com static nxt_req_app_link_t *
230167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc)
231167Smax.romanov@nginx.com {
232167Smax.romanov@nginx.com     nxt_mp_t            *mp;
233167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
234167Smax.romanov@nginx.com 
235167Smax.romanov@nginx.com     mp = rc->conn->mem_pool;
236167Smax.romanov@nginx.com 
237167Smax.romanov@nginx.com     ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t));
238167Smax.romanov@nginx.com 
239167Smax.romanov@nginx.com     if (nxt_slow_path(ra == NULL)) {
240167Smax.romanov@nginx.com         return NULL;
241167Smax.romanov@nginx.com     }
242167Smax.romanov@nginx.com 
243167Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD create", ra->req_id);
244167Smax.romanov@nginx.com 
245167Smax.romanov@nginx.com     nxt_memzero(ra, sizeof(nxt_req_app_link_t));
246167Smax.romanov@nginx.com 
247167Smax.romanov@nginx.com     ra->req_id = rc->req_id;
248167Smax.romanov@nginx.com     ra->app_port = NULL;
249167Smax.romanov@nginx.com     ra->rc = rc;
250167Smax.romanov@nginx.com 
251167Smax.romanov@nginx.com     ra->mem_pool = mp;
252167Smax.romanov@nginx.com 
253167Smax.romanov@nginx.com     ra->work.handler = NULL;
254167Smax.romanov@nginx.com     ra->work.task = &task->thread->engine->task;
255167Smax.romanov@nginx.com     ra->work.obj = ra;
256167Smax.romanov@nginx.com     ra->work.data = task->thread->engine;
257167Smax.romanov@nginx.com 
258167Smax.romanov@nginx.com     return ra;
259167Smax.romanov@nginx.com }
260167Smax.romanov@nginx.com 
261167Smax.romanov@nginx.com 
262167Smax.romanov@nginx.com static void
263167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data)
264167Smax.romanov@nginx.com {
265167Smax.romanov@nginx.com     nxt_req_app_link_t  *ra;
266167Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
267167Smax.romanov@nginx.com 
268167Smax.romanov@nginx.com     ra = obj;
269167Smax.romanov@nginx.com     engine = data;
270167Smax.romanov@nginx.com 
271167Smax.romanov@nginx.com     if (task->thread->engine != engine) {
272167Smax.romanov@nginx.com         ra->work.handler = nxt_router_ra_release;
273167Smax.romanov@nginx.com         ra->work.task = &engine->task;
274167Smax.romanov@nginx.com         ra->work.next = NULL;
275167Smax.romanov@nginx.com 
276167Smax.romanov@nginx.com         nxt_debug(task, "ra #%uxD post release to %p", ra->req_id, engine);
277167Smax.romanov@nginx.com 
278167Smax.romanov@nginx.com         nxt_event_engine_post(engine, &ra->work);
279167Smax.romanov@nginx.com 
280167Smax.romanov@nginx.com         return;
281167Smax.romanov@nginx.com     }
282167Smax.romanov@nginx.com 
283167Smax.romanov@nginx.com     nxt_debug(task, "ra #%uxD release", ra->req_id);
284167Smax.romanov@nginx.com 
285167Smax.romanov@nginx.com     if (ra->app_port != NULL) {
286167Smax.romanov@nginx.com 
287167Smax.romanov@nginx.com         if (ra->rc->conn != NULL) {
288167Smax.romanov@nginx.com             ra->rc->app_port = ra->app_port;
289167Smax.romanov@nginx.com 
290167Smax.romanov@nginx.com         } else {
291167Smax.romanov@nginx.com             nxt_router_app_release_port(task, ra->app_port, ra->app_port->app);
292167Smax.romanov@nginx.com         }
293167Smax.romanov@nginx.com     }
294167Smax.romanov@nginx.com 
295167Smax.romanov@nginx.com     nxt_mp_release(ra->mem_pool, ra);
296167Smax.romanov@nginx.com }
297167Smax.romanov@nginx.com 
298167Smax.romanov@nginx.com 
299141Smax.romanov@nginx.com void
300141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
301141Smax.romanov@nginx.com {
302141Smax.romanov@nginx.com     nxt_port_new_port_handler(task, msg);
303141Smax.romanov@nginx.com 
304192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
305141Smax.romanov@nginx.com         return;
306141Smax.romanov@nginx.com     }
307141Smax.romanov@nginx.com 
308192Smax.romanov@nginx.com     if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) {
309192Smax.romanov@nginx.com         msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
310141Smax.romanov@nginx.com     }
311192Smax.romanov@nginx.com 
312192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
313141Smax.romanov@nginx.com }
314141Smax.romanov@nginx.com 
315141Smax.romanov@nginx.com 
316139Sigor@sysoev.ru void
317139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
318115Sigor@sysoev.ru {
319139Sigor@sysoev.ru     size_t                  dump_size;
320198Sigor@sysoev.ru     nxt_int_t               ret;
321139Sigor@sysoev.ru     nxt_buf_t               *b;
322139Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
323139Sigor@sysoev.ru 
324139Sigor@sysoev.ru     b = msg->buf;
325139Sigor@sysoev.ru 
326139Sigor@sysoev.ru     dump_size = nxt_buf_used_size(b);
327139Sigor@sysoev.ru 
328139Sigor@sysoev.ru     if (dump_size > 300) {
329139Sigor@sysoev.ru         dump_size = 300;
33053Sigor@sysoev.ru     }
33153Sigor@sysoev.ru 
332139Sigor@sysoev.ru     nxt_debug(task, "router conf data (%z): %*s",
333139Sigor@sysoev.ru               msg->size, dump_size, b->mem.pos);
334139Sigor@sysoev.ru 
335139Sigor@sysoev.ru     tmcf = nxt_router_temp_conf(task);
336139Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
337139Sigor@sysoev.ru         return;
33853Sigor@sysoev.ru     }
33953Sigor@sysoev.ru 
340139Sigor@sysoev.ru     tmcf->conf->router = nxt_router;
341139Sigor@sysoev.ru     tmcf->stream = msg->port_msg.stream;
342139Sigor@sysoev.ru     tmcf->port = nxt_runtime_port_find(task->thread->runtime,
343198Sigor@sysoev.ru                                        msg->port_msg.pid,
344198Sigor@sysoev.ru                                        msg->port_msg.reply_port);
345198Sigor@sysoev.ru 
346198Sigor@sysoev.ru     ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free);
347198Sigor@sysoev.ru 
348198Sigor@sysoev.ru     if (nxt_fast_path(ret == NXT_OK)) {
349198Sigor@sysoev.ru         nxt_router_conf_apply(task, tmcf, NULL);
350198Sigor@sysoev.ru 
351198Sigor@sysoev.ru     } else {
352198Sigor@sysoev.ru         nxt_router_conf_error(task, tmcf);
353139Sigor@sysoev.ru     }
35453Sigor@sysoev.ru }
35553Sigor@sysoev.ru 
35653Sigor@sysoev.ru 
357192Smax.romanov@nginx.com void
358192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
359192Smax.romanov@nginx.com {
360192Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, msg);
361192Smax.romanov@nginx.com 
362192Smax.romanov@nginx.com     if (msg->port_msg.stream == 0) {
363192Smax.romanov@nginx.com         return;
364192Smax.romanov@nginx.com     }
365192Smax.romanov@nginx.com 
366192Smax.romanov@nginx.com     msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
367192Smax.romanov@nginx.com 
368192Smax.romanov@nginx.com     nxt_port_rpc_handler(task, msg);
369192Smax.romanov@nginx.com }
370192Smax.romanov@nginx.com 
371192Smax.romanov@nginx.com 
37253Sigor@sysoev.ru static nxt_router_temp_conf_t *
373139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task)
37453Sigor@sysoev.ru {
37565Sigor@sysoev.ru     nxt_mp_t                *mp, *tmp;
37653Sigor@sysoev.ru     nxt_router_conf_t       *rtcf;
37753Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
37853Sigor@sysoev.ru 
37965Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
38053Sigor@sysoev.ru     if (nxt_slow_path(mp == NULL)) {
38153Sigor@sysoev.ru         return NULL;
38253Sigor@sysoev.ru     }
38353Sigor@sysoev.ru 
38465Sigor@sysoev.ru     rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t));
38553Sigor@sysoev.ru     if (nxt_slow_path(rtcf == NULL)) {
38653Sigor@sysoev.ru         goto fail;
38753Sigor@sysoev.ru     }
38853Sigor@sysoev.ru 
38953Sigor@sysoev.ru     rtcf->mem_pool = mp;
39053Sigor@sysoev.ru 
39165Sigor@sysoev.ru     tmp = nxt_mp_create(1024, 128, 256, 32);
39253Sigor@sysoev.ru     if (nxt_slow_path(tmp == NULL)) {
39353Sigor@sysoev.ru         goto fail;
39453Sigor@sysoev.ru     }
39553Sigor@sysoev.ru 
39665Sigor@sysoev.ru     tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t));
39753Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
39853Sigor@sysoev.ru         goto temp_fail;
39953Sigor@sysoev.ru     }
40053Sigor@sysoev.ru 
40153Sigor@sysoev.ru     tmcf->mem_pool = tmp;
40253Sigor@sysoev.ru     tmcf->conf = rtcf;
403139Sigor@sysoev.ru     tmcf->count = 1;
404139Sigor@sysoev.ru     tmcf->engine = task->thread->engine;
40553Sigor@sysoev.ru 
40653Sigor@sysoev.ru     tmcf->engines = nxt_array_create(tmcf->mem_pool, 4,
40753Sigor@sysoev.ru                                      sizeof(nxt_router_engine_conf_t));
40853Sigor@sysoev.ru     if (nxt_slow_path(tmcf->engines == NULL)) {
40953Sigor@sysoev.ru         goto temp_fail;
41053Sigor@sysoev.ru     }
41153Sigor@sysoev.ru 
41253Sigor@sysoev.ru     nxt_queue_init(&tmcf->deleting);
41353Sigor@sysoev.ru     nxt_queue_init(&tmcf->keeping);
41453Sigor@sysoev.ru     nxt_queue_init(&tmcf->updating);
41553Sigor@sysoev.ru     nxt_queue_init(&tmcf->pending);
41653Sigor@sysoev.ru     nxt_queue_init(&tmcf->creating);
417133Sigor@sysoev.ru     nxt_queue_init(&tmcf->apps);
418133Sigor@sysoev.ru     nxt_queue_init(&tmcf->previous);
41953Sigor@sysoev.ru 
42053Sigor@sysoev.ru     return tmcf;
42153Sigor@sysoev.ru 
42253Sigor@sysoev.ru temp_fail:
42353Sigor@sysoev.ru 
42465Sigor@sysoev.ru     nxt_mp_destroy(tmp);
42553Sigor@sysoev.ru 
42653Sigor@sysoev.ru fail:
42753Sigor@sysoev.ru 
42865Sigor@sysoev.ru     nxt_mp_destroy(mp);
42953Sigor@sysoev.ru 
43053Sigor@sysoev.ru     return NULL;
43153Sigor@sysoev.ru }
43253Sigor@sysoev.ru 
43353Sigor@sysoev.ru 
434198Sigor@sysoev.ru static void
435198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
436139Sigor@sysoev.ru {
437139Sigor@sysoev.ru     nxt_int_t                    ret;
438139Sigor@sysoev.ru     nxt_router_t                 *router;
439139Sigor@sysoev.ru     nxt_runtime_t                *rt;
440198Sigor@sysoev.ru     nxt_queue_link_t             *qlk;
441198Sigor@sysoev.ru     nxt_socket_conf_t            *skcf;
442198Sigor@sysoev.ru     nxt_router_temp_conf_t       *tmcf;
443139Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
444139Sigor@sysoev.ru 
445198Sigor@sysoev.ru     tmcf = obj;
446198Sigor@sysoev.ru 
447198Sigor@sysoev.ru     qlk = nxt_queue_first(&tmcf->pending);
448198Sigor@sysoev.ru 
449198Sigor@sysoev.ru     if (qlk != nxt_queue_tail(&tmcf->pending)) {
450198Sigor@sysoev.ru         nxt_queue_remove(qlk);
451198Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->creating, qlk);
452198Sigor@sysoev.ru 
453198Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
454198Sigor@sysoev.ru 
455198Sigor@sysoev.ru         nxt_router_listen_socket_rpc_create(task, tmcf, skcf);
456198Sigor@sysoev.ru 
457198Sigor@sysoev.ru         return;
458139Sigor@sysoev.ru     }
459139Sigor@sysoev.ru 
460139Sigor@sysoev.ru     rt = task->thread->runtime;
461139Sigor@sysoev.ru 
462139Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
463139Sigor@sysoev.ru 
464198Sigor@sysoev.ru     router = tmcf->conf->router;
465198Sigor@sysoev.ru 
466139Sigor@sysoev.ru     ret = nxt_router_engines_create(task, router, tmcf, interface);
467139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
468198Sigor@sysoev.ru         goto fail;
469139Sigor@sysoev.ru     }
470139Sigor@sysoev.ru 
471139Sigor@sysoev.ru     ret = nxt_router_threads_create(task, rt, tmcf);
472139Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
473198Sigor@sysoev.ru         goto fail;
474139Sigor@sysoev.ru     }
475139Sigor@sysoev.ru 
476139Sigor@sysoev.ru     nxt_router_apps_sort(router, tmcf);
477139Sigor@sysoev.ru 
478139Sigor@sysoev.ru     nxt_router_engines_post(tmcf);
479139Sigor@sysoev.ru 
480139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->updating);
481139Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->creating);
482139Sigor@sysoev.ru 
483198Sigor@sysoev.ru     nxt_router_conf_ready(task, tmcf);
484198Sigor@sysoev.ru 
485198Sigor@sysoev.ru     return;
486198Sigor@sysoev.ru 
487198Sigor@sysoev.ru fail:
488198Sigor@sysoev.ru 
489198Sigor@sysoev.ru     nxt_router_conf_error(task, tmcf);
490198Sigor@sysoev.ru 
491198Sigor@sysoev.ru     return;
492139Sigor@sysoev.ru }
493139Sigor@sysoev.ru 
494139Sigor@sysoev.ru 
495139Sigor@sysoev.ru static void
496139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data)
497139Sigor@sysoev.ru {
498153Sigor@sysoev.ru     nxt_joint_job_t  *job;
499153Sigor@sysoev.ru 
500153Sigor@sysoev.ru     job = obj;
501153Sigor@sysoev.ru 
502198Sigor@sysoev.ru     nxt_router_conf_ready(task, job->tmcf);
503139Sigor@sysoev.ru }
504139Sigor@sysoev.ru 
505139Sigor@sysoev.ru 
506139Sigor@sysoev.ru static void
507198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
508139Sigor@sysoev.ru {
509139Sigor@sysoev.ru     nxt_debug(task, "temp conf count:%D", tmcf->count);
510139Sigor@sysoev.ru 
511139Sigor@sysoev.ru     if (--tmcf->count == 0) {
512193Smax.romanov@nginx.com         nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST);
513139Sigor@sysoev.ru     }
514139Sigor@sysoev.ru }
515139Sigor@sysoev.ru 
516139Sigor@sysoev.ru 
517139Sigor@sysoev.ru static void
518139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
519139Sigor@sysoev.ru {
520148Sigor@sysoev.ru     nxt_socket_t       s;
521149Sigor@sysoev.ru     nxt_router_t       *router;
522148Sigor@sysoev.ru     nxt_queue_link_t   *qlk;
523148Sigor@sysoev.ru     nxt_socket_conf_t  *skcf;
524148Sigor@sysoev.ru 
525198Sigor@sysoev.ru     nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf");
526198Sigor@sysoev.ru 
527148Sigor@sysoev.ru     for (qlk = nxt_queue_first(&tmcf->creating);
528148Sigor@sysoev.ru          qlk != nxt_queue_tail(&tmcf->creating);
529148Sigor@sysoev.ru          qlk = nxt_queue_next(qlk))
530148Sigor@sysoev.ru     {
531148Sigor@sysoev.ru         skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link);
532148Sigor@sysoev.ru         s = skcf->listen.socket;
533148Sigor@sysoev.ru 
534148Sigor@sysoev.ru         if (s != -1) {
535148Sigor@sysoev.ru             nxt_socket_close(task, s);
536148Sigor@sysoev.ru         }
537148Sigor@sysoev.ru 
538148Sigor@sysoev.ru         nxt_free(skcf->socket);
539148Sigor@sysoev.ru     }
540148Sigor@sysoev.ru 
541149Sigor@sysoev.ru     router = tmcf->conf->router;
542149Sigor@sysoev.ru 
543149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->keeping);
544149Sigor@sysoev.ru     nxt_queue_add(&router->sockets, &tmcf->deleting);
545149Sigor@sysoev.ru 
546148Sigor@sysoev.ru     // TODO: new engines and threads
547148Sigor@sysoev.ru 
548139Sigor@sysoev.ru     nxt_mp_destroy(tmcf->conf->mem_pool);
549139Sigor@sysoev.ru 
550193Smax.romanov@nginx.com     nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR);
551139Sigor@sysoev.ru }
552139Sigor@sysoev.ru 
553139Sigor@sysoev.ru 
554139Sigor@sysoev.ru static void
555139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
556193Smax.romanov@nginx.com     nxt_port_msg_type_t type)
557139Sigor@sysoev.ru {
558193Smax.romanov@nginx.com     nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL);
559139Sigor@sysoev.ru }
560139Sigor@sysoev.ru 
561139Sigor@sysoev.ru 
562115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_conf[] = {
563115Sigor@sysoev.ru     {
564133Sigor@sysoev.ru         nxt_string("listeners_threads"),
565115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
566115Sigor@sysoev.ru         offsetof(nxt_router_conf_t, threads),
567115Sigor@sysoev.ru     },
568115Sigor@sysoev.ru };
569115Sigor@sysoev.ru 
570115Sigor@sysoev.ru 
571133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_app_conf[] = {
572115Sigor@sysoev.ru     {
573133Sigor@sysoev.ru         nxt_string("type"),
574115Sigor@sysoev.ru         NXT_CONF_MAP_STR,
575133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, type),
576115Sigor@sysoev.ru     },
577115Sigor@sysoev.ru 
578115Sigor@sysoev.ru     {
579133Sigor@sysoev.ru         nxt_string("workers"),
580115Sigor@sysoev.ru         NXT_CONF_MAP_INT32,
581133Sigor@sysoev.ru         offsetof(nxt_router_app_conf_t, workers),
582133Sigor@sysoev.ru     },
583133Sigor@sysoev.ru };
584133Sigor@sysoev.ru 
585133Sigor@sysoev.ru 
586133Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_listener_conf[] = {
587133Sigor@sysoev.ru     {
588133Sigor@sysoev.ru         nxt_string("application"),
589133Sigor@sysoev.ru         NXT_CONF_MAP_STR,
590133Sigor@sysoev.ru         offsetof(nxt_router_listener_conf_t, application),
591115Sigor@sysoev.ru     },
592115Sigor@sysoev.ru };
593115Sigor@sysoev.ru 
594115Sigor@sysoev.ru 
595115Sigor@sysoev.ru static nxt_conf_map_t  nxt_router_http_conf[] = {
596115Sigor@sysoev.ru     {
597115Sigor@sysoev.ru         nxt_string("header_buffer_size"),
598115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
599115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_buffer_size),
600115Sigor@sysoev.ru     },
601115Sigor@sysoev.ru 
602115Sigor@sysoev.ru     {
603115Sigor@sysoev.ru         nxt_string("large_header_buffer_size"),
604115Sigor@sysoev.ru         NXT_CONF_MAP_SIZE,
605115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, large_header_buffer_size),
606115Sigor@sysoev.ru     },
607115Sigor@sysoev.ru 
608115Sigor@sysoev.ru     {
609*206Smax.romanov@nginx.com         nxt_string("large_header_buffers"),
610*206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
611*206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, large_header_buffers),
612*206Smax.romanov@nginx.com     },
613*206Smax.romanov@nginx.com 
614*206Smax.romanov@nginx.com     {
615*206Smax.romanov@nginx.com         nxt_string("body_buffer_size"),
616*206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
617*206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_buffer_size),
618*206Smax.romanov@nginx.com     },
619*206Smax.romanov@nginx.com 
620*206Smax.romanov@nginx.com     {
621*206Smax.romanov@nginx.com         nxt_string("max_body_size"),
622*206Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
623*206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, max_body_size),
624*206Smax.romanov@nginx.com     },
625*206Smax.romanov@nginx.com 
626*206Smax.romanov@nginx.com     {
627115Sigor@sysoev.ru         nxt_string("header_read_timeout"),
628115Sigor@sysoev.ru         NXT_CONF_MAP_MSEC,
629115Sigor@sysoev.ru         offsetof(nxt_socket_conf_t, header_read_timeout),
630115Sigor@sysoev.ru     },
631*206Smax.romanov@nginx.com 
632*206Smax.romanov@nginx.com     {
633*206Smax.romanov@nginx.com         nxt_string("body_read_timeout"),
634*206Smax.romanov@nginx.com         NXT_CONF_MAP_MSEC,
635*206Smax.romanov@nginx.com         offsetof(nxt_socket_conf_t, body_read_timeout),
636*206Smax.romanov@nginx.com     },
637115Sigor@sysoev.ru };
638115Sigor@sysoev.ru 
639115Sigor@sysoev.ru 
64053Sigor@sysoev.ru static nxt_int_t
641115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
642115Sigor@sysoev.ru     u_char *start, u_char *end)
64353Sigor@sysoev.ru {
644133Sigor@sysoev.ru     u_char                      *p;
645133Sigor@sysoev.ru     size_t                      size;
646115Sigor@sysoev.ru     nxt_mp_t                    *mp;
647115Sigor@sysoev.ru     uint32_t                    next;
648115Sigor@sysoev.ru     nxt_int_t                   ret;
649115Sigor@sysoev.ru     nxt_str_t                   name;
650133Sigor@sysoev.ru     nxt_app_t                   *app, *prev;
651133Sigor@sysoev.ru     nxt_app_type_t              type;
652115Sigor@sysoev.ru     nxt_sockaddr_t              *sa;
653133Sigor@sysoev.ru     nxt_conf_value_t            *conf, *http;
654133Sigor@sysoev.ru     nxt_conf_value_t            *applications, *application;
655133Sigor@sysoev.ru     nxt_conf_value_t            *listeners, *listener;
656115Sigor@sysoev.ru     nxt_socket_conf_t           *skcf;
657133Sigor@sysoev.ru     nxt_router_app_conf_t       apcf;
658115Sigor@sysoev.ru     nxt_router_listener_conf_t  lscf;
659115Sigor@sysoev.ru 
660115Sigor@sysoev.ru     static nxt_str_t  http_path = nxt_string("/http");
661133Sigor@sysoev.ru     static nxt_str_t  applications_path = nxt_string("/applications");
662115Sigor@sysoev.ru     static nxt_str_t  listeners_path = nxt_string("/listeners");
663115Sigor@sysoev.ru 
664115Sigor@sysoev.ru     conf = nxt_conf_json_parse(tmcf->mem_pool, start, end);
665115Sigor@sysoev.ru     if (conf == NULL) {
666115Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "configuration parsing error");
667115Sigor@sysoev.ru         return NXT_ERROR;
668115Sigor@sysoev.ru     }
669115Sigor@sysoev.ru 
670136Svbart@nginx.com     ret = nxt_conf_map_object(conf, nxt_router_conf,
671136Svbart@nginx.com                               nxt_nitems(nxt_router_conf), tmcf->conf);
672115Sigor@sysoev.ru     if (ret != NXT_OK) {
673133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "root map error");
674115Sigor@sysoev.ru         return NXT_ERROR;
675115Sigor@sysoev.ru     }
676115Sigor@sysoev.ru 
677117Sigor@sysoev.ru     if (tmcf->conf->threads == 0) {
678117Sigor@sysoev.ru         tmcf->conf->threads = nxt_ncpu;
679117Sigor@sysoev.ru     }
680117Sigor@sysoev.ru 
681133Sigor@sysoev.ru     applications = nxt_conf_get_path(conf, &applications_path);
682133Sigor@sysoev.ru     if (applications == NULL) {
683133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block");
684115Sigor@sysoev.ru         return NXT_ERROR;
685115Sigor@sysoev.ru     }
686115Sigor@sysoev.ru 
687133Sigor@sysoev.ru     next = 0;
688133Sigor@sysoev.ru 
689133Sigor@sysoev.ru     for ( ;; ) {
690133Sigor@sysoev.ru         application = nxt_conf_next_object_member(applications, &name, &next);
691133Sigor@sysoev.ru         if (application == NULL) {
692133Sigor@sysoev.ru             break;
693133Sigor@sysoev.ru         }
694133Sigor@sysoev.ru 
695133Sigor@sysoev.ru         nxt_debug(task, "application \"%V\"", &name);
696133Sigor@sysoev.ru 
697144Smax.romanov@nginx.com         size = nxt_conf_json_length(application, NULL);
698144Smax.romanov@nginx.com 
699144Smax.romanov@nginx.com         app = nxt_malloc(sizeof(nxt_app_t) + name.length + size);
700133Sigor@sysoev.ru         if (app == NULL) {
701133Sigor@sysoev.ru             goto fail;
702133Sigor@sysoev.ru         }
703133Sigor@sysoev.ru 
704144Smax.romanov@nginx.com         nxt_memzero(app, sizeof(nxt_app_t));
705144Smax.romanov@nginx.com 
706144Smax.romanov@nginx.com         app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t));
707144Smax.romanov@nginx.com         app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length);
708133Sigor@sysoev.ru 
709133Sigor@sysoev.ru         p = nxt_conf_json_print(app->conf.start, application, NULL);
710133Sigor@sysoev.ru         app->conf.length = p - app->conf.start;
711133Sigor@sysoev.ru 
712144Smax.romanov@nginx.com         nxt_assert(app->conf.length <= size);
713144Smax.romanov@nginx.com 
714133Sigor@sysoev.ru         nxt_debug(task, "application conf \"%V\"", &app->conf);
715133Sigor@sysoev.ru 
716133Sigor@sysoev.ru         prev = nxt_router_app_find(&tmcf->conf->router->apps, &name);
717133Sigor@sysoev.ru 
718133Sigor@sysoev.ru         if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) {
719133Sigor@sysoev.ru             nxt_free(app);
720133Sigor@sysoev.ru 
721133Sigor@sysoev.ru             nxt_queue_remove(&prev->link);
722133Sigor@sysoev.ru             nxt_queue_insert_tail(&tmcf->previous, &prev->link);
723133Sigor@sysoev.ru             continue;
724133Sigor@sysoev.ru         }
725133Sigor@sysoev.ru 
726136Svbart@nginx.com         ret = nxt_conf_map_object(application, nxt_router_app_conf,
727136Svbart@nginx.com                                   nxt_nitems(nxt_router_app_conf), &apcf);
728133Sigor@sysoev.ru         if (ret != NXT_OK) {
729133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "application map error");
730133Sigor@sysoev.ru             goto app_fail;
731133Sigor@sysoev.ru         }
732115Sigor@sysoev.ru 
733133Sigor@sysoev.ru         nxt_debug(task, "application type: %V", &apcf.type);
734133Sigor@sysoev.ru         nxt_debug(task, "application workers: %D", apcf.workers);
735133Sigor@sysoev.ru 
736141Smax.romanov@nginx.com         type = nxt_app_parse_type(&apcf.type);
737141Smax.romanov@nginx.com 
738141Smax.romanov@nginx.com         if (type == NXT_APP_UNKNOWN) {
739141Smax.romanov@nginx.com             nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
740141Smax.romanov@nginx.com                     &apcf.type);
741141Smax.romanov@nginx.com             goto app_fail;
742141Smax.romanov@nginx.com         }
743141Smax.romanov@nginx.com 
744141Smax.romanov@nginx.com         if (nxt_app_modules[type] == NULL) {
745133Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"",
746133Sigor@sysoev.ru                     &apcf.type);
747133Sigor@sysoev.ru             goto app_fail;
748133Sigor@sysoev.ru         }
749133Sigor@sysoev.ru 
750133Sigor@sysoev.ru         ret = nxt_thread_mutex_create(&app->mutex);
751133Sigor@sysoev.ru         if (ret != NXT_OK) {
752133Sigor@sysoev.ru             goto app_fail;
753133Sigor@sysoev.ru         }
754133Sigor@sysoev.ru 
755141Smax.romanov@nginx.com         nxt_queue_init(&app->ports);
756141Smax.romanov@nginx.com         nxt_queue_init(&app->requests);
757141Smax.romanov@nginx.com 
758144Smax.romanov@nginx.com         app->name.length = name.length;
759144Smax.romanov@nginx.com         nxt_memcpy(app->name.start, name.start, name.length);
760144Smax.romanov@nginx.com 
761133Sigor@sysoev.ru         app->type = type;
762133Sigor@sysoev.ru         app->max_workers = apcf.workers;
763133Sigor@sysoev.ru         app->live = 1;
764141Smax.romanov@nginx.com         app->module = nxt_app_modules[type];
765133Sigor@sysoev.ru 
766133Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->apps, &app->link);
767133Sigor@sysoev.ru     }
768133Sigor@sysoev.ru 
769133Sigor@sysoev.ru     http = nxt_conf_get_path(conf, &http_path);
770133Sigor@sysoev.ru #if 0
771133Sigor@sysoev.ru     if (http == NULL) {
772133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"http\" block");
773133Sigor@sysoev.ru         return NXT_ERROR;
774133Sigor@sysoev.ru     }
775133Sigor@sysoev.ru #endif
776133Sigor@sysoev.ru 
777133Sigor@sysoev.ru     listeners = nxt_conf_get_path(conf, &listeners_path);
778115Sigor@sysoev.ru     if (listeners == NULL) {
779133Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block");
780115Sigor@sysoev.ru         return NXT_ERROR;
781115Sigor@sysoev.ru     }
78253Sigor@sysoev.ru 
783133Sigor@sysoev.ru     next = 0;
78453Sigor@sysoev.ru 
785133Sigor@sysoev.ru     mp = tmcf->conf->mem_pool;
786115Sigor@sysoev.ru 
787115Sigor@sysoev.ru     for ( ;; ) {
788115Sigor@sysoev.ru         listener = nxt_conf_next_object_member(listeners, &name, &next);
789115Sigor@sysoev.ru         if (listener == NULL) {
790115Sigor@sysoev.ru             break;
791115Sigor@sysoev.ru         }
79253Sigor@sysoev.ru 
793115Sigor@sysoev.ru         sa = nxt_sockaddr_parse(mp, &name);
794115Sigor@sysoev.ru         if (sa == NULL) {
795115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name);
796133Sigor@sysoev.ru             goto fail;
797115Sigor@sysoev.ru         }
798115Sigor@sysoev.ru 
799115Sigor@sysoev.ru         sa->type = SOCK_STREAM;
800115Sigor@sysoev.ru 
801115Sigor@sysoev.ru         nxt_debug(task, "router listener: \"%*s\"",
802115Sigor@sysoev.ru                   sa->length, nxt_sockaddr_start(sa));
80353Sigor@sysoev.ru 
804115Sigor@sysoev.ru         skcf = nxt_router_socket_conf(task, mp, sa);
805115Sigor@sysoev.ru         if (skcf == NULL) {
806133Sigor@sysoev.ru             goto fail;
807115Sigor@sysoev.ru         }
80853Sigor@sysoev.ru 
809136Svbart@nginx.com         ret = nxt_conf_map_object(listener, nxt_router_listener_conf,
810136Svbart@nginx.com                                   nxt_nitems(nxt_router_listener_conf), &lscf);
811115Sigor@sysoev.ru         if (ret != NXT_OK) {
812115Sigor@sysoev.ru             nxt_log(task, NXT_LOG_CRIT, "listener map error");
813133Sigor@sysoev.ru             goto fail;
814115Sigor@sysoev.ru         }
81553Sigor@sysoev.ru 
816133Sigor@sysoev.ru         nxt_debug(task, "application: %V", &lscf.application);
817133Sigor@sysoev.ru 
818133Sigor@sysoev.ru         // STUB, default values if http block is not defined.
819133Sigor@sysoev.ru         skcf->header_buffer_size = 2048;
820133Sigor@sysoev.ru         skcf->large_header_buffer_size = 8192;
821*206Smax.romanov@nginx.com         skcf->large_header_buffers = 4;
822*206Smax.romanov@nginx.com         skcf->body_buffer_size = 16 * 1024;
823*206Smax.romanov@nginx.com         skcf->max_body_size = 2 * 1024 * 1024;
824133Sigor@sysoev.ru         skcf->header_read_timeout = 5000;
825*206Smax.romanov@nginx.com         skcf->body_read_timeout = 5000;
82653Sigor@sysoev.ru 
827133Sigor@sysoev.ru         if (http != NULL) {
828136Svbart@nginx.com             ret = nxt_conf_map_object(http, nxt_router_http_conf,
829136Svbart@nginx.com                                       nxt_nitems(nxt_router_http_conf), skcf);
830133Sigor@sysoev.ru             if (ret != NXT_OK) {
831133Sigor@sysoev.ru                 nxt_log(task, NXT_LOG_CRIT, "http map error");
832133Sigor@sysoev.ru                 goto fail;
833133Sigor@sysoev.ru             }
834115Sigor@sysoev.ru         }
835115Sigor@sysoev.ru 
836115Sigor@sysoev.ru         skcf->listen.handler = nxt_router_conn_init;
837115Sigor@sysoev.ru         skcf->router_conf = tmcf->conf;
838160Sigor@sysoev.ru         skcf->router_conf->count++;
839133Sigor@sysoev.ru         skcf->application = nxt_router_listener_application(tmcf,
840133Sigor@sysoev.ru                                                             &lscf.application);
841115Sigor@sysoev.ru 
842115Sigor@sysoev.ru         nxt_queue_insert_tail(&tmcf->pending, &skcf->link);
843115Sigor@sysoev.ru     }
84453Sigor@sysoev.ru 
845198Sigor@sysoev.ru     nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf);
846198Sigor@sysoev.ru 
84753Sigor@sysoev.ru     return NXT_OK;
848133Sigor@sysoev.ru 
849133Sigor@sysoev.ru app_fail:
850133Sigor@sysoev.ru 
851133Sigor@sysoev.ru     nxt_free(app);
852133Sigor@sysoev.ru 
853133Sigor@sysoev.ru fail:
854133Sigor@sysoev.ru 
855141Smax.romanov@nginx.com     nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
856141Smax.romanov@nginx.com 
857141Smax.romanov@nginx.com         nxt_queue_remove(&app->link);
858133Sigor@sysoev.ru         nxt_thread_mutex_destroy(&app->mutex);
859133Sigor@sysoev.ru         nxt_free(app);
860141Smax.romanov@nginx.com 
861141Smax.romanov@nginx.com     } nxt_queue_loop;
862133Sigor@sysoev.ru 
863133Sigor@sysoev.ru     return NXT_ERROR;
864133Sigor@sysoev.ru }
865133Sigor@sysoev.ru 
866133Sigor@sysoev.ru 
867133Sigor@sysoev.ru static nxt_app_t *
868133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name)
869133Sigor@sysoev.ru {
870141Smax.romanov@nginx.com     nxt_app_t  *app;
871141Smax.romanov@nginx.com 
872141Smax.romanov@nginx.com     nxt_queue_each(app, queue, nxt_app_t, link) {
873133Sigor@sysoev.ru 
874133Sigor@sysoev.ru         if (nxt_strstr_eq(name, &app->name)) {
875133Sigor@sysoev.ru             return app;
876133Sigor@sysoev.ru         }
877141Smax.romanov@nginx.com 
878141Smax.romanov@nginx.com     } nxt_queue_loop;
879133Sigor@sysoev.ru 
880133Sigor@sysoev.ru     return NULL;
881133Sigor@sysoev.ru }
882133Sigor@sysoev.ru 
883133Sigor@sysoev.ru 
884133Sigor@sysoev.ru static nxt_app_t *
885133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name)
886133Sigor@sysoev.ru {
887133Sigor@sysoev.ru     nxt_app_t  *app;
888133Sigor@sysoev.ru 
889133Sigor@sysoev.ru     app = nxt_router_app_find(&tmcf->apps, name);
890133Sigor@sysoev.ru 
891133Sigor@sysoev.ru     if (app == NULL) {
892134Sigor@sysoev.ru         app = nxt_router_app_find(&tmcf->previous, name);
893133Sigor@sysoev.ru     }
894133Sigor@sysoev.ru 
895133Sigor@sysoev.ru     return app;
89653Sigor@sysoev.ru }
89753Sigor@sysoev.ru 
89853Sigor@sysoev.ru 
89953Sigor@sysoev.ru static nxt_socket_conf_t *
90065Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa)
90153Sigor@sysoev.ru {
902163Smax.romanov@nginx.com     nxt_socket_conf_t  *skcf;
903163Smax.romanov@nginx.com 
904163Smax.romanov@nginx.com     skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t));
905163Smax.romanov@nginx.com     if (nxt_slow_path(skcf == NULL)) {
90653Sigor@sysoev.ru         return NULL;
90753Sigor@sysoev.ru     }
90853Sigor@sysoev.ru 
909163Smax.romanov@nginx.com     skcf->sockaddr = sa;
910163Smax.romanov@nginx.com 
911163Smax.romanov@nginx.com     skcf->listen.sockaddr = sa;
912163Smax.romanov@nginx.com     skcf->listen.socklen = sa->socklen;
913163Smax.romanov@nginx.com     skcf->listen.address_length = sa->length;
914163Smax.romanov@nginx.com 
915163Smax.romanov@nginx.com     skcf->listen.socket = -1;
916163Smax.romanov@nginx.com     skcf->listen.backlog = NXT_LISTEN_BACKLOG;
917163Smax.romanov@nginx.com     skcf->listen.flags = NXT_NONBLOCK;
918163Smax.romanov@nginx.com     skcf->listen.read_after_accept = 1;
919163Smax.romanov@nginx.com 
920163Smax.romanov@nginx.com     return skcf;
92153Sigor@sysoev.ru }
92253Sigor@sysoev.ru 
92353Sigor@sysoev.ru 
92453Sigor@sysoev.ru static void
92553Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router,
92653Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf)
92753Sigor@sysoev.ru {
92853Sigor@sysoev.ru     nxt_queue_link_t   *nqlk, *oqlk, *next;
92953Sigor@sysoev.ru     nxt_socket_conf_t  *nskcf, *oskcf;
93053Sigor@sysoev.ru 
93153Sigor@sysoev.ru     for (nqlk = nxt_queue_first(&tmcf->pending);
93253Sigor@sysoev.ru          nqlk != nxt_queue_tail(&tmcf->pending);
93353Sigor@sysoev.ru          nqlk = next)
93453Sigor@sysoev.ru     {
93553Sigor@sysoev.ru         next = nxt_queue_next(nqlk);
93653Sigor@sysoev.ru         nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link);
93753Sigor@sysoev.ru 
93853Sigor@sysoev.ru         for (oqlk = nxt_queue_first(&router->sockets);
93953Sigor@sysoev.ru              oqlk != nxt_queue_tail(&router->sockets);
94053Sigor@sysoev.ru              oqlk = nxt_queue_next(oqlk))
94153Sigor@sysoev.ru         {
94253Sigor@sysoev.ru             oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link);
94353Sigor@sysoev.ru 
944115Sigor@sysoev.ru             if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) {
945115Sigor@sysoev.ru                 nskcf->socket = oskcf->socket;
946115Sigor@sysoev.ru                 nskcf->listen.socket = oskcf->listen.socket;
947115Sigor@sysoev.ru 
94853Sigor@sysoev.ru                 nxt_queue_remove(oqlk);
94953Sigor@sysoev.ru                 nxt_queue_insert_tail(&tmcf->keeping, oqlk);
95053Sigor@sysoev.ru 
95153Sigor@sysoev.ru                 nxt_queue_remove(nqlk);
95253Sigor@sysoev.ru                 nxt_queue_insert_tail(&tmcf->updating, nqlk);
95353Sigor@sysoev.ru 
95453Sigor@sysoev.ru                 break;
95553Sigor@sysoev.ru             }
95653Sigor@sysoev.ru         }
95753Sigor@sysoev.ru     }
95853Sigor@sysoev.ru 
95953Sigor@sysoev.ru     nxt_queue_add(&tmcf->deleting, &router->sockets);
960115Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
96153Sigor@sysoev.ru }
96253Sigor@sysoev.ru 
96353Sigor@sysoev.ru 
964198Sigor@sysoev.ru static void
965198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(nxt_task_t *task,
966198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf)
967198Sigor@sysoev.ru {
968198Sigor@sysoev.ru     uint32_t          stream;
969198Sigor@sysoev.ru     nxt_buf_t         *b;
970198Sigor@sysoev.ru     nxt_port_t        *main_port, *router_port;
971198Sigor@sysoev.ru     nxt_runtime_t     *rt;
972198Sigor@sysoev.ru     nxt_socket_rpc_t  *rpc;
973198Sigor@sysoev.ru 
974198Sigor@sysoev.ru     rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t));
975198Sigor@sysoev.ru     if (rpc == NULL) {
976198Sigor@sysoev.ru         goto fail;
977198Sigor@sysoev.ru     }
978198Sigor@sysoev.ru 
979198Sigor@sysoev.ru     rpc->socket_conf = skcf;
980