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