xref: /unit/src/nxt_controller.c (revision 1526:5c2a0b6f92e7)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Valentin V. Bartenev
5  * Copyright (C) NGINX, Inc.
6  */
7 
8 #include <nxt_main.h>
9 #include <nxt_runtime.h>
10 #include <nxt_main_process.h>
11 #include <nxt_conf.h>
12 #include <nxt_cert.h>
13 
14 
15 typedef struct {
16     nxt_conf_value_t  *root;
17     nxt_mp_t          *pool;
18 } nxt_controller_conf_t;
19 
20 
21 typedef struct {
22     nxt_http_request_parse_t  parser;
23     size_t                    length;
24     nxt_controller_conf_t     conf;
25     nxt_conn_t                *conn;
26     nxt_queue_link_t          link;
27 } nxt_controller_request_t;
28 
29 
30 typedef struct {
31     nxt_uint_t        status;
32     nxt_conf_value_t  *conf;
33 
34     u_char            *title;
35     nxt_str_t         detail;
36     ssize_t           offset;
37     nxt_uint_t        line;
38     nxt_uint_t        column;
39 } nxt_controller_response_t;
40 
41 
42 static nxt_int_t nxt_controller_prefork(nxt_task_t *task,
43     nxt_process_t *process, nxt_mp_t *mp);
44 static nxt_int_t nxt_controller_start(nxt_task_t *task,
45     nxt_process_data_t *data);
46 static void nxt_controller_process_new_port_handler(nxt_task_t *task,
47     nxt_port_recv_msg_t *msg);
48 static void nxt_controller_send_current_conf(nxt_task_t *task);
49 static void nxt_controller_router_ready_handler(nxt_task_t *task,
50     nxt_port_recv_msg_t *msg);
51 static void nxt_controller_remove_pid_handler(nxt_task_t *task,
52     nxt_port_recv_msg_t *msg);
53 static nxt_int_t nxt_controller_conf_default(void);
54 static void nxt_controller_conf_init_handler(nxt_task_t *task,
55     nxt_port_recv_msg_t *msg, void *data);
56 static void nxt_controller_flush_requests(nxt_task_t *task);
57 static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, nxt_mp_t *mp,
58     nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data);
59 
60 static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data);
61 static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data);
62 static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c,
63     uintptr_t data);
64 static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj,
65     void *data);
66 static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj,
67     void *data);
68 static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj,
69     void *data);
70 static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data);
71 static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj,
72     void *data);
73 static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj,
74     void *data);
75 static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data);
76 static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data);
77 
78 static nxt_int_t nxt_controller_request_content_length(void *ctx,
79     nxt_http_field_t *field, uintptr_t data);
80 
81 static void nxt_controller_process_request(nxt_task_t *task,
82     nxt_controller_request_t *req);
83 static void nxt_controller_process_config(nxt_task_t *task,
84     nxt_controller_request_t *req, nxt_str_t *path);
85 static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task);
86 #if (NXT_TLS)
87 static void nxt_controller_process_cert(nxt_task_t *task,
88     nxt_controller_request_t *req, nxt_str_t *path);
89 static void nxt_controller_process_cert_save(nxt_task_t *task,
90     nxt_port_recv_msg_t *msg, void *data);
91 static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name);
92 static void nxt_controller_cert_cleanup(nxt_task_t *task, void *obj,
93     void *data);
94 #endif
95 static void nxt_controller_conf_handler(nxt_task_t *task,
96     nxt_port_recv_msg_t *msg, void *data);
97 static void nxt_controller_conf_store(nxt_task_t *task,
98     nxt_conf_value_t *conf);
99 static void nxt_controller_response(nxt_task_t *task,
100     nxt_controller_request_t *req, nxt_controller_response_t *resp);
101 static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now,
102     struct tm *tm, size_t size, const char *format);
103 
104 
105 static nxt_http_field_proc_t  nxt_controller_request_fields[] = {
106     { nxt_string("Content-Length"),
107       &nxt_controller_request_content_length, 0 },
108 };
109 
110 static nxt_lvlhsh_t            nxt_controller_fields_hash;
111 
112 static nxt_uint_t              nxt_controller_listening;
113 static nxt_uint_t              nxt_controller_router_ready;
114 static nxt_controller_conf_t   nxt_controller_conf;
115 static nxt_queue_t             nxt_controller_waiting_requests;
116 static nxt_bool_t              nxt_controller_waiting_init_conf;
117 
118 
119 static const nxt_event_conn_state_t  nxt_controller_conn_read_state;
120 static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state;
121 static const nxt_event_conn_state_t  nxt_controller_conn_write_state;
122 static const nxt_event_conn_state_t  nxt_controller_conn_close_state;
123 
124 
125 static const nxt_port_handlers_t  nxt_controller_process_port_handlers = {
126     .quit           = nxt_signal_quit_handler,
127     .new_port       = nxt_controller_process_new_port_handler,
128     .change_file    = nxt_port_change_log_file_handler,
129     .mmap           = nxt_port_mmap_handler,
130     .process_ready  = nxt_controller_router_ready_handler,
131     .data           = nxt_port_data_handler,
132     .remove_pid     = nxt_controller_remove_pid_handler,
133     .rpc_ready      = nxt_port_rpc_handler,
134     .rpc_error      = nxt_port_rpc_handler,
135 };
136 
137 
138 const nxt_process_init_t  nxt_controller_process = {
139     .name           = "controller",
140     .type           = NXT_PROCESS_CONTROLLER,
141     .prefork        = nxt_controller_prefork,
142     .restart        = 1,
143     .setup          = nxt_process_core_setup,
144     .start          = nxt_controller_start,
145     .port_handlers  = &nxt_controller_process_port_handlers,
146     .signals        = nxt_process_signals,
147 };
148 
149 
150 static nxt_int_t
151 nxt_controller_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
152 {
153     ssize_t                n;
154     nxt_int_t              ret;
155     nxt_str_t              *conf;
156     nxt_file_t             file;
157     nxt_runtime_t          *rt;
158     nxt_file_info_t        fi;
159     nxt_controller_init_t  ctrl_init;
160 
161     nxt_log(task, NXT_LOG_INFO, "controller started");
162 
163     rt = task->thread->runtime;
164 
165     nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t));
166 
167     conf = &ctrl_init.conf;
168 
169     nxt_memzero(&file, sizeof(nxt_file_t));
170 
171     file.name = (nxt_file_name_t *) rt->conf;
172 
173     ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0);
174 
175     if (ret == NXT_OK) {
176         ret = nxt_file_info(&file, &fi);
177 
178         if (nxt_fast_path(ret == NXT_OK && nxt_is_file(&fi))) {
179             conf->length = nxt_file_size(&fi);
180             conf->start = nxt_mp_alloc(mp, conf->length);
181             if (nxt_slow_path(conf->start == NULL)) {
182                 nxt_file_close(task, &file);
183                 return NXT_ERROR;
184             }
185 
186             n = nxt_file_read(&file, conf->start, conf->length, 0);
187 
188             if (nxt_slow_path(n != (ssize_t) conf->length)) {
189                 conf->start = NULL;
190                 conf->length = 0;
191 
192                 nxt_alert(task, "failed to restore previous configuration: "
193                           "cannot read the file");
194             }
195         }
196 
197         nxt_file_close(task, &file);
198     }
199 
200 #if (NXT_TLS)
201     ctrl_init.certs = nxt_cert_store_load(task, mp);
202 
203     nxt_mp_cleanup(mp, nxt_controller_cert_cleanup, task, ctrl_init.certs, rt);
204 #endif
205 
206     process->data.controller = ctrl_init;
207 
208     return NXT_OK;
209 }
210 
211 
212 #if (NXT_TLS)
213 
214 static void
215 nxt_controller_cert_cleanup(nxt_task_t *task, void *obj, void *data)
216 {
217     pid_t          main_pid;
218     nxt_array_t    *certs;
219     nxt_runtime_t  *rt;
220 
221     certs = obj;
222     rt = data;
223 
224     main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid;
225 
226     if (nxt_pid == main_pid && certs != NULL) {
227         nxt_cert_store_release(certs);
228     }
229 }
230 
231 #endif
232 
233 
234 static nxt_int_t
235 nxt_controller_start(nxt_task_t *task, nxt_process_data_t *data)
236 {
237     nxt_mp_t               *mp;
238     nxt_int_t              ret;
239     nxt_str_t              *json;
240     nxt_conf_value_t       *conf;
241     nxt_conf_validation_t  vldt;
242     nxt_controller_init_t  *init;
243 
244     ret = nxt_http_fields_hash(&nxt_controller_fields_hash,
245                                nxt_controller_request_fields,
246                                nxt_nitems(nxt_controller_request_fields));
247 
248     if (nxt_slow_path(ret != NXT_OK)) {
249         return NXT_ERROR;
250     }
251 
252     nxt_queue_init(&nxt_controller_waiting_requests);
253 
254     init = &data->controller;
255 
256 #if (NXT_TLS)
257     if (init->certs != NULL) {
258         nxt_cert_info_init(task, init->certs);
259         nxt_cert_store_release(init->certs);
260     }
261 #endif
262 
263     json = &init->conf;
264 
265     if (json->start == NULL) {
266         return NXT_OK;
267     }
268 
269     mp = nxt_mp_create(1024, 128, 256, 32);
270     if (nxt_slow_path(mp == NULL)) {
271         return NXT_ERROR;
272     }
273 
274     conf = nxt_conf_json_parse_str(mp, json);
275     if (nxt_slow_path(conf == NULL)) {
276         nxt_alert(task, "failed to restore previous configuration: "
277                   "file is corrupted or not enough memory");
278 
279         nxt_mp_destroy(mp);
280         return NXT_OK;
281     }
282 
283     nxt_memzero(&vldt, sizeof(nxt_conf_validation_t));
284 
285     vldt.pool = nxt_mp_create(1024, 128, 256, 32);
286     if (nxt_slow_path(vldt.pool == NULL)) {
287         nxt_mp_destroy(mp);
288         return NXT_ERROR;
289     }
290 
291     vldt.conf = conf;
292 
293     ret = nxt_conf_validate(&vldt);
294 
295     if (nxt_slow_path(ret != NXT_OK)) {
296 
297         if (ret == NXT_DECLINED) {
298             nxt_alert(task, "the previous configuration is invalid: %V",
299                       &vldt.error);
300 
301             nxt_mp_destroy(vldt.pool);
302             nxt_mp_destroy(mp);
303 
304             return NXT_OK;
305         }
306 
307         /* ret == NXT_ERROR */
308 
309         return NXT_ERROR;
310     }
311 
312     nxt_mp_destroy(vldt.pool);
313 
314     nxt_controller_conf.root = conf;
315     nxt_controller_conf.pool = mp;
316 
317     return NXT_OK;
318 }
319 
320 
321 static void
322 nxt_controller_process_new_port_handler(nxt_task_t *task,
323     nxt_port_recv_msg_t *msg)
324 {
325     nxt_port_new_port_handler(task, msg);
326 
327     if (msg->u.new_port->type != NXT_PROCESS_ROUTER
328         || !nxt_controller_router_ready)
329     {
330         return;
331     }
332 
333     nxt_controller_send_current_conf(task);
334 }
335 
336 
337 static void
338 nxt_controller_send_current_conf(nxt_task_t *task)
339 {
340     nxt_int_t         rc;
341     nxt_runtime_t     *rt;
342     nxt_conf_value_t  *conf;
343 
344     conf = nxt_controller_conf.root;
345 
346     if (conf != NULL) {
347         rc = nxt_controller_conf_send(task, nxt_controller_conf.pool, conf,
348                                       nxt_controller_conf_init_handler, NULL);
349 
350         if (nxt_fast_path(rc == NXT_OK)) {
351             nxt_controller_waiting_init_conf = 1;
352 
353             return;
354         }
355 
356         nxt_mp_destroy(nxt_controller_conf.pool);
357 
358         if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) {
359             nxt_abort();
360         }
361     }
362 
363     if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) {
364         nxt_abort();
365     }
366 
367     rt = task->thread->runtime;
368 
369     if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) {
370         nxt_abort();
371     }
372 
373     nxt_controller_listening = 1;
374 
375     nxt_controller_flush_requests(task);
376 }
377 
378 
379 static void
380 nxt_controller_router_ready_handler(nxt_task_t *task,
381     nxt_port_recv_msg_t *msg)
382 {
383     nxt_port_t     *router_port;
384     nxt_runtime_t  *rt;
385 
386     rt = task->thread->runtime;
387 
388     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
389 
390     nxt_controller_router_ready = 1;
391 
392     if (router_port != NULL) {
393         nxt_controller_send_current_conf(task);
394     }
395 }
396 
397 
398 static void
399 nxt_controller_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
400 {
401     nxt_pid_t      pid;
402     nxt_process_t  *process;
403     nxt_runtime_t  *rt;
404 
405     rt = task->thread->runtime;
406 
407     nxt_assert(nxt_buf_used_size(msg->buf) == sizeof(pid));
408 
409     nxt_memcpy(&pid, msg->buf->mem.pos, sizeof(pid));
410 
411     process = nxt_runtime_process_find(rt, pid);
412     if (process != NULL && nxt_process_type(process) == NXT_PROCESS_ROUTER) {
413         nxt_controller_router_ready = 0;
414     }
415 
416     nxt_port_remove_pid_handler(task, msg);
417 }
418 
419 
420 static nxt_int_t
421 nxt_controller_conf_default(void)
422 {
423     nxt_mp_t          *mp;
424     nxt_conf_value_t  *conf;
425 
426     static const nxt_str_t json
427         = nxt_string("{ \"listeners\": {}, \"applications\": {} }");
428 
429     mp = nxt_mp_create(1024, 128, 256, 32);
430 
431     if (nxt_slow_path(mp == NULL)) {
432         return NXT_ERROR;
433     }
434 
435     conf = nxt_conf_json_parse_str(mp, &json);
436 
437     if (nxt_slow_path(conf == NULL)) {
438         return NXT_ERROR;
439     }
440 
441     nxt_controller_conf.root = conf;
442     nxt_controller_conf.pool = mp;
443 
444     return NXT_OK;
445 }
446 
447 
448 static void
449 nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
450     void *data)
451 {
452     nxt_runtime_t  *rt;
453 
454     nxt_controller_waiting_init_conf = 0;
455 
456     if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) {
457         nxt_alert(task, "failed to apply previous configuration");
458 
459         nxt_mp_destroy(nxt_controller_conf.pool);
460 
461         if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) {
462             nxt_abort();
463         }
464     }
465 
466     if (nxt_controller_listening == 0) {
467         rt = task->thread->runtime;
468 
469         if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket)
470                           == NULL))
471         {
472             nxt_abort();
473         }
474 
475         nxt_controller_listening = 1;
476     }
477 
478     nxt_controller_flush_requests(task);
479 }
480 
481 
482 static void
483 nxt_controller_flush_requests(nxt_task_t *task)
484 {
485     nxt_queue_t               queue;
486     nxt_controller_request_t  *req;
487 
488     nxt_queue_init(&queue);
489     nxt_queue_add(&queue, &nxt_controller_waiting_requests);
490 
491     nxt_queue_init(&nxt_controller_waiting_requests);
492 
493     nxt_queue_each(req, &queue, nxt_controller_request_t, link) {
494         nxt_controller_process_request(task, req);
495     } nxt_queue_loop;
496 }
497 
498 
499 static nxt_int_t
500 nxt_controller_conf_send(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf,
501     nxt_port_rpc_handler_t handler, void *data)
502 {
503     void           *mem;
504     u_char         *end;
505     size_t         size;
506     uint32_t       stream;
507     nxt_fd_t       fd;
508     nxt_int_t      rc;
509     nxt_buf_t      *b;
510     nxt_port_t     *router_port, *controller_port;
511     nxt_runtime_t  *rt;
512 
513     rt = task->thread->runtime;
514 
515     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
516 
517     nxt_assert(router_port != NULL);
518     nxt_assert(nxt_controller_router_ready);
519 
520     controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
521 
522     size = nxt_conf_json_length(conf, NULL);
523 
524     b = nxt_buf_mem_alloc(mp, sizeof(size_t), 0);
525     if (nxt_slow_path(b == NULL)) {
526         return NXT_ERROR;
527     }
528 
529     fd = nxt_shm_open(task, size);
530     if (nxt_slow_path(fd == -1)) {
531         return NXT_ERROR;
532     }
533 
534     mem = nxt_mem_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
535     if (nxt_slow_path(mem == MAP_FAILED)) {
536         goto fail;
537     }
538 
539     end = nxt_conf_json_print(mem, conf, NULL);
540 
541     nxt_mem_munmap(mem, size);
542 
543     size = end - (u_char *) mem;
544 
545     b->mem.free = nxt_cpymem(b->mem.pos, &size, sizeof(size_t));
546 
547     stream = nxt_port_rpc_register_handler(task, controller_port,
548                                            handler, handler,
549                                            router_port->pid, data);
550     if (nxt_slow_path(stream == 0)) {
551         goto fail;
552     }
553 
554     rc = nxt_port_socket_write(task, router_port,
555                                NXT_PORT_MSG_DATA_LAST | NXT_PORT_MSG_CLOSE_FD,
556                                fd, stream, controller_port->id, b);
557 
558     if (nxt_slow_path(rc != NXT_OK)) {
559         nxt_port_rpc_cancel(task, controller_port, stream);
560 
561         goto fail;
562     }
563 
564     return NXT_OK;
565 
566 fail:
567 
568     nxt_fd_close(fd);
569 
570     return NXT_ERROR;
571 }
572 
573 
574 nxt_int_t
575 nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt)
576 {
577     nxt_listen_socket_t  *ls;
578 
579     ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t));
580     if (ls == NULL) {
581         return NXT_ERROR;
582     }
583 
584     ls->sockaddr = rt->controller_listen;
585 
586     nxt_listen_socket_remote_size(ls);
587 
588     ls->socket = -1;
589     ls->backlog = NXT_LISTEN_BACKLOG;
590     ls->read_after_accept = 1;
591     ls->flags = NXT_NONBLOCK;
592 
593 #if 0
594     /* STUB */
595     wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t));
596     if (wq == NULL) {
597         return NXT_ERROR;
598     }
599     nxt_work_queue_name(wq, "listen");
600     /**/
601 
602     ls->work_queue = wq;
603 #endif
604     ls->handler = nxt_controller_conn_init;
605 
606     if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) {
607         return NXT_ERROR;
608     }
609 
610     rt->controller_socket = ls;
611 
612     return NXT_OK;
613 }
614 
615 
616 static void
617 nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data)
618 {
619     nxt_buf_t                 *b;
620     nxt_conn_t                *c;
621     nxt_event_engine_t        *engine;
622     nxt_controller_request_t  *r;
623 
624     c = obj;
625 
626     nxt_debug(task, "controller conn init fd:%d", c->socket.fd);
627 
628     r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t));
629     if (nxt_slow_path(r == NULL)) {
630         nxt_controller_conn_free(task, c, NULL);
631         return;
632     }
633 
634     r->conn = c;
635 
636     if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool)
637                       != NXT_OK))
638     {
639         nxt_controller_conn_free(task, c, NULL);
640         return;
641     }
642 
643     r->parser.encoded_slashes = 1;
644 
645     b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0);
646     if (nxt_slow_path(b == NULL)) {
647         nxt_controller_conn_free(task, c, NULL);
648         return;
649     }
650 
651     c->read = b;
652     c->socket.data = r;
653     c->socket.read_ready = 1;
654     c->read_state = &nxt_controller_conn_read_state;
655 
656     engine = task->thread->engine;
657     c->read_work_queue = &engine->read_work_queue;
658     c->write_work_queue = &engine->write_work_queue;
659 
660     nxt_conn_read(engine, c);
661 }
662 
663 
664 static const nxt_event_conn_state_t  nxt_controller_conn_read_state
665     nxt_aligned(64) =
666 {
667     .ready_handler = nxt_controller_conn_read,
668     .close_handler = nxt_controller_conn_close,
669     .error_handler = nxt_controller_conn_read_error,
670 
671     .timer_handler = nxt_controller_conn_read_timeout,
672     .timer_value = nxt_controller_conn_timeout_value,
673     .timer_data = 60 * 1000,
674 };
675 
676 
677 static void
678 nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data)
679 {
680     size_t                    preread;
681     nxt_buf_t                 *b;
682     nxt_int_t                 rc;
683     nxt_conn_t                *c;
684     nxt_controller_request_t  *r;
685 
686     c = obj;
687     r = data;
688 
689     nxt_debug(task, "controller conn read");
690 
691     nxt_queue_remove(&c->link);
692     nxt_queue_self(&c->link);
693 
694     b = c->read;
695 
696     rc = nxt_http_parse_request(&r->parser, &b->mem);
697 
698     if (nxt_slow_path(rc != NXT_DONE)) {
699 
700         if (rc == NXT_AGAIN) {
701             if (nxt_buf_mem_free_size(&b->mem) == 0) {
702                 nxt_log(task, NXT_LOG_ERR, "too long request headers");
703                 nxt_controller_conn_close(task, c, r);
704                 return;
705             }
706 
707             nxt_conn_read(task->thread->engine, c);
708             return;
709         }
710 
711         /* rc == NXT_ERROR */
712 
713         nxt_log(task, NXT_LOG_ERR, "parsing error");
714 
715         nxt_controller_conn_close(task, c, r);
716         return;
717     }
718 
719     rc = nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash,
720                                  r);
721 
722     if (nxt_slow_path(rc != NXT_OK)) {
723         nxt_controller_conn_close(task, c, r);
724         return;
725     }
726 
727     preread = nxt_buf_mem_used_size(&b->mem);
728 
729     nxt_debug(task, "controller request header parsing complete, "
730                     "body length: %uz, preread: %uz",
731                     r->length, preread);
732 
733     if (preread >= r->length) {
734         nxt_controller_process_request(task, r);
735         return;
736     }
737 
738     if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) {
739         b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0);
740         if (nxt_slow_path(b == NULL)) {
741             nxt_controller_conn_free(task, c, NULL);
742             return;
743         }
744 
745         b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread);
746 
747         c->read = b;
748     }
749 
750     c->read_state = &nxt_controller_conn_body_read_state;
751 
752     nxt_conn_read(task->thread->engine, c);
753 }
754 
755 
756 static nxt_msec_t
757 nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data)
758 {
759     return (nxt_msec_t) data;
760 }
761 
762 
763 static void
764 nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data)
765 {
766     nxt_conn_t  *c;
767 
768     c = obj;
769 
770     nxt_debug(task, "controller conn read error");
771 
772     nxt_controller_conn_close(task, c, data);
773 }
774 
775 
776 static void
777 nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data)
778 {
779     nxt_timer_t  *timer;
780     nxt_conn_t   *c;
781 
782     timer = obj;
783 
784     c = nxt_read_timer_conn(timer);
785     c->socket.timedout = 1;
786     c->socket.closed = 1;
787 
788     nxt_debug(task, "controller conn read timeout");
789 
790     nxt_controller_conn_close(task, c, data);
791 }
792 
793 
794 static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state
795     nxt_aligned(64) =
796 {
797     .ready_handler = nxt_controller_conn_body_read,
798     .close_handler = nxt_controller_conn_close,
799     .error_handler = nxt_controller_conn_read_error,
800 
801     .timer_handler = nxt_controller_conn_read_timeout,
802     .timer_value = nxt_controller_conn_timeout_value,
803     .timer_data = 60 * 1000,
804     .timer_autoreset = 1,
805 };
806 
807 
808 static void
809 nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data)
810 {
811     size_t                    read;
812     nxt_buf_t                 *b;
813     nxt_conn_t                *c;
814     nxt_controller_request_t  *r;
815 
816     c = obj;
817     r = data;
818     b = c->read;
819 
820     read = nxt_buf_mem_used_size(&b->mem);
821 
822     nxt_debug(task, "controller conn body read: %uz of %uz",
823               read, r->length);
824 
825     if (read >= r->length) {
826         nxt_controller_process_request(task, r);
827         return;
828     }
829 
830     nxt_conn_read(task->thread->engine, c);
831 }
832 
833 
834 static const nxt_event_conn_state_t  nxt_controller_conn_write_state
835     nxt_aligned(64) =
836 {
837     .ready_handler = nxt_controller_conn_write,
838     .error_handler = nxt_controller_conn_write_error,
839 
840     .timer_handler = nxt_controller_conn_write_timeout,
841     .timer_value = nxt_controller_conn_timeout_value,
842     .timer_data = 60 * 1000,
843     .timer_autoreset = 1,
844 };
845 
846 
847 static void
848 nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data)
849 {
850     nxt_buf_t   *b;
851     nxt_conn_t  *c;
852 
853     c = obj;
854 
855     nxt_debug(task, "controller conn write");
856 
857     b = c->write;
858 
859     if (b->mem.pos != b->mem.free) {
860         nxt_conn_write(task->thread->engine, c);
861         return;
862     }
863 
864     nxt_debug(task, "controller conn write complete");
865 
866     nxt_controller_conn_close(task, c, data);
867 }
868 
869 
870 static void
871 nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data)
872 {
873     nxt_conn_t  *c;
874 
875     c = obj;
876 
877     nxt_debug(task, "controller conn write error");
878 
879     nxt_controller_conn_close(task, c, data);
880 }
881 
882 
883 static void
884 nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data)
885 {
886     nxt_conn_t   *c;
887     nxt_timer_t  *timer;
888 
889     timer = obj;
890 
891     c = nxt_write_timer_conn(timer);
892     c->socket.timedout = 1;
893     c->socket.closed = 1;
894 
895     nxt_debug(task, "controller conn write timeout");
896 
897     nxt_controller_conn_close(task, c, data);
898 }
899 
900 
901 static const nxt_event_conn_state_t  nxt_controller_conn_close_state
902     nxt_aligned(64) =
903 {
904     .ready_handler = nxt_controller_conn_free,
905 };
906 
907 
908 static void
909 nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data)
910 {
911     nxt_conn_t  *c;
912 
913     c = obj;
914 
915     nxt_debug(task, "controller conn close");
916 
917     nxt_queue_remove(&c->link);
918 
919     c->write_state = &nxt_controller_conn_close_state;
920 
921     nxt_conn_close(task->thread->engine, c);
922 }
923 
924 
925 static void
926 nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data)
927 {
928     nxt_conn_t  *c;
929 
930     c = obj;
931 
932     nxt_debug(task, "controller conn free");
933 
934     nxt_sockaddr_cache_free(task->thread->engine, c);
935 
936     nxt_conn_free(task, c);
937 }
938 
939 
940 static nxt_int_t
941 nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field,
942     uintptr_t data)
943 {
944     off_t                     length;
945     nxt_controller_request_t  *r;
946 
947     r = ctx;
948 
949     length = nxt_off_t_parse(field->value, field->value_length);
950 
951     if (nxt_fast_path(length >= 0)) {
952 
953         if (nxt_slow_path(length > NXT_SIZE_T_MAX)) {
954             nxt_log_error(NXT_LOG_ERR, &r->conn->log,
955                           "Content-Length is too big");
956             return NXT_ERROR;
957         }
958 
959         r->length = length;
960         return NXT_OK;
961     }
962 
963     nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid");
964 
965     return NXT_ERROR;
966 }
967 
968 
969 static void
970 nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
971 {
972     uint32_t                   i, count;
973     nxt_str_t                  path;
974     nxt_conn_t                 *c;
975     nxt_conf_value_t           *value;
976     nxt_controller_response_t  resp;
977 #if (NXT_TLS)
978     nxt_conf_value_t           *certs;
979 
980     static nxt_str_t certificates = nxt_string("certificates");
981 #endif
982     static nxt_str_t config = nxt_string("config");
983 
984     c = req->conn;
985     path = req->parser.path;
986 
987     if (path.length > 1 && path.start[path.length - 1] == '/') {
988         path.length--;
989     }
990 
991     if (nxt_str_start(&path, "/config", 7)
992         && (path.length == 7 || path.start[7] == '/'))
993     {
994         if (path.length == 7) {
995             path.length = 1;
996 
997         } else {
998             path.length -= 7;
999             path.start += 7;
1000         }
1001 
1002         nxt_controller_process_config(task, req, &path);
1003         return;
1004     }
1005 
1006 #if (NXT_TLS)
1007 
1008     if (nxt_str_start(&path, "/certificates", 13)
1009         && (path.length == 13 || path.start[13] == '/'))
1010     {
1011         if (path.length == 13) {
1012             path.length = 1;
1013 
1014         } else {
1015             path.length -= 13;
1016             path.start += 13;
1017         }
1018 
1019         nxt_controller_process_cert(task, req, &path);
1020         return;
1021     }
1022 
1023 #endif
1024 
1025     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1026 
1027     if (path.length == 1 && path.start[0] == '/') {
1028 
1029         if (!nxt_str_eq(&req->parser.method, "GET", 3)) {
1030             goto invalid_method;
1031         }
1032 
1033         count = 1;
1034 #if (NXT_TLS)
1035         count++;
1036 #endif
1037 
1038         value = nxt_conf_create_object(c->mem_pool, count);
1039         if (nxt_slow_path(value == NULL)) {
1040             goto alloc_fail;
1041         }
1042 
1043         i = 0;
1044 
1045 #if (NXT_TLS)
1046         certs = nxt_cert_info_get_all(c->mem_pool);
1047         if (nxt_slow_path(certs == NULL)) {
1048             goto alloc_fail;
1049         }
1050 
1051         nxt_conf_set_member(value, &certificates, certs, i++);
1052 #endif
1053 
1054         nxt_conf_set_member(value, &config, nxt_controller_conf.root, i);
1055 
1056         resp.status = 200;
1057         resp.conf = value;
1058 
1059         nxt_controller_response(task, req, &resp);
1060         return;
1061     }
1062 
1063     resp.status = 404;
1064     resp.title = (u_char *) "Value doesn't exist.";
1065     resp.offset = -1;
1066 
1067     nxt_controller_response(task, req, &resp);
1068     return;
1069 
1070 invalid_method:
1071 
1072     resp.status = 405;
1073     resp.title = (u_char *) "Invalid method.";
1074     resp.offset = -1;
1075 
1076     nxt_controller_response(task, req, &resp);
1077     return;
1078 
1079 alloc_fail:
1080 
1081     resp.status = 500;
1082     resp.title = (u_char *) "Memory allocation failed.";
1083     resp.offset = -1;
1084 
1085     nxt_controller_response(task, req, &resp);
1086     return;
1087 }
1088 
1089 
1090 static void
1091 nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req,
1092     nxt_str_t *path)
1093 {
1094     nxt_mp_t                   *mp;
1095     nxt_int_t                  rc;
1096     nxt_conn_t                 *c;
1097     nxt_bool_t                 post;
1098     nxt_buf_mem_t              *mbuf;
1099     nxt_conf_op_t              *ops;
1100     nxt_conf_value_t           *value;
1101     nxt_conf_validation_t      vldt;
1102     nxt_conf_json_error_t      error;
1103     nxt_controller_response_t  resp;
1104 
1105     static const nxt_str_t empty_obj = nxt_string("{}");
1106 
1107     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1108 
1109     c = req->conn;
1110 
1111     if (nxt_str_eq(&req->parser.method, "GET", 3)) {
1112 
1113         value = nxt_conf_get_path(nxt_controller_conf.root, path);
1114 
1115         if (value == NULL) {
1116             goto not_found;
1117         }
1118 
1119         resp.status = 200;
1120         resp.conf = value;
1121 
1122         nxt_controller_response(task, req, &resp);
1123         return;
1124     }
1125 
1126     if (nxt_str_eq(&req->parser.method, "POST", 4)) {
1127         if (path->length == 1) {
1128             goto not_allowed;
1129         }
1130 
1131         post = 1;
1132 
1133     } else {
1134         post = 0;
1135     }
1136 
1137     if (post || nxt_str_eq(&req->parser.method, "PUT", 3)) {
1138 
1139         if (nxt_controller_check_postpone_request(task)) {
1140             nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link);
1141             return;
1142         }
1143 
1144         mp = nxt_mp_create(1024, 128, 256, 32);
1145 
1146         if (nxt_slow_path(mp == NULL)) {
1147             goto alloc_fail;
1148         }
1149 
1150         mbuf = &c->read->mem;
1151 
1152         nxt_memzero(&error, sizeof(nxt_conf_json_error_t));
1153 
1154         /* Skip UTF-8 BOM. */
1155         if (nxt_buf_mem_used_size(mbuf) >= 3
1156             && nxt_memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0)
1157         {
1158             mbuf->pos += 3;
1159         }
1160 
1161         value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error);
1162 
1163         if (value == NULL) {
1164             nxt_mp_destroy(mp);
1165 
1166             if (error.pos == NULL) {
1167                 goto alloc_fail;
1168             }
1169 
1170             resp.status = 400;
1171             resp.title = (u_char *) "Invalid JSON.";
1172             resp.detail.length = nxt_strlen(error.detail);
1173             resp.detail.start = error.detail;
1174             resp.offset = error.pos - mbuf->pos;
1175 
1176             nxt_conf_json_position(mbuf->pos, error.pos,
1177                                    &resp.line, &resp.column);
1178 
1179             nxt_controller_response(task, req, &resp);
1180             return;
1181         }
1182 
1183         if (path->length != 1) {
1184             rc = nxt_conf_op_compile(c->mem_pool, &ops,
1185                                      nxt_controller_conf.root,
1186                                      path, value, post);
1187 
1188             if (rc != NXT_CONF_OP_OK) {
1189                 nxt_mp_destroy(mp);
1190 
1191                 switch (rc) {
1192                 case NXT_CONF_OP_NOT_FOUND:
1193                     goto not_found;
1194 
1195                 case NXT_CONF_OP_NOT_ALLOWED:
1196                     goto not_allowed;
1197                 }
1198 
1199                 /* rc == NXT_CONF_OP_ERROR */
1200                 goto alloc_fail;
1201             }
1202 
1203             value = nxt_conf_clone(mp, ops, nxt_controller_conf.root);
1204 
1205             if (nxt_slow_path(value == NULL)) {
1206                 nxt_mp_destroy(mp);
1207                 goto alloc_fail;
1208             }
1209         }
1210 
1211         nxt_memzero(&vldt, sizeof(nxt_conf_validation_t));
1212 
1213         vldt.conf = value;
1214         vldt.pool = c->mem_pool;
1215 
1216         rc = nxt_conf_validate(&vldt);
1217 
1218         if (nxt_slow_path(rc != NXT_OK)) {
1219             nxt_mp_destroy(mp);
1220 
1221             if (rc == NXT_DECLINED) {
1222                 resp.detail = vldt.error;
1223                 goto invalid_conf;
1224             }
1225 
1226             /* rc == NXT_ERROR */
1227             goto alloc_fail;
1228         }
1229 
1230         rc = nxt_controller_conf_send(task, mp, value,
1231                                       nxt_controller_conf_handler, req);
1232 
1233         if (nxt_slow_path(rc != NXT_OK)) {
1234             nxt_mp_destroy(mp);
1235 
1236             /* rc == NXT_ERROR */
1237             goto alloc_fail;
1238         }
1239 
1240         req->conf.root = value;
1241         req->conf.pool = mp;
1242 
1243         nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link);
1244 
1245         return;
1246     }
1247 
1248     if (nxt_str_eq(&req->parser.method, "DELETE", 6)) {
1249 
1250         if (nxt_controller_check_postpone_request(task)) {
1251             nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link);
1252             return;
1253         }
1254 
1255         if (path->length == 1) {
1256             mp = nxt_mp_create(1024, 128, 256, 32);
1257 
1258             if (nxt_slow_path(mp == NULL)) {
1259                 goto alloc_fail;
1260             }
1261 
1262             value = nxt_conf_json_parse_str(mp, &empty_obj);
1263 
1264         } else {
1265             rc = nxt_conf_op_compile(c->mem_pool, &ops,
1266                                      nxt_controller_conf.root,
1267                                      path, NULL, 0);
1268 
1269             if (rc != NXT_OK) {
1270                 if (rc == NXT_CONF_OP_NOT_FOUND) {
1271                     goto not_found;
1272                 }
1273 
1274                 /* rc == NXT_CONF_OP_ERROR */
1275                 goto alloc_fail;
1276             }
1277 
1278             mp = nxt_mp_create(1024, 128, 256, 32);
1279 
1280             if (nxt_slow_path(mp == NULL)) {
1281                 goto alloc_fail;
1282             }
1283 
1284             value = nxt_conf_clone(mp, ops, nxt_controller_conf.root);
1285         }
1286 
1287         if (nxt_slow_path(value == NULL)) {
1288             nxt_mp_destroy(mp);
1289             goto alloc_fail;
1290         }
1291 
1292         nxt_memzero(&vldt, sizeof(nxt_conf_validation_t));
1293 
1294         vldt.conf = value;
1295         vldt.pool = c->mem_pool;
1296 
1297         rc = nxt_conf_validate(&vldt);
1298 
1299         if (nxt_slow_path(rc != NXT_OK)) {
1300             nxt_mp_destroy(mp);
1301 
1302             if (rc == NXT_DECLINED) {
1303                 resp.detail = vldt.error;
1304                 goto invalid_conf;
1305             }
1306 
1307             /* rc == NXT_ERROR */
1308             goto alloc_fail;
1309         }
1310 
1311         rc = nxt_controller_conf_send(task, mp, value,
1312                                       nxt_controller_conf_handler, req);
1313 
1314         if (nxt_slow_path(rc != NXT_OK)) {
1315             nxt_mp_destroy(mp);
1316 
1317             /* rc == NXT_ERROR */
1318             goto alloc_fail;
1319         }
1320 
1321         req->conf.root = value;
1322         req->conf.pool = mp;
1323 
1324         nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link);
1325 
1326         return;
1327     }
1328 
1329 not_allowed:
1330 
1331     resp.status = 405;
1332     resp.title = (u_char *) "Method isn't allowed.";
1333     resp.offset = -1;
1334 
1335     nxt_controller_response(task, req, &resp);
1336     return;
1337 
1338 not_found:
1339 
1340     resp.status = 404;
1341     resp.title = (u_char *) "Value doesn't exist.";
1342     resp.offset = -1;
1343 
1344     nxt_controller_response(task, req, &resp);
1345     return;
1346 
1347 invalid_conf:
1348 
1349     resp.status = 400;
1350     resp.title = (u_char *) "Invalid configuration.";
1351     resp.offset = -1;
1352 
1353     nxt_controller_response(task, req, &resp);
1354     return;
1355 
1356 alloc_fail:
1357 
1358     resp.status = 500;
1359     resp.title = (u_char *) "Memory allocation failed.";
1360     resp.offset = -1;
1361 
1362     nxt_controller_response(task, req, &resp);
1363 }
1364 
1365 
1366 static nxt_bool_t
1367 nxt_controller_check_postpone_request(nxt_task_t *task)
1368 {
1369     nxt_port_t     *router_port;
1370     nxt_runtime_t  *rt;
1371 
1372     if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)
1373         || nxt_controller_waiting_init_conf
1374         || !nxt_controller_router_ready)
1375     {
1376         return 1;
1377     }
1378 
1379     rt = task->thread->runtime;
1380 
1381     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
1382 
1383     return (router_port == NULL);
1384 }
1385 
1386 
1387 #if (NXT_TLS)
1388 
1389 static void
1390 nxt_controller_process_cert(nxt_task_t *task,
1391     nxt_controller_request_t *req, nxt_str_t *path)
1392 {
1393     u_char                     *p;
1394     nxt_str_t                  name;
1395     nxt_int_t                  ret;
1396     nxt_conn_t                 *c;
1397     nxt_cert_t                 *cert;
1398     nxt_conf_value_t           *value;
1399     nxt_controller_response_t  resp;
1400 
1401     name.length = path->length - 1;
1402     name.start = path->start + 1;
1403 
1404     p = nxt_memchr(name.start, '/', name.length);
1405 
1406     if (p != NULL) {
1407         name.length = p - name.start;
1408 
1409         path->length -= p - path->start;
1410         path->start = p;
1411 
1412     } else {
1413         path = NULL;
1414     }
1415 
1416     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1417 
1418     c = req->conn;
1419 
1420     if (nxt_str_eq(&req->parser.method, "GET", 3)) {
1421 
1422         if (name.length != 0) {
1423             value = nxt_cert_info_get(&name);
1424             if (value == NULL) {
1425                 goto cert_not_found;
1426             }
1427 
1428             if (path != NULL) {
1429                 value = nxt_conf_get_path(value, path);
1430                 if (value == NULL) {
1431                     goto not_found;
1432                 }
1433             }
1434 
1435         } else {
1436             value = nxt_cert_info_get_all(c->mem_pool);
1437             if (value == NULL) {
1438                 goto alloc_fail;
1439             }
1440         }
1441 
1442         resp.status = 200;
1443         resp.conf = value;
1444 
1445         nxt_controller_response(task, req, &resp);
1446         return;
1447     }
1448 
1449     if (name.length == 0 || path != NULL) {
1450         goto invalid_name;
1451     }
1452 
1453     if (nxt_str_eq(&req->parser.method, "PUT", 3)) {
1454         value = nxt_cert_info_get(&name);
1455         if (value != NULL) {
1456             goto exists_cert;
1457         }
1458 
1459         cert = nxt_cert_mem(task, &c->read->mem);
1460         if (cert == NULL) {
1461             goto invalid_cert;
1462         }
1463 
1464         ret = nxt_cert_info_save(&name, cert);
1465 
1466         nxt_cert_destroy(cert);
1467 
1468         if (nxt_slow_path(ret != NXT_OK)) {
1469             goto alloc_fail;
1470         }
1471 
1472         nxt_cert_store_get(task, &name, c->mem_pool,
1473                            nxt_controller_process_cert_save, req);
1474         return;
1475     }
1476 
1477     if (nxt_str_eq(&req->parser.method, "DELETE", 6)) {
1478 
1479         if (nxt_controller_cert_in_use(&name)) {
1480             goto cert_in_use;
1481         }
1482 
1483         if (nxt_cert_info_delete(&name) != NXT_OK) {
1484             goto cert_not_found;
1485         }
1486 
1487         nxt_cert_store_delete(task, &name, c->mem_pool);
1488 
1489         resp.status = 200;
1490         resp.title = (u_char *) "Certificate deleted.";
1491 
1492         nxt_controller_response(task, req, &resp);
1493         return;
1494     }
1495 
1496     resp.status = 405;
1497     resp.title = (u_char *) "Invalid method.";
1498     resp.offset = -1;
1499 
1500     nxt_controller_response(task, req, &resp);
1501     return;
1502 
1503 invalid_name:
1504 
1505     resp.status = 400;
1506     resp.title = (u_char *) "Invalid certificate name.";
1507     resp.offset = -1;
1508 
1509     nxt_controller_response(task, req, &resp);
1510     return;
1511 
1512 invalid_cert:
1513 
1514     resp.status = 400;
1515     resp.title = (u_char *) "Invalid certificate.";
1516     resp.offset = -1;
1517 
1518     nxt_controller_response(task, req, &resp);
1519     return;
1520 
1521 exists_cert:
1522 
1523     resp.status = 400;
1524     resp.title = (u_char *) "Certificate already exists.";
1525     resp.offset = -1;
1526 
1527     nxt_controller_response(task, req, &resp);
1528     return;
1529 
1530 cert_in_use:
1531 
1532     resp.status = 400;
1533     resp.title = (u_char *) "Certificate is used in the configuration.";
1534     resp.offset = -1;
1535 
1536     nxt_controller_response(task, req, &resp);
1537     return;
1538 
1539 cert_not_found:
1540 
1541     resp.status = 404;
1542     resp.title = (u_char *) "Certificate doesn't exist.";
1543     resp.offset = -1;
1544 
1545     nxt_controller_response(task, req, &resp);
1546     return;
1547 
1548 not_found:
1549 
1550     resp.status = 404;
1551     resp.title = (u_char *) "Invalid path.";
1552     resp.offset = -1;
1553 
1554     nxt_controller_response(task, req, &resp);
1555     return;
1556 
1557 alloc_fail:
1558 
1559     resp.status = 500;
1560     resp.title = (u_char *) "Memory allocation failed.";
1561     resp.offset = -1;
1562 
1563     nxt_controller_response(task, req, &resp);
1564     return;
1565 }
1566 
1567 
1568 static void
1569 nxt_controller_process_cert_save(nxt_task_t *task, nxt_port_recv_msg_t *msg,
1570     void *data)
1571 {
1572     nxt_conn_t                *c;
1573     nxt_buf_mem_t             *mbuf;
1574     nxt_controller_request_t  *req;
1575     nxt_controller_response_t  resp;
1576 
1577     req = data;
1578 
1579     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1580 
1581     if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) {
1582         resp.status = 500;
1583         resp.title = (u_char *) "Failed to store certificate.";
1584 
1585         nxt_controller_response(task, req, &resp);
1586         return;
1587     }
1588 
1589     c = req->conn;
1590 
1591     mbuf = &c->read->mem;
1592 
1593     nxt_fd_write(msg->fd, mbuf->pos, nxt_buf_mem_used_size(mbuf));
1594 
1595     nxt_fd_close(msg->fd);
1596 
1597     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1598 
1599     resp.status = 200;
1600     resp.title = (u_char *) "Certificate chain uploaded.";
1601 
1602     nxt_controller_response(task, req, &resp);
1603 }
1604 
1605 
1606 static nxt_bool_t
1607 nxt_controller_cert_in_use(nxt_str_t *name)
1608 {
1609     uint32_t          next;
1610     nxt_str_t         str;
1611     nxt_conf_value_t  *listeners, *listener, *value;
1612 
1613     static nxt_str_t  listeners_path = nxt_string("/listeners");
1614     static nxt_str_t  certificate_path = nxt_string("/tls/certificate");
1615 
1616     listeners = nxt_conf_get_path(nxt_controller_conf.root, &listeners_path);
1617 
1618     if (listeners != NULL) {
1619         next = 0;
1620 
1621         for ( ;; ) {
1622             listener = nxt_conf_next_object_member(listeners, &str, &next);
1623             if (listener == NULL) {
1624                 break;
1625             }
1626 
1627             value = nxt_conf_get_path(listener, &certificate_path);
1628             if (value == NULL) {
1629                 continue;
1630             }
1631 
1632             nxt_conf_get_string(value, &str);
1633 
1634             if (nxt_strstr_eq(&str, name)) {
1635                 return 1;
1636             }
1637         }
1638     }
1639 
1640     return 0;
1641 }
1642 
1643 #endif
1644 
1645 
1646 static void
1647 nxt_controller_conf_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
1648     void *data)
1649 {
1650     nxt_controller_request_t   *req;
1651     nxt_controller_response_t  resp;
1652 
1653     req = data;
1654 
1655     nxt_debug(task, "controller conf ready: %*s",
1656               nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos);
1657 
1658     nxt_queue_remove(&req->link);
1659 
1660     nxt_memzero(&resp, sizeof(nxt_controller_response_t));
1661 
1662     if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) {
1663         nxt_mp_destroy(nxt_controller_conf.pool);
1664 
1665         nxt_controller_conf = req->conf;
1666 
1667         nxt_controller_conf_store(task, req->conf.root);
1668 
1669         resp.status = 200;
1670         resp.title = (u_char *) "Reconfiguration done.";
1671 
1672     } else {
1673         nxt_mp_destroy(req->conf.pool);
1674 
1675         resp.status = 500;
1676         resp.title = (u_char *) "Failed to apply new configuration.";
1677         resp.offset = -1;
1678     }
1679 
1680     nxt_controller_response(task, req, &resp);
1681 
1682     nxt_controller_flush_requests(task);
1683 }
1684 
1685 
1686 static void
1687 nxt_controller_conf_store(nxt_task_t *task, nxt_conf_value_t *conf)
1688 {
1689     size_t         size;
1690     nxt_buf_t      *b;
1691     nxt_port_t     *main_port;
1692     nxt_runtime_t  *rt;
1693 
1694     rt = task->thread->runtime;
1695 
1696     main_port = rt->port_by_type[NXT_PROCESS_MAIN];
1697 
1698     size = nxt_conf_json_length(conf, NULL);
1699 
1700     b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size);
1701 
1702     if (nxt_fast_path(b != NULL)) {
1703         b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL);
1704 
1705         (void) nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CONF_STORE,
1706                                      -1, 0, -1, b);
1707     }
1708 }
1709 
1710 
1711 static void
1712 nxt_controller_response(nxt_task_t *task, nxt_controller_request_t *req,
1713     nxt_controller_response_t *resp)
1714 {
1715     size_t                  size;
1716     nxt_str_t               status_line, str;
1717     nxt_buf_t               *b, *body;
1718     nxt_conn_t              *c;
1719     nxt_uint_t              n;
1720     nxt_conf_value_t        *value, *location;
1721     nxt_conf_json_pretty_t  pretty;
1722 
1723     static nxt_str_t  success_str = nxt_string("success");
1724     static nxt_str_t  error_str = nxt_string("error");
1725     static nxt_str_t  detail_str = nxt_string("detail");
1726     static nxt_str_t  location_str = nxt_string("location");
1727     static nxt_str_t  offset_str = nxt_string("offset");
1728     static nxt_str_t  line_str = nxt_string("line");
1729     static nxt_str_t  column_str = nxt_string("column");
1730 
1731     static nxt_time_string_t  date_cache = {
1732         (nxt_atomic_uint_t) -1,
1733         nxt_controller_date,
1734         "%s, %02d %s %4d %02d:%02d:%02d GMT",
1735         nxt_length("Wed, 31 Dec 1986 16:40:00 GMT"),
1736         NXT_THREAD_TIME_GMT,
1737         NXT_THREAD_TIME_SEC,
1738     };
1739 
1740     switch (resp->status) {
1741 
1742     case 200:
1743         nxt_str_set(&status_line, "200 OK");
1744         break;
1745 
1746     case 400:
1747         nxt_str_set(&status_line, "400 Bad Request");
1748         break;
1749 
1750     case 404:
1751         nxt_str_set(&status_line, "404 Not Found");
1752         break;
1753 
1754     case 405:
1755         nxt_str_set(&status_line, "405 Method Not Allowed");
1756         break;
1757 
1758     default:
1759         nxt_str_set(&status_line, "500 Internal Server Error");
1760         break;
1761     }
1762 
1763     c = req->conn;
1764     value = resp->conf;
1765 
1766     if (value == NULL) {
1767         n = 1
1768             + (resp->detail.length != 0)
1769             + (resp->status >= 400 && resp->offset != -1);
1770 
1771         value = nxt_conf_create_object(c->mem_pool, n);
1772 
1773         if (nxt_slow_path(value == NULL)) {
1774             nxt_controller_conn_close(task, c, req);
1775             return;
1776         }
1777 
1778         str.length = nxt_strlen(resp->title);
1779         str.start = resp->title;
1780 
1781         if (resp->status < 400) {
1782             nxt_conf_set_member_string(value, &success_str, &str, 0);
1783 
1784         } else {
1785             nxt_conf_set_member_string(value, &error_str, &str, 0);
1786         }
1787 
1788         n = 0;
1789 
1790         if (resp->detail.length != 0) {
1791             n++;
1792 
1793             nxt_conf_set_member_string(value, &detail_str, &resp->detail, n);
1794         }
1795 
1796         if (resp->status >= 400 && resp->offset != -1) {
1797             n++;
1798 
1799             location = nxt_conf_create_object(c->mem_pool,
1800                                               resp->line != 0 ? 3 : 1);
1801 
1802             nxt_conf_set_member(value, &location_str, location, n);
1803 
1804             nxt_conf_set_member_integer(location, &offset_str, resp->offset, 0);
1805 
1806             if (resp->line != 0) {
1807                 nxt_conf_set_member_integer(location, &line_str,
1808                                             resp->line, 1);
1809 
1810                 nxt_conf_set_member_integer(location, &column_str,
1811                                             resp->column, 2);
1812             }
1813         }
1814     }
1815 
1816     nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t));
1817 
1818     size = nxt_conf_json_length(value, &pretty) + 2;
1819 
1820     body = nxt_buf_mem_alloc(c->mem_pool, size, 0);
1821     if (nxt_slow_path(body == NULL)) {
1822         nxt_controller_conn_close(task, c, req);
1823         return;
1824     }
1825 
1826     nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t));
1827 
1828     body->mem.free = nxt_conf_json_print(body->mem.free, value, &pretty);
1829 
1830     body->mem.free = nxt_cpymem(body->mem.free, "\r\n", 2);
1831 
1832     size = nxt_length("HTTP/1.1 " "\r\n") + status_line.length
1833            + nxt_length("Server: " NXT_SERVER "\r\n")
1834            + nxt_length("Date: Wed, 31 Dec 1986 16:40:00 GMT\r\n")
1835            + nxt_length("Content-Type: application/json\r\n")
1836            + nxt_length("Content-Length: " "\r\n") + NXT_SIZE_T_LEN
1837            + nxt_length("Connection: close\r\n")
1838            + nxt_length("\r\n");
1839 
1840     b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
1841     if (nxt_slow_path(b == NULL)) {
1842         nxt_controller_conn_close(task, c, req);
1843         return;
1844     }
1845 
1846     b->next = body;
1847 
1848     nxt_str_set(&str, "HTTP/1.1 ");
1849 
1850     b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length);
1851     b->mem.free = nxt_cpymem(b->mem.free, status_line.start,
1852                              status_line.length);
1853 
1854     nxt_str_set(&str, "\r\n"
1855                       "Server: " NXT_SERVER "\r\n"
1856                       "Date: ");
1857 
1858     b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length);
1859 
1860     b->mem.free = nxt_thread_time_string(task->thread, &date_cache,
1861                                          b->mem.free);
1862 
1863     nxt_str_set(&str, "\r\n"
1864                       "Content-Type: application/json\r\n"
1865                       "Content-Length: ");
1866 
1867     b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length);
1868 
1869     b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, "%uz",
1870                               nxt_buf_mem_used_size(&body->mem));
1871 
1872     nxt_str_set(&str, "\r\n"
1873                       "Connection: close\r\n"
1874                       "\r\n");
1875 
1876     b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length);
1877 
1878     c->write = b;
1879     c->write_state = &nxt_controller_conn_write_state;
1880 
1881     nxt_conn_write(task->thread->engine, c);
1882 }
1883 
1884 
1885 static u_char *
1886 nxt_controller_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
1887     size_t size, const char *format)
1888 {
1889     static const char  *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
1890                                    "Sat" };
1891 
1892     static const char  *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1893                                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1894 
1895     return nxt_sprintf(buf, buf + size, format,
1896                        week[tm->tm_wday], tm->tm_mday,
1897                        month[tm->tm_mon], tm->tm_year + 1900,
1898                        tm->tm_hour, tm->tm_min, tm->tm_sec);
1899 }
1900