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> 1020Sigor@sysoev.ru #include <nxt_master_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; 2333Svbart@nginx.com 2444Svbart@nginx.com nxt_controller_conf_t conf; 2527Svbart@nginx.com } nxt_controller_request_t; 2627Svbart@nginx.com 2727Svbart@nginx.com 2844Svbart@nginx.com typedef struct { 29106Svbart@nginx.com nxt_str_t status_line; 30106Svbart@nginx.com nxt_conf_value_t *conf; 31106Svbart@nginx.com nxt_str_t json; 3244Svbart@nginx.com } nxt_controller_response_t; 3344Svbart@nginx.com 3444Svbart@nginx.com 3520Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 3620Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 3762Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 3820Sigor@sysoev.ru uintptr_t data); 3920Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 4020Sigor@sysoev.ru void *data); 4120Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 4220Sigor@sysoev.ru void *data); 4327Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 4427Svbart@nginx.com void *data); 4527Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 4627Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 4727Svbart@nginx.com void *data); 4827Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 4927Svbart@nginx.com void *data); 5020Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 5120Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 5220Sigor@sysoev.ru 5327Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 5467Svbart@nginx.com nxt_http_field_t *field, nxt_log_t *log); 5527Svbart@nginx.com 5627Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 5762Sigor@sysoev.ru nxt_conn_t *c, nxt_controller_request_t *r); 58*121Svbart@nginx.com static nxt_int_t nxt_controller_conf_apply(nxt_task_t *task, 59*121Svbart@nginx.com nxt_conf_value_t *conf); 6062Sigor@sysoev.ru static nxt_int_t nxt_controller_response(nxt_task_t *task, nxt_conn_t *c, 6144Svbart@nginx.com nxt_controller_response_t *resp); 6245Svbart@nginx.com static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp, 6365Sigor@sysoev.ru nxt_mp_t *pool); 6427Svbart@nginx.com 6527Svbart@nginx.com 6660Svbart@nginx.com static nxt_http_fields_hash_entry_t nxt_controller_request_fields[] = { 6727Svbart@nginx.com { nxt_string("Content-Length"), 6827Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 6927Svbart@nginx.com 7027Svbart@nginx.com { nxt_null_string, NULL, 0 } 7127Svbart@nginx.com }; 7227Svbart@nginx.com 7360Svbart@nginx.com static nxt_http_fields_hash_t *nxt_controller_fields_hash; 7427Svbart@nginx.com 7544Svbart@nginx.com 7644Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 7727Svbart@nginx.com 7820Sigor@sysoev.ru 7920Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 8027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 8127Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 8220Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 8320Sigor@sysoev.ru 8420Sigor@sysoev.ru 8520Sigor@sysoev.ru nxt_int_t 8620Sigor@sysoev.ru nxt_controller_start(nxt_task_t *task, nxt_runtime_t *rt) 8720Sigor@sysoev.ru { 8865Sigor@sysoev.ru nxt_mp_t *mp; 89106Svbart@nginx.com nxt_conf_value_t *conf; 9027Svbart@nginx.com nxt_http_fields_hash_t *hash; 9127Svbart@nginx.com 9244Svbart@nginx.com static const nxt_str_t json 93116Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 9444Svbart@nginx.com 9560Svbart@nginx.com hash = nxt_http_fields_hash_create(nxt_controller_request_fields, 9660Svbart@nginx.com rt->mem_pool); 9727Svbart@nginx.com if (nxt_slow_path(hash == NULL)) { 9827Svbart@nginx.com return NXT_ERROR; 9927Svbart@nginx.com } 10027Svbart@nginx.com 10160Svbart@nginx.com nxt_controller_fields_hash = hash; 10227Svbart@nginx.com 10354Sigor@sysoev.ru if (nxt_listen_event(task, rt->controller_socket) == NULL) { 10420Sigor@sysoev.ru return NXT_ERROR; 10520Sigor@sysoev.ru } 10620Sigor@sysoev.ru 10765Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 10844Svbart@nginx.com 10944Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 11044Svbart@nginx.com return NXT_ERROR; 11144Svbart@nginx.com } 11244Svbart@nginx.com 113106Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 11444Svbart@nginx.com 11544Svbart@nginx.com if (conf == NULL) { 11644Svbart@nginx.com return NXT_ERROR; 11744Svbart@nginx.com } 11844Svbart@nginx.com 11944Svbart@nginx.com nxt_controller_conf.root = conf; 12044Svbart@nginx.com nxt_controller_conf.pool = mp; 12144Svbart@nginx.com 12220Sigor@sysoev.ru return NXT_OK; 12320Sigor@sysoev.ru } 12420Sigor@sysoev.ru 12520Sigor@sysoev.ru 12620Sigor@sysoev.ru nxt_int_t 12720Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 12820Sigor@sysoev.ru { 12920Sigor@sysoev.ru nxt_sockaddr_t *sa; 13020Sigor@sysoev.ru nxt_listen_socket_t *ls; 13120Sigor@sysoev.ru 13220Sigor@sysoev.ru sa = rt->controller_listen; 13320Sigor@sysoev.ru 13420Sigor@sysoev.ru if (rt->controller_listen == NULL) { 13520Sigor@sysoev.ru sa = nxt_sockaddr_alloc(rt->mem_pool, sizeof(struct sockaddr_in), 13620Sigor@sysoev.ru NXT_INET_ADDR_STR_LEN); 13720Sigor@sysoev.ru if (sa == NULL) { 13820Sigor@sysoev.ru return NXT_ERROR; 13920Sigor@sysoev.ru } 14020Sigor@sysoev.ru 14120Sigor@sysoev.ru sa->type = SOCK_STREAM; 14220Sigor@sysoev.ru sa->u.sockaddr_in.sin_family = AF_INET; 14320Sigor@sysoev.ru sa->u.sockaddr_in.sin_port = htons(8443); 14420Sigor@sysoev.ru 14520Sigor@sysoev.ru nxt_sockaddr_text(sa); 14620Sigor@sysoev.ru 14720Sigor@sysoev.ru rt->controller_listen = sa; 14820Sigor@sysoev.ru } 14920Sigor@sysoev.ru 15065Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 15120Sigor@sysoev.ru if (ls == NULL) { 15220Sigor@sysoev.ru return NXT_ERROR; 15320Sigor@sysoev.ru } 15420Sigor@sysoev.ru 15520Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 15620Sigor@sysoev.ru sa->socklen, sa->length); 15720Sigor@sysoev.ru if (ls->sockaddr == NULL) { 15820Sigor@sysoev.ru return NXT_ERROR; 15920Sigor@sysoev.ru } 16020Sigor@sysoev.ru 16120Sigor@sysoev.ru ls->sockaddr->type = sa->type; 162103Sigor@sysoev.ru ls->socklen = sa->socklen; 163103Sigor@sysoev.ru ls->address_length = sa->length; 16420Sigor@sysoev.ru 16520Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 16620Sigor@sysoev.ru 16720Sigor@sysoev.ru ls->socket = -1; 16820Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 16920Sigor@sysoev.ru ls->read_after_accept = 1; 17020Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 17120Sigor@sysoev.ru 17220Sigor@sysoev.ru #if 0 17320Sigor@sysoev.ru /* STUB */ 17465Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 17520Sigor@sysoev.ru if (wq == NULL) { 17620Sigor@sysoev.ru return NXT_ERROR; 17720Sigor@sysoev.ru } 17820Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 17920Sigor@sysoev.ru /**/ 18020Sigor@sysoev.ru 18120Sigor@sysoev.ru ls->work_queue = wq; 18220Sigor@sysoev.ru #endif 18320Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 18420Sigor@sysoev.ru 18520Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 18620Sigor@sysoev.ru return NXT_ERROR; 18720Sigor@sysoev.ru } 18820Sigor@sysoev.ru 18920Sigor@sysoev.ru rt->controller_socket = ls; 19020Sigor@sysoev.ru 19120Sigor@sysoev.ru return NXT_OK; 19220Sigor@sysoev.ru } 19320Sigor@sysoev.ru 19420Sigor@sysoev.ru 19520Sigor@sysoev.ru static void 19620Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 19720Sigor@sysoev.ru { 19827Svbart@nginx.com nxt_buf_t *b; 19962Sigor@sysoev.ru nxt_conn_t *c; 20027Svbart@nginx.com nxt_event_engine_t *engine; 20127Svbart@nginx.com nxt_controller_request_t *r; 20220Sigor@sysoev.ru 20320Sigor@sysoev.ru c = obj; 20420Sigor@sysoev.ru 20520Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 20620Sigor@sysoev.ru 20765Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 20827Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 20927Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 21027Svbart@nginx.com return; 21127Svbart@nginx.com } 21227Svbart@nginx.com 21360Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 21460Svbart@nginx.com != NXT_OK)) 21560Svbart@nginx.com { 21660Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 21760Svbart@nginx.com return; 21860Svbart@nginx.com } 21927Svbart@nginx.com 22067Svbart@nginx.com r->parser.fields_hash = nxt_controller_fields_hash; 22167Svbart@nginx.com 22220Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 22320Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 22420Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 22520Sigor@sysoev.ru return; 22620Sigor@sysoev.ru } 22720Sigor@sysoev.ru 22820Sigor@sysoev.ru c->read = b; 22927Svbart@nginx.com c->socket.data = r; 23020Sigor@sysoev.ru c->socket.read_ready = 1; 23120Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 23220Sigor@sysoev.ru 23320Sigor@sysoev.ru engine = task->thread->engine; 23420Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 23527Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 23620Sigor@sysoev.ru 23762Sigor@sysoev.ru nxt_conn_read(engine, c); 23820Sigor@sysoev.ru } 23920Sigor@sysoev.ru 24020Sigor@sysoev.ru 24120Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 24220Sigor@sysoev.ru nxt_aligned(64) = 24320Sigor@sysoev.ru { 24456Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 24556Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 24656Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 24720Sigor@sysoev.ru 24856Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 24956Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 25056Sigor@sysoev.ru .timer_data = 60 * 1000, 25120Sigor@sysoev.ru }; 25220Sigor@sysoev.ru 25320Sigor@sysoev.ru 25420Sigor@sysoev.ru static void 25520Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 25620Sigor@sysoev.ru { 25727Svbart@nginx.com size_t preread; 25827Svbart@nginx.com nxt_buf_t *b; 25927Svbart@nginx.com nxt_int_t rc; 26062Sigor@sysoev.ru nxt_conn_t *c; 26127Svbart@nginx.com nxt_controller_request_t *r; 26220Sigor@sysoev.ru 26320Sigor@sysoev.ru c = obj; 26427Svbart@nginx.com r = data; 26520Sigor@sysoev.ru 26620Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 26720Sigor@sysoev.ru 26827Svbart@nginx.com nxt_queue_remove(&c->link); 26927Svbart@nginx.com nxt_queue_self(&c->link); 27027Svbart@nginx.com 27127Svbart@nginx.com b = c->read; 27227Svbart@nginx.com 27327Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 27427Svbart@nginx.com 27527Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 27627Svbart@nginx.com 27727Svbart@nginx.com if (rc == NXT_AGAIN) { 27827Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 27927Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 28027Svbart@nginx.com nxt_controller_conn_close(task, c, r); 28127Svbart@nginx.com return; 28227Svbart@nginx.com } 28327Svbart@nginx.com 28462Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 28527Svbart@nginx.com return; 28627Svbart@nginx.com } 28727Svbart@nginx.com 28827Svbart@nginx.com /* rc == NXT_ERROR */ 28927Svbart@nginx.com 29027Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 29127Svbart@nginx.com 29227Svbart@nginx.com nxt_controller_conn_close(task, c, r); 29327Svbart@nginx.com return; 29427Svbart@nginx.com } 29527Svbart@nginx.com 29667Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, r, task->log); 29760Svbart@nginx.com 29860Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 29960Svbart@nginx.com nxt_controller_conn_close(task, c, r); 30060Svbart@nginx.com return; 30160Svbart@nginx.com } 30260Svbart@nginx.com 30327Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 30427Svbart@nginx.com 30527Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 306107Svbart@nginx.com "body length: %uz, preread: %uz", 30727Svbart@nginx.com r->length, preread); 30827Svbart@nginx.com 30927Svbart@nginx.com if (preread >= r->length) { 31027Svbart@nginx.com nxt_controller_process_request(task, c, r); 31127Svbart@nginx.com return; 31227Svbart@nginx.com } 31327Svbart@nginx.com 31427Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 31527Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 31627Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 31727Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 31827Svbart@nginx.com return; 31927Svbart@nginx.com } 32027Svbart@nginx.com 32127Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 32227Svbart@nginx.com 32327Svbart@nginx.com c->read = b; 32427Svbart@nginx.com } 32527Svbart@nginx.com 32627Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 32727Svbart@nginx.com 32862Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 32920Sigor@sysoev.ru } 33020Sigor@sysoev.ru 33120Sigor@sysoev.ru 33220Sigor@sysoev.ru static nxt_msec_t 33362Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 33420Sigor@sysoev.ru { 33520Sigor@sysoev.ru return (nxt_msec_t) data; 33620Sigor@sysoev.ru } 33720Sigor@sysoev.ru 33820Sigor@sysoev.ru 33920Sigor@sysoev.ru static void 34020Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 34120Sigor@sysoev.ru { 34262Sigor@sysoev.ru nxt_conn_t *c; 34320Sigor@sysoev.ru 34420Sigor@sysoev.ru c = obj; 34520Sigor@sysoev.ru 34620Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 34720Sigor@sysoev.ru 34827Svbart@nginx.com nxt_controller_conn_close(task, c, data); 34920Sigor@sysoev.ru } 35020Sigor@sysoev.ru 35120Sigor@sysoev.ru 35220Sigor@sysoev.ru static void 35320Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 35420Sigor@sysoev.ru { 35562Sigor@sysoev.ru nxt_timer_t *timer; 35662Sigor@sysoev.ru nxt_conn_t *c; 35720Sigor@sysoev.ru 35862Sigor@sysoev.ru timer = obj; 35920Sigor@sysoev.ru 36062Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 36120Sigor@sysoev.ru c->socket.timedout = 1; 36220Sigor@sysoev.ru c->socket.closed = 1; 36320Sigor@sysoev.ru 36420Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 36520Sigor@sysoev.ru 36627Svbart@nginx.com nxt_controller_conn_close(task, c, data); 36727Svbart@nginx.com } 36827Svbart@nginx.com 36927Svbart@nginx.com 37027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 37127Svbart@nginx.com nxt_aligned(64) = 37227Svbart@nginx.com { 37356Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 37456Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 37556Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 37627Svbart@nginx.com 37756Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 37856Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 37956Sigor@sysoev.ru .timer_data = 60 * 1000, 38056Sigor@sysoev.ru .timer_autoreset = 1, 38127Svbart@nginx.com }; 38227Svbart@nginx.com 38327Svbart@nginx.com 38427Svbart@nginx.com static void 38527Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 38627Svbart@nginx.com { 387107Svbart@nginx.com size_t read; 388107Svbart@nginx.com nxt_buf_t *b; 389107Svbart@nginx.com nxt_conn_t *c; 390107Svbart@nginx.com nxt_controller_request_t *r; 39127Svbart@nginx.com 39227Svbart@nginx.com c = obj; 393107Svbart@nginx.com r = data; 39427Svbart@nginx.com b = c->read; 39527Svbart@nginx.com 396107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 39727Svbart@nginx.com 398107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 399107Svbart@nginx.com read, r->length); 40027Svbart@nginx.com 401107Svbart@nginx.com if (read >= r->length) { 40227Svbart@nginx.com nxt_controller_process_request(task, c, data); 40327Svbart@nginx.com return; 40427Svbart@nginx.com } 40527Svbart@nginx.com 40662Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 40727Svbart@nginx.com } 40827Svbart@nginx.com 40927Svbart@nginx.com 41027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 41127Svbart@nginx.com nxt_aligned(64) = 41227Svbart@nginx.com { 41356Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 41456Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 41527Svbart@nginx.com 41656Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 41756Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 41856Sigor@sysoev.ru .timer_data = 60 * 1000, 41956Sigor@sysoev.ru .timer_autoreset = 1, 42027Svbart@nginx.com }; 42127Svbart@nginx.com 42227Svbart@nginx.com 42327Svbart@nginx.com static void 42427Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 42527Svbart@nginx.com { 42662Sigor@sysoev.ru nxt_buf_t *b; 42762Sigor@sysoev.ru nxt_conn_t *c; 42827Svbart@nginx.com 42927Svbart@nginx.com c = obj; 43027Svbart@nginx.com 43127Svbart@nginx.com nxt_debug(task, "controller conn write"); 43227Svbart@nginx.com 43327Svbart@nginx.com b = c->write; 43427Svbart@nginx.com 43527Svbart@nginx.com if (b->mem.pos != b->mem.free) { 43662Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 43727Svbart@nginx.com return; 43827Svbart@nginx.com } 43927Svbart@nginx.com 44027Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 44127Svbart@nginx.com 44227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 44327Svbart@nginx.com } 44427Svbart@nginx.com 44527Svbart@nginx.com 44627Svbart@nginx.com static void 44727Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 44827Svbart@nginx.com { 44962Sigor@sysoev.ru nxt_conn_t *c; 45027Svbart@nginx.com 45127Svbart@nginx.com c = obj; 45227Svbart@nginx.com 45327Svbart@nginx.com nxt_debug(task, "controller conn write error"); 45427Svbart@nginx.com 45527Svbart@nginx.com nxt_controller_conn_close(task, c, data); 45627Svbart@nginx.com } 45727Svbart@nginx.com 45827Svbart@nginx.com 45927Svbart@nginx.com static void 46027Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 46127Svbart@nginx.com { 46262Sigor@sysoev.ru nxt_conn_t *c; 46362Sigor@sysoev.ru nxt_timer_t *timer; 46427Svbart@nginx.com 46562Sigor@sysoev.ru timer = obj; 46627Svbart@nginx.com 46762Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 46827Svbart@nginx.com c->socket.timedout = 1; 46927Svbart@nginx.com c->socket.closed = 1; 47027Svbart@nginx.com 47127Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 47227Svbart@nginx.com 47327Svbart@nginx.com nxt_controller_conn_close(task, c, data); 47420Sigor@sysoev.ru } 47520Sigor@sysoev.ru 47620Sigor@sysoev.ru 47720Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 47820Sigor@sysoev.ru nxt_aligned(64) = 47920Sigor@sysoev.ru { 48056Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 48120Sigor@sysoev.ru }; 48220Sigor@sysoev.ru 48320Sigor@sysoev.ru 48420Sigor@sysoev.ru static void 48520Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 48620Sigor@sysoev.ru { 48762Sigor@sysoev.ru nxt_conn_t *c; 48820Sigor@sysoev.ru 48920Sigor@sysoev.ru c = obj; 49020Sigor@sysoev.ru 49120Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 49220Sigor@sysoev.ru 49327Svbart@nginx.com nxt_queue_remove(&c->link); 49427Svbart@nginx.com 49520Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 49620Sigor@sysoev.ru 49762Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 49820Sigor@sysoev.ru } 49920Sigor@sysoev.ru 50020Sigor@sysoev.ru 50120Sigor@sysoev.ru static void 50220Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 50320Sigor@sysoev.ru { 50462Sigor@sysoev.ru nxt_conn_t *c; 50520Sigor@sysoev.ru 50620Sigor@sysoev.ru c = obj; 50720Sigor@sysoev.ru 50820Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 50920Sigor@sysoev.ru 51065Sigor@sysoev.ru nxt_mp_destroy(c->mem_pool); 51120Sigor@sysoev.ru 51220Sigor@sysoev.ru //nxt_free(c); 51320Sigor@sysoev.ru } 51427Svbart@nginx.com 51527Svbart@nginx.com 51627Svbart@nginx.com static nxt_int_t 51760Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 51867Svbart@nginx.com nxt_log_t *log) 51927Svbart@nginx.com { 52027Svbart@nginx.com off_t length; 52127Svbart@nginx.com nxt_controller_request_t *r; 52227Svbart@nginx.com 52327Svbart@nginx.com r = ctx; 52427Svbart@nginx.com 52560Svbart@nginx.com length = nxt_off_t_parse(field->value.start, field->value.length); 52627Svbart@nginx.com 52727Svbart@nginx.com if (nxt_fast_path(length > 0)) { 528107Svbart@nginx.com 529107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 530107Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is too big"); 531107Svbart@nginx.com return NXT_ERROR; 532107Svbart@nginx.com } 53327Svbart@nginx.com 53427Svbart@nginx.com r->length = length; 53527Svbart@nginx.com return NXT_OK; 53627Svbart@nginx.com } 53727Svbart@nginx.com 53860Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is invalid"); 53927Svbart@nginx.com 54027Svbart@nginx.com return NXT_ERROR; 54127Svbart@nginx.com } 54227Svbart@nginx.com 54327Svbart@nginx.com 54427Svbart@nginx.com static void 54562Sigor@sysoev.ru nxt_controller_process_request(nxt_task_t *task, nxt_conn_t *c, 54644Svbart@nginx.com nxt_controller_request_t *req) 54727Svbart@nginx.com { 54865Sigor@sysoev.ru nxt_mp_t *mp; 54951Svbart@nginx.com nxt_int_t rc; 55046Svbart@nginx.com nxt_str_t path; 55151Svbart@nginx.com nxt_uint_t status; 55251Svbart@nginx.com nxt_buf_mem_t *mbuf; 553106Svbart@nginx.com nxt_conf_op_t *ops; 554106Svbart@nginx.com nxt_conf_value_t *value; 55544Svbart@nginx.com nxt_controller_response_t resp; 55644Svbart@nginx.com 55751Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 55851Svbart@nginx.com 559112Smax.romanov@nginx.com path = req->parser.path; 56051Svbart@nginx.com 56151Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 56251Svbart@nginx.com path.length--; 56351Svbart@nginx.com } 56451Svbart@nginx.com 56544Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 56644Svbart@nginx.com 56744Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 56846Svbart@nginx.com 569106Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, &path); 57051Svbart@nginx.com 57151Svbart@nginx.com if (value == NULL) { 57251Svbart@nginx.com status = 404; 57351Svbart@nginx.com goto done; 57451Svbart@nginx.com } 57551Svbart@nginx.com 576106Svbart@nginx.com resp.conf = value; 57746Svbart@nginx.com 57851Svbart@nginx.com status = 200; 57951Svbart@nginx.com goto done; 58051Svbart@nginx.com } 58151Svbart@nginx.com 58251Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 58346Svbart@nginx.com 58465Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 58551Svbart@nginx.com 58651Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 58751Svbart@nginx.com status = 500; 58851Svbart@nginx.com goto done; 58946Svbart@nginx.com } 59046Svbart@nginx.com 59151Svbart@nginx.com mbuf = &c->read->mem; 59251Svbart@nginx.com 59391Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free); 59451Svbart@nginx.com 59551Svbart@nginx.com if (value == NULL) { 59665Sigor@sysoev.ru nxt_mp_destroy(mp); 59751Svbart@nginx.com status = 400; 598116Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Invalid JSON.\" }"); 59951Svbart@nginx.com goto done; 60051Svbart@nginx.com } 60151Svbart@nginx.com 60251Svbart@nginx.com if (path.length != 1) { 603106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 604106Svbart@nginx.com nxt_controller_conf.root, 605106Svbart@nginx.com &path, value); 60646Svbart@nginx.com 60751Svbart@nginx.com if (rc != NXT_OK) { 60851Svbart@nginx.com if (rc == NXT_DECLINED) { 60951Svbart@nginx.com status = 404; 61051Svbart@nginx.com goto done; 61151Svbart@nginx.com } 61246Svbart@nginx.com 61351Svbart@nginx.com status = 500; 61451Svbart@nginx.com goto done; 61551Svbart@nginx.com } 61651Svbart@nginx.com 617106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 61851Svbart@nginx.com 61951Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 62065Sigor@sysoev.ru nxt_mp_destroy(mp); 62151Svbart@nginx.com status = 500; 62251Svbart@nginx.com goto done; 62351Svbart@nginx.com } 62446Svbart@nginx.com } 62544Svbart@nginx.com 626116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 627*121Svbart@nginx.com nxt_mp_destroy(mp); 628116Svbart@nginx.com status = 400; 629116Svbart@nginx.com nxt_str_set(&resp.json, 630116Svbart@nginx.com "{ \"error\": \"Invalid configuration.\" }"); 631116Svbart@nginx.com goto done; 632116Svbart@nginx.com } 633116Svbart@nginx.com 634*121Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_apply(task, value) != NXT_OK)) { 635*121Svbart@nginx.com nxt_mp_destroy(mp); 636*121Svbart@nginx.com status = 500; 637*121Svbart@nginx.com goto done; 638*121Svbart@nginx.com } 639*121Svbart@nginx.com 64065Sigor@sysoev.ru nxt_mp_destroy(nxt_controller_conf.pool); 64151Svbart@nginx.com 64251Svbart@nginx.com nxt_controller_conf.root = value; 64351Svbart@nginx.com nxt_controller_conf.pool = mp; 64444Svbart@nginx.com 645106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"success\": \"Updated.\" }"); 64651Svbart@nginx.com 64751Svbart@nginx.com status = 200; 64851Svbart@nginx.com goto done; 64951Svbart@nginx.com } 65027Svbart@nginx.com 65151Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 65251Svbart@nginx.com 65351Svbart@nginx.com if (path.length == 1) { 65465Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 65544Svbart@nginx.com 65651Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 65751Svbart@nginx.com status = 500; 65851Svbart@nginx.com goto done; 65951Svbart@nginx.com } 66051Svbart@nginx.com 661106Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &empty_obj); 66227Svbart@nginx.com 66344Svbart@nginx.com } else { 664106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 665106Svbart@nginx.com nxt_controller_conf.root, 666106Svbart@nginx.com &path, NULL); 66751Svbart@nginx.com 66851Svbart@nginx.com if (rc != NXT_OK) { 66951Svbart@nginx.com if (rc == NXT_DECLINED) { 67051Svbart@nginx.com status = 404; 67151Svbart@nginx.com goto done; 67251Svbart@nginx.com } 67351Svbart@nginx.com 67451Svbart@nginx.com status = 500; 67551Svbart@nginx.com goto done; 67651Svbart@nginx.com } 67751Svbart@nginx.com 67865Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 67951Svbart@nginx.com 68051Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 68151Svbart@nginx.com status = 500; 68251Svbart@nginx.com goto done; 68351Svbart@nginx.com } 68451Svbart@nginx.com 685106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 68651Svbart@nginx.com } 68751Svbart@nginx.com 68851Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 68965Sigor@sysoev.ru nxt_mp_destroy(mp); 69051Svbart@nginx.com status = 500; 69151Svbart@nginx.com goto done; 69244Svbart@nginx.com } 69344Svbart@nginx.com 694116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 695*121Svbart@nginx.com nxt_mp_destroy(mp); 696116Svbart@nginx.com status = 400; 697116Svbart@nginx.com nxt_str_set(&resp.json, 698116Svbart@nginx.com "{ \"error\": \"Invalid configuration.\" }"); 699116Svbart@nginx.com goto done; 700116Svbart@nginx.com } 701116Svbart@nginx.com 702*121Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_apply(task, value) != NXT_OK)) { 703*121Svbart@nginx.com nxt_mp_destroy(mp); 704*121Svbart@nginx.com status = 500; 705*121Svbart@nginx.com goto done; 706*121Svbart@nginx.com } 707*121Svbart@nginx.com 70865Sigor@sysoev.ru nxt_mp_destroy(nxt_controller_conf.pool); 70951Svbart@nginx.com 71051Svbart@nginx.com nxt_controller_conf.root = value; 71151Svbart@nginx.com nxt_controller_conf.pool = mp; 71251Svbart@nginx.com 713106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"success\": \"Deleted.\" }"); 71451Svbart@nginx.com 71551Svbart@nginx.com status = 200; 71651Svbart@nginx.com goto done; 71751Svbart@nginx.com } 71851Svbart@nginx.com 71951Svbart@nginx.com status = 405; 72051Svbart@nginx.com 72151Svbart@nginx.com done: 72251Svbart@nginx.com 72351Svbart@nginx.com switch (status) { 72451Svbart@nginx.com 72551Svbart@nginx.com case 200: 72651Svbart@nginx.com nxt_str_set(&resp.status_line, "200 OK"); 72751Svbart@nginx.com break; 72851Svbart@nginx.com 72951Svbart@nginx.com case 400: 73051Svbart@nginx.com nxt_str_set(&resp.status_line, "400 Bad Request"); 73151Svbart@nginx.com break; 73251Svbart@nginx.com 73351Svbart@nginx.com case 404: 73451Svbart@nginx.com nxt_str_set(&resp.status_line, "404 Not Found"); 735106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Value doesn't exist.\" }"); 73651Svbart@nginx.com break; 73751Svbart@nginx.com 73851Svbart@nginx.com case 405: 73944Svbart@nginx.com nxt_str_set(&resp.status_line, "405 Method Not Allowed"); 740106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Invalid method.\" }"); 74151Svbart@nginx.com break; 74251Svbart@nginx.com 74351Svbart@nginx.com case 500: 74451Svbart@nginx.com nxt_str_set(&resp.status_line, "500 Internal Server Error"); 745106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Memory allocation failed.\" }"); 74651Svbart@nginx.com break; 74729Svbart@nginx.com } 74827Svbart@nginx.com 74944Svbart@nginx.com if (nxt_controller_response(task, c, &resp) != NXT_OK) { 75044Svbart@nginx.com nxt_controller_conn_close(task, c, req); 75127Svbart@nginx.com } 75227Svbart@nginx.com } 75327Svbart@nginx.com 75427Svbart@nginx.com 75527Svbart@nginx.com static nxt_int_t 756*121Svbart@nginx.com nxt_controller_conf_apply(nxt_task_t *task, nxt_conf_value_t *conf) 757*121Svbart@nginx.com { 758*121Svbart@nginx.com size_t size; 759*121Svbart@nginx.com uint32_t next, n; 760*121Svbart@nginx.com nxt_mp_t *mp; 761*121Svbart@nginx.com nxt_buf_t *b; 762*121Svbart@nginx.com nxt_int_t rc; 763*121Svbart@nginx.com nxt_str_t ls_name, name; 764*121Svbart@nginx.com nxt_port_t *port; 765*121Svbart@nginx.com nxt_uint_t lss_count; 766*121Svbart@nginx.com nxt_runtime_t *rt; 767*121Svbart@nginx.com nxt_conf_value_t *lss, *ls, *rtr, *rtr_lss, *rtr_ls, *app_name, *apps, 768*121Svbart@nginx.com *app, *value; 769*121Svbart@nginx.com 770*121Svbart@nginx.com static nxt_str_t lss_str = nxt_string("listeners"); 771*121Svbart@nginx.com static nxt_str_t app_str = nxt_string("application"); 772*121Svbart@nginx.com static nxt_str_t apps_str = nxt_string("applications"); 773*121Svbart@nginx.com static nxt_str_t type_str = nxt_string("type"); 774*121Svbart@nginx.com static nxt_str_t app_type_str = nxt_string("_application_type"); 775*121Svbart@nginx.com static nxt_str_t workers_str = nxt_string("workers"); 776*121Svbart@nginx.com static nxt_str_t app_workers_str = nxt_string("_application_workers"); 777*121Svbart@nginx.com static nxt_str_t rtr_str = nxt_string("router"); 778*121Svbart@nginx.com static nxt_str_t http_str = nxt_string("http"); 779*121Svbart@nginx.com 780*121Svbart@nginx.com static nxt_str_t rtr_json = nxt_string("{ \"threads\": 0 }"); 781*121Svbart@nginx.com static nxt_str_t http_json = nxt_string( 782*121Svbart@nginx.com "{ \"header_buffer_size\": 2096," 783*121Svbart@nginx.com " \"large_header_buffer_size\": 16384, " 784*121Svbart@nginx.com " \"header_read_timeout\": 60000 }" 785*121Svbart@nginx.com ); 786*121Svbart@nginx.com 787*121Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 788*121Svbart@nginx.com 789*121Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 790*121Svbart@nginx.com return NXT_ERROR; 791*121Svbart@nginx.com } 792*121Svbart@nginx.com 793*121Svbart@nginx.com lss_count = 0; 794*121Svbart@nginx.com 795*121Svbart@nginx.com lss = nxt_conf_get_object_member(conf, &lss_str, NULL); 796*121Svbart@nginx.com 797*121Svbart@nginx.com if (lss != NULL) { 798*121Svbart@nginx.com lss_count = nxt_conf_object_members_count(lss); 799*121Svbart@nginx.com } 800*121Svbart@nginx.com 801*121Svbart@nginx.com apps = nxt_conf_get_object_member(conf, &apps_str, NULL); 802*121Svbart@nginx.com 803*121Svbart@nginx.com if (nxt_slow_path(apps == NULL)) { 804*121Svbart@nginx.com goto error; 805*121Svbart@nginx.com } 806*121Svbart@nginx.com 807*121Svbart@nginx.com rtr_lss = nxt_conf_create_object(mp, lss_count); 808*121Svbart@nginx.com 809*121Svbart@nginx.com if (nxt_slow_path(rtr_lss == NULL)) { 810*121Svbart@nginx.com goto error; 811*121Svbart@nginx.com } 812*121Svbart@nginx.com 813*121Svbart@nginx.com n = 0; 814*121Svbart@nginx.com next = 0; 815*121Svbart@nginx.com 816*121Svbart@nginx.com for ( ;; ) { 817*121Svbart@nginx.com ls = nxt_conf_next_object_member(lss, &ls_name, &next); 818*121Svbart@nginx.com if (ls == NULL) { 819*121Svbart@nginx.com break; 820*121Svbart@nginx.com } 821*121Svbart@nginx.com 822*121Svbart@nginx.com rtr_ls = nxt_conf_create_object(mp, 3); 823*121Svbart@nginx.com 824*121Svbart@nginx.com if (nxt_slow_path(rtr_ls == NULL)) { 825*121Svbart@nginx.com goto error; 826*121Svbart@nginx.com } 827*121Svbart@nginx.com 828*121Svbart@nginx.com app_name = nxt_conf_get_object_member(ls, &app_str, NULL); 829*121Svbart@nginx.com 830*121Svbart@nginx.com if (nxt_slow_path(app_name == NULL)) { 831*121Svbart@nginx.com goto error; 832*121Svbart@nginx.com } 833*121Svbart@nginx.com 834*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr_ls, &app_str, app_name, 0); 835*121Svbart@nginx.com 836*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 837*121Svbart@nginx.com goto error; 838*121Svbart@nginx.com } 839*121Svbart@nginx.com 840*121Svbart@nginx.com nxt_conf_get_string(app_name, &name); 841*121Svbart@nginx.com 842*121Svbart@nginx.com app = nxt_conf_get_object_member(apps, &name, NULL); 843*121Svbart@nginx.com 844*121Svbart@nginx.com if (nxt_slow_path(app == NULL)) { 845*121Svbart@nginx.com goto error; 846*121Svbart@nginx.com } 847*121Svbart@nginx.com 848*121Svbart@nginx.com value = nxt_conf_get_object_member(app, &type_str, NULL); 849*121Svbart@nginx.com 850*121Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 851*121Svbart@nginx.com goto error; 852*121Svbart@nginx.com } 853*121Svbart@nginx.com 854*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr_ls, &app_type_str, value, 1); 855*121Svbart@nginx.com 856*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 857*121Svbart@nginx.com goto error; 858*121Svbart@nginx.com } 859*121Svbart@nginx.com 860*121Svbart@nginx.com value = nxt_conf_get_object_member(app, &workers_str, NULL); 861*121Svbart@nginx.com 862*121Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 863*121Svbart@nginx.com goto error; 864*121Svbart@nginx.com } 865*121Svbart@nginx.com 866*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr_ls, &app_workers_str, value, 2); 867*121Svbart@nginx.com 868*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 869*121Svbart@nginx.com goto error; 870*121Svbart@nginx.com } 871*121Svbart@nginx.com 872*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr_lss, &ls_name, rtr_ls, n); 873*121Svbart@nginx.com 874*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 875*121Svbart@nginx.com goto error; 876*121Svbart@nginx.com } 877*121Svbart@nginx.com 878*121Svbart@nginx.com n++; 879*121Svbart@nginx.com } 880*121Svbart@nginx.com 881*121Svbart@nginx.com rtr = nxt_conf_create_object(mp, 3); 882*121Svbart@nginx.com 883*121Svbart@nginx.com if (nxt_slow_path(rtr == NULL)) { 884*121Svbart@nginx.com goto error; 885*121Svbart@nginx.com } 886*121Svbart@nginx.com 887*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr, &lss_str, rtr_lss, 0); 888*121Svbart@nginx.com 889*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 890*121Svbart@nginx.com goto error; 891*121Svbart@nginx.com } 892*121Svbart@nginx.com 893*121Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &rtr_json); 894*121Svbart@nginx.com 895*121Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 896*121Svbart@nginx.com goto error; 897*121Svbart@nginx.com } 898*121Svbart@nginx.com 899*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr, &rtr_str, value, 1); 900*121Svbart@nginx.com 901*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 902*121Svbart@nginx.com goto error; 903*121Svbart@nginx.com } 904*121Svbart@nginx.com 905*121Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &http_json); 906*121Svbart@nginx.com 907*121Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 908*121Svbart@nginx.com goto error; 909*121Svbart@nginx.com } 910*121Svbart@nginx.com 911*121Svbart@nginx.com rc = nxt_conf_set_object_member(mp, rtr, &http_str, value, 2); 912*121Svbart@nginx.com 913*121Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 914*121Svbart@nginx.com goto error; 915*121Svbart@nginx.com } 916*121Svbart@nginx.com 917*121Svbart@nginx.com rt = task->thread->runtime; 918*121Svbart@nginx.com 919*121Svbart@nginx.com nxt_runtime_port_each(rt, port) { 920*121Svbart@nginx.com 921*121Svbart@nginx.com if (port->type == NXT_PROCESS_ROUTER) { 922*121Svbart@nginx.com break; 923*121Svbart@nginx.com } 924*121Svbart@nginx.com 925*121Svbart@nginx.com } nxt_runtime_port_loop; 926*121Svbart@nginx.com 927*121Svbart@nginx.com size = nxt_conf_json_length(rtr, NULL); 928*121Svbart@nginx.com 929*121Svbart@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 930*121Svbart@nginx.com 931*121Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, rtr, NULL); 932*121Svbart@nginx.com 933*121Svbart@nginx.com nxt_mp_destroy(mp); 934*121Svbart@nginx.com 935*121Svbart@nginx.com nxt_debug(task, "conf for router: \"%*s\"", 936*121Svbart@nginx.com b->mem.free - b->mem.pos, b->mem.pos); 937*121Svbart@nginx.com 938*121Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, -1, 0, 0, b); 939*121Svbart@nginx.com 940*121Svbart@nginx.com return NXT_OK; 941*121Svbart@nginx.com 942*121Svbart@nginx.com error: 943*121Svbart@nginx.com 944*121Svbart@nginx.com nxt_mp_destroy(mp); 945*121Svbart@nginx.com return NXT_ERROR; 946*121Svbart@nginx.com } 947*121Svbart@nginx.com 948*121Svbart@nginx.com 949*121Svbart@nginx.com static nxt_int_t 95062Sigor@sysoev.ru nxt_controller_response(nxt_task_t *task, nxt_conn_t *c, 95144Svbart@nginx.com nxt_controller_response_t *resp) 95233Svbart@nginx.com { 95344Svbart@nginx.com size_t size; 95433Svbart@nginx.com nxt_buf_t *b; 95533Svbart@nginx.com 95645Svbart@nginx.com size = sizeof("HTTP/1.0 " "\r\n\r\n") - 1 + resp->status_line.length; 95733Svbart@nginx.com 95844Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 95933Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 96044Svbart@nginx.com return NXT_ERROR; 96133Svbart@nginx.com } 96233Svbart@nginx.com 96344Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, "HTTP/1.0 ", sizeof("HTTP/1.0 ") - 1); 96444Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, resp->status_line.start, 96544Svbart@nginx.com resp->status_line.length); 96644Svbart@nginx.com 96744Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, "\r\n\r\n", sizeof("\r\n\r\n") - 1); 96844Svbart@nginx.com 96945Svbart@nginx.com b->next = nxt_controller_response_body(resp, c->mem_pool); 97045Svbart@nginx.com 97145Svbart@nginx.com if (nxt_slow_path(b->next == NULL)) { 97245Svbart@nginx.com return NXT_ERROR; 97344Svbart@nginx.com } 97433Svbart@nginx.com 97533Svbart@nginx.com c->write = b; 97644Svbart@nginx.com c->write_state = &nxt_controller_conn_write_state; 97733Svbart@nginx.com 97862Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 97933Svbart@nginx.com 98044Svbart@nginx.com return NXT_OK; 98133Svbart@nginx.com } 98245Svbart@nginx.com 98345Svbart@nginx.com 98445Svbart@nginx.com static nxt_buf_t * 98565Sigor@sysoev.ru nxt_controller_response_body(nxt_controller_response_t *resp, nxt_mp_t *pool) 98645Svbart@nginx.com { 98745Svbart@nginx.com size_t size; 98845Svbart@nginx.com nxt_buf_t *b; 989106Svbart@nginx.com nxt_conf_value_t *value; 99045Svbart@nginx.com nxt_conf_json_pretty_t pretty; 99145Svbart@nginx.com 992106Svbart@nginx.com if (resp->conf) { 993106Svbart@nginx.com value = resp->conf; 99445Svbart@nginx.com 99545Svbart@nginx.com } else { 996106Svbart@nginx.com value = nxt_conf_json_parse_str(pool, &resp->json); 99745Svbart@nginx.com 99845Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 99945Svbart@nginx.com return NULL; 100045Svbart@nginx.com } 100145Svbart@nginx.com } 100245Svbart@nginx.com 100345Svbart@nginx.com nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 100445Svbart@nginx.com 1005106Svbart@nginx.com size = nxt_conf_json_length(value, &pretty) + 2; 100645Svbart@nginx.com 100745Svbart@nginx.com b = nxt_buf_mem_alloc(pool, size, 0); 100845Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 100945Svbart@nginx.com return NULL; 101045Svbart@nginx.com } 101145Svbart@nginx.com 101245Svbart@nginx.com nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 101345Svbart@nginx.com 1014106Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, value, &pretty); 101545Svbart@nginx.com 101645Svbart@nginx.com *b->mem.free++ = '\r'; 101745Svbart@nginx.com *b->mem.free++ = '\n'; 101845Svbart@nginx.com 101945Svbart@nginx.com return b; 102045Svbart@nginx.com } 1021