120Sigor@sysoev.ru 220Sigor@sysoev.ru /* 320Sigor@sysoev.ru * Copyright (C) Igor Sysoev 420Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 520Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 620Sigor@sysoev.ru */ 720Sigor@sysoev.ru 820Sigor@sysoev.ru #include <nxt_main.h> 920Sigor@sysoev.ru #include <nxt_runtime.h> 10240Sigor@sysoev.ru #include <nxt_main_process.h> 1129Svbart@nginx.com #include <nxt_conf.h> 12*774Svbart@nginx.com #include <nxt_cert.h> 1320Sigor@sysoev.ru 1420Sigor@sysoev.ru 1527Svbart@nginx.com typedef struct { 16106Svbart@nginx.com nxt_conf_value_t *root; 17106Svbart@nginx.com nxt_mp_t *pool; 1844Svbart@nginx.com } nxt_controller_conf_t; 1944Svbart@nginx.com 2044Svbart@nginx.com 2144Svbart@nginx.com typedef struct { 2227Svbart@nginx.com nxt_http_request_parse_t parser; 2327Svbart@nginx.com size_t length; 2444Svbart@nginx.com nxt_controller_conf_t conf; 25140Svbart@nginx.com nxt_conn_t *conn; 26140Svbart@nginx.com nxt_queue_link_t link; 2727Svbart@nginx.com } nxt_controller_request_t; 2827Svbart@nginx.com 2927Svbart@nginx.com 3044Svbart@nginx.com typedef struct { 31208Svbart@nginx.com nxt_uint_t status; 32106Svbart@nginx.com nxt_conf_value_t *conf; 33208Svbart@nginx.com 34208Svbart@nginx.com u_char *title; 35357Svbart@nginx.com nxt_str_t detail; 36208Svbart@nginx.com ssize_t offset; 37208Svbart@nginx.com nxt_uint_t line; 38208Svbart@nginx.com nxt_uint_t column; 3944Svbart@nginx.com } nxt_controller_response_t; 4044Svbart@nginx.com 4144Svbart@nginx.com 42248Svbart@nginx.com static void nxt_controller_process_new_port_handler(nxt_task_t *task, 43248Svbart@nginx.com nxt_port_recv_msg_t *msg); 44662Smax.romanov@nginx.com static void nxt_controller_send_current_conf(nxt_task_t *task); 45662Smax.romanov@nginx.com static void nxt_controller_router_ready_handler(nxt_task_t *task, 46662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 47249Svbart@nginx.com static nxt_int_t nxt_controller_conf_default(void); 48249Svbart@nginx.com static void nxt_controller_conf_init_handler(nxt_task_t *task, 49249Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 50249Svbart@nginx.com static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, 51249Svbart@nginx.com nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data); 52248Svbart@nginx.com 5320Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 5420Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 5562Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 5620Sigor@sysoev.ru uintptr_t data); 5720Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 5820Sigor@sysoev.ru void *data); 5920Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 6020Sigor@sysoev.ru void *data); 6127Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 6227Svbart@nginx.com void *data); 6327Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 6427Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 6527Svbart@nginx.com void *data); 6627Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 6727Svbart@nginx.com void *data); 6820Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 6920Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 7020Sigor@sysoev.ru 7127Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 72417Svbart@nginx.com nxt_http_field_t *field, uintptr_t data); 7327Svbart@nginx.com 7427Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 75140Svbart@nginx.com nxt_controller_request_t *req); 76*774Svbart@nginx.com static void nxt_controller_process_config(nxt_task_t *task, 77*774Svbart@nginx.com nxt_controller_request_t *req, nxt_str_t *path); 78*774Svbart@nginx.com #if (NXT_TLS) 79*774Svbart@nginx.com static void nxt_controller_process_cert(nxt_task_t *task, 80*774Svbart@nginx.com nxt_controller_request_t *req, nxt_str_t *path); 81*774Svbart@nginx.com static void nxt_controller_process_cert_save(nxt_task_t *task, 82*774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 83*774Svbart@nginx.com static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name); 84*774Svbart@nginx.com #endif 85238Svbart@nginx.com static void nxt_controller_conf_handler(nxt_task_t *task, 86238Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 87314Svbart@nginx.com static void nxt_controller_conf_store(nxt_task_t *task, 88314Svbart@nginx.com nxt_conf_value_t *conf); 89140Svbart@nginx.com static void nxt_controller_response(nxt_task_t *task, 90140Svbart@nginx.com nxt_controller_request_t *req, nxt_controller_response_t *resp); 91208Svbart@nginx.com static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, 92208Svbart@nginx.com struct tm *tm, size_t size, const char *format); 9327Svbart@nginx.com 9427Svbart@nginx.com 95417Svbart@nginx.com static nxt_http_field_proc_t nxt_controller_request_fields[] = { 9627Svbart@nginx.com { nxt_string("Content-Length"), 9727Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 9827Svbart@nginx.com }; 9927Svbart@nginx.com 100417Svbart@nginx.com static nxt_lvlhsh_t nxt_controller_fields_hash; 10127Svbart@nginx.com 102314Svbart@nginx.com static nxt_uint_t nxt_controller_listening; 103662Smax.romanov@nginx.com static nxt_uint_t nxt_controller_router_ready; 104238Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 105238Svbart@nginx.com static nxt_queue_t nxt_controller_waiting_requests; 10627Svbart@nginx.com 10720Sigor@sysoev.ru 10820Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 10927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 11027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 11120Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 11220Sigor@sysoev.ru 11320Sigor@sysoev.ru 114320Smax.romanov@nginx.com nxt_port_handlers_t nxt_controller_process_port_handlers = { 115662Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 116662Smax.romanov@nginx.com .new_port = nxt_controller_process_new_port_handler, 117662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 118662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 119662Smax.romanov@nginx.com .process_ready = nxt_controller_router_ready_handler, 120662Smax.romanov@nginx.com .data = nxt_port_data_handler, 121662Smax.romanov@nginx.com .remove_pid = nxt_port_remove_pid_handler, 122662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 123662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 124248Svbart@nginx.com }; 125248Svbart@nginx.com 126248Svbart@nginx.com 12720Sigor@sysoev.ru nxt_int_t 128141Smax.romanov@nginx.com nxt_controller_start(nxt_task_t *task, void *data) 12920Sigor@sysoev.ru { 130417Svbart@nginx.com nxt_mp_t *mp; 131417Svbart@nginx.com nxt_int_t ret; 132417Svbart@nginx.com nxt_str_t *json; 133417Svbart@nginx.com nxt_runtime_t *rt; 134417Svbart@nginx.com nxt_conf_value_t *conf; 135417Svbart@nginx.com nxt_event_engine_t *engine; 136417Svbart@nginx.com nxt_conf_validation_t vldt; 137*774Svbart@nginx.com nxt_controller_init_t *init; 13827Svbart@nginx.com 139141Smax.romanov@nginx.com rt = task->thread->runtime; 140141Smax.romanov@nginx.com 141337Sigor@sysoev.ru engine = task->thread->engine; 142337Sigor@sysoev.ru 143337Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 144337Sigor@sysoev.ru if (nxt_slow_path(engine->mem_pool == NULL)) { 145337Sigor@sysoev.ru return NXT_ERROR; 146337Sigor@sysoev.ru } 147337Sigor@sysoev.ru 148417Svbart@nginx.com ret = nxt_http_fields_hash(&nxt_controller_fields_hash, rt->mem_pool, 149417Svbart@nginx.com nxt_controller_request_fields, 150417Svbart@nginx.com nxt_nitems(nxt_controller_request_fields)); 151417Svbart@nginx.com 152417Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 15327Svbart@nginx.com return NXT_ERROR; 15427Svbart@nginx.com } 15527Svbart@nginx.com 156248Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 15727Svbart@nginx.com 158*774Svbart@nginx.com init = data; 159*774Svbart@nginx.com 160*774Svbart@nginx.com #if (NXT_TLS) 161314Svbart@nginx.com 162*774Svbart@nginx.com if (init->certs != NULL) { 163*774Svbart@nginx.com nxt_cert_info_init(task, init->certs); 164*774Svbart@nginx.com nxt_cert_store_release(init->certs); 165*774Svbart@nginx.com } 166*774Svbart@nginx.com 167*774Svbart@nginx.com #endif 168*774Svbart@nginx.com 169*774Svbart@nginx.com json = &init->conf; 170*774Svbart@nginx.com 171*774Svbart@nginx.com if (json->start == NULL) { 172314Svbart@nginx.com return NXT_OK; 173314Svbart@nginx.com } 174314Svbart@nginx.com 175314Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 176314Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 177314Svbart@nginx.com return NXT_ERROR; 178314Svbart@nginx.com } 179314Svbart@nginx.com 180314Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, json); 181314Svbart@nginx.com nxt_free(json->start); 182314Svbart@nginx.com 183314Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 184564Svbart@nginx.com nxt_alert(task, "failed to restore previous configuration: " 185564Svbart@nginx.com "file is corrupted or not enough memory"); 186314Svbart@nginx.com 187314Svbart@nginx.com nxt_mp_destroy(mp); 188314Svbart@nginx.com return NXT_OK; 189314Svbart@nginx.com } 190314Svbart@nginx.com 191357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 192314Svbart@nginx.com 193357Svbart@nginx.com vldt.pool = nxt_mp_create(1024, 128, 256, 32); 194357Svbart@nginx.com if (nxt_slow_path(vldt.pool == NULL)) { 195357Svbart@nginx.com return NXT_ERROR; 196314Svbart@nginx.com } 197314Svbart@nginx.com 198357Svbart@nginx.com vldt.conf = conf; 199357Svbart@nginx.com 200357Svbart@nginx.com ret = nxt_conf_validate(&vldt); 201357Svbart@nginx.com 202357Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 203357Svbart@nginx.com 204357Svbart@nginx.com if (ret == NXT_DECLINED) { 205564Svbart@nginx.com nxt_alert(task, "the previous configuration is invalid: %V", 206564Svbart@nginx.com &vldt.error); 207357Svbart@nginx.com 208357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 209357Svbart@nginx.com nxt_mp_destroy(mp); 210357Svbart@nginx.com 211357Svbart@nginx.com return NXT_OK; 212357Svbart@nginx.com } 213357Svbart@nginx.com 214357Svbart@nginx.com /* ret == NXT_ERROR */ 215357Svbart@nginx.com 216357Svbart@nginx.com return NXT_ERROR; 217357Svbart@nginx.com } 218357Svbart@nginx.com 219357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 220314Svbart@nginx.com 221314Svbart@nginx.com nxt_controller_conf.root = conf; 222314Svbart@nginx.com nxt_controller_conf.pool = mp; 223314Svbart@nginx.com 224248Svbart@nginx.com return NXT_OK; 225248Svbart@nginx.com } 226248Svbart@nginx.com 227248Svbart@nginx.com 228248Svbart@nginx.com static void 229248Svbart@nginx.com nxt_controller_process_new_port_handler(nxt_task_t *task, 230248Svbart@nginx.com nxt_port_recv_msg_t *msg) 231248Svbart@nginx.com { 232662Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 233662Smax.romanov@nginx.com 234662Smax.romanov@nginx.com if (msg->u.new_port->type != NXT_PROCESS_ROUTER 235662Smax.romanov@nginx.com || !nxt_controller_router_ready) 236662Smax.romanov@nginx.com { 237662Smax.romanov@nginx.com return; 238662Smax.romanov@nginx.com } 239662Smax.romanov@nginx.com 240662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 241662Smax.romanov@nginx.com } 242662Smax.romanov@nginx.com 243662Smax.romanov@nginx.com 244662Smax.romanov@nginx.com static void 245662Smax.romanov@nginx.com nxt_controller_send_current_conf(nxt_task_t *task) 246662Smax.romanov@nginx.com { 247249Svbart@nginx.com nxt_int_t rc; 248248Svbart@nginx.com nxt_runtime_t *rt; 249248Svbart@nginx.com nxt_conf_value_t *conf; 250248Svbart@nginx.com 251249Svbart@nginx.com conf = nxt_controller_conf.root; 252249Svbart@nginx.com 253249Svbart@nginx.com if (conf != NULL) { 254249Svbart@nginx.com rc = nxt_controller_conf_send(task, conf, 255249Svbart@nginx.com nxt_controller_conf_init_handler, NULL); 25644Svbart@nginx.com 257249Svbart@nginx.com if (nxt_fast_path(rc == NXT_OK)) { 258249Svbart@nginx.com return; 259249Svbart@nginx.com } 260249Svbart@nginx.com 261249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 262249Svbart@nginx.com 263249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 264249Svbart@nginx.com nxt_abort(); 265249Svbart@nginx.com } 26644Svbart@nginx.com } 26744Svbart@nginx.com 268249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 269248Svbart@nginx.com nxt_abort(); 27044Svbart@nginx.com } 27144Svbart@nginx.com 272248Svbart@nginx.com rt = task->thread->runtime; 273140Svbart@nginx.com 274248Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { 275248Svbart@nginx.com nxt_abort(); 276248Svbart@nginx.com } 277314Svbart@nginx.com 278314Svbart@nginx.com nxt_controller_listening = 1; 27920Sigor@sysoev.ru } 28020Sigor@sysoev.ru 28120Sigor@sysoev.ru 282662Smax.romanov@nginx.com static void 283662Smax.romanov@nginx.com nxt_controller_router_ready_handler(nxt_task_t *task, 284662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg) 285662Smax.romanov@nginx.com { 286662Smax.romanov@nginx.com nxt_port_t *router_port; 287662Smax.romanov@nginx.com nxt_runtime_t *rt; 288662Smax.romanov@nginx.com 289662Smax.romanov@nginx.com rt = task->thread->runtime; 290662Smax.romanov@nginx.com 291662Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 292662Smax.romanov@nginx.com 293662Smax.romanov@nginx.com nxt_controller_router_ready = 1; 294662Smax.romanov@nginx.com 295662Smax.romanov@nginx.com if (router_port != NULL) { 296662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 297662Smax.romanov@nginx.com } 298662Smax.romanov@nginx.com } 299662Smax.romanov@nginx.com 300662Smax.romanov@nginx.com 301249Svbart@nginx.com static nxt_int_t 302249Svbart@nginx.com nxt_controller_conf_default(void) 303249Svbart@nginx.com { 304249Svbart@nginx.com nxt_mp_t *mp; 305249Svbart@nginx.com nxt_conf_value_t *conf; 306249Svbart@nginx.com 307249Svbart@nginx.com static const nxt_str_t json 308249Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 309249Svbart@nginx.com 310249Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 311249Svbart@nginx.com 312249Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 313249Svbart@nginx.com return NXT_ERROR; 314249Svbart@nginx.com } 315249Svbart@nginx.com 316249Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 317249Svbart@nginx.com 318249Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 319249Svbart@nginx.com return NXT_ERROR; 320249Svbart@nginx.com } 321249Svbart@nginx.com 322249Svbart@nginx.com nxt_controller_conf.root = conf; 323249Svbart@nginx.com nxt_controller_conf.pool = mp; 324249Svbart@nginx.com 325249Svbart@nginx.com return NXT_OK; 326249Svbart@nginx.com } 327249Svbart@nginx.com 328249Svbart@nginx.com 329249Svbart@nginx.com static void 330249Svbart@nginx.com nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 331249Svbart@nginx.com void *data) 332249Svbart@nginx.com { 333314Svbart@nginx.com nxt_runtime_t *rt; 334314Svbart@nginx.com 335249Svbart@nginx.com if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { 336564Svbart@nginx.com nxt_alert(task, "failed to apply previous configuration"); 337314Svbart@nginx.com 338249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 339249Svbart@nginx.com 340249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 341249Svbart@nginx.com nxt_abort(); 342249Svbart@nginx.com } 343249Svbart@nginx.com } 344314Svbart@nginx.com 345314Svbart@nginx.com if (nxt_controller_listening == 0) { 346314Svbart@nginx.com rt = task->thread->runtime; 347314Svbart@nginx.com 348314Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) 349314Svbart@nginx.com == NULL)) 350314Svbart@nginx.com { 351314Svbart@nginx.com nxt_abort(); 352314Svbart@nginx.com } 353314Svbart@nginx.com 354314Svbart@nginx.com nxt_controller_listening = 1; 355314Svbart@nginx.com } 356249Svbart@nginx.com } 357249Svbart@nginx.com 358249Svbart@nginx.com 359249Svbart@nginx.com static nxt_int_t 360249Svbart@nginx.com nxt_controller_conf_send(nxt_task_t *task, nxt_conf_value_t *conf, 361249Svbart@nginx.com nxt_port_rpc_handler_t handler, void *data) 362249Svbart@nginx.com { 363249Svbart@nginx.com size_t size; 364249Svbart@nginx.com uint32_t stream; 365249Svbart@nginx.com nxt_int_t rc; 366249Svbart@nginx.com nxt_buf_t *b; 367249Svbart@nginx.com nxt_port_t *router_port, *controller_port; 368249Svbart@nginx.com nxt_runtime_t *rt; 369249Svbart@nginx.com 370249Svbart@nginx.com rt = task->thread->runtime; 371249Svbart@nginx.com 372249Svbart@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 373249Svbart@nginx.com 374662Smax.romanov@nginx.com if (nxt_slow_path(router_port == NULL || !nxt_controller_router_ready)) { 375249Svbart@nginx.com return NXT_DECLINED; 376249Svbart@nginx.com } 377249Svbart@nginx.com 378249Svbart@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 379249Svbart@nginx.com 380249Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 381249Svbart@nginx.com 382249Svbart@nginx.com b = nxt_port_mmap_get_buf(task, router_port, size); 383379Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 384379Smax.romanov@nginx.com return NXT_ERROR; 385379Smax.romanov@nginx.com } 386249Svbart@nginx.com 387249Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 388249Svbart@nginx.com 389249Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, controller_port, 390249Svbart@nginx.com handler, handler, 391249Svbart@nginx.com router_port->pid, data); 392249Svbart@nginx.com 393645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 394645Svbart@nginx.com return NXT_ERROR; 395645Svbart@nginx.com } 396645Svbart@nginx.com 397249Svbart@nginx.com rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_DATA_LAST, -1, 398249Svbart@nginx.com stream, controller_port->id, b); 399249Svbart@nginx.com 400249Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 401249Svbart@nginx.com nxt_port_rpc_cancel(task, controller_port, stream); 402249Svbart@nginx.com return NXT_ERROR; 403249Svbart@nginx.com } 404249Svbart@nginx.com 405249Svbart@nginx.com return NXT_OK; 406249Svbart@nginx.com } 407249Svbart@nginx.com 408249Svbart@nginx.com 40920Sigor@sysoev.ru nxt_int_t 41020Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 41120Sigor@sysoev.ru { 41220Sigor@sysoev.ru nxt_sockaddr_t *sa; 41320Sigor@sysoev.ru nxt_listen_socket_t *ls; 41420Sigor@sysoev.ru 41520Sigor@sysoev.ru sa = rt->controller_listen; 41620Sigor@sysoev.ru 41765Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 41820Sigor@sysoev.ru if (ls == NULL) { 41920Sigor@sysoev.ru return NXT_ERROR; 42020Sigor@sysoev.ru } 42120Sigor@sysoev.ru 42220Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 42320Sigor@sysoev.ru sa->socklen, sa->length); 42420Sigor@sysoev.ru if (ls->sockaddr == NULL) { 42520Sigor@sysoev.ru return NXT_ERROR; 42620Sigor@sysoev.ru } 42720Sigor@sysoev.ru 42820Sigor@sysoev.ru ls->sockaddr->type = sa->type; 429312Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 43020Sigor@sysoev.ru 431359Sigor@sysoev.ru nxt_listen_socket_remote_size(ls); 43220Sigor@sysoev.ru 43320Sigor@sysoev.ru ls->socket = -1; 43420Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 43520Sigor@sysoev.ru ls->read_after_accept = 1; 43620Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 43720Sigor@sysoev.ru 43820Sigor@sysoev.ru #if 0 43920Sigor@sysoev.ru /* STUB */ 44065Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 44120Sigor@sysoev.ru if (wq == NULL) { 44220Sigor@sysoev.ru return NXT_ERROR; 44320Sigor@sysoev.ru } 44420Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 44520Sigor@sysoev.ru /**/ 44620Sigor@sysoev.ru 44720Sigor@sysoev.ru ls->work_queue = wq; 44820Sigor@sysoev.ru #endif 44920Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 45020Sigor@sysoev.ru 45120Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 45220Sigor@sysoev.ru return NXT_ERROR; 45320Sigor@sysoev.ru } 45420Sigor@sysoev.ru 45520Sigor@sysoev.ru rt->controller_socket = ls; 45620Sigor@sysoev.ru 45720Sigor@sysoev.ru return NXT_OK; 45820Sigor@sysoev.ru } 45920Sigor@sysoev.ru 46020Sigor@sysoev.ru 46120Sigor@sysoev.ru static void 46220Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 46320Sigor@sysoev.ru { 46427Svbart@nginx.com nxt_buf_t *b; 46562Sigor@sysoev.ru nxt_conn_t *c; 46627Svbart@nginx.com nxt_event_engine_t *engine; 46727Svbart@nginx.com nxt_controller_request_t *r; 46820Sigor@sysoev.ru 46920Sigor@sysoev.ru c = obj; 47020Sigor@sysoev.ru 47120Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 47220Sigor@sysoev.ru 47365Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 47427Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 47527Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 47627Svbart@nginx.com return; 47727Svbart@nginx.com } 47827Svbart@nginx.com 479140Svbart@nginx.com r->conn = c; 480140Svbart@nginx.com 48160Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 48260Svbart@nginx.com != NXT_OK)) 48360Svbart@nginx.com { 48460Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 48560Svbart@nginx.com return; 48660Svbart@nginx.com } 48727Svbart@nginx.com 48820Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 48920Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 49020Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 49120Sigor@sysoev.ru return; 49220Sigor@sysoev.ru } 49320Sigor@sysoev.ru 49420Sigor@sysoev.ru c->read = b; 49527Svbart@nginx.com c->socket.data = r; 49620Sigor@sysoev.ru c->socket.read_ready = 1; 49720Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 49820Sigor@sysoev.ru 49920Sigor@sysoev.ru engine = task->thread->engine; 50020Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 50127Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 50220Sigor@sysoev.ru 50362Sigor@sysoev.ru nxt_conn_read(engine, c); 50420Sigor@sysoev.ru } 50520Sigor@sysoev.ru 50620Sigor@sysoev.ru 50720Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 50820Sigor@sysoev.ru nxt_aligned(64) = 50920Sigor@sysoev.ru { 51056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 51156Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 51256Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 51320Sigor@sysoev.ru 51456Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 51556Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 51656Sigor@sysoev.ru .timer_data = 60 * 1000, 51720Sigor@sysoev.ru }; 51820Sigor@sysoev.ru 51920Sigor@sysoev.ru 52020Sigor@sysoev.ru static void 52120Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 52220Sigor@sysoev.ru { 52327Svbart@nginx.com size_t preread; 52427Svbart@nginx.com nxt_buf_t *b; 52527Svbart@nginx.com nxt_int_t rc; 52662Sigor@sysoev.ru nxt_conn_t *c; 52727Svbart@nginx.com nxt_controller_request_t *r; 52820Sigor@sysoev.ru 52920Sigor@sysoev.ru c = obj; 53027Svbart@nginx.com r = data; 53120Sigor@sysoev.ru 53220Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 53320Sigor@sysoev.ru 53427Svbart@nginx.com nxt_queue_remove(&c->link); 53527Svbart@nginx.com nxt_queue_self(&c->link); 53627Svbart@nginx.com 53727Svbart@nginx.com b = c->read; 53827Svbart@nginx.com 53927Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 54027Svbart@nginx.com 54127Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 54227Svbart@nginx.com 54327Svbart@nginx.com if (rc == NXT_AGAIN) { 54427Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 54527Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 54627Svbart@nginx.com nxt_controller_conn_close(task, c, r); 54727Svbart@nginx.com return; 54827Svbart@nginx.com } 54927Svbart@nginx.com 55062Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 55127Svbart@nginx.com return; 55227Svbart@nginx.com } 55327Svbart@nginx.com 55427Svbart@nginx.com /* rc == NXT_ERROR */ 55527Svbart@nginx.com 55627Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 55727Svbart@nginx.com 55827Svbart@nginx.com nxt_controller_conn_close(task, c, r); 55927Svbart@nginx.com return; 56027Svbart@nginx.com } 56127Svbart@nginx.com 562417Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash, 563417Svbart@nginx.com r); 56460Svbart@nginx.com 56560Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 56660Svbart@nginx.com nxt_controller_conn_close(task, c, r); 56760Svbart@nginx.com return; 56860Svbart@nginx.com } 56960Svbart@nginx.com 57027Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 57127Svbart@nginx.com 57227Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 573107Svbart@nginx.com "body length: %uz, preread: %uz", 57427Svbart@nginx.com r->length, preread); 57527Svbart@nginx.com 57627Svbart@nginx.com if (preread >= r->length) { 577140Svbart@nginx.com nxt_controller_process_request(task, r); 57827Svbart@nginx.com return; 57927Svbart@nginx.com } 58027Svbart@nginx.com 58127Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 58227Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 58327Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 58427Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 58527Svbart@nginx.com return; 58627Svbart@nginx.com } 58727Svbart@nginx.com 58827Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 58927Svbart@nginx.com 59027Svbart@nginx.com c->read = b; 59127Svbart@nginx.com } 59227Svbart@nginx.com 59327Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 59427Svbart@nginx.com 59562Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 59620Sigor@sysoev.ru } 59720Sigor@sysoev.ru 59820Sigor@sysoev.ru 59920Sigor@sysoev.ru static nxt_msec_t 60062Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 60120Sigor@sysoev.ru { 60220Sigor@sysoev.ru return (nxt_msec_t) data; 60320Sigor@sysoev.ru } 60420Sigor@sysoev.ru 60520Sigor@sysoev.ru 60620Sigor@sysoev.ru static void 60720Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 60820Sigor@sysoev.ru { 60962Sigor@sysoev.ru nxt_conn_t *c; 61020Sigor@sysoev.ru 61120Sigor@sysoev.ru c = obj; 61220Sigor@sysoev.ru 61320Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 61420Sigor@sysoev.ru 61527Svbart@nginx.com nxt_controller_conn_close(task, c, data); 61620Sigor@sysoev.ru } 61720Sigor@sysoev.ru 61820Sigor@sysoev.ru 61920Sigor@sysoev.ru static void 62020Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 62120Sigor@sysoev.ru { 62262Sigor@sysoev.ru nxt_timer_t *timer; 62362Sigor@sysoev.ru nxt_conn_t *c; 62420Sigor@sysoev.ru 62562Sigor@sysoev.ru timer = obj; 62620Sigor@sysoev.ru 62762Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 62820Sigor@sysoev.ru c->socket.timedout = 1; 62920Sigor@sysoev.ru c->socket.closed = 1; 63020Sigor@sysoev.ru 63120Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 63220Sigor@sysoev.ru 63327Svbart@nginx.com nxt_controller_conn_close(task, c, data); 63427Svbart@nginx.com } 63527Svbart@nginx.com 63627Svbart@nginx.com 63727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 63827Svbart@nginx.com nxt_aligned(64) = 63927Svbart@nginx.com { 64056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 64156Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 64256Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 64327Svbart@nginx.com 64456Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 64556Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 64656Sigor@sysoev.ru .timer_data = 60 * 1000, 64756Sigor@sysoev.ru .timer_autoreset = 1, 64827Svbart@nginx.com }; 64927Svbart@nginx.com 65027Svbart@nginx.com 65127Svbart@nginx.com static void 65227Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 65327Svbart@nginx.com { 654107Svbart@nginx.com size_t read; 655107Svbart@nginx.com nxt_buf_t *b; 656107Svbart@nginx.com nxt_conn_t *c; 657107Svbart@nginx.com nxt_controller_request_t *r; 65827Svbart@nginx.com 65927Svbart@nginx.com c = obj; 660107Svbart@nginx.com r = data; 66127Svbart@nginx.com b = c->read; 66227Svbart@nginx.com 663107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 66427Svbart@nginx.com 665107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 666107Svbart@nginx.com read, r->length); 66727Svbart@nginx.com 668107Svbart@nginx.com if (read >= r->length) { 669140Svbart@nginx.com nxt_controller_process_request(task, r); 67027Svbart@nginx.com return; 67127Svbart@nginx.com } 67227Svbart@nginx.com 67362Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 67427Svbart@nginx.com } 67527Svbart@nginx.com 67627Svbart@nginx.com 67727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 67827Svbart@nginx.com nxt_aligned(64) = 67927Svbart@nginx.com { 68056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 68156Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 68227Svbart@nginx.com 68356Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 68456Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 68556Sigor@sysoev.ru .timer_data = 60 * 1000, 68656Sigor@sysoev.ru .timer_autoreset = 1, 68727Svbart@nginx.com }; 68827Svbart@nginx.com 68927Svbart@nginx.com 69027Svbart@nginx.com static void 69127Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 69227Svbart@nginx.com { 69362Sigor@sysoev.ru nxt_buf_t *b; 69462Sigor@sysoev.ru nxt_conn_t *c; 69527Svbart@nginx.com 69627Svbart@nginx.com c = obj; 69727Svbart@nginx.com 69827Svbart@nginx.com nxt_debug(task, "controller conn write"); 69927Svbart@nginx.com 70027Svbart@nginx.com b = c->write; 70127Svbart@nginx.com 70227Svbart@nginx.com if (b->mem.pos != b->mem.free) { 70362Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 70427Svbart@nginx.com return; 70527Svbart@nginx.com } 70627Svbart@nginx.com 70727Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 70827Svbart@nginx.com 70927Svbart@nginx.com nxt_controller_conn_close(task, c, data); 71027Svbart@nginx.com } 71127Svbart@nginx.com 71227Svbart@nginx.com 71327Svbart@nginx.com static void 71427Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 71527Svbart@nginx.com { 71662Sigor@sysoev.ru nxt_conn_t *c; 71727Svbart@nginx.com 71827Svbart@nginx.com c = obj; 71927Svbart@nginx.com 72027Svbart@nginx.com nxt_debug(task, "controller conn write error"); 72127Svbart@nginx.com 72227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 72327Svbart@nginx.com } 72427Svbart@nginx.com 72527Svbart@nginx.com 72627Svbart@nginx.com static void 72727Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 72827Svbart@nginx.com { 72962Sigor@sysoev.ru nxt_conn_t *c; 73062Sigor@sysoev.ru nxt_timer_t *timer; 73127Svbart@nginx.com 73262Sigor@sysoev.ru timer = obj; 73327Svbart@nginx.com 73462Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 73527Svbart@nginx.com c->socket.timedout = 1; 73627Svbart@nginx.com c->socket.closed = 1; 73727Svbart@nginx.com 73827Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 73927Svbart@nginx.com 74027Svbart@nginx.com nxt_controller_conn_close(task, c, data); 74120Sigor@sysoev.ru } 74220Sigor@sysoev.ru 74320Sigor@sysoev.ru 74420Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 74520Sigor@sysoev.ru nxt_aligned(64) = 74620Sigor@sysoev.ru { 74756Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 74820Sigor@sysoev.ru }; 74920Sigor@sysoev.ru 75020Sigor@sysoev.ru 75120Sigor@sysoev.ru static void 75220Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 75320Sigor@sysoev.ru { 75462Sigor@sysoev.ru nxt_conn_t *c; 75520Sigor@sysoev.ru 75620Sigor@sysoev.ru c = obj; 75720Sigor@sysoev.ru 75820Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 75920Sigor@sysoev.ru 76027Svbart@nginx.com nxt_queue_remove(&c->link); 76127Svbart@nginx.com 76220Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 76320Sigor@sysoev.ru 76462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 76520Sigor@sysoev.ru } 76620Sigor@sysoev.ru 76720Sigor@sysoev.ru 76820Sigor@sysoev.ru static void 76920Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 77020Sigor@sysoev.ru { 77162Sigor@sysoev.ru nxt_conn_t *c; 77220Sigor@sysoev.ru 77320Sigor@sysoev.ru c = obj; 77420Sigor@sysoev.ru 77520Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 77620Sigor@sysoev.ru 777337Sigor@sysoev.ru nxt_sockaddr_cache_free(task->thread->engine, c); 778337Sigor@sysoev.ru 779386Sigor@sysoev.ru nxt_conn_free(task, c); 78020Sigor@sysoev.ru } 78127Svbart@nginx.com 78227Svbart@nginx.com 78327Svbart@nginx.com static nxt_int_t 78460Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 785417Svbart@nginx.com uintptr_t data) 78627Svbart@nginx.com { 78727Svbart@nginx.com off_t length; 78827Svbart@nginx.com nxt_controller_request_t *r; 78927Svbart@nginx.com 79027Svbart@nginx.com r = ctx; 79127Svbart@nginx.com 792417Svbart@nginx.com length = nxt_off_t_parse(field->value, field->value_length); 79327Svbart@nginx.com 794710Svbart@nginx.com if (nxt_fast_path(length >= 0)) { 795107Svbart@nginx.com 796107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 797417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, 798417Svbart@nginx.com "Content-Length is too big"); 799107Svbart@nginx.com return NXT_ERROR; 800107Svbart@nginx.com } 80127Svbart@nginx.com 80227Svbart@nginx.com r->length = length; 80327Svbart@nginx.com return NXT_OK; 80427Svbart@nginx.com } 80527Svbart@nginx.com 806417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid"); 80727Svbart@nginx.com 80827Svbart@nginx.com return NXT_ERROR; 80927Svbart@nginx.com } 81027Svbart@nginx.com 81127Svbart@nginx.com 81227Svbart@nginx.com static void 813140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 81427Svbart@nginx.com { 815*774Svbart@nginx.com uint32_t i, count; 816*774Svbart@nginx.com nxt_str_t path; 817*774Svbart@nginx.com nxt_conn_t *c; 818*774Svbart@nginx.com nxt_conf_value_t *value; 819*774Svbart@nginx.com nxt_controller_response_t resp; 820*774Svbart@nginx.com #if (NXT_TLS) 821*774Svbart@nginx.com nxt_conf_value_t *certs; 822*774Svbart@nginx.com 823*774Svbart@nginx.com static nxt_str_t certificates = nxt_string("certificates"); 824*774Svbart@nginx.com #endif 825*774Svbart@nginx.com static nxt_str_t config = nxt_string("config"); 826*774Svbart@nginx.com 827*774Svbart@nginx.com c = req->conn; 828*774Svbart@nginx.com path = req->parser.path; 829*774Svbart@nginx.com 830*774Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 831*774Svbart@nginx.com path.length--; 832*774Svbart@nginx.com } 833*774Svbart@nginx.com 834*774Svbart@nginx.com if (nxt_str_start(&path, "/config", 7) 835*774Svbart@nginx.com && (path.length == 7 || path.start[7] == '/')) 836*774Svbart@nginx.com { 837*774Svbart@nginx.com if (path.length == 7) { 838*774Svbart@nginx.com path.length = 1; 839*774Svbart@nginx.com 840*774Svbart@nginx.com } else { 841*774Svbart@nginx.com path.length -= 7; 842*774Svbart@nginx.com path.start += 7; 843*774Svbart@nginx.com } 844*774Svbart@nginx.com 845*774Svbart@nginx.com nxt_controller_process_config(task, req, &path); 846*774Svbart@nginx.com return; 847*774Svbart@nginx.com } 848*774Svbart@nginx.com 849*774Svbart@nginx.com #if (NXT_TLS) 850*774Svbart@nginx.com 851*774Svbart@nginx.com if (nxt_str_start(&path, "/certificates", 13) 852*774Svbart@nginx.com && (path.length == 13 || path.start[13] == '/')) 853*774Svbart@nginx.com { 854*774Svbart@nginx.com if (path.length == 13) { 855*774Svbart@nginx.com path.length = 1; 856*774Svbart@nginx.com 857*774Svbart@nginx.com } else { 858*774Svbart@nginx.com path.length -= 13; 859*774Svbart@nginx.com path.start += 13; 860*774Svbart@nginx.com } 861*774Svbart@nginx.com 862*774Svbart@nginx.com nxt_controller_process_cert(task, req, &path); 863*774Svbart@nginx.com return; 864*774Svbart@nginx.com } 865*774Svbart@nginx.com 866*774Svbart@nginx.com #endif 867*774Svbart@nginx.com 868*774Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 869*774Svbart@nginx.com 870*774Svbart@nginx.com if (path.length == 1 && path.start[0] == '/') { 871*774Svbart@nginx.com 872*774Svbart@nginx.com if (!nxt_str_eq(&req->parser.method, "GET", 3)) { 873*774Svbart@nginx.com goto invalid_method; 874*774Svbart@nginx.com } 875*774Svbart@nginx.com 876*774Svbart@nginx.com count = 1; 877*774Svbart@nginx.com #if (NXT_TLS) 878*774Svbart@nginx.com count++; 879*774Svbart@nginx.com #endif 880*774Svbart@nginx.com 881*774Svbart@nginx.com value = nxt_conf_create_object(c->mem_pool, count); 882*774Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 883*774Svbart@nginx.com goto alloc_fail; 884*774Svbart@nginx.com } 885*774Svbart@nginx.com 886*774Svbart@nginx.com i = 0; 887*774Svbart@nginx.com 888*774Svbart@nginx.com #if (NXT_TLS) 889*774Svbart@nginx.com certs = nxt_cert_info_get_all(c->mem_pool); 890*774Svbart@nginx.com if (nxt_slow_path(certs == NULL)) { 891*774Svbart@nginx.com goto alloc_fail; 892*774Svbart@nginx.com } 893*774Svbart@nginx.com 894*774Svbart@nginx.com nxt_conf_set_member(value, &certificates, certs, i++); 895*774Svbart@nginx.com #endif 896*774Svbart@nginx.com 897*774Svbart@nginx.com nxt_conf_set_member(value, &config, nxt_controller_conf.root, i); 898*774Svbart@nginx.com 899*774Svbart@nginx.com resp.status = 200; 900*774Svbart@nginx.com resp.conf = value; 901*774Svbart@nginx.com 902*774Svbart@nginx.com nxt_controller_response(task, req, &resp); 903*774Svbart@nginx.com return; 904*774Svbart@nginx.com } 905*774Svbart@nginx.com 906*774Svbart@nginx.com resp.status = 404; 907*774Svbart@nginx.com resp.title = (u_char *) "Value doesn't exist."; 908*774Svbart@nginx.com resp.offset = -1; 909*774Svbart@nginx.com 910*774Svbart@nginx.com nxt_controller_response(task, req, &resp); 911*774Svbart@nginx.com return; 912*774Svbart@nginx.com 913*774Svbart@nginx.com invalid_method: 914*774Svbart@nginx.com 915*774Svbart@nginx.com resp.status = 405; 916*774Svbart@nginx.com resp.title = (u_char *) "Invalid method."; 917*774Svbart@nginx.com resp.offset = -1; 918*774Svbart@nginx.com 919*774Svbart@nginx.com nxt_controller_response(task, req, &resp); 920*774Svbart@nginx.com return; 921*774Svbart@nginx.com 922*774Svbart@nginx.com alloc_fail: 923*774Svbart@nginx.com 924*774Svbart@nginx.com resp.status = 500; 925*774Svbart@nginx.com resp.title = (u_char *) "Memory allocation failed."; 926*774Svbart@nginx.com resp.offset = -1; 927*774Svbart@nginx.com 928*774Svbart@nginx.com nxt_controller_response(task, req, &resp); 929*774Svbart@nginx.com return; 930*774Svbart@nginx.com } 931*774Svbart@nginx.com 932*774Svbart@nginx.com 933*774Svbart@nginx.com static void 934*774Svbart@nginx.com nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, 935*774Svbart@nginx.com nxt_str_t *path) 936*774Svbart@nginx.com { 93765Sigor@sysoev.ru nxt_mp_t *mp; 93851Svbart@nginx.com nxt_int_t rc; 939140Svbart@nginx.com nxt_conn_t *c; 94051Svbart@nginx.com nxt_buf_mem_t *mbuf; 941106Svbart@nginx.com nxt_conf_op_t *ops; 942106Svbart@nginx.com nxt_conf_value_t *value; 943357Svbart@nginx.com nxt_conf_validation_t vldt; 944208Svbart@nginx.com nxt_conf_json_error_t error; 94544Svbart@nginx.com nxt_controller_response_t resp; 94644Svbart@nginx.com 94751Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 94851Svbart@nginx.com 949*774Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 950632Svbart@nginx.com 951*774Svbart@nginx.com c = req->conn; 95244Svbart@nginx.com 95344Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 95446Svbart@nginx.com 955*774Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, path); 95651Svbart@nginx.com 95751Svbart@nginx.com if (value == NULL) { 958208Svbart@nginx.com goto not_found; 95951Svbart@nginx.com } 96051Svbart@nginx.com 961208Svbart@nginx.com resp.status = 200; 962106Svbart@nginx.com resp.conf = value; 96346Svbart@nginx.com 964208Svbart@nginx.com nxt_controller_response(task, req, &resp); 965208Svbart@nginx.com return; 96651Svbart@nginx.com } 96751Svbart@nginx.com 96851Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 96946Svbart@nginx.com 970238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 971238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 972238Svbart@nginx.com return; 973238Svbart@nginx.com } 974238Svbart@nginx.com 97565Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 97651Svbart@nginx.com 97751Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 978208Svbart@nginx.com goto alloc_fail; 97946Svbart@nginx.com } 98046Svbart@nginx.com 98151Svbart@nginx.com mbuf = &c->read->mem; 98251Svbart@nginx.com 983208Svbart@nginx.com nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); 984208Svbart@nginx.com 985208Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 98651Svbart@nginx.com 98751Svbart@nginx.com if (value == NULL) { 98865Sigor@sysoev.ru nxt_mp_destroy(mp); 989208Svbart@nginx.com 990208Svbart@nginx.com if (error.pos == NULL) { 991208Svbart@nginx.com goto alloc_fail; 992208Svbart@nginx.com } 993208Svbart@nginx.com 994208Svbart@nginx.com resp.status = 400; 995208Svbart@nginx.com resp.title = (u_char *) "Invalid JSON."; 996357Svbart@nginx.com resp.detail.length = nxt_strlen(error.detail); 997357Svbart@nginx.com resp.detail.start = error.detail; 998208Svbart@nginx.com resp.offset = error.pos - mbuf->pos; 999208Svbart@nginx.com 1000208Svbart@nginx.com nxt_conf_json_position(mbuf->pos, error.pos, 1001208Svbart@nginx.com &resp.line, &resp.column); 1002208Svbart@nginx.com 1003208Svbart@nginx.com nxt_controller_response(task, req, &resp); 1004208Svbart@nginx.com return; 100551Svbart@nginx.com } 100651Svbart@nginx.com 1007*774Svbart@nginx.com if (path->length != 1) { 1008106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 1009106Svbart@nginx.com nxt_controller_conf.root, 1010*774Svbart@nginx.com path, value); 101146Svbart@nginx.com 101251Svbart@nginx.com if (rc != NXT_OK) { 1013619Svbart@nginx.com nxt_mp_destroy(mp); 1014619Svbart@nginx.com 101551Svbart@nginx.com if (rc == NXT_DECLINED) { 1016208Svbart@nginx.com goto not_found; 101751Svbart@nginx.com } 101846Svbart@nginx.com 1019208Svbart@nginx.com goto alloc_fail; 102051Svbart@nginx.com } 102151Svbart@nginx.com 1022106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 102351Svbart@nginx.com 102451Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 102565Sigor@sysoev.ru nxt_mp_destroy(mp); 1026208Svbart@nginx.com goto alloc_fail; 102751Svbart@nginx.com } 102846Svbart@nginx.com } 102944Svbart@nginx.com 1030357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 1031357Svbart@nginx.com 1032357Svbart@nginx.com vldt.conf = value; 1033357Svbart@nginx.com vldt.pool = c->mem_pool; 1034357Svbart@nginx.com 1035357Svbart@nginx.com rc = nxt_conf_validate(&vldt); 1036357Svbart@nginx.com 1037357Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1038121Svbart@nginx.com nxt_mp_destroy(mp); 1039357Svbart@nginx.com 1040357Svbart@nginx.com if (rc == NXT_DECLINED) { 1041357Svbart@nginx.com resp.detail = vldt.error; 1042357Svbart@nginx.com goto invalid_conf; 1043357Svbart@nginx.com } 1044357Svbart@nginx.com 1045357Svbart@nginx.com /* rc == NXT_ERROR */ 1046357