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; 34208Svbart@nginx.com u_char *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); 43249Svbart@nginx.com static nxt_int_t nxt_controller_conf_default(void); 44249Svbart@nginx.com static void nxt_controller_conf_init_handler(nxt_task_t *task, 45249Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 46249Svbart@nginx.com static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, 47249Svbart@nginx.com nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data); 48248Svbart@nginx.com 4920Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 5020Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 5162Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 5220Sigor@sysoev.ru uintptr_t data); 5320Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 5420Sigor@sysoev.ru void *data); 5520Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 5620Sigor@sysoev.ru void *data); 5727Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 5827Svbart@nginx.com void *data); 5927Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 6027Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 6127Svbart@nginx.com void *data); 6227Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 6327Svbart@nginx.com void *data); 6420Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 6520Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 6620Sigor@sysoev.ru 6727Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 6867Svbart@nginx.com nxt_http_field_t *field, nxt_log_t *log); 6927Svbart@nginx.com 7027Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 71140Svbart@nginx.com nxt_controller_request_t *req); 72238Svbart@nginx.com static void nxt_controller_conf_handler(nxt_task_t *task, 73238Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 74314Svbart@nginx.com static void nxt_controller_conf_store(nxt_task_t *task, 75314Svbart@nginx.com nxt_conf_value_t *conf); 76140Svbart@nginx.com static void nxt_controller_response(nxt_task_t *task, 77140Svbart@nginx.com nxt_controller_request_t *req, nxt_controller_response_t *resp); 78208Svbart@nginx.com static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, 79208Svbart@nginx.com struct tm *tm, size_t size, const char *format); 8027Svbart@nginx.com 8127Svbart@nginx.com 8260Svbart@nginx.com static nxt_http_fields_hash_entry_t nxt_controller_request_fields[] = { 8327Svbart@nginx.com { nxt_string("Content-Length"), 8427Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 8527Svbart@nginx.com 8627Svbart@nginx.com { nxt_null_string, NULL, 0 } 8727Svbart@nginx.com }; 8827Svbart@nginx.com 8960Svbart@nginx.com static nxt_http_fields_hash_t *nxt_controller_fields_hash; 9027Svbart@nginx.com 91314Svbart@nginx.com static nxt_uint_t nxt_controller_listening; 92238Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 93238Svbart@nginx.com static nxt_queue_t nxt_controller_waiting_requests; 9427Svbart@nginx.com 9520Sigor@sysoev.ru 9620Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 9727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 9827Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 9920Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 10020Sigor@sysoev.ru 10120Sigor@sysoev.ru 102320Smax.romanov@nginx.com nxt_port_handlers_t nxt_controller_process_port_handlers = { 103320Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 104320Smax.romanov@nginx.com .new_port = nxt_controller_process_new_port_handler, 105320Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 106320Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 107320Smax.romanov@nginx.com .data = nxt_port_data_handler, 108320Smax.romanov@nginx.com .remove_pid = nxt_port_remove_pid_handler, 109320Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 110320Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 111248Svbart@nginx.com }; 112248Svbart@nginx.com 113248Svbart@nginx.com 11420Sigor@sysoev.ru nxt_int_t 115141Smax.romanov@nginx.com nxt_controller_start(nxt_task_t *task, void *data) 11620Sigor@sysoev.ru { 117314Svbart@nginx.com nxt_mp_t *mp; 118314Svbart@nginx.com nxt_str_t *json; 119141Smax.romanov@nginx.com nxt_runtime_t *rt; 120314Svbart@nginx.com nxt_conf_value_t *conf; 121*337Sigor@sysoev.ru nxt_event_engine_t *engine; 12227Svbart@nginx.com nxt_http_fields_hash_t *hash; 12327Svbart@nginx.com 124141Smax.romanov@nginx.com rt = task->thread->runtime; 125141Smax.romanov@nginx.com 126*337Sigor@sysoev.ru engine = task->thread->engine; 127*337Sigor@sysoev.ru 128*337Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 129*337Sigor@sysoev.ru if (nxt_slow_path(engine->mem_pool == NULL)) { 130*337Sigor@sysoev.ru return NXT_ERROR; 131*337Sigor@sysoev.ru } 132*337Sigor@sysoev.ru 13360Svbart@nginx.com hash = nxt_http_fields_hash_create(nxt_controller_request_fields, 13460Svbart@nginx.com rt->mem_pool); 13527Svbart@nginx.com if (nxt_slow_path(hash == NULL)) { 13627Svbart@nginx.com return NXT_ERROR; 13727Svbart@nginx.com } 13827Svbart@nginx.com 13960Svbart@nginx.com nxt_controller_fields_hash = hash; 140248Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 14127Svbart@nginx.com 142314Svbart@nginx.com json = data; 143314Svbart@nginx.com 144314Svbart@nginx.com if (json->length == 0) { 145314Svbart@nginx.com return NXT_OK; 146314Svbart@nginx.com } 147314Svbart@nginx.com 148314Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 149314Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 150314Svbart@nginx.com return NXT_ERROR; 151314Svbart@nginx.com } 152314Svbart@nginx.com 153314Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, json); 154314Svbart@nginx.com nxt_free(json->start); 155314Svbart@nginx.com 156314Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 157314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, 158314Svbart@nginx.com "failed to restore previous configuration: " 159314Svbart@nginx.com "file is corrupted or not enough memory"); 160314Svbart@nginx.com 161314Svbart@nginx.com nxt_mp_destroy(mp); 162314Svbart@nginx.com return NXT_OK; 163314Svbart@nginx.com } 164314Svbart@nginx.com 165314Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(conf) != NXT_OK)) { 166314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, 167314Svbart@nginx.com "failed to restore previous configuration: " 168314Svbart@nginx.com "invalid configuration"); 169314Svbart@nginx.com 170314Svbart@nginx.com nxt_mp_destroy(mp); 171314Svbart@nginx.com return NXT_OK; 172314Svbart@nginx.com } 173314Svbart@nginx.com 174314Svbart@nginx.com 175314Svbart@nginx.com nxt_controller_conf.root = conf; 176314Svbart@nginx.com nxt_controller_conf.pool = mp; 177314Svbart@nginx.com 178248Svbart@nginx.com return NXT_OK; 179248Svbart@nginx.com } 180248Svbart@nginx.com 181248Svbart@nginx.com 182248Svbart@nginx.com static void 183248Svbart@nginx.com nxt_controller_process_new_port_handler(nxt_task_t *task, 184248Svbart@nginx.com nxt_port_recv_msg_t *msg) 185248Svbart@nginx.com { 186249Svbart@nginx.com nxt_int_t rc; 187248Svbart@nginx.com nxt_runtime_t *rt; 188248Svbart@nginx.com nxt_conf_value_t *conf; 189248Svbart@nginx.com 190248Svbart@nginx.com nxt_port_new_port_handler(task, msg); 191248Svbart@nginx.com 192249Svbart@nginx.com if (msg->new_port->type != NXT_PROCESS_ROUTER) { 193248Svbart@nginx.com return; 19420Sigor@sysoev.ru } 19520Sigor@sysoev.ru 196249Svbart@nginx.com conf = nxt_controller_conf.root; 197249Svbart@nginx.com 198249Svbart@nginx.com if (conf != NULL) { 199249Svbart@nginx.com rc = nxt_controller_conf_send(task, conf, 200249Svbart@nginx.com nxt_controller_conf_init_handler, NULL); 20144Svbart@nginx.com 202249Svbart@nginx.com if (nxt_fast_path(rc == NXT_OK)) { 203249Svbart@nginx.com return; 204249Svbart@nginx.com } 205249Svbart@nginx.com 206249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 207249Svbart@nginx.com 208249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 209249Svbart@nginx.com nxt_abort(); 210249Svbart@nginx.com } 21144Svbart@nginx.com } 21244Svbart@nginx.com 213249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 214248Svbart@nginx.com nxt_abort(); 21544Svbart@nginx.com } 21644Svbart@nginx.com 217248Svbart@nginx.com rt = task->thread->runtime; 218140Svbart@nginx.com 219248Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { 220248Svbart@nginx.com nxt_abort(); 221248Svbart@nginx.com } 222314Svbart@nginx.com 223314Svbart@nginx.com nxt_controller_listening = 1; 22420Sigor@sysoev.ru } 22520Sigor@sysoev.ru 22620Sigor@sysoev.ru 227249Svbart@nginx.com static nxt_int_t 228249Svbart@nginx.com nxt_controller_conf_default(void) 229249Svbart@nginx.com { 230249Svbart@nginx.com nxt_mp_t *mp; 231249Svbart@nginx.com nxt_conf_value_t *conf; 232249Svbart@nginx.com 233249Svbart@nginx.com static const nxt_str_t json 234249Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 235249Svbart@nginx.com 236249Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 237249Svbart@nginx.com 238249Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 239249Svbart@nginx.com return NXT_ERROR; 240249Svbart@nginx.com } 241249Svbart@nginx.com 242249Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 243249Svbart@nginx.com 244249Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 245249Svbart@nginx.com return NXT_ERROR; 246249Svbart@nginx.com } 247249Svbart@nginx.com 248249Svbart@nginx.com nxt_controller_conf.root = conf; 249249Svbart@nginx.com nxt_controller_conf.pool = mp; 250249Svbart@nginx.com 251249Svbart@nginx.com return NXT_OK; 252249Svbart@nginx.com } 253249Svbart@nginx.com 254249Svbart@nginx.com 255249Svbart@nginx.com static void 256249Svbart@nginx.com nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 257249Svbart@nginx.com void *data) 258249Svbart@nginx.com { 259314Svbart@nginx.com nxt_runtime_t *rt; 260314Svbart@nginx.com 261249Svbart@nginx.com if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { 262314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, "failed to apply previous configuration"); 263314Svbart@nginx.com 264249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 265249Svbart@nginx.com 266249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 267249Svbart@nginx.com nxt_abort(); 268249Svbart@nginx.com } 269249Svbart@nginx.com } 270314Svbart@nginx.com 271314Svbart@nginx.com if (nxt_controller_listening == 0) { 272314Svbart@nginx.com rt = task->thread->runtime; 273314Svbart@nginx.com 274314Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) 275314Svbart@nginx.com == NULL)) 276314Svbart@nginx.com { 277314Svbart@nginx.com nxt_abort(); 278314Svbart@nginx.com } 279314Svbart@nginx.com 280314Svbart@nginx.com nxt_controller_listening = 1; 281314Svbart@nginx.com } 282249Svbart@nginx.com } 283249Svbart@nginx.com 284249Svbart@nginx.com 285249Svbart@nginx.com static nxt_int_t 286249Svbart@nginx.com nxt_controller_conf_send(nxt_task_t *task, nxt_conf_value_t *conf, 287249Svbart@nginx.com nxt_port_rpc_handler_t handler, void *data) 288249Svbart@nginx.com { 289249Svbart@nginx.com size_t size; 290249Svbart@nginx.com uint32_t stream; 291249Svbart@nginx.com nxt_int_t rc; 292249Svbart@nginx.com nxt_buf_t *b; 293249Svbart@nginx.com nxt_port_t *router_port, *controller_port; 294249Svbart@nginx.com nxt_runtime_t *rt; 295249Svbart@nginx.com 296249Svbart@nginx.com rt = task->thread->runtime; 297249Svbart@nginx.com 298249Svbart@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 299249Svbart@nginx.com 300249Svbart@nginx.com if (nxt_slow_path(router_port == NULL)) { 301249Svbart@nginx.com return NXT_DECLINED; 302249Svbart@nginx.com } 303249Svbart@nginx.com 304249Svbart@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 305249Svbart@nginx.com 306249Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 307249Svbart@nginx.com 308249Svbart@nginx.com b = nxt_port_mmap_get_buf(task, router_port, size); 309249Svbart@nginx.com 310249Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 311249Svbart@nginx.com 312249Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, controller_port, 313249Svbart@nginx.com handler, handler, 314249Svbart@nginx.com router_port->pid, data); 315249Svbart@nginx.com 316249Svbart@nginx.com rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_DATA_LAST, -1, 317249Svbart@nginx.com stream, controller_port->id, b); 318249Svbart@nginx.com 319249Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 320249Svbart@nginx.com nxt_port_rpc_cancel(task, controller_port, stream); 321249Svbart@nginx.com return NXT_ERROR; 322249Svbart@nginx.com } 323249Svbart@nginx.com 324249Svbart@nginx.com return NXT_OK; 325249Svbart@nginx.com } 326249Svbart@nginx.com 327249Svbart@nginx.com 32820Sigor@sysoev.ru nxt_int_t 32920Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 33020Sigor@sysoev.ru { 33120Sigor@sysoev.ru nxt_sockaddr_t *sa; 33220Sigor@sysoev.ru nxt_listen_socket_t *ls; 33320Sigor@sysoev.ru 33420Sigor@sysoev.ru sa = rt->controller_listen; 33520Sigor@sysoev.ru 33665Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 33720Sigor@sysoev.ru if (ls == NULL) { 33820Sigor@sysoev.ru return NXT_ERROR; 33920Sigor@sysoev.ru } 34020Sigor@sysoev.ru 34120Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 34220Sigor@sysoev.ru sa->socklen, sa->length); 34320Sigor@sysoev.ru if (ls->sockaddr == NULL) { 34420Sigor@sysoev.ru return NXT_ERROR; 34520Sigor@sysoev.ru } 34620Sigor@sysoev.ru 34720Sigor@sysoev.ru ls->sockaddr->type = sa->type; 348312Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 34920Sigor@sysoev.ru 350312Sigor@sysoev.ru nxt_listen_socket_remote_size(ls, sa); 35120Sigor@sysoev.ru 35220Sigor@sysoev.ru ls->socket = -1; 35320Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 35420Sigor@sysoev.ru ls->read_after_accept = 1; 35520Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 35620Sigor@sysoev.ru 35720Sigor@sysoev.ru #if 0 35820Sigor@sysoev.ru /* STUB */ 35965Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 36020Sigor@sysoev.ru if (wq == NULL) { 36120Sigor@sysoev.ru return NXT_ERROR; 36220Sigor@sysoev.ru } 36320Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 36420Sigor@sysoev.ru /**/ 36520Sigor@sysoev.ru 36620Sigor@sysoev.ru ls->work_queue = wq; 36720Sigor@sysoev.ru #endif 36820Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 36920Sigor@sysoev.ru 37020Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 37120Sigor@sysoev.ru return NXT_ERROR; 37220Sigor@sysoev.ru } 37320Sigor@sysoev.ru 37420Sigor@sysoev.ru rt->controller_socket = ls; 37520Sigor@sysoev.ru 37620Sigor@sysoev.ru return NXT_OK; 37720Sigor@sysoev.ru } 37820Sigor@sysoev.ru 37920Sigor@sysoev.ru 38020Sigor@sysoev.ru static void 38120Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 38220Sigor@sysoev.ru { 38327Svbart@nginx.com nxt_buf_t *b; 38462Sigor@sysoev.ru nxt_conn_t *c; 38527Svbart@nginx.com nxt_event_engine_t *engine; 38627Svbart@nginx.com nxt_controller_request_t *r; 38720Sigor@sysoev.ru 38820Sigor@sysoev.ru c = obj; 38920Sigor@sysoev.ru 39020Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 39120Sigor@sysoev.ru 39265Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 39327Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 39427Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 39527Svbart@nginx.com return; 39627Svbart@nginx.com } 39727Svbart@nginx.com 398140Svbart@nginx.com r->conn = c; 399140Svbart@nginx.com 40060Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 40160Svbart@nginx.com != NXT_OK)) 40260Svbart@nginx.com { 40360Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 40460Svbart@nginx.com return; 40560Svbart@nginx.com } 40627Svbart@nginx.com 40767Svbart@nginx.com r->parser.fields_hash = nxt_controller_fields_hash; 40867Svbart@nginx.com 40920Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 41020Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 41120Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 41220Sigor@sysoev.ru return; 41320Sigor@sysoev.ru } 41420Sigor@sysoev.ru 41520Sigor@sysoev.ru c->read = b; 41627Svbart@nginx.com c->socket.data = r; 41720Sigor@sysoev.ru c->socket.read_ready = 1; 41820Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 41920Sigor@sysoev.ru 42020Sigor@sysoev.ru engine = task->thread->engine; 42120Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 42227Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 42320Sigor@sysoev.ru 42462Sigor@sysoev.ru nxt_conn_read(engine, c); 42520Sigor@sysoev.ru } 42620Sigor@sysoev.ru 42720Sigor@sysoev.ru 42820Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 42920Sigor@sysoev.ru nxt_aligned(64) = 43020Sigor@sysoev.ru { 43156Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 43256Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 43356Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 43420Sigor@sysoev.ru 43556Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 43656Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 43756Sigor@sysoev.ru .timer_data = 60 * 1000, 43820Sigor@sysoev.ru }; 43920Sigor@sysoev.ru 44020Sigor@sysoev.ru 44120Sigor@sysoev.ru static void 44220Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 44320Sigor@sysoev.ru { 44427Svbart@nginx.com size_t preread; 44527Svbart@nginx.com nxt_buf_t *b; 44627Svbart@nginx.com nxt_int_t rc; 44762Sigor@sysoev.ru nxt_conn_t *c; 44827Svbart@nginx.com nxt_controller_request_t *r; 44920Sigor@sysoev.ru 45020Sigor@sysoev.ru c = obj; 45127Svbart@nginx.com r = data; 45220Sigor@sysoev.ru 45320Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 45420Sigor@sysoev.ru 45527Svbart@nginx.com nxt_queue_remove(&c->link); 45627Svbart@nginx.com nxt_queue_self(&c->link); 45727Svbart@nginx.com 45827Svbart@nginx.com b = c->read; 45927Svbart@nginx.com 46027Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 46127Svbart@nginx.com 46227Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 46327Svbart@nginx.com 46427Svbart@nginx.com if (rc == NXT_AGAIN) { 46527Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 46627Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 46727Svbart@nginx.com nxt_controller_conn_close(task, c, r); 46827Svbart@nginx.com return; 46927Svbart@nginx.com } 47027Svbart@nginx.com 47162Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 47227Svbart@nginx.com return; 47327Svbart@nginx.com } 47427Svbart@nginx.com 47527Svbart@nginx.com /* rc == NXT_ERROR */ 47627Svbart@nginx.com 47727Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 47827Svbart@nginx.com 47927Svbart@nginx.com nxt_controller_conn_close(task, c, r); 48027Svbart@nginx.com return; 48127Svbart@nginx.com } 48227Svbart@nginx.com 48367Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, r, task->log); 48460Svbart@nginx.com 48560Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 48660Svbart@nginx.com nxt_controller_conn_close(task, c, r); 48760Svbart@nginx.com return; 48860Svbart@nginx.com } 48960Svbart@nginx.com 49027Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 49127Svbart@nginx.com 49227Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 493107Svbart@nginx.com "body length: %uz, preread: %uz", 49427Svbart@nginx.com r->length, preread); 49527Svbart@nginx.com 49627Svbart@nginx.com if (preread >= r->length) { 497140Svbart@nginx.com nxt_controller_process_request(task, r); 49827Svbart@nginx.com return; 49927Svbart@nginx.com } 50027Svbart@nginx.com 50127Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 50227Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 50327Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 50427Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 50527Svbart@nginx.com return; 50627Svbart@nginx.com } 50727Svbart@nginx.com 50827Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 50927Svbart@nginx.com 51027Svbart@nginx.com c->read = b; 51127Svbart@nginx.com } 51227Svbart@nginx.com 51327Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 51427Svbart@nginx.com 51562Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 51620Sigor@sysoev.ru } 51720Sigor@sysoev.ru 51820Sigor@sysoev.ru 51920Sigor@sysoev.ru static nxt_msec_t 52062Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 52120Sigor@sysoev.ru { 52220Sigor@sysoev.ru return (nxt_msec_t) data; 52320Sigor@sysoev.ru } 52420Sigor@sysoev.ru 52520Sigor@sysoev.ru 52620Sigor@sysoev.ru static void 52720Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 52820Sigor@sysoev.ru { 52962Sigor@sysoev.ru nxt_conn_t *c; 53020Sigor@sysoev.ru 53120Sigor@sysoev.ru c = obj; 53220Sigor@sysoev.ru 53320Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 53420Sigor@sysoev.ru 53527Svbart@nginx.com nxt_controller_conn_close(task, c, data); 53620Sigor@sysoev.ru } 53720Sigor@sysoev.ru 53820Sigor@sysoev.ru 53920Sigor@sysoev.ru static void 54020Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 54120Sigor@sysoev.ru { 54262Sigor@sysoev.ru nxt_timer_t *timer; 54362Sigor@sysoev.ru nxt_conn_t *c; 54420Sigor@sysoev.ru 54562Sigor@sysoev.ru timer = obj; 54620Sigor@sysoev.ru 54762Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 54820Sigor@sysoev.ru c->socket.timedout = 1; 54920Sigor@sysoev.ru c->socket.closed = 1; 55020Sigor@sysoev.ru 55120Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 55220Sigor@sysoev.ru 55327Svbart@nginx.com nxt_controller_conn_close(task, c, data); 55427Svbart@nginx.com } 55527Svbart@nginx.com 55627Svbart@nginx.com 55727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 55827Svbart@nginx.com nxt_aligned(64) = 55927Svbart@nginx.com { 56056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 56156Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 56256Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 56327Svbart@nginx.com 56456Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 56556Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 56656Sigor@sysoev.ru .timer_data = 60 * 1000, 56756Sigor@sysoev.ru .timer_autoreset = 1, 56827Svbart@nginx.com }; 56927Svbart@nginx.com 57027Svbart@nginx.com 57127Svbart@nginx.com static void 57227Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 57327Svbart@nginx.com { 574107Svbart@nginx.com size_t read; 575107Svbart@nginx.com nxt_buf_t *b; 576107Svbart@nginx.com nxt_conn_t *c; 577107Svbart@nginx.com nxt_controller_request_t *r; 57827Svbart@nginx.com 57927Svbart@nginx.com c = obj; 580107Svbart@nginx.com r = data; 58127Svbart@nginx.com b = c->read; 58227Svbart@nginx.com 583107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 58427Svbart@nginx.com 585107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 586107Svbart@nginx.com read, r->length); 58727Svbart@nginx.com 588107Svbart@nginx.com if (read >= r->length) { 589140Svbart@nginx.com nxt_controller_process_request(task, r); 59027Svbart@nginx.com return; 59127Svbart@nginx.com } 59227Svbart@nginx.com 59362Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 59427Svbart@nginx.com } 59527Svbart@nginx.com 59627Svbart@nginx.com 59727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 59827Svbart@nginx.com nxt_aligned(64) = 59927Svbart@nginx.com { 60056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 60156Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 60227Svbart@nginx.com 60356Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 60456Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 60556Sigor@sysoev.ru .timer_data = 60 * 1000, 60656Sigor@sysoev.ru .timer_autoreset = 1, 60727Svbart@nginx.com }; 60827Svbart@nginx.com 60927Svbart@nginx.com 61027Svbart@nginx.com static void 61127Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 61227Svbart@nginx.com { 61362Sigor@sysoev.ru nxt_buf_t *b; 61462Sigor@sysoev.ru nxt_conn_t *c; 61527Svbart@nginx.com 61627Svbart@nginx.com c = obj; 61727Svbart@nginx.com 61827Svbart@nginx.com nxt_debug(task, "controller conn write"); 61927Svbart@nginx.com 62027Svbart@nginx.com b = c->write; 62127Svbart@nginx.com 62227Svbart@nginx.com if (b->mem.pos != b->mem.free) { 62362Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 62427Svbart@nginx.com return; 62527Svbart@nginx.com } 62627Svbart@nginx.com 62727Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 62827Svbart@nginx.com 62927Svbart@nginx.com nxt_controller_conn_close(task, c, data); 63027Svbart@nginx.com } 63127Svbart@nginx.com 63227Svbart@nginx.com 63327Svbart@nginx.com static void 63427Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 63527Svbart@nginx.com { 63662Sigor@sysoev.ru nxt_conn_t *c; 63727Svbart@nginx.com 63827Svbart@nginx.com c = obj; 63927Svbart@nginx.com 64027Svbart@nginx.com nxt_debug(task, "controller conn write error"); 64127Svbart@nginx.com 64227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 64327Svbart@nginx.com } 64427Svbart@nginx.com 64527Svbart@nginx.com 64627Svbart@nginx.com static void 64727Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 64827Svbart@nginx.com { 64962Sigor@sysoev.ru nxt_conn_t *c; 65062Sigor@sysoev.ru nxt_timer_t *timer; 65127Svbart@nginx.com 65262Sigor@sysoev.ru timer = obj; 65327Svbart@nginx.com 65462Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 65527Svbart@nginx.com c->socket.timedout = 1; 65627Svbart@nginx.com c->socket.closed = 1; 65727Svbart@nginx.com 65827Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 65927Svbart@nginx.com 66027Svbart@nginx.com nxt_controller_conn_close(task, c, data); 66120Sigor@sysoev.ru } 66220Sigor@sysoev.ru 66320Sigor@sysoev.ru 66420Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 66520Sigor@sysoev.ru nxt_aligned(64) = 66620Sigor@sysoev.ru { 66756Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 66820Sigor@sysoev.ru }; 66920Sigor@sysoev.ru 67020Sigor@sysoev.ru 67120Sigor@sysoev.ru static void 67220Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 67320Sigor@sysoev.ru { 67462Sigor@sysoev.ru nxt_conn_t *c; 67520Sigor@sysoev.ru 67620Sigor@sysoev.ru c = obj; 67720Sigor@sysoev.ru 67820Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 67920Sigor@sysoev.ru 68027Svbart@nginx.com nxt_queue_remove(&c->link); 68127Svbart@nginx.com 68220Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 68320Sigor@sysoev.ru 68462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 68520Sigor@sysoev.ru } 68620Sigor@sysoev.ru 68720Sigor@sysoev.ru 68820Sigor@sysoev.ru static void 68920Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 69020Sigor@sysoev.ru { 69162Sigor@sysoev.ru nxt_conn_t *c; 69220Sigor@sysoev.ru 69320Sigor@sysoev.ru c = obj; 69420Sigor@sysoev.ru 69520Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 69620Sigor@sysoev.ru 697*337Sigor@sysoev.ru nxt_sockaddr_cache_free(task->thread->engine, c); 698*337Sigor@sysoev.ru 69965Sigor@sysoev.ru nxt_mp_destroy(c->mem_pool); 70020Sigor@sysoev.ru 70120Sigor@sysoev.ru //nxt_free(c); 70220Sigor@sysoev.ru } 70327Svbart@nginx.com 70427Svbart@nginx.com 70527Svbart@nginx.com static nxt_int_t 70660Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 70767Svbart@nginx.com nxt_log_t *log) 70827Svbart@nginx.com { 70927Svbart@nginx.com off_t length; 71027Svbart@nginx.com nxt_controller_request_t *r; 71127Svbart@nginx.com 71227Svbart@nginx.com r = ctx; 71327Svbart@nginx.com 71460Svbart@nginx.com length = nxt_off_t_parse(field->value.start, field->value.length); 71527Svbart@nginx.com 71627Svbart@nginx.com if (nxt_fast_path(length > 0)) { 717107Svbart@nginx.com 718107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 719107Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is too big"); 720107Svbart@nginx.com return NXT_ERROR; 721107Svbart@nginx.com } 72227Svbart@nginx.com 72327Svbart@nginx.com r->length = length; 72427Svbart@nginx.com return NXT_OK; 72527Svbart@nginx.com } 72627Svbart@nginx.com 72760Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is invalid"); 72827Svbart@nginx.com 72927Svbart@nginx.com return NXT_ERROR; 73027Svbart@nginx.com } 73127Svbart@nginx.com 73227Svbart@nginx.com 73327Svbart@nginx.com static void 734140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 73527Svbart@nginx.com { 73665Sigor@sysoev.ru nxt_mp_t *mp; 73751Svbart@nginx.com nxt_int_t rc; 73846Svbart@nginx.com nxt_str_t path; 739140Svbart@nginx.com nxt_conn_t *c; 74051Svbart@nginx.com nxt_buf_mem_t *mbuf; 741106Svbart@nginx.com nxt_conf_op_t *ops; 742106Svbart@nginx.com nxt_conf_value_t *value; 743208Svbart@nginx.com nxt_conf_json_error_t error; 74444Svbart@nginx.com nxt_controller_response_t resp; 74544Svbart@nginx.com 74651Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 74751Svbart@nginx.com 748140Svbart@nginx.com c = req->conn; 749112Smax.romanov@nginx.com path = req->parser.path; 75051Svbart@nginx.com 75151Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 75251Svbart@nginx.com path.length--; 75351Svbart@nginx.com } 75451Svbart@nginx.com 75544Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 75644Svbart@nginx.com 75744Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 75846Svbart@nginx.com 759106Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, &path); 76051Svbart@nginx.com 76151Svbart@nginx.com if (value == NULL) { 762208Svbart@nginx.com goto not_found; 76351Svbart@nginx.com } 76451Svbart@nginx.com 765208Svbart@nginx.com resp.status = 200; 766106Svbart@nginx.com resp.conf = value; 76746Svbart@nginx.com 768208Svbart@nginx.com nxt_controller_response(task, req, &resp); 769208Svbart@nginx.com return; 77051Svbart@nginx.com } 77151Svbart@nginx.com 77251Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 77346Svbart@nginx.com 774238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 775238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 776238Svbart@nginx.com return; 777238Svbart@nginx.com } 778238Svbart@nginx.com 77965Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 78051Svbart@nginx.com 78151Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 782208Svbart@nginx.com goto alloc_fail; 78346Svbart@nginx.com } 78446Svbart@nginx.com 78551Svbart@nginx.com mbuf = &c->read->mem; 78651Svbart@nginx.com 787208Svbart@nginx.com nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); 788208Svbart@nginx.com 789208Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 79051Svbart@nginx.com 79151Svbart@nginx.com if (value == NULL) { 79265Sigor@sysoev.ru nxt_mp_destroy(mp); 793208Svbart@nginx.com 794208Svbart@nginx.com if (error.pos == NULL) { 795208Svbart@nginx.com goto alloc_fail; 796208Svbart@nginx.com } 797208Svbart@nginx.com 798208Svbart@nginx.com resp.status = 400; 799208Svbart@nginx.com resp.title = (u_char *) "Invalid JSON."; 800208Svbart@nginx.com resp.detail = error.detail; 801208Svbart@nginx.com resp.offset = error.pos - mbuf->pos; 802208Svbart@nginx.com 803208Svbart@nginx.com nxt_conf_json_position(mbuf->pos, error.pos, 804208Svbart@nginx.com &resp.line, &resp.column); 805208Svbart@nginx.com 806208Svbart@nginx.com nxt_controller_response(task, req, &resp); 807208Svbart@nginx.com return; 80851Svbart@nginx.com } 80951Svbart@nginx.com 81051Svbart@nginx.com if (path.length != 1) { 811106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 812106Svbart@nginx.com nxt_controller_conf.root, 813106Svbart@nginx.com &path, value); 81446Svbart@nginx.com 81551Svbart@nginx.com if (rc != NXT_OK) { 81651Svbart@nginx.com if (rc == NXT_DECLINED) { 817208Svbart@nginx.com goto not_found; 81851Svbart@nginx.com } 81946Svbart@nginx.com 820208Svbart@nginx.com goto alloc_fail; 82151Svbart@nginx.com } 82251Svbart@nginx.com 823106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 82451Svbart@nginx.com 82551Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 82665Sigor@sysoev.ru nxt_mp_destroy(mp); 827208Svbart@nginx.com goto alloc_fail; 82851Svbart@nginx.com } 82946Svbart@nginx.com } 83044Svbart@nginx.com 831116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 832121Svbart@nginx.com nxt_mp_destroy(mp); 833208Svbart@nginx.com goto invalid_conf; 834116Svbart@nginx.com } 835116Svbart@nginx.com 836249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 837249Svbart@nginx.com nxt_controller_conf_handler, req); 838247Svbart@nginx.com 839247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 840121Svbart@nginx.com nxt_mp_destroy(mp); 841247Svbart@nginx.com 842247Svbart@nginx.com if (rc == NXT_DECLINED) { 843247Svbart@nginx.com goto no_router; 844247Svbart@nginx.com } 845247Svbart@nginx.com 846247Svbart@nginx.com /* rc == NXT_ERROR */ 847208Svbart@nginx.com goto alloc_fail; 848121Svbart@nginx.com } 849121Svbart@nginx.com 850249Svbart@nginx.com req->conf.root = value; 851249Svbart@nginx.com req->conf.pool = mp; 852249Svbart@nginx.com 853249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 854249Svbart@nginx.com 855140Svbart@nginx.com return; 85651Svbart@nginx.com } 85727Svbart@nginx.com 85851Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 85951Svbart@nginx.com 860238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 861238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 862238Svbart@nginx.com return; 863238Svbart@nginx.com } 864238Svbart@nginx.com 86551Svbart@nginx.com if (path.length == 1) { 86665Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 86744Svbart@nginx.com 86851Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 869208Svbart@nginx.com goto alloc_fail; 87051Svbart@nginx.com } 87151Svbart@nginx.com 872106Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &empty_obj); 87327Svbart@nginx.com 87444Svbart@nginx.com } else { 875106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 876106Svbart@nginx.com nxt_controller_conf.root, 877106Svbart@nginx.com &path, NULL); 87851Svbart@nginx.com 87951Svbart@nginx.com if (rc != NXT_OK) { 88051Svbart@nginx.com if (rc == NXT_DECLINED) { 881208Svbart@nginx.com goto not_found; 88251Svbart@nginx.com } 88351Svbart@nginx.com 884208Svbart@nginx.com goto alloc_fail; 88551Svbart@nginx.com } 88651Svbart@nginx.com 88765Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 88851Svbart@nginx.com 88951Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 890208Svbart@nginx.com goto alloc_fail; 89151Svbart@nginx.com } 89251Svbart@nginx.com 893106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 89451Svbart@nginx.com } 89551Svbart@nginx.com 89651Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 89765Sigor@sysoev.ru nxt_mp_destroy(mp); 898208Svbart@nginx.com goto alloc_fail; 89944Svbart@nginx.com } 90044Svbart@nginx.com 901116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 902121Svbart@nginx.com nxt_mp_destroy(mp); 903208Svbart@nginx.com goto invalid_conf; 904116Svbart@nginx.com } 905116Svbart@nginx.com 906249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 907249Svbart@nginx.com nxt_controller_conf_handler, req); 908247Svbart@nginx.com 909247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 910121Svbart@nginx.com nxt_mp_destroy(mp); 911247Svbart@nginx.com 912247Svbart@nginx.com if (rc == NXT_DECLINED) { 913247Svbart@nginx.com goto no_router; 914247Svbart@nginx.com } 915247Svbart@nginx.com 916247Svbart@nginx.com /* rc == NXT_ERROR */ 917208Svbart@nginx.com goto alloc_fail; 918121Svbart@nginx.com } 919121Svbart@nginx.com 920249Svbart@nginx.com req->conf.root = value; 921249Svbart@nginx.com req->conf.pool = mp; 922249Svbart@nginx.com 923249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 924249Svbart@nginx.com 925140Svbart@nginx.com return; 92651Svbart@nginx.com } 92751Svbart@nginx.com 928208Svbart@nginx.com resp.status = 405; 929208Svbart@nginx.com resp.title = (u_char *) "Invalid method."; 930208Svbart@nginx.com resp.offset = -1; 93151Svbart@nginx.com 932208Svbart@nginx.com nxt_controller_response(task, req, &resp); 933208Svbart@nginx.com return; 93451Svbart@nginx.com 935208Svbart@nginx.com not_found: 936208Svbart@nginx.com 937208Svbart@nginx.com resp.status = 404; 938208Svbart@nginx.com resp.title = (u_char *) "Value doesn't exist."; 939208Svbart@nginx.com resp.offset = -1; 940208Svbart@nginx.com 941208Svbart@nginx.com nxt_controller_response(task, req, &resp); 942208Svbart@nginx.com return; 943208Svbart@nginx.com 944208Svbart@nginx.com invalid_conf: 945208Svbart@nginx.com 946208Svbart@nginx.com resp.status = 400; 947208Svbart@nginx.com resp.title = (u_char *) "Invalid configuration."; 948208Svbart@nginx.com resp.offset = -1; 949208Svbart@nginx.com 950208Svbart@nginx.com nxt_controller_response(task, req, &resp); 951208Svbart@nginx.com return; 952247Svbart@nginx.com 953247Svbart@nginx.com alloc_fail: 954247Svbart@nginx.com 955247Svbart@nginx.com resp.status = 500; 956247Svbart@nginx.com resp.title = (u_char *) "Memory allocation failed."; 957247Svbart@nginx.com resp.offset = -1; 958247Svbart@nginx.com 959247Svbart@nginx.com nxt_controller_response(task, req, &resp); 960247Svbart@nginx.com return; 961247Svbart@nginx.com 962247Svbart@nginx.com no_router: 963247Svbart@nginx.com 964247Svbart@nginx.com resp.status = 500; 965247Svbart@nginx.com resp.title = (u_char *) "Router process isn't available."; 966247Svbart@nginx.com resp.offset = -1; 967247Svbart@nginx.com 968247Svbart@nginx.com nxt_controller_response(task, req, &resp); 969247Svbart@nginx.com return; 97027Svbart@nginx.com } 97127Svbart@nginx.com 97227Svbart@nginx.com 973193Smax.romanov@nginx.com static void 974193Smax.romanov@nginx.com nxt_controller_conf_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 975193Smax.romanov@nginx.com void *data) 976140Svbart@nginx.com { 977238Svbart@nginx.com nxt_queue_t queue; 978140Svbart@nginx.com nxt_controller_request_t *req; 979140Svbart@nginx.com nxt_controller_response_t resp; 980140Svbart@nginx.com 981238Svbart@nginx.com req = data; 982238Svbart@nginx.com 983201Svbart@nginx.com nxt_debug(task, "controller conf ready: %*s", 984201Svbart@nginx.com nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); 985140Svbart@nginx.com 986238Svbart@nginx.com nxt_queue_remove(&req->link); 987140Svbart@nginx.com 988238Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 989140Svbart@nginx.com 990193Smax.romanov@nginx.com if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { 991140Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 992140Svbart@nginx.com 993140Svbart@nginx.com nxt_controller_conf = req->conf; 994140Svbart@nginx.com 995314Svbart@nginx.com nxt_controller_conf_store(task, req->conf.root); 996314Svbart@nginx.com 997208Svbart@nginx.com resp.status = 200; 998208Svbart@nginx.com resp.title = (u_char *) "Reconfiguration done."; 999140Svbart@nginx.com 1000140Svbart@nginx.com } else { 1001140Svbart@nginx.com nxt_mp_destroy(req->conf.pool); 1002140Svbart@nginx.com 1003208Svbart@nginx.com resp.status = 500; 1004208Svbart@nginx.com resp.title = (u_char *) "Failed to apply new configuration."; 1005208Svbart@nginx.com resp.offset = -1; 1006140Svbart@nginx.com } 1007140Svbart@nginx.com 1008140Svbart@nginx.com nxt_controller_response(task, req, &resp); 1009140Svbart@nginx.com 1010238Svbart@nginx.com nxt_queue_init(&queue); 1011238Svbart@nginx.com nxt_queue_add(&queue, &nxt_controller_waiting_requests); 1012140Svbart@nginx.com 1013238Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 1014121Svbart@nginx.com 1015238Svbart@nginx.com nxt_queue_each(req, &queue, nxt_controller_request_t, link) { 1016238Svbart@nginx.com nxt_controller_process_request(task, req); 1017238Svbart@nginx.com } nxt_queue_loop; 1018121Svbart@nginx.com } 1019121Svbart@nginx.com 1020121Svbart@nginx.com 1021140Svbart@nginx.com static void 1022314Svbart@nginx.com nxt_controller_conf_store(nxt_task_t *task, nxt_conf_value_t *conf) 1023314Svbart@nginx.com { 1024314Svbart@nginx.com size_t size; 1025314Svbart@nginx.com nxt_buf_t *b; 1026314Svbart@nginx.com nxt_port_t *main_port; 1027314Svbart@nginx.com nxt_runtime_t *rt; 1028314Svbart@nginx.com 1029314Svbart@nginx.com rt = task->thread->runtime; 1030314Svbart@nginx.com 1031314Svbart@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1032314Svbart@nginx.com 1033314Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 1034