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 102*320Smax.romanov@nginx.com nxt_port_handlers_t nxt_controller_process_port_handlers = { 103*320Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 104*320Smax.romanov@nginx.com .new_port = nxt_controller_process_new_port_handler, 105*320Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 106*320Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 107*320Smax.romanov@nginx.com .data = nxt_port_data_handler, 108*320Smax.romanov@nginx.com .remove_pid = nxt_port_remove_pid_handler, 109*320Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 110*320Smax.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; 12127Svbart@nginx.com nxt_http_fields_hash_t *hash; 12227Svbart@nginx.com 123141Smax.romanov@nginx.com rt = task->thread->runtime; 124141Smax.romanov@nginx.com 12560Svbart@nginx.com hash = nxt_http_fields_hash_create(nxt_controller_request_fields, 12660Svbart@nginx.com rt->mem_pool); 12727Svbart@nginx.com if (nxt_slow_path(hash == NULL)) { 12827Svbart@nginx.com return NXT_ERROR; 12927Svbart@nginx.com } 13027Svbart@nginx.com 13160Svbart@nginx.com nxt_controller_fields_hash = hash; 132248Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 13327Svbart@nginx.com 134314Svbart@nginx.com json = data; 135314Svbart@nginx.com 136314Svbart@nginx.com if (json->length == 0) { 137314Svbart@nginx.com return NXT_OK; 138314Svbart@nginx.com } 139314Svbart@nginx.com 140314Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 141314Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 142314Svbart@nginx.com return NXT_ERROR; 143314Svbart@nginx.com } 144314Svbart@nginx.com 145314Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, json); 146314Svbart@nginx.com nxt_free(json->start); 147314Svbart@nginx.com 148314Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 149314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, 150314Svbart@nginx.com "failed to restore previous configuration: " 151314Svbart@nginx.com "file is corrupted or not enough memory"); 152314Svbart@nginx.com 153314Svbart@nginx.com nxt_mp_destroy(mp); 154314Svbart@nginx.com return NXT_OK; 155314Svbart@nginx.com } 156314Svbart@nginx.com 157314Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(conf) != NXT_OK)) { 158314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, 159314Svbart@nginx.com "failed to restore previous configuration: " 160314Svbart@nginx.com "invalid configuration"); 161314Svbart@nginx.com 162314Svbart@nginx.com nxt_mp_destroy(mp); 163314Svbart@nginx.com return NXT_OK; 164314Svbart@nginx.com } 165314Svbart@nginx.com 166314Svbart@nginx.com 167314Svbart@nginx.com nxt_controller_conf.root = conf; 168314Svbart@nginx.com nxt_controller_conf.pool = mp; 169314Svbart@nginx.com 170248Svbart@nginx.com return NXT_OK; 171248Svbart@nginx.com } 172248Svbart@nginx.com 173248Svbart@nginx.com 174248Svbart@nginx.com static void 175248Svbart@nginx.com nxt_controller_process_new_port_handler(nxt_task_t *task, 176248Svbart@nginx.com nxt_port_recv_msg_t *msg) 177248Svbart@nginx.com { 178249Svbart@nginx.com nxt_int_t rc; 179248Svbart@nginx.com nxt_runtime_t *rt; 180248Svbart@nginx.com nxt_conf_value_t *conf; 181248Svbart@nginx.com 182248Svbart@nginx.com nxt_port_new_port_handler(task, msg); 183248Svbart@nginx.com 184249Svbart@nginx.com if (msg->new_port->type != NXT_PROCESS_ROUTER) { 185248Svbart@nginx.com return; 18620Sigor@sysoev.ru } 18720Sigor@sysoev.ru 188249Svbart@nginx.com conf = nxt_controller_conf.root; 189249Svbart@nginx.com 190249Svbart@nginx.com if (conf != NULL) { 191249Svbart@nginx.com rc = nxt_controller_conf_send(task, conf, 192249Svbart@nginx.com nxt_controller_conf_init_handler, NULL); 19344Svbart@nginx.com 194249Svbart@nginx.com if (nxt_fast_path(rc == NXT_OK)) { 195249Svbart@nginx.com return; 196249Svbart@nginx.com } 197249Svbart@nginx.com 198249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 199249Svbart@nginx.com 200249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 201249Svbart@nginx.com nxt_abort(); 202249Svbart@nginx.com } 20344Svbart@nginx.com } 20444Svbart@nginx.com 205249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 206248Svbart@nginx.com nxt_abort(); 20744Svbart@nginx.com } 20844Svbart@nginx.com 209248Svbart@nginx.com rt = task->thread->runtime; 210140Svbart@nginx.com 211248Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { 212248Svbart@nginx.com nxt_abort(); 213248Svbart@nginx.com } 214314Svbart@nginx.com 215314Svbart@nginx.com nxt_controller_listening = 1; 21620Sigor@sysoev.ru } 21720Sigor@sysoev.ru 21820Sigor@sysoev.ru 219249Svbart@nginx.com static nxt_int_t 220249Svbart@nginx.com nxt_controller_conf_default(void) 221249Svbart@nginx.com { 222249Svbart@nginx.com nxt_mp_t *mp; 223249Svbart@nginx.com nxt_conf_value_t *conf; 224249Svbart@nginx.com 225249Svbart@nginx.com static const nxt_str_t json 226249Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 227249Svbart@nginx.com 228249Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 229249Svbart@nginx.com 230249Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 231249Svbart@nginx.com return NXT_ERROR; 232249Svbart@nginx.com } 233249Svbart@nginx.com 234249Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 235249Svbart@nginx.com 236249Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 237249Svbart@nginx.com return NXT_ERROR; 238249Svbart@nginx.com } 239249Svbart@nginx.com 240249Svbart@nginx.com nxt_controller_conf.root = conf; 241249Svbart@nginx.com nxt_controller_conf.pool = mp; 242249Svbart@nginx.com 243249Svbart@nginx.com return NXT_OK; 244249Svbart@nginx.com } 245249Svbart@nginx.com 246249Svbart@nginx.com 247249Svbart@nginx.com static void 248249Svbart@nginx.com nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 249249Svbart@nginx.com void *data) 250249Svbart@nginx.com { 251314Svbart@nginx.com nxt_runtime_t *rt; 252314Svbart@nginx.com 253249Svbart@nginx.com if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { 254314Svbart@nginx.com nxt_log(task, NXT_LOG_ALERT, "failed to apply previous configuration"); 255314Svbart@nginx.com 256249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 257249Svbart@nginx.com 258249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 259249Svbart@nginx.com nxt_abort(); 260249Svbart@nginx.com } 261249Svbart@nginx.com } 262314Svbart@nginx.com 263314Svbart@nginx.com if (nxt_controller_listening == 0) { 264314Svbart@nginx.com rt = task->thread->runtime; 265314Svbart@nginx.com 266314Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) 267314Svbart@nginx.com == NULL)) 268314Svbart@nginx.com { 269314Svbart@nginx.com nxt_abort(); 270314Svbart@nginx.com } 271314Svbart@nginx.com 272314Svbart@nginx.com nxt_controller_listening = 1; 273314Svbart@nginx.com } 274249Svbart@nginx.com } 275249Svbart@nginx.com 276249Svbart@nginx.com 277249Svbart@nginx.com static nxt_int_t 278249Svbart@nginx.com nxt_controller_conf_send(nxt_task_t *task, nxt_conf_value_t *conf, 279249Svbart@nginx.com nxt_port_rpc_handler_t handler, void *data) 280249Svbart@nginx.com { 281249Svbart@nginx.com size_t size; 282249Svbart@nginx.com uint32_t stream; 283249Svbart@nginx.com nxt_int_t rc; 284249Svbart@nginx.com nxt_buf_t *b; 285249Svbart@nginx.com nxt_port_t *router_port, *controller_port; 286249Svbart@nginx.com nxt_runtime_t *rt; 287249Svbart@nginx.com 288249Svbart@nginx.com rt = task->thread->runtime; 289249Svbart@nginx.com 290249Svbart@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 291249Svbart@nginx.com 292249Svbart@nginx.com if (nxt_slow_path(router_port == NULL)) { 293249Svbart@nginx.com return NXT_DECLINED; 294249Svbart@nginx.com } 295249Svbart@nginx.com 296249Svbart@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 297249Svbart@nginx.com 298249Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 299249Svbart@nginx.com 300249Svbart@nginx.com b = nxt_port_mmap_get_buf(task, router_port, size); 301249Svbart@nginx.com 302249Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 303249Svbart@nginx.com 304249Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, controller_port, 305249Svbart@nginx.com handler, handler, 306249Svbart@nginx.com router_port->pid, data); 307249Svbart@nginx.com 308249Svbart@nginx.com rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_DATA_LAST, -1, 309249Svbart@nginx.com stream, controller_port->id, b); 310249Svbart@nginx.com 311249Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 312249Svbart@nginx.com nxt_port_rpc_cancel(task, controller_port, stream); 313249Svbart@nginx.com return NXT_ERROR; 314249Svbart@nginx.com } 315249Svbart@nginx.com 316249Svbart@nginx.com return NXT_OK; 317249Svbart@nginx.com } 318249Svbart@nginx.com 319249Svbart@nginx.com 32020Sigor@sysoev.ru nxt_int_t 32120Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 32220Sigor@sysoev.ru { 32320Sigor@sysoev.ru nxt_sockaddr_t *sa; 32420Sigor@sysoev.ru nxt_listen_socket_t *ls; 32520Sigor@sysoev.ru 32620Sigor@sysoev.ru sa = rt->controller_listen; 32720Sigor@sysoev.ru 32865Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 32920Sigor@sysoev.ru if (ls == NULL) { 33020Sigor@sysoev.ru return NXT_ERROR; 33120Sigor@sysoev.ru } 33220Sigor@sysoev.ru 33320Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 33420Sigor@sysoev.ru sa->socklen, sa->length); 33520Sigor@sysoev.ru if (ls->sockaddr == NULL) { 33620Sigor@sysoev.ru return NXT_ERROR; 33720Sigor@sysoev.ru } 33820Sigor@sysoev.ru 33920Sigor@sysoev.ru ls->sockaddr->type = sa->type; 340312Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 34120Sigor@sysoev.ru 342312Sigor@sysoev.ru nxt_listen_socket_remote_size(ls, sa); 34320Sigor@sysoev.ru 34420Sigor@sysoev.ru ls->socket = -1; 34520Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 34620Sigor@sysoev.ru ls->read_after_accept = 1; 34720Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 34820Sigor@sysoev.ru 34920Sigor@sysoev.ru #if 0 35020Sigor@sysoev.ru /* STUB */ 35165Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 35220Sigor@sysoev.ru if (wq == NULL) { 35320Sigor@sysoev.ru return NXT_ERROR; 35420Sigor@sysoev.ru } 35520Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 35620Sigor@sysoev.ru /**/ 35720Sigor@sysoev.ru 35820Sigor@sysoev.ru ls->work_queue = wq; 35920Sigor@sysoev.ru #endif 36020Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 36120Sigor@sysoev.ru 36220Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 36320Sigor@sysoev.ru return NXT_ERROR; 36420Sigor@sysoev.ru } 36520Sigor@sysoev.ru 36620Sigor@sysoev.ru rt->controller_socket = ls; 36720Sigor@sysoev.ru 36820Sigor@sysoev.ru return NXT_OK; 36920Sigor@sysoev.ru } 37020Sigor@sysoev.ru 37120Sigor@sysoev.ru 37220Sigor@sysoev.ru static void 37320Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 37420Sigor@sysoev.ru { 37527Svbart@nginx.com nxt_buf_t *b; 37662Sigor@sysoev.ru nxt_conn_t *c; 37727Svbart@nginx.com nxt_event_engine_t *engine; 37827Svbart@nginx.com nxt_controller_request_t *r; 37920Sigor@sysoev.ru 38020Sigor@sysoev.ru c = obj; 38120Sigor@sysoev.ru 38220Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 38320Sigor@sysoev.ru 38465Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 38527Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 38627Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 38727Svbart@nginx.com return; 38827Svbart@nginx.com } 38927Svbart@nginx.com 390140Svbart@nginx.com r->conn = c; 391140Svbart@nginx.com 39260Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 39360Svbart@nginx.com != NXT_OK)) 39460Svbart@nginx.com { 39560Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 39660Svbart@nginx.com return; 39760Svbart@nginx.com } 39827Svbart@nginx.com 39967Svbart@nginx.com r->parser.fields_hash = nxt_controller_fields_hash; 40067Svbart@nginx.com 40120Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 40220Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 40320Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 40420Sigor@sysoev.ru return; 40520Sigor@sysoev.ru } 40620Sigor@sysoev.ru 40720Sigor@sysoev.ru c->read = b; 40827Svbart@nginx.com c->socket.data = r; 40920Sigor@sysoev.ru c->socket.read_ready = 1; 41020Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 41120Sigor@sysoev.ru 41220Sigor@sysoev.ru engine = task->thread->engine; 41320Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 41427Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 41520Sigor@sysoev.ru 41662Sigor@sysoev.ru nxt_conn_read(engine, c); 41720Sigor@sysoev.ru } 41820Sigor@sysoev.ru 41920Sigor@sysoev.ru 42020Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 42120Sigor@sysoev.ru nxt_aligned(64) = 42220Sigor@sysoev.ru { 42356Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 42456Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 42556Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 42620Sigor@sysoev.ru 42756Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 42856Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 42956Sigor@sysoev.ru .timer_data = 60 * 1000, 43020Sigor@sysoev.ru }; 43120Sigor@sysoev.ru 43220Sigor@sysoev.ru 43320Sigor@sysoev.ru static void 43420Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 43520Sigor@sysoev.ru { 43627Svbart@nginx.com size_t preread; 43727Svbart@nginx.com nxt_buf_t *b; 43827Svbart@nginx.com nxt_int_t rc; 43962Sigor@sysoev.ru nxt_conn_t *c; 44027Svbart@nginx.com nxt_controller_request_t *r; 44120Sigor@sysoev.ru 44220Sigor@sysoev.ru c = obj; 44327Svbart@nginx.com r = data; 44420Sigor@sysoev.ru 44520Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 44620Sigor@sysoev.ru 44727Svbart@nginx.com nxt_queue_remove(&c->link); 44827Svbart@nginx.com nxt_queue_self(&c->link); 44927Svbart@nginx.com 45027Svbart@nginx.com b = c->read; 45127Svbart@nginx.com 45227Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 45327Svbart@nginx.com 45427Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 45527Svbart@nginx.com 45627Svbart@nginx.com if (rc == NXT_AGAIN) { 45727Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 45827Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 45927Svbart@nginx.com nxt_controller_conn_close(task, c, r); 46027Svbart@nginx.com return; 46127Svbart@nginx.com } 46227Svbart@nginx.com 46362Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 46427Svbart@nginx.com return; 46527Svbart@nginx.com } 46627Svbart@nginx.com 46727Svbart@nginx.com /* rc == NXT_ERROR */ 46827Svbart@nginx.com 46927Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 47027Svbart@nginx.com 47127Svbart@nginx.com nxt_controller_conn_close(task, c, r); 47227Svbart@nginx.com return; 47327Svbart@nginx.com } 47427Svbart@nginx.com 47567Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, r, task->log); 47660Svbart@nginx.com 47760Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 47860Svbart@nginx.com nxt_controller_conn_close(task, c, r); 47960Svbart@nginx.com return; 48060Svbart@nginx.com } 48160Svbart@nginx.com 48227Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 48327Svbart@nginx.com 48427Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 485107Svbart@nginx.com "body length: %uz, preread: %uz", 48627Svbart@nginx.com r->length, preread); 48727Svbart@nginx.com 48827Svbart@nginx.com if (preread >= r->length) { 489140Svbart@nginx.com nxt_controller_process_request(task, r); 49027Svbart@nginx.com return; 49127Svbart@nginx.com } 49227Svbart@nginx.com 49327Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 49427Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 49527Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 49627Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 49727Svbart@nginx.com return; 49827Svbart@nginx.com } 49927Svbart@nginx.com 50027Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 50127Svbart@nginx.com 50227Svbart@nginx.com c->read = b; 50327Svbart@nginx.com } 50427Svbart@nginx.com 50527Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 50627Svbart@nginx.com 50762Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 50820Sigor@sysoev.ru } 50920Sigor@sysoev.ru 51020Sigor@sysoev.ru 51120Sigor@sysoev.ru static nxt_msec_t 51262Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 51320Sigor@sysoev.ru { 51420Sigor@sysoev.ru return (nxt_msec_t) data; 51520Sigor@sysoev.ru } 51620Sigor@sysoev.ru 51720Sigor@sysoev.ru 51820Sigor@sysoev.ru static void 51920Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 52020Sigor@sysoev.ru { 52162Sigor@sysoev.ru nxt_conn_t *c; 52220Sigor@sysoev.ru 52320Sigor@sysoev.ru c = obj; 52420Sigor@sysoev.ru 52520Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 52620Sigor@sysoev.ru 52727Svbart@nginx.com nxt_controller_conn_close(task, c, data); 52820Sigor@sysoev.ru } 52920Sigor@sysoev.ru 53020Sigor@sysoev.ru 53120Sigor@sysoev.ru static void 53220Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 53320Sigor@sysoev.ru { 53462Sigor@sysoev.ru nxt_timer_t *timer; 53562Sigor@sysoev.ru nxt_conn_t *c; 53620Sigor@sysoev.ru 53762Sigor@sysoev.ru timer = obj; 53820Sigor@sysoev.ru 53962Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 54020Sigor@sysoev.ru c->socket.timedout = 1; 54120Sigor@sysoev.ru c->socket.closed = 1; 54220Sigor@sysoev.ru 54320Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 54420Sigor@sysoev.ru 54527Svbart@nginx.com nxt_controller_conn_close(task, c, data); 54627Svbart@nginx.com } 54727Svbart@nginx.com 54827Svbart@nginx.com 54927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 55027Svbart@nginx.com nxt_aligned(64) = 55127Svbart@nginx.com { 55256Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 55356Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 55456Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 55527Svbart@nginx.com 55656Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 55756Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 55856Sigor@sysoev.ru .timer_data = 60 * 1000, 55956Sigor@sysoev.ru .timer_autoreset = 1, 56027Svbart@nginx.com }; 56127Svbart@nginx.com 56227Svbart@nginx.com 56327Svbart@nginx.com static void 56427Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 56527Svbart@nginx.com { 566107Svbart@nginx.com size_t read; 567107Svbart@nginx.com nxt_buf_t *b; 568107Svbart@nginx.com nxt_conn_t *c; 569107Svbart@nginx.com nxt_controller_request_t *r; 57027Svbart@nginx.com 57127Svbart@nginx.com c = obj; 572107Svbart@nginx.com r = data; 57327Svbart@nginx.com b = c->read; 57427Svbart@nginx.com 575107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 57627Svbart@nginx.com 577107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 578107Svbart@nginx.com read, r->length); 57927Svbart@nginx.com 580107Svbart@nginx.com if (read >= r->length) { 581140Svbart@nginx.com nxt_controller_process_request(task, r); 58227Svbart@nginx.com return; 58327Svbart@nginx.com } 58427Svbart@nginx.com 58562Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 58627Svbart@nginx.com } 58727Svbart@nginx.com 58827Svbart@nginx.com 58927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 59027Svbart@nginx.com nxt_aligned(64) = 59127Svbart@nginx.com { 59256Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 59356Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 59427Svbart@nginx.com 59556Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 59656Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 59756Sigor@sysoev.ru .timer_data = 60 * 1000, 59856Sigor@sysoev.ru .timer_autoreset = 1, 59927Svbart@nginx.com }; 60027Svbart@nginx.com 60127Svbart@nginx.com 60227Svbart@nginx.com static void 60327Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 60427Svbart@nginx.com { 60562Sigor@sysoev.ru nxt_buf_t *b; 60662Sigor@sysoev.ru nxt_conn_t *c; 60727Svbart@nginx.com 60827Svbart@nginx.com c = obj; 60927Svbart@nginx.com 61027Svbart@nginx.com nxt_debug(task, "controller conn write"); 61127Svbart@nginx.com 61227Svbart@nginx.com b = c->write; 61327Svbart@nginx.com 61427Svbart@nginx.com if (b->mem.pos != b->mem.free) { 61562Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 61627Svbart@nginx.com return; 61727Svbart@nginx.com } 61827Svbart@nginx.com 61927Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 62027Svbart@nginx.com 62127Svbart@nginx.com nxt_controller_conn_close(task, c, data); 62227Svbart@nginx.com } 62327Svbart@nginx.com 62427Svbart@nginx.com 62527Svbart@nginx.com static void 62627Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 62727Svbart@nginx.com { 62862Sigor@sysoev.ru nxt_conn_t *c; 62927Svbart@nginx.com 63027Svbart@nginx.com c = obj; 63127Svbart@nginx.com 63227Svbart@nginx.com nxt_debug(task, "controller conn write error"); 63327Svbart@nginx.com 63427Svbart@nginx.com nxt_controller_conn_close(task, c, data); 63527Svbart@nginx.com } 63627Svbart@nginx.com 63727Svbart@nginx.com 63827Svbart@nginx.com static void 63927Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 64027Svbart@nginx.com { 64162Sigor@sysoev.ru nxt_conn_t *c; 64262Sigor@sysoev.ru nxt_timer_t *timer; 64327Svbart@nginx.com 64462Sigor@sysoev.ru timer = obj; 64527Svbart@nginx.com 64662Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 64727Svbart@nginx.com c->socket.timedout = 1; 64827Svbart@nginx.com c->socket.closed = 1; 64927Svbart@nginx.com 65027Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 65127Svbart@nginx.com 65227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 65320Sigor@sysoev.ru } 65420Sigor@sysoev.ru 65520Sigor@sysoev.ru 65620Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 65720Sigor@sysoev.ru nxt_aligned(64) = 65820Sigor@sysoev.ru { 65956Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 66020Sigor@sysoev.ru }; 66120Sigor@sysoev.ru 66220Sigor@sysoev.ru 66320Sigor@sysoev.ru static void 66420Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 66520Sigor@sysoev.ru { 66662Sigor@sysoev.ru nxt_conn_t *c; 66720Sigor@sysoev.ru 66820Sigor@sysoev.ru c = obj; 66920Sigor@sysoev.ru 67020Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 67120Sigor@sysoev.ru 67227Svbart@nginx.com nxt_queue_remove(&c->link); 67327Svbart@nginx.com 67420Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 67520Sigor@sysoev.ru 67662Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 67720Sigor@sysoev.ru } 67820Sigor@sysoev.ru 67920Sigor@sysoev.ru 68020Sigor@sysoev.ru static void 68120Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 68220Sigor@sysoev.ru { 68362Sigor@sysoev.ru nxt_conn_t *c; 68420Sigor@sysoev.ru 68520Sigor@sysoev.ru c = obj; 68620Sigor@sysoev.ru 68720Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 68820Sigor@sysoev.ru 68965Sigor@sysoev.ru nxt_mp_destroy(c->mem_pool); 69020Sigor@sysoev.ru 69120Sigor@sysoev.ru //nxt_free(c); 69220Sigor@sysoev.ru } 69327Svbart@nginx.com 69427Svbart@nginx.com 69527Svbart@nginx.com static nxt_int_t 69660Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 69767Svbart@nginx.com nxt_log_t *log) 69827Svbart@nginx.com { 69927Svbart@nginx.com off_t length; 70027Svbart@nginx.com nxt_controller_request_t *r; 70127Svbart@nginx.com 70227Svbart@nginx.com r = ctx; 70327Svbart@nginx.com 70460Svbart@nginx.com length = nxt_off_t_parse(field->value.start, field->value.length); 70527Svbart@nginx.com 70627Svbart@nginx.com if (nxt_fast_path(length > 0)) { 707107Svbart@nginx.com 708107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 709107Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is too big"); 710107Svbart@nginx.com return NXT_ERROR; 711107Svbart@nginx.com } 71227Svbart@nginx.com 71327Svbart@nginx.com r->length = length; 71427Svbart@nginx.com return NXT_OK; 71527Svbart@nginx.com } 71627Svbart@nginx.com 71760Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is invalid"); 71827Svbart@nginx.com 71927Svbart@nginx.com return NXT_ERROR; 72027Svbart@nginx.com } 72127Svbart@nginx.com 72227Svbart@nginx.com 72327Svbart@nginx.com static void 724140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 72527Svbart@nginx.com { 72665Sigor@sysoev.ru nxt_mp_t *mp; 72751Svbart@nginx.com nxt_int_t rc; 72846Svbart@nginx.com nxt_str_t path; 729140Svbart@nginx.com nxt_conn_t *c; 73051Svbart@nginx.com nxt_buf_mem_t *mbuf; 731106Svbart@nginx.com nxt_conf_op_t *ops; 732106Svbart@nginx.com nxt_conf_value_t *value; 733208Svbart@nginx.com nxt_conf_json_error_t error; 73444Svbart@nginx.com nxt_controller_response_t resp; 73544Svbart@nginx.com 73651Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 73751Svbart@nginx.com 738140Svbart@nginx.com c = req->conn; 739112Smax.romanov@nginx.com path = req->parser.path; 74051Svbart@nginx.com 74151Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 74251Svbart@nginx.com path.length--; 74351Svbart@nginx.com } 74451Svbart@nginx.com 74544Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 74644Svbart@nginx.com 74744Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 74846Svbart@nginx.com 749106Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, &path); 75051Svbart@nginx.com 75151Svbart@nginx.com if (value == NULL) { 752208Svbart@nginx.com goto not_found; 75351Svbart@nginx.com } 75451Svbart@nginx.com 755208Svbart@nginx.com resp.status = 200; 756106Svbart@nginx.com resp.conf = value; 75746Svbart@nginx.com 758208Svbart@nginx.com nxt_controller_response(task, req, &resp); 759208Svbart@nginx.com return; 76051Svbart@nginx.com } 76151Svbart@nginx.com 76251Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 76346Svbart@nginx.com 764238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 765238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 766238Svbart@nginx.com return; 767238Svbart@nginx.com } 768238Svbart@nginx.com 76965Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 77051Svbart@nginx.com 77151Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 772208Svbart@nginx.com goto alloc_fail; 77346Svbart@nginx.com } 77446Svbart@nginx.com 77551Svbart@nginx.com mbuf = &c->read->mem; 77651Svbart@nginx.com 777208Svbart@nginx.com nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); 778208Svbart@nginx.com 779208Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 78051Svbart@nginx.com 78151Svbart@nginx.com if (value == NULL) { 78265Sigor@sysoev.ru nxt_mp_destroy(mp); 783208Svbart@nginx.com 784208Svbart@nginx.com if (error.pos == NULL) { 785208Svbart@nginx.com goto alloc_fail; 786208Svbart@nginx.com } 787208Svbart@nginx.com 788208Svbart@nginx.com resp.status = 400; 789208Svbart@nginx.com resp.title = (u_char *) "Invalid JSON."; 790208Svbart@nginx.com resp.detail = error.detail; 791208Svbart@nginx.com resp.offset = error.pos - mbuf->pos; 792208Svbart@nginx.com 793208Svbart@nginx.com nxt_conf_json_position(mbuf->pos, error.pos, 794208Svbart@nginx.com &resp.line, &resp.column); 795208Svbart@nginx.com 796208Svbart@nginx.com nxt_controller_response(task, req, &resp); 797208Svbart@nginx.com return; 79851Svbart@nginx.com } 79951Svbart@nginx.com 80051Svbart@nginx.com if (path.length != 1) { 801106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 802106Svbart@nginx.com nxt_controller_conf.root, 803106Svbart@nginx.com &path, value); 80446Svbart@nginx.com 80551Svbart@nginx.com if (rc != NXT_OK) { 80651Svbart@nginx.com if (rc == NXT_DECLINED) { 807208Svbart@nginx.com goto not_found; 80851Svbart@nginx.com } 80946Svbart@nginx.com 810208Svbart@nginx.com goto alloc_fail; 81151Svbart@nginx.com } 81251Svbart@nginx.com 813106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 81451Svbart@nginx.com 81551Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 81665Sigor@sysoev.ru nxt_mp_destroy(mp); 817208Svbart@nginx.com goto alloc_fail; 81851Svbart@nginx.com } 81946Svbart@nginx.com } 82044Svbart@nginx.com 821116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 822121Svbart@nginx.com nxt_mp_destroy(mp); 823208Svbart@nginx.com goto invalid_conf; 824116Svbart@nginx.com } 825116Svbart@nginx.com 826249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 827249Svbart@nginx.com nxt_controller_conf_handler, req); 828247Svbart@nginx.com 829247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 830121Svbart@nginx.com nxt_mp_destroy(mp); 831247Svbart@nginx.com 832247Svbart@nginx.com if (rc == NXT_DECLINED) { 833247Svbart@nginx.com goto no_router; 834247Svbart@nginx.com } 835247Svbart@nginx.com 836247Svbart@nginx.com /* rc == NXT_ERROR */ 837208Svbart@nginx.com goto alloc_fail; 838121Svbart@nginx.com } 839121Svbart@nginx.com 840249Svbart@nginx.com req->conf.root = value; 841249Svbart@nginx.com req->conf.pool = mp; 842249Svbart@nginx.com 843249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 844249Svbart@nginx.com 845140Svbart@nginx.com return; 84651Svbart@nginx.com } 84727Svbart@nginx.com 84851Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 84951Svbart@nginx.com 850238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 851238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 852238Svbart@nginx.com return; 853238Svbart@nginx.com } 854238Svbart@nginx.com 85551Svbart@nginx.com if (path.length == 1) { 85665Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 85744Svbart@nginx.com 85851Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 859208Svbart@nginx.com goto alloc_fail; 86051Svbart@nginx.com } 86151Svbart@nginx.com 862106Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &empty_obj); 86327Svbart@nginx.com 86444Svbart@nginx.com } else { 865106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 866106Svbart@nginx.com nxt_controller_conf.root, 867106Svbart@nginx.com &path, NULL); 86851Svbart@nginx.com 86951Svbart@nginx.com if (rc != NXT_OK) { 87051Svbart@nginx.com if (rc == NXT_DECLINED) { 871208Svbart@nginx.com goto not_found; 87251Svbart@nginx.com } 87351Svbart@nginx.com 874208Svbart@nginx.com goto alloc_fail; 87551Svbart@nginx.com } 87651Svbart@nginx.com 87765Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 87851Svbart@nginx.com 87951Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 880208Svbart@nginx.com goto alloc_fail; 88151Svbart@nginx.com } 88251Svbart@nginx.com 883106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 88451Svbart@nginx.com } 88551Svbart@nginx.com 88651Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 88765Sigor@sysoev.ru nxt_mp_destroy(mp); 888208Svbart@nginx.com goto alloc_fail; 88944Svbart@nginx.com } 89044Svbart@nginx.com 891116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 892121Svbart@nginx.com nxt_mp_destroy(mp); 893208Svbart@nginx.com goto invalid_conf; 894116Svbart@nginx.com } 895116Svbart@nginx.com 896249Svbart@nginx.com rc = nxt_controller_conf_send(task, value, 897249Svbart@nginx.com nxt_controller_conf_handler, req); 898247Svbart@nginx.com 899247Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 900121Svbart@nginx.com nxt_mp_destroy(mp); 901247Svbart@nginx.com 902247Svbart@nginx.com if (rc == NXT_DECLINED) { 903247Svbart@nginx.com goto no_router; 904247Svbart@nginx.com } 905247Svbart@nginx.com 906247Svbart@nginx.com /* rc == NXT_ERROR */ 907208Svbart@nginx.com goto alloc_fail; 908121Svbart@nginx.com } 909121Svbart@nginx.com 910249Svbart@nginx.com req->conf.root = value; 911249Svbart@nginx.com req->conf.pool = mp; 912249Svbart@nginx.com 913249Svbart@nginx.com nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); 914249Svbart@nginx.com 915140Svbart@nginx.com return; 91651Svbart@nginx.com } 91751Svbart@nginx.com 918208Svbart@nginx.com resp.status = 405; 919208Svbart@nginx.com resp.title = (u_char *) "Invalid method."; 920208Svbart@nginx.com resp.offset = -1; 92151Svbart@nginx.com 922208Svbart@nginx.com nxt_controller_response(task, req, &resp); 923208Svbart@nginx.com return; 92451Svbart@nginx.com 925208Svbart@nginx.com not_found: 926208Svbart@nginx.com 927208Svbart@nginx.com resp.status = 404; 928208Svbart@nginx.com resp.title = (u_char *) "Value doesn't exist."; 929208Svbart@nginx.com resp.offset = -1; 930208Svbart@nginx.com 931208Svbart@nginx.com nxt_controller_response(task, req, &resp); 932208Svbart@nginx.com return; 933208Svbart@nginx.com 934208Svbart@nginx.com invalid_conf: 935208Svbart@nginx.com 936208Svbart@nginx.com resp.status = 400; 937208Svbart@nginx.com resp.title = (u_char *) "Invalid configuration."; 938208Svbart@nginx.com resp.offset = -1; 939208Svbart@nginx.com 940208Svbart@nginx.com nxt_controller_response(task, req, &resp); 941208Svbart@nginx.com return; 942247Svbart@nginx.com 943247Svbart@nginx.com alloc_fail: 944247Svbart@nginx.com 945247Svbart@nginx.com resp.status = 500; 946247Svbart@nginx.com resp.title = (u_char *) "Memory allocation failed."; 947247Svbart@nginx.com resp.offset = -1; 948247Svbart@nginx.com 949247Svbart@nginx.com nxt_controller_response(task, req, &resp); 950247Svbart@nginx.com return; 951247Svbart@nginx.com 952247Svbart@nginx.com no_router: 953247Svbart@nginx.com 954247Svbart@nginx.com resp.status = 500; 955247Svbart@nginx.com resp.title = (u_char *) "Router process isn't available."; 956247Svbart@nginx.com resp.offset = -1; 957247Svbart@nginx.com 958247Svbart@nginx.com nxt_controller_response(task, req, &resp); 959247Svbart@nginx.com return; 96027Svbart@nginx.com } 96127Svbart@nginx.com 96227Svbart@nginx.com 963193Smax.romanov@nginx.com static void 964193Smax.romanov@nginx.com nxt_controller_conf_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 965193Smax.romanov@nginx.com void *data) 966140Svbart@nginx.com { 967238Svbart@nginx.com nxt_queue_t queue; 968140Svbart@nginx.com nxt_controller_request_t *req; 969140Svbart@nginx.com nxt_controller_response_t resp; 970140Svbart@nginx.com 971238Svbart@nginx.com req = data; 972238Svbart@nginx.com 973201Svbart@nginx.com nxt_debug(task, "controller conf ready: %*s", 974201Svbart@nginx.com nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); 975140Svbart@nginx.com 976238Svbart@nginx.com nxt_queue_remove(&req->link); 977140Svbart@nginx.com 978238Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 979140Svbart@nginx.com 980193Smax.romanov@nginx.com if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { 981140Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 982140Svbart@nginx.com 983140Svbart@nginx.com nxt_controller_conf = req->conf; 984140Svbart@nginx.com 985314Svbart@nginx.com nxt_controller_conf_store(task, req->conf.root); 986314Svbart@nginx.com 987208Svbart@nginx.com resp.status = 200; 988208Svbart@nginx.com resp.title = (u_char *) "Reconfiguration done."; 989140Svbart@nginx.com 990140Svbart@nginx.com } else { 991140Svbart@nginx.com nxt_mp_destroy(req->conf.pool); 992140Svbart@nginx.com 993208Svbart@nginx.com resp.status = 500; 994208Svbart@nginx.com resp.title = (u_char *) "Failed to apply new configuration."; 995208Svbart@nginx.com resp.offset = -1; 996140Svbart@nginx.com } 997140Svbart@nginx.com 998140Svbart@nginx.com nxt_controller_response(task, req, &resp); 999140Svbart@nginx.com 1000238Svbart@nginx.com nxt_queue_init(&queue); 1001238Svbart@nginx.com nxt_queue_add(&queue, &nxt_controller_waiting_requests); 1002140Svbart@nginx.com 1003238Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 1004121Svbart@nginx.com 1005238Svbart@nginx.com nxt_queue_each(req, &queue, nxt_controller_request_t, link) { 1006238Svbart@nginx.com nxt_controller_process_request(task, req); 1007238Svbart@nginx.com } nxt_queue_loop; 1008121Svbart@nginx.com } 1009121Svbart@nginx.com 1010121Svbart@nginx.com 1011140Svbart@nginx.com static void 1012314Svbart@nginx.com nxt_controller_conf_store(nxt_task_t *task, nxt_conf_value_t *conf) 1013314Svbart@nginx.com { 1014314Svbart@nginx.com size_t size; 1015314Svbart@nginx.com nxt_buf_t *b; 1016314Svbart@nginx.com nxt_port_t *main_port; 1017314Svbart@nginx.com nxt_runtime_t *rt; 1018314Svbart@nginx.com 1019314Svbart@nginx.com rt = task->thread->runtime; 1020314Svbart@nginx.com 1021314Svbart@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1022314Svbart@nginx.com 1023314Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 1024314Svbart@nginx.com 1025314Svbart@nginx.com b = nxt_buf_mem_alloc(main_port->mem_pool, size, 0); 1026314Svbart@nginx.com 1027314Svbart@nginx.com if (nxt_fast_path(b != NULL)) { 1028314Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 1029314Svbart@nginx.com 1030314Svbart@nginx.com (void) nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CONF_STORE, 1031314Svbart@nginx.com -1, 0, -1, b); 1032314Svbart@nginx.com } 1033314Svbart@nginx.com } 1034314Svbart@nginx.com 1035