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> 1220Sigor@sysoev.ru 1320Sigor@sysoev.ru 1427Svbart@nginx.com typedef struct { 15106Svbart@nginx.com nxt_conf_value_t *root; 16106Svbart@nginx.com nxt_mp_t *pool; 1744Svbart@nginx.com } nxt_controller_conf_t; 1844Svbart@nginx.com 1944Svbart@nginx.com 2044Svbart@nginx.com typedef struct { 2127Svbart@nginx.com nxt_http_request_parse_t parser; 2227Svbart@nginx.com size_t length; 2344Svbart@nginx.com nxt_controller_conf_t conf; 24140Svbart@nginx.com nxt_conn_t *conn; 25140Svbart@nginx.com nxt_queue_link_t link; 2627Svbart@nginx.com } nxt_controller_request_t; 2727Svbart@nginx.com 2827Svbart@nginx.com 2944Svbart@nginx.com typedef struct { 30208Svbart@nginx.com nxt_uint_t status; 31106Svbart@nginx.com nxt_conf_value_t *conf; 32208Svbart@nginx.com 33208Svbart@nginx.com u_char *title; 34357Svbart@nginx.com nxt_str_t detail; 35208Svbart@nginx.com ssize_t offset; 36208Svbart@nginx.com nxt_uint_t line; 37208Svbart@nginx.com nxt_uint_t column; 3844Svbart@nginx.com } nxt_controller_response_t; 3944Svbart@nginx.com 4044Svbart@nginx.com 41248Svbart@nginx.com static void nxt_controller_process_new_port_handler(nxt_task_t *task, 42248Svbart@nginx.com nxt_port_recv_msg_t *msg); 43662Smax.romanov@nginx.com static void nxt_controller_send_current_conf(nxt_task_t *task); 44662Smax.romanov@nginx.com static void nxt_controller_router_ready_handler(nxt_task_t *task, 45662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 46249Svbart@nginx.com static nxt_int_t nxt_controller_conf_default(void); 47249Svbart@nginx.com static void nxt_controller_conf_init_handler(nxt_task_t *task, 48249Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 49249Svbart@nginx.com static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, 50249Svbart@nginx.com nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data); 51248Svbart@nginx.com 5220Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 5320Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 5462Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 5520Sigor@sysoev.ru uintptr_t data); 5620Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 5720Sigor@sysoev.ru void *data); 5820Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 5920Sigor@sysoev.ru void *data); 6027Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 6127Svbart@nginx.com void *data); 6227Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 6327Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 6427Svbart@nginx.com void *data); 6527Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 6627Svbart@nginx.com void *data); 6720Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 6820Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 6920Sigor@sysoev.ru 7027Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 71417Svbart@nginx.com nxt_http_field_t *field, uintptr_t data); 7227Svbart@nginx.com 7327Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 74140Svbart@nginx.com nxt_controller_request_t *req); 75238Svbart@nginx.com static void nxt_controller_conf_handler(nxt_task_t *task, 76238Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 77314Svbart@nginx.com static void nxt_controller_conf_store(nxt_task_t *task, 78314Svbart@nginx.com nxt_conf_value_t *conf); 79140Svbart@nginx.com static void nxt_controller_response(nxt_task_t *task, 80140Svbart@nginx.com nxt_controller_request_t *req, nxt_controller_response_t *resp); 81208Svbart@nginx.com static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, 82208Svbart@nginx.com struct tm *tm, size_t size, const char *format); 8327Svbart@nginx.com 8427Svbart@nginx.com 85417Svbart@nginx.com static nxt_http_field_proc_t nxt_controller_request_fields[] = { 8627Svbart@nginx.com { nxt_string("Content-Length"), 8727Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 8827Svbart@nginx.com }; 8927Svbart@nginx.com 90417Svbart@nginx.com static nxt_lvlhsh_t nxt_controller_fields_hash; 9127Svbart@nginx.com 92314Svbart@nginx.com static nxt_uint_t nxt_controller_listening; 93662Smax.romanov@nginx.com static nxt_uint_t nxt_controller_router_ready; 94238Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 95238Svbart@nginx.com static nxt_queue_t nxt_controller_waiting_requests; 9627Svbart@nginx.com 9720Sigor@sysoev.ru 9820Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 9927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 10027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 10120Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 10220Sigor@sysoev.ru 10320Sigor@sysoev.ru 104320Smax.romanov@nginx.com nxt_port_handlers_t nxt_controller_process_port_handlers = { 105662Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 106662Smax.romanov@nginx.com .new_port = nxt_controller_process_new_port_handler, 107662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 108662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 109662Smax.romanov@nginx.com .process_ready = nxt_controller_router_ready_handler, 110662Smax.romanov@nginx.com .data = nxt_port_data_handler, 111662Smax.romanov@nginx.com .remove_pid = nxt_port_remove_pid_handler, 112662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 113662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 114248Svbart@nginx.com }; 115248Svbart@nginx.com 116248Svbart@nginx.com 11720Sigor@sysoev.ru nxt_int_t 118141Smax.romanov@nginx.com nxt_controller_start(nxt_task_t *task, void *data) 11920Sigor@sysoev.ru { 120417Svbart@nginx.com nxt_mp_t *mp; 121417Svbart@nginx.com nxt_int_t ret; 122417Svbart@nginx.com nxt_str_t *json; 123417Svbart@nginx.com nxt_runtime_t *rt; 124417Svbart@nginx.com nxt_conf_value_t *conf; 125417Svbart@nginx.com nxt_event_engine_t *engine; 126417Svbart@nginx.com nxt_conf_validation_t vldt; 12727Svbart@nginx.com 128141Smax.romanov@nginx.com rt = task->thread->runtime; 129141Smax.romanov@nginx.com 130337Sigor@sysoev.ru engine = task->thread->engine; 131337Sigor@sysoev.ru 132337Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 133337Sigor@sysoev.ru if (nxt_slow_path(engine->mem_pool == NULL)) { 134337Sigor@sysoev.ru return NXT_ERROR; 135337Sigor@sysoev.ru } 136337Sigor@sysoev.ru 137417Svbart@nginx.com ret = nxt_http_fields_hash(&nxt_controller_fields_hash, rt->mem_pool, 138417Svbart@nginx.com nxt_controller_request_fields, 139417Svbart@nginx.com nxt_nitems(nxt_controller_request_fields)); 140417Svbart@nginx.com 141417Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14227Svbart@nginx.com return NXT_ERROR; 14327Svbart@nginx.com } 14427Svbart@nginx.com 145248Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 14627Svbart@nginx.com 147314Svbart@nginx.com json = data; 148314Svbart@nginx.com 149314Svbart@nginx.com if (json->length == 0) { 150314Svbart@nginx.com return NXT_OK; 151314Svbart@nginx.com } 152314Svbart@nginx.com 153314Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 154314Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 155314Svbart@nginx.com return NXT_ERROR; 156314Svbart@nginx.com } 157314Svbart@nginx.com 158314Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, json); 159314Svbart@nginx.com nxt_free(json->start); 160314Svbart@nginx.com 161314Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 162564Svbart@nginx.com nxt_alert(task, "failed to restore previous configuration: " 163564Svbart@nginx.com "file is corrupted or not enough memory"); 164314Svbart@nginx.com 165314Svbart@nginx.com nxt_mp_destroy(mp); 166314Svbart@nginx.com return NXT_OK; 167314Svbart@nginx.com } 168314Svbart@nginx.com 169357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 170314Svbart@nginx.com 171357Svbart@nginx.com vldt.pool = nxt_mp_create(1024, 128, 256, 32); 172357Svbart@nginx.com if (nxt_slow_path(vldt.pool == NULL)) { 173357Svbart@nginx.com return NXT_ERROR; 174314Svbart@nginx.com } 175314Svbart@nginx.com 176357Svbart@nginx.com vldt.conf = conf; 177357Svbart@nginx.com 178357Svbart@nginx.com ret = nxt_conf_validate(&vldt); 179357Svbart@nginx.com 180357Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 181357Svbart@nginx.com 182357Svbart@nginx.com if (ret == NXT_DECLINED) { 183564Svbart@nginx.com nxt_alert(task, "the previous configuration is invalid: %V", 184564Svbart@nginx.com &vldt.error); 185357Svbart@nginx.com 186357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 187357Svbart@nginx.com nxt_mp_destroy(mp); 188357Svbart@nginx.com 189357Svbart@nginx.com return NXT_OK; 190357Svbart@nginx.com } 191357Svbart@nginx.com 192357Svbart@nginx.com /* ret == NXT_ERROR */ 193357Svbart@nginx.com 194357Svbart@nginx.com return NXT_ERROR; 195357Svbart@nginx.com } 196357Svbart@nginx.com 197357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 198314Svbart@nginx.com 199314Svbart@nginx.com nxt_controller_conf.root = conf; 200314Svbart@nginx.com nxt_controller_conf.pool = mp; 201314Svbart@nginx.com 202248Svbart@nginx.com return NXT_OK; 203248Svbart@nginx.com } 204248Svbart@nginx.com 205248Svbart@nginx.com 206248Svbart@nginx.com static void 207248Svbart@nginx.com nxt_controller_process_new_port_handler(nxt_task_t *task, 208248Svbart@nginx.com nxt_port_recv_msg_t *msg) 209248Svbart@nginx.com { 210662Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 211662Smax.romanov@nginx.com 212662Smax.romanov@nginx.com if (msg->u.new_port->type != NXT_PROCESS_ROUTER 213662Smax.romanov@nginx.com || !nxt_controller_router_ready) 214662Smax.romanov@nginx.com { 215662Smax.romanov@nginx.com return; 216662Smax.romanov@nginx.com } 217662Smax.romanov@nginx.com 218662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 219662Smax.romanov@nginx.com } 220662Smax.romanov@nginx.com 221662Smax.romanov@nginx.com 222662Smax.romanov@nginx.com static void 223662Smax.romanov@nginx.com nxt_controller_send_current_conf(nxt_task_t *task) 224662Smax.romanov@nginx.com { 225249Svbart@nginx.com nxt_int_t rc; 226248Svbart@nginx.com nxt_runtime_t *rt; 227248Svbart@nginx.com nxt_conf_value_t *conf; 228248Svbart@nginx.com 229249Svbart@nginx.com conf = nxt_controller_conf.root; 230249Svbart@nginx.com 231249Svbart@nginx.com if (conf != NULL) { 232249Svbart@nginx.com rc = nxt_controller_conf_send(task, conf, 233249Svbart@nginx.com nxt_controller_conf_init_handler, NULL); 23444Svbart@nginx.com 235249Svbart@nginx.com if (nxt_fast_path(rc == NXT_OK)) { 236249Svbart@nginx.com return; 237249Svbart@nginx.com } 238249Svbart@nginx.com 239249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 240249Svbart@nginx.com 241249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 242249Svbart@nginx.com nxt_abort(); 243249Svbart@nginx.com } 24444Svbart@nginx.com } 24544Svbart@nginx.com 246249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 247248Svbart@nginx.com nxt_abort(); 24844Svbart@nginx.com } 24944Svbart@nginx.com 250248Svbart@nginx.com rt = task->thread->runtime; 251140Svbart@nginx.com 252248Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { 253248Svbart@nginx.com nxt_abort(); 254248Svbart@nginx.com } 255314Svbart@nginx.com 256314Svbart@nginx.com nxt_controller_listening = 1; 25720Sigor@sysoev.ru } 25820Sigor@sysoev.ru 25920Sigor@sysoev.ru 260662Smax.romanov@nginx.com static void 261662Smax.romanov@nginx.com nxt_controller_router_ready_handler(nxt_task_t *task, 262662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg) 263662Smax.romanov@nginx.com { 264662Smax.romanov@nginx.com nxt_port_t *router_port; 265662Smax.romanov@nginx.com nxt_runtime_t *rt; 266662Smax.romanov@nginx.com 267662Smax.romanov@nginx.com rt = task->thread->runtime; 268662Smax.romanov@nginx.com 269662Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 270662Smax.romanov@nginx.com 271662Smax.romanov@nginx.com nxt_controller_router_ready = 1; 272662Smax.romanov@nginx.com 273662Smax.romanov@nginx.com if (router_port != NULL) { 274662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 275662Smax.romanov@nginx.com } 276662Smax.romanov@nginx.com } 277662Smax.romanov@nginx.com 278662Smax.romanov@nginx.com 279249Svbart@nginx.com static nxt_int_t 280249Svbart@nginx.com nxt_controller_conf_default(void) 281249Svbart@nginx.com { 282249Svbart@nginx.com nxt_mp_t *mp; 283249Svbart@nginx.com nxt_conf_value_t *conf; 284249Svbart@nginx.com 285249Svbart@nginx.com static const nxt_str_t json 286249Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 287249Svbart@nginx.com 288249Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 289249Svbart@nginx.com 290249Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 291249Svbart@nginx.com return NXT_ERROR; 292249Svbart@nginx.com } 293249Svbart@nginx.com 294249Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 295249Svbart@nginx.com 296249Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 297249Svbart@nginx.com return NXT_ERROR; 298249Svbart@nginx.com } 299249Svbart@nginx.com 300249Svbart@nginx.com nxt_controller_conf.root = conf; 301249Svbart@nginx.com nxt_controller_conf.pool = mp; 302249Svbart@nginx.com 303249Svbart@nginx.com return NXT_OK; 304249Svbart@nginx.com } 305249Svbart@nginx.com 306249Svbart@nginx.com 307249Svbart@nginx.com static void 308249Svbart@nginx.com nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 309249Svbart@nginx.com void *data) 310249Svbart@nginx.com { 311314Svbart@nginx.com nxt_runtime_t *rt; 312314Svbart@nginx.com 313249Svbart@nginx.com if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { 314564Svbart@nginx.com nxt_alert(task, "failed to apply previous configuration"); 315314Svbart@nginx.com 316249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 317249Svbart@nginx.com 318249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 319249Svbart@nginx.com nxt_abort(); 320249Svbart@nginx.com } 321249Svbart@nginx.com } 322314Svbart@nginx.com 323314Svbart@nginx.com if (nxt_controller_listening == 0) { 324314Svbart@nginx.com rt = task->thread->runtime; 325314Svbart@nginx.com 326314Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) 327314Svbart@nginx.com == NULL)) 328314Svbart@nginx.com { 329314Svbart@nginx.com nxt_abort(); 330314Svbart@nginx.com } 331314Svbart@nginx.com 332314Svbart@nginx.com nxt_controller_listening = 1; 333314Svbart@nginx.com } 334249Svbart@nginx.com } 335249Svbart@nginx.com 336249Svbart@nginx.com 337249Svbart@nginx.com static nxt_int_t 338249Svbart@nginx.com nxt_controller_conf_send(nxt_task_t *task, nxt_conf_value_t *conf, 339249Svbart@nginx.com nxt_port_rpc_handler_t handler, void *data) 340249Svbart@nginx.com { 341249Svbart@nginx.com size_t size; 342249Svbart@nginx.com uint32_t stream; 343249Svbart@nginx.com nxt_int_t rc; 344249Svbart@nginx.com nxt_buf_t *b; 345249Svbart@nginx.com nxt_port_t *router_port, *controller_port; 346249Svbart@nginx.com nxt_runtime_t *rt; 347249Svbart@nginx.com 348249Svbart@nginx.com rt = task->thread->runtime; 349249Svbart@nginx.com 350249Svbart@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 351249Svbart@nginx.com 352662Smax.romanov@nginx.com if (nxt_slow_path(router_port == NULL || !nxt_controller_router_ready)) { 353249Svbart@nginx.com return NXT_DECLINED; 354249Svbart@nginx.com } 355249Svbart@nginx.com 356249Svbart@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 357249Svbart@nginx.com 358249Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 359249Svbart@nginx.com 360249Svbart@nginx.com b = nxt_port_mmap_get_buf(task, router_port, size); 361379Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 362379Smax.romanov@nginx.com return NXT_ERROR; 363379Smax.romanov@nginx.com } 364249Svbart@nginx.com 365249Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 366249Svbart@nginx.com 367249Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, controller_port, 368249Svbart@nginx.com handler, handler, 369249Svbart@nginx.com router_port->pid, data); 370249Svbart@nginx.com 371645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 372645Svbart@nginx.com return NXT_ERROR; 373645Svbart@nginx.com } 374645Svbart@nginx.com 375249Svbart@nginx.com rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_DATA_LAST, -1, 376249Svbart@nginx.com stream, controller_port->id, b); 377249Svbart@nginx.com 378249Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 379249Svbart@nginx.com nxt_port_rpc_cancel(task, controller_port, stream); 380249Svbart@nginx.com return NXT_ERROR; 381249Svbart@nginx.com } 382249Svbart@nginx.com 383249Svbart@nginx.com return NXT_OK; 384249Svbart@nginx.com } 385249Svbart@nginx.com 386249Svbart@nginx.com 38720Sigor@sysoev.ru nxt_int_t 38820Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 38920Sigor@sysoev.ru { 39020Sigor@sysoev.ru nxt_sockaddr_t *sa; 39120Sigor@sysoev.ru nxt_listen_socket_t *ls; 39220Sigor@sysoev.ru 39320Sigor@sysoev.ru sa = rt->controller_listen; 39420Sigor@sysoev.ru 39565Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 39620Sigor@sysoev.ru if (ls == NULL) { 39720Sigor@sysoev.ru return NXT_ERROR; 39820Sigor@sysoev.ru } 39920Sigor@sysoev.ru 40020Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 40120Sigor@sysoev.ru sa->socklen, sa->length); 40220Sigor@sysoev.ru if (ls->sockaddr == NULL) { 40320Sigor@sysoev.ru return NXT_ERROR; 40420Sigor@sysoev.ru } 40520Sigor@sysoev.ru 40620Sigor@sysoev.ru ls->sockaddr->type = sa->type; 407312Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 40820Sigor@sysoev.ru 409359Sigor@sysoev.ru nxt_listen_socket_remote_size(ls); 41020Sigor@sysoev.ru 41120Sigor@sysoev.ru ls->socket = -1; 41220Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 41320Sigor@sysoev.ru ls->read_after_accept = 1; 41420Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 41520Sigor@sysoev.ru 41620Sigor@sysoev.ru #if 0 41720Sigor@sysoev.ru /* STUB */ 41865Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 41920Sigor@sysoev.ru if (wq == NULL) { 42020Sigor@sysoev.ru return NXT_ERROR; 42120Sigor@sysoev.ru } 42220Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 42320Sigor@sysoev.ru /**/ 42420Sigor@sysoev.ru 42520Sigor@sysoev.ru ls->work_queue = wq; 42620Sigor@sysoev.ru #endif 42720Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 42820Sigor@sysoev.ru 42920Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 43020Sigor@sysoev.ru return NXT_ERROR; 43120Sigor@sysoev.ru } 43220Sigor@sysoev.ru 43320Sigor@sysoev.ru rt->controller_socket = ls; 43420Sigor@sysoev.ru 43520Sigor@sysoev.ru return NXT_OK; 43620Sigor@sysoev.ru } 43720Sigor@sysoev.ru 43820Sigor@sysoev.ru 43920Sigor@sysoev.ru static void 44020Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 44120Sigor@sysoev.ru { 44227Svbart@nginx.com nxt_buf_t *b; 44362Sigor@sysoev.ru nxt_conn_t *c; 44427Svbart@nginx.com nxt_event_engine_t *engine; 44527Svbart@nginx.com nxt_controller_request_t *r; 44620Sigor@sysoev.ru 44720Sigor@sysoev.ru c = obj; 44820Sigor@sysoev.ru 44920Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 45020Sigor@sysoev.ru 45165Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 45227Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 45327Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 45427Svbart@nginx.com return; 45527Svbart@nginx.com } 45627Svbart@nginx.com 457140Svbart@nginx.com r->conn = c; 458140Svbart@nginx.com 45960Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 46060Svbart@nginx.com != NXT_OK)) 46160Svbart@nginx.com { 46260Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 46360Svbart@nginx.com return; 46460Svbart@nginx.com } 46527Svbart@nginx.com 46620Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 46720Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 46820Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 46920Sigor@sysoev.ru return; 47020Sigor@sysoev.ru } 47120Sigor@sysoev.ru 47220Sigor@sysoev.ru c->read = b; 47327Svbart@nginx.com c->socket.data = r; 47420Sigor@sysoev.ru c->socket.read_ready = 1; 47520Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 47620Sigor@sysoev.ru 47720Sigor@sysoev.ru engine = task->thread->engine; 47820Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 47927Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 48020Sigor@sysoev.ru 48162Sigor@sysoev.ru nxt_conn_read(engine, c); 48220Sigor@sysoev.ru } 48320Sigor@sysoev.ru 48420Sigor@sysoev.ru 48520Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 48620Sigor@sysoev.ru nxt_aligned(64) = 48720Sigor@sysoev.ru { 48856Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 48956Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 49056Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 49120Sigor@sysoev.ru 49256Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 49356Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 49456Sigor@sysoev.ru .timer_data = 60 * 1000, 49520Sigor@sysoev.ru }; 49620Sigor@sysoev.ru 49720Sigor@sysoev.ru 49820Sigor@sysoev.ru static void 49920Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 50020Sigor@sysoev.ru { 50127Svbart@nginx.com size_t preread; 50227Svbart@nginx.com nxt_buf_t *b; 50327Svbart@nginx.com nxt_int_t rc; 50462Sigor@sysoev.ru nxt_conn_t *c; 50527Svbart@nginx.com nxt_controller_request_t *r; 50620Sigor@sysoev.ru 50720Sigor@sysoev.ru c = obj; 50827Svbart@nginx.com r = data; 50920Sigor@sysoev.ru 51020Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 51120Sigor@sysoev.ru 51227Svbart@nginx.com nxt_queue_remove(&c->link); 51327Svbart@nginx.com nxt_queue_self(&c->link); 51427Svbart@nginx.com 51527Svbart@nginx.com b = c->read; 51627Svbart@nginx.com 51727Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 51827Svbart@nginx.com 51927Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 52027Svbart@nginx.com 52127Svbart@nginx.com if (rc == NXT_AGAIN) { 52227Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 52327Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 52427Svbart@nginx.com nxt_controller_conn_close(task, c, r); 52527Svbart@nginx.com return; 52627Svbart@nginx.com } 52727Svbart@nginx.com 52862Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 52927Svbart@nginx.com return; 53027Svbart@nginx.com } 53127Svbart@nginx.com 53227Svbart@nginx.com /* rc == NXT_ERROR */ 53327Svbart@nginx.com 53427Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 53527Svbart@nginx.com 53627Svbart@nginx.com nxt_controller_conn_close(task, c, r); 53727Svbart@nginx.com return; 53827Svbart@nginx.com } 53927Svbart@nginx.com 540417Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash, 541417Svbart@nginx.com r); 54260Svbart@nginx.com 54360Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 54460Svbart@nginx.com nxt_controller_conn_close(task, c, r); 54560Svbart@nginx.com return; 54660Svbart@nginx.com } 54760Svbart@nginx.com 54827Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 54927Svbart@nginx.com 55027Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 551107Svbart@nginx.com "body length: %uz, preread: %uz", 55227Svbart@nginx.com r->length, preread); 55327Svbart@nginx.com 55427Svbart@nginx.com if (preread >= r->length) { 555140Svbart@nginx.com nxt_controller_process_request(task, r); 55627Svbart@nginx.com return; 55727Svbart@nginx.com } 55827Svbart@nginx.com 55927Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 56027Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 56127Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 56227Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 56327Svbart@nginx.com return; 56427Svbart@nginx.com } 56527Svbart@nginx.com 56627Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 56727Svbart@nginx.com 56827Svbart@nginx.com c->read = b; 56927Svbart@nginx.com } 57027Svbart@nginx.com 57127Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 57227Svbart@nginx.com 57362Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 57420Sigor@sysoev.ru } 57520Sigor@sysoev.ru 57620Sigor@sysoev.ru 57720Sigor@sysoev.ru static nxt_msec_t 57862Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 57920Sigor@sysoev.ru { 58020Sigor@sysoev.ru return (nxt_msec_t) data; 58120Sigor@sysoev.ru } 58220Sigor@sysoev.ru 58320Sigor@sysoev.ru 58420Sigor@sysoev.ru static void 58520Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 58620Sigor@sysoev.ru { 58762Sigor@sysoev.ru nxt_conn_t *c; 58820Sigor@sysoev.ru 58920Sigor@sysoev.ru c = obj; 59020Sigor@sysoev.ru 59120Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 59220Sigor@sysoev.ru 59327Svbart@nginx.com nxt_controller_conn_close(task, c, data); 59420Sigor@sysoev.ru } 59520Sigor@sysoev.ru 59620Sigor@sysoev.ru 59720Sigor@sysoev.ru static void 59820Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 59920Sigor@sysoev.ru { 60062Sigor@sysoev.ru nxt_timer_t *timer; 60162Sigor@sysoev.ru nxt_conn_t *c; 60220Sigor@sysoev.ru 60362Sigor@sysoev.ru timer = obj; 60420Sigor@sysoev.ru 60562Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 60620Sigor@sysoev.ru c->socket.timedout = 1; 60720Sigor@sysoev.ru c->socket.closed = 1; 60820Sigor@sysoev.ru 60920Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 61020Sigor@sysoev.ru 61127Svbart@nginx.com nxt_controller_conn_close(task, c, data); 61227Svbart@nginx.com } 61327Svbart@nginx.com 61427Svbart@nginx.com 61527Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 61627Svbart@nginx.com nxt_aligned(64) = 61727Svbart@nginx.com { 61856Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 61956Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 62056Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 62127Svbart@nginx.com 62256Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 62356Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 62456Sigor@sysoev.ru .timer_data = 60 * 1000, 62556Sigor@sysoev.ru .timer_autoreset = 1, 62627Svbart@nginx.com }; 62727Svbart@nginx.com 62827Svbart@nginx.com 62927Svbart@nginx.com static void 63027Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 63127Svbart@nginx.com { 632107Svbart@nginx.com size_t read; 633107Svbart@nginx.com nxt_buf_t *b; 634107Svbart@nginx.com nxt_conn_t *c; 635107Svbart@nginx.com nxt_controller_request_t *r; 63627Svbart@nginx.com 63727Svbart@nginx.com c = obj; 638107Svbart@nginx.com r = data; 63927Svbart@nginx.com b = c->read; 64027Svbart@nginx.com 641107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 64227Svbart@nginx.com 643107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 644107Svbart@nginx.com read, r->length); 64527Svbart@nginx.com 646107Svbart@nginx.com if (read >= r->length) { 647140Svbart@nginx.com nxt_controller_process_request(task, r); 64827Svbart@nginx.com return; 64927Svbart@nginx.com } 65027Svbart@nginx.com 65162Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 65227Svbart@nginx.com } 65327Svbart@nginx.com 65427Svbart@nginx.com 65527Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 65627Svbart@nginx.com nxt_aligned(64) = 65727Svbart@nginx.com { 65856Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 65956Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 66027Svbart@nginx.com 66156Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 66256Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 66356Sigor@sysoev.ru .timer_data = 60 * 1000, 66456Sigor@sysoev.ru .timer_autoreset = 1, 66527Svbart@nginx.com }; 66627Svbart@nginx.com 66727Svbart@nginx.com 66827Svbart@nginx.com static void 66927Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 67027Svbart@nginx.com { 67162Sigor@sysoev.ru nxt_buf_t *b; 67262Sigor@sysoev.ru nxt_conn_t *c; 67327Svbart@nginx.com 67427Svbart@nginx.com c = obj; 67527Svbart@nginx.com 67627Svbart@nginx.com nxt_debug(task, "controller conn write"); 67727Svbart@nginx.com 67827Svbart@nginx.com b = c->write; 67927Svbart@nginx.com 68027Svbart@nginx.com if (b->mem.pos != b->mem.free) { 68162Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 68227Svbart@nginx.com return; 68327Svbart@nginx.com } 68427Svbart@nginx.com 68527Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 68627Svbart@nginx.com 68727Svbart@nginx.com nxt_controller_conn_close(task, c, data); 68827Svbart@nginx.com } 68927Svbart@nginx.com 69027Svbart@nginx.com 69127Svbart@nginx.com static void 69227Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 69327Svbart@nginx.com { 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 error"); 69927Svbart@nginx.com 70027Svbart@nginx.com nxt_controller_conn_close(task, c, data); 70127Svbart@nginx.com } 70227Svbart@nginx.com 70327Svbart@nginx.com 70427Svbart@nginx.com static void 70527Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 70627Svbart@nginx.com { 70762Sigor@sysoev.ru nxt_conn_t *c; 70862Sigor@sysoev.ru nxt_timer_t *timer; 70927Svbart@nginx.com 71062Sigor@sysoev.ru timer = obj; 71127Svbart@nginx.com 71262Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 71327Svbart@nginx.com c->socket.timedout = 1; 71427Svbart@nginx.com c->socket.closed = 1; 71527Svbart@nginx.com 71627Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 71727Svbart@nginx.com 71827Svbart@nginx.com nxt_controller_conn_close(task, c, data); 71920Sigor@sysoev.ru } 72020Sigor@sysoev.ru 72120Sigor@sysoev.ru 72220Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 72320Sigor@sysoev.ru nxt_aligned(64) = 72420Sigor@sysoev.ru { 72556Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 72620Sigor@sysoev.ru }; 72720Sigor@sysoev.ru 72820Sigor@sysoev.ru 72920Sigor@sysoev.ru static void 73020Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 73120Sigor@sysoev.ru { 73262Sigor@sysoev.ru nxt_conn_t *c; 73320Sigor@sysoev.ru 73420Sigor@sysoev.ru c = obj; 73520Sigor@sysoev.ru 73620Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 73720Sigor@sysoev.ru 73827Svbart@nginx.com nxt_queue_remove(&c->link); 73927Svbart@nginx.com 74020Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 74120Sigor@sysoev.ru 74262Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 74320Sigor@sysoev.ru } 74420Sigor@sysoev.ru 74520Sigor@sysoev.ru 74620Sigor@sysoev.ru static void 74720Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 74820Sigor@sysoev.ru { 74962Sigor@sysoev.ru nxt_conn_t *c; 75020Sigor@sysoev.ru 75120Sigor@sysoev.ru c = obj; 75220Sigor@sysoev.ru 75320Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 75420Sigor@sysoev.ru 755337Sigor@sysoev.ru nxt_sockaddr_cache_free(task->thread->engine, c); 756337Sigor@sysoev.ru 757386Sigor@sysoev.ru nxt_conn_free(task, c); 75820Sigor@sysoev.ru } 75927Svbart@nginx.com 76027Svbart@nginx.com 76127Svbart@nginx.com static nxt_int_t 76260Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 763417Svbart@nginx.com uintptr_t data) 76427Svbart@nginx.com { 76527Svbart@nginx.com off_t length; 76627Svbart@nginx.com nxt_controller_request_t *r; 76727Svbart@nginx.com 76827Svbart@nginx.com r = ctx; 76927Svbart@nginx.com 770417Svbart@nginx.com length = nxt_off_t_parse(field->value, field->value_length); 77127Svbart@nginx.com 772*710Svbart@nginx.com if (nxt_fast_path(length >= 0)) { 773107Svbart@nginx.com 774107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 775417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, 776417Svbart@nginx.com "Content-Length is too big"); 777107Svbart@nginx.com return NXT_ERROR; 778107Svbart@nginx.com } 77927Svbart@nginx.com 78027Svbart@nginx.com r->length = length; 78127Svbart@nginx.com return NXT_OK; 78227Svbart@nginx.com } 78327Svbart@nginx.com 784417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid"); 78527Svbart@nginx.com 78627Svbart@nginx.com return NXT_ERROR; 78727Svbart@nginx.com } 78827Svbart@nginx.com 78927Svbart@nginx.com 79027Svbart@nginx.com static void 791140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 79227Svbart@nginx.com { 79365Sigor@sysoev.ru nxt_mp_t *mp; 79451Svbart@nginx.com nxt_int_t rc; 79546Svbart@nginx.com nxt_str_t path; 796140Svbart@nginx.com nxt_conn_t *c; 79751Svbart@nginx.com nxt_buf_mem_t *mbuf; 798106Svbart@nginx.com nxt_conf_op_t *ops; 799106Svbart@nginx.com nxt_conf_value_t *value; 800357Svbart@nginx.com nxt_conf_validation_t vldt; 801208Svbart@nginx.com nxt_conf_json_error_t error; 80244Svbart@nginx.com nxt_controller_response_t resp; 80344Svbart@nginx.com 80451Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 80551Svbart@nginx.com 806140Svbart@nginx.com c = req->conn; 807112Smax.romanov@nginx.com path = req->parser.path; 80851Svbart@nginx.com 809632Svbart@nginx.com if (nxt_str_start(&path, "/config", 7)) { 810632Svbart@nginx.com 811632Svbart@nginx.com if (path.length == 7) { 812632Svbart@nginx.com path.length = 1; 813632Svbart@nginx.com 814632Svbart@nginx.com } else if (path.start[7] == '/') { 815632Svbart@nginx.com path.length -= 7; 816632Svbart@nginx.com path.start += 7; 817632Svbart@nginx.com } 818632Svbart@nginx.com } 819632Svbart@nginx.com 82051Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 82151Svbart@nginx.com path.length--; 82251Svbart@nginx.com } 82351Svbart@nginx.com 82444Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 82544Svbart@nginx.com 82644Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 82746Svbart@nginx.com 828106Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, &path); 82951Svbart@nginx.com 83051Svbart@nginx.com if (value == NULL) { 831208Svbart@nginx.com goto not_found; 83251Svbart@nginx.com } 83351Svbart@nginx.com 834208Svbart@nginx.com resp.status = 200; 835106Svbart@nginx.com resp.conf = value; 83646Svbart@nginx.com 837208Svbart@nginx.com nxt_controller_response(task, req, &resp); 838208Svbart@nginx.com return; 83951Svbart@nginx.com } 84051Svbart@nginx.com 84151Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 84246Svbart@nginx.com 843238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 844238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 845238Svbart@nginx.com return; 846238Svbart@nginx.com } 847238Svbart@nginx.com 84865Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 84951Svbart@nginx.com 85051Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 851208Svbart@nginx.com goto alloc_fail; 85246Svbart@nginx.com } 85346Svbart@nginx.com 85451Svbart@nginx.com mbuf = &c->read->mem; 85551Svbart@nginx.com 856208Svbart@nginx.com nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); 857208Svbart@nginx.com 858208Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 85951Svbart@nginx.com 86051Svbart@nginx.com if (value == NULL) { 86165Sigor@sysoev.ru nxt_mp_destroy(mp); 862208Svbart@nginx.com 863208Svbart@nginx.com if (error.pos == NULL) { 864208Svbart@nginx.com goto alloc_fail; 865208Svbart@nginx.com } 866208Svbart@nginx.com 867208Svbart@nginx.com resp.status = 400; 868208Svbart@nginx.com resp.title = (u_char *) "Invalid JSON."; 869357Svbart@nginx.com resp.detail.length = nxt_strlen(error.detail); 870357Svbart@nginx.com resp.detail.start = error.detail; 871208Svbart@nginx.com resp.offset = error.pos - mbuf->pos; 872208Svbart@nginx.com 873208Svbart@nginx.com nxt_conf_json_position(mbuf->pos, error.pos, 874208Svbart@nginx.com &resp.line, &resp.column); 875208Svbart@nginx.com 876208Svbart@nginx.com nxt_controller_response(task, req, &resp); 877208Svbart@nginx.com return; 87851Svbart@nginx.com } 87951Svbart@nginx.com 88051Svbart@nginx.com if (path.length != 1) { 881106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 882106Svbart@nginx.com nxt_controller_conf.root, 883106Svbart@nginx.com &path, value); 88446Svbart@nginx.com 88551Svbart@nginx.com if (rc != NXT_OK) { 886619Svbart@nginx.com nxt_mp_destroy(mp); 887619Svbart@nginx.com 88851Svbart@nginx.com if (rc == NXT_DECLINED) { 889208Svbart@nginx.com goto not_found; 89051Svbart@nginx.com } 89146Svbart@nginx.com 892208Svbart@nginx.com goto alloc_fail; 89351Svbart@nginx.com } 89451Svbart@nginx.com 895106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 89651Svbart@nginx.com 89751Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 89865Sigor@sysoev.ru nxt_mp_destroy(mp); 899208Svbart@nginx.com goto alloc_fail; 90051Svbart@nginx.com } 90146Svbart@nginx.com } 90244Svbart@nginx.com 903357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 904357Svbart@nginx.com 905357Svbart@nginx.com vldt.conf = value; 906357Svbart@nginx.com vldt.pool = c->mem_pool; 907357Svbart@nginx.com 908357Svbart@nginx.com rc = nxt_conf_validate(&vldt); 909357Svbart@nginx.com 910357Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 911121Svbart@nginx.com nxt_mp_destroy(mp); 912357Svbart@nginx.com 913357Svbart@nginx.com if (rc == NXT_DECLINED) { 914357Svbart@nginx.com resp.detail = vldt.error; 915357Svbart@nginx.com goto invalid_conf; 916357Svbart@nginx.com } 917357Svbart@nginx.com 918357Svbart@nginx.com /* rc == NXT_ERROR */ 919357Svbart@nginx.com goto alloc_fail; 920116Svbart@nginx.com } 921116Svbart@nginx.com 922249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 923249Svbart@nginx.com nxt_controller_conf_handler, req); 924247Svbart@nginx.com 925247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 926121Svbart@nginx.com nxt_mp_destroy(mp); 927247Svbart@nginx.com 928247Svbart@nginx.com if (rc == NXT_DECLINED) { 929247Svbart@nginx.com goto no_router; 930247Svbart@nginx.com } 931247Svbart@nginx.com 932247Svbart@nginx.com /* rc == NXT_ERROR */ 933208Svbart@nginx.com goto alloc_fail; 934121Svbart@nginx.com } 935121Svbart@nginx.com 936249Svbart@nginx.com req->conf.root = value; 937249Svbart@nginx.com req->conf.pool = mp; 938249Svbart@nginx.com 939249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 940249Svbart@nginx.com 941140Svbart@nginx.com return; 94251Svbart@nginx.com } 94327Svbart@nginx.com 94451Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 94551Svbart@nginx.com 946238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 947238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 948238Svbart@nginx.com return; 949238Svbart@nginx.com } 950238Svbart@nginx.com 95151Svbart@nginx.com if (path.length == 1) { 95265Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 95344Svbart@nginx.com 95451Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 955208Svbart@nginx.com goto alloc_fail; 95651Svbart@nginx.com } 95751Svbart@nginx.com 958106Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &empty_obj); 95927Svbart@nginx.com 96044Svbart@nginx.com } else { 961106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 962106Svbart@nginx.com nxt_controller_conf.root, 963106Svbart@nginx.com &path, NULL); 96451Svbart@nginx.com 96551Svbart@nginx.com if (rc != NXT_OK) { 96651Svbart@nginx.com if (rc == NXT_DECLINED) { 967208Svbart@nginx.com goto not_found; 96851Svbart@nginx.com } 96951Svbart@nginx.com 970208Svbart@nginx.com goto alloc_fail; 97151Svbart@nginx.com } 97251Svbart@nginx.com 97365Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 97451Svbart@nginx.com 97551Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 976208Svbart@nginx.com goto alloc_fail; 97751Svbart@nginx.com } 97851Svbart@nginx.com 979106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 98051Svbart@nginx.com } 98151Svbart@nginx.com 98251Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 98365Sigor@sysoev.ru nxt_mp_destroy(mp); 984208Svbart@nginx.com goto alloc_fail; 98544Svbart@nginx.com } 98644Svbart@nginx.com 987357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 988357Svbart@nginx.com 989357Svbart@nginx.com vldt.conf = value; 990357Svbart@nginx.com vldt.pool = c->mem_pool; 991357Svbart@nginx.com 992357Svbart@nginx.com rc = nxt_conf_validate(&vldt); 993357Svbart@nginx.com 994357Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 995121Svbart@nginx.com nxt_mp_destroy(mp); 996357Svbart@nginx.com 997357Svbart@nginx.com if (rc == NXT_DECLINED) { 998357Svbart@nginx.com resp.detail = vldt.error; 999357Svbart@nginx.com goto invalid_conf; 1000357Svbart@nginx.com } 1001357Svbart@nginx.com 1002357Svbart@nginx.com /* rc == NXT_ERROR */ 1003357Svbart@nginx.com goto alloc_fail; 1004116Svbart@nginx.com } 1005116Svbart@nginx.com 1006249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 1007249Svbart@nginx.com nxt_controller_conf_handler, req); 1008247Svbart@nginx.com 1009247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1010121Svbart@nginx.com nxt_mp_destroy(mp); 1011247Svbart@nginx.com 1012247Svbart@nginx.com if (rc == NXT_DECLINED) { 1013247Svbart@nginx.com goto no_router; 1014247Svbart@nginx.com } 1015247Svbart@nginx.com 1016247Svbart@nginx.com /* rc == NXT_ERROR */ 1017208Svbart@nginx.com goto alloc_fail; 1018121Svbart@nginx.com } 1019121Svbart@nginx.com 1020249Svbart@nginx.com req->conf.root = value; 1021249Svbart@nginx.com req->conf.pool = mp; 1022249Svbart@nginx.com 1023249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 1024249Svbart@nginx.com 1025140Svbart@nginx.com return; 102651Svbart@nginx.com } 102751Svbart@nginx.com 1028208Svbart@nginx.com resp.status = 405; 1029208Svbart@nginx.com resp.title = (u_char *) "Invalid method."; 1030208Svbart@nginx.com resp.offset = -1; 103151Svbart@nginx.com 1032208Svbart@nginx.com nxt_controller_response(task, req, &resp); 1033208Svbart@nginx.com return; 103451Svbart@nginx.com 1035208Svbart@nginx.com not_found: 1036208Svbart@nginx.com 1037208Svbart@nginx.com resp.status = 404; 1038208Svbart@nginx.com resp.title = (u_char *) "Value doesn't exist."; 1039208Svbart@nginx.com resp.offset = -1; 1040208Svbart@nginx.com 1041208Svbart@nginx.com nxt_controller_response(task, req, &resp); 1042208Svbart@nginx.com&