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; 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 { 30106Svbart@nginx.com nxt_str_t status_line; 31106Svbart@nginx.com nxt_conf_value_t *conf; 32106Svbart@nginx.com nxt_str_t json; 3344Svbart@nginx.com } nxt_controller_response_t; 3444Svbart@nginx.com 3544Svbart@nginx.com 3620Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 3720Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 3862Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 3920Sigor@sysoev.ru uintptr_t data); 4020Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 4120Sigor@sysoev.ru void *data); 4220Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 4320Sigor@sysoev.ru void *data); 4427Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 4527Svbart@nginx.com void *data); 4627Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 4727Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 4827Svbart@nginx.com void *data); 4927Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 5027Svbart@nginx.com void *data); 5120Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 5220Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 5320Sigor@sysoev.ru 5427Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 5567Svbart@nginx.com nxt_http_field_t *field, nxt_log_t *log); 5627Svbart@nginx.com 5727Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 58140Svbart@nginx.com nxt_controller_request_t *req); 59121Svbart@nginx.com static nxt_int_t nxt_controller_conf_apply(nxt_task_t *task, 60140Svbart@nginx.com nxt_controller_request_t *req); 61140Svbart@nginx.com static void nxt_controller_process_waiting(nxt_task_t *task); 62140Svbart@nginx.com static nxt_int_t nxt_controller_conf_pass(nxt_task_t *task, 63121Svbart@nginx.com nxt_conf_value_t *conf); 64140Svbart@nginx.com static void nxt_controller_response(nxt_task_t *task, 65140Svbart@nginx.com nxt_controller_request_t *req, nxt_controller_response_t *resp); 6645Svbart@nginx.com static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp, 6765Sigor@sysoev.ru nxt_mp_t *pool); 6827Svbart@nginx.com 6927Svbart@nginx.com 7060Svbart@nginx.com static nxt_http_fields_hash_entry_t nxt_controller_request_fields[] = { 7127Svbart@nginx.com { nxt_string("Content-Length"), 7227Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 7327Svbart@nginx.com 7427Svbart@nginx.com { nxt_null_string, NULL, 0 } 7527Svbart@nginx.com }; 7627Svbart@nginx.com 7760Svbart@nginx.com static nxt_http_fields_hash_t *nxt_controller_fields_hash; 7827Svbart@nginx.com 7944Svbart@nginx.com 80140Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 81140Svbart@nginx.com static nxt_queue_t nxt_controller_waiting_requests; 82140Svbart@nginx.com static nxt_controller_request_t *nxt_controller_current_request; 8327Svbart@nginx.com 8420Sigor@sysoev.ru 8520Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 8627Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 8727Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 8820Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 8920Sigor@sysoev.ru 9020Sigor@sysoev.ru 9120Sigor@sysoev.ru nxt_int_t 92*141Smax.romanov@nginx.com nxt_controller_start(nxt_task_t *task, void *data) 9320Sigor@sysoev.ru { 9465Sigor@sysoev.ru nxt_mp_t *mp; 95*141Smax.romanov@nginx.com nxt_runtime_t *rt; 96106Svbart@nginx.com nxt_conf_value_t *conf; 9727Svbart@nginx.com nxt_http_fields_hash_t *hash; 9827Svbart@nginx.com 9944Svbart@nginx.com static const nxt_str_t json 100116Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 10144Svbart@nginx.com 102*141Smax.romanov@nginx.com rt = task->thread->runtime; 103*141Smax.romanov@nginx.com 10460Svbart@nginx.com hash = nxt_http_fields_hash_create(nxt_controller_request_fields, 10560Svbart@nginx.com rt->mem_pool); 10627Svbart@nginx.com if (nxt_slow_path(hash == NULL)) { 10727Svbart@nginx.com return NXT_ERROR; 10827Svbart@nginx.com } 10927Svbart@nginx.com 11060Svbart@nginx.com nxt_controller_fields_hash = hash; 11127Svbart@nginx.com 11254Sigor@sysoev.ru if (nxt_listen_event(task, rt->controller_socket) == NULL) { 11320Sigor@sysoev.ru return NXT_ERROR; 11420Sigor@sysoev.ru } 11520Sigor@sysoev.ru 11665Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 11744Svbart@nginx.com 11844Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 11944Svbart@nginx.com return NXT_ERROR; 12044Svbart@nginx.com } 12144Svbart@nginx.com 122106Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 12344Svbart@nginx.com 12444Svbart@nginx.com if (conf == NULL) { 12544Svbart@nginx.com return NXT_ERROR; 12644Svbart@nginx.com } 12744Svbart@nginx.com 12844Svbart@nginx.com nxt_controller_conf.root = conf; 12944Svbart@nginx.com nxt_controller_conf.pool = mp; 13044Svbart@nginx.com 131140Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 132140Svbart@nginx.com 13320Sigor@sysoev.ru return NXT_OK; 13420Sigor@sysoev.ru } 13520Sigor@sysoev.ru 13620Sigor@sysoev.ru 13720Sigor@sysoev.ru nxt_int_t 13820Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 13920Sigor@sysoev.ru { 14020Sigor@sysoev.ru nxt_sockaddr_t *sa; 14120Sigor@sysoev.ru nxt_listen_socket_t *ls; 14220Sigor@sysoev.ru 14320Sigor@sysoev.ru sa = rt->controller_listen; 14420Sigor@sysoev.ru 14520Sigor@sysoev.ru if (rt->controller_listen == NULL) { 14620Sigor@sysoev.ru sa = nxt_sockaddr_alloc(rt->mem_pool, sizeof(struct sockaddr_in), 14720Sigor@sysoev.ru NXT_INET_ADDR_STR_LEN); 14820Sigor@sysoev.ru if (sa == NULL) { 14920Sigor@sysoev.ru return NXT_ERROR; 15020Sigor@sysoev.ru } 15120Sigor@sysoev.ru 15220Sigor@sysoev.ru sa->type = SOCK_STREAM; 15320Sigor@sysoev.ru sa->u.sockaddr_in.sin_family = AF_INET; 15420Sigor@sysoev.ru sa->u.sockaddr_in.sin_port = htons(8443); 15520Sigor@sysoev.ru 15620Sigor@sysoev.ru nxt_sockaddr_text(sa); 15720Sigor@sysoev.ru 15820Sigor@sysoev.ru rt->controller_listen = sa; 15920Sigor@sysoev.ru } 16020Sigor@sysoev.ru 16165Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 16220Sigor@sysoev.ru if (ls == NULL) { 16320Sigor@sysoev.ru return NXT_ERROR; 16420Sigor@sysoev.ru } 16520Sigor@sysoev.ru 16620Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 16720Sigor@sysoev.ru sa->socklen, sa->length); 16820Sigor@sysoev.ru if (ls->sockaddr == NULL) { 16920Sigor@sysoev.ru return NXT_ERROR; 17020Sigor@sysoev.ru } 17120Sigor@sysoev.ru 17220Sigor@sysoev.ru ls->sockaddr->type = sa->type; 173103Sigor@sysoev.ru ls->socklen = sa->socklen; 174103Sigor@sysoev.ru ls->address_length = sa->length; 17520Sigor@sysoev.ru 17620Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 17720Sigor@sysoev.ru 17820Sigor@sysoev.ru ls->socket = -1; 17920Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 18020Sigor@sysoev.ru ls->read_after_accept = 1; 18120Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 18220Sigor@sysoev.ru 18320Sigor@sysoev.ru #if 0 18420Sigor@sysoev.ru /* STUB */ 18565Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 18620Sigor@sysoev.ru if (wq == NULL) { 18720Sigor@sysoev.ru return NXT_ERROR; 18820Sigor@sysoev.ru } 18920Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 19020Sigor@sysoev.ru /**/ 19120Sigor@sysoev.ru 19220Sigor@sysoev.ru ls->work_queue = wq; 19320Sigor@sysoev.ru #endif 19420Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 19520Sigor@sysoev.ru 19620Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 19720Sigor@sysoev.ru return NXT_ERROR; 19820Sigor@sysoev.ru } 19920Sigor@sysoev.ru 20020Sigor@sysoev.ru rt->controller_socket = ls; 20120Sigor@sysoev.ru 20220Sigor@sysoev.ru return NXT_OK; 20320Sigor@sysoev.ru } 20420Sigor@sysoev.ru 20520Sigor@sysoev.ru 20620Sigor@sysoev.ru static void 20720Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 20820Sigor@sysoev.ru { 20927Svbart@nginx.com nxt_buf_t *b; 21062Sigor@sysoev.ru nxt_conn_t *c; 21127Svbart@nginx.com nxt_event_engine_t *engine; 21227Svbart@nginx.com nxt_controller_request_t *r; 21320Sigor@sysoev.ru 21420Sigor@sysoev.ru c = obj; 21520Sigor@sysoev.ru 21620Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 21720Sigor@sysoev.ru 21865Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 21927Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 22027Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 22127Svbart@nginx.com return; 22227Svbart@nginx.com } 22327Svbart@nginx.com 224140Svbart@nginx.com r->conn = c; 225140Svbart@nginx.com 22660Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 22760Svbart@nginx.com != NXT_OK)) 22860Svbart@nginx.com { 22960Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 23060Svbart@nginx.com return; 23160Svbart@nginx.com } 23227Svbart@nginx.com 23367Svbart@nginx.com r->parser.fields_hash = nxt_controller_fields_hash; 23467Svbart@nginx.com 23520Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 23620Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 23720Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 23820Sigor@sysoev.ru return; 23920Sigor@sysoev.ru } 24020Sigor@sysoev.ru 24120Sigor@sysoev.ru c->read = b; 24227Svbart@nginx.com c->socket.data = r; 24320Sigor@sysoev.ru c->socket.read_ready = 1; 24420Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 24520Sigor@sysoev.ru 24620Sigor@sysoev.ru engine = task->thread->engine; 24720Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 24827Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 24920Sigor@sysoev.ru 25062Sigor@sysoev.ru nxt_conn_read(engine, c); 25120Sigor@sysoev.ru } 25220Sigor@sysoev.ru 25320Sigor@sysoev.ru 25420Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 25520Sigor@sysoev.ru nxt_aligned(64) = 25620Sigor@sysoev.ru { 25756Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 25856Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 25956Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 26020Sigor@sysoev.ru 26156Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 26256Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 26356Sigor@sysoev.ru .timer_data = 60 * 1000, 26420Sigor@sysoev.ru }; 26520Sigor@sysoev.ru 26620Sigor@sysoev.ru 26720Sigor@sysoev.ru static void 26820Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 26920Sigor@sysoev.ru { 27027Svbart@nginx.com size_t preread; 27127Svbart@nginx.com nxt_buf_t *b; 27227Svbart@nginx.com nxt_int_t rc; 27362Sigor@sysoev.ru nxt_conn_t *c; 27427Svbart@nginx.com nxt_controller_request_t *r; 27520Sigor@sysoev.ru 27620Sigor@sysoev.ru c = obj; 27727Svbart@nginx.com r = data; 27820Sigor@sysoev.ru 27920Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 28020Sigor@sysoev.ru 28127Svbart@nginx.com nxt_queue_remove(&c->link); 28227Svbart@nginx.com nxt_queue_self(&c->link); 28327Svbart@nginx.com 28427Svbart@nginx.com b = c->read; 28527Svbart@nginx.com 28627Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 28727Svbart@nginx.com 28827Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 28927Svbart@nginx.com 29027Svbart@nginx.com if (rc == NXT_AGAIN) { 29127Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 29227Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 29327Svbart@nginx.com nxt_controller_conn_close(task, c, r); 29427Svbart@nginx.com return; 29527Svbart@nginx.com } 29627Svbart@nginx.com 29762Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 29827Svbart@nginx.com return; 29927Svbart@nginx.com } 30027Svbart@nginx.com 30127Svbart@nginx.com /* rc == NXT_ERROR */ 30227Svbart@nginx.com 30327Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 30427Svbart@nginx.com 30527Svbart@nginx.com nxt_controller_conn_close(task, c, r); 30627Svbart@nginx.com return; 30727Svbart@nginx.com } 30827Svbart@nginx.com 30967Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, r, task->log); 31060Svbart@nginx.com 31160Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 31260Svbart@nginx.com nxt_controller_conn_close(task, c, r); 31360Svbart@nginx.com return; 31460Svbart@nginx.com } 31560Svbart@nginx.com 31627Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 31727Svbart@nginx.com 31827Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 319107Svbart@nginx.com "body length: %uz, preread: %uz", 32027Svbart@nginx.com r->length, preread); 32127Svbart@nginx.com 32227Svbart@nginx.com if (preread >= r->length) { 323140Svbart@nginx.com nxt_controller_process_request(task, r); 32427Svbart@nginx.com return; 32527Svbart@nginx.com } 32627Svbart@nginx.com 32727Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 32827Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 32927Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 33027Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 33127Svbart@nginx.com return; 33227Svbart@nginx.com } 33327Svbart@nginx.com 33427Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 33527Svbart@nginx.com 33627Svbart@nginx.com c->read = b; 33727Svbart@nginx.com } 33827Svbart@nginx.com 33927Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 34027Svbart@nginx.com 34162Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 34220Sigor@sysoev.ru } 34320Sigor@sysoev.ru 34420Sigor@sysoev.ru 34520Sigor@sysoev.ru static nxt_msec_t 34662Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 34720Sigor@sysoev.ru { 34820Sigor@sysoev.ru return (nxt_msec_t) data; 34920Sigor@sysoev.ru } 35020Sigor@sysoev.ru 35120Sigor@sysoev.ru 35220Sigor@sysoev.ru static void 35320Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 35420Sigor@sysoev.ru { 35562Sigor@sysoev.ru nxt_conn_t *c; 35620Sigor@sysoev.ru 35720Sigor@sysoev.ru c = obj; 35820Sigor@sysoev.ru 35920Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 36020Sigor@sysoev.ru 36127Svbart@nginx.com nxt_controller_conn_close(task, c, data); 36220Sigor@sysoev.ru } 36320Sigor@sysoev.ru 36420Sigor@sysoev.ru 36520Sigor@sysoev.ru static void 36620Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 36720Sigor@sysoev.ru { 36862Sigor@sysoev.ru nxt_timer_t *timer; 36962Sigor@sysoev.ru nxt_conn_t *c; 37020Sigor@sysoev.ru 37162Sigor@sysoev.ru timer = obj; 37220Sigor@sysoev.ru 37362Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 37420Sigor@sysoev.ru c->socket.timedout = 1; 37520Sigor@sysoev.ru c->socket.closed = 1; 37620Sigor@sysoev.ru 37720Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 37820Sigor@sysoev.ru 37927Svbart@nginx.com nxt_controller_conn_close(task, c, data); 38027Svbart@nginx.com } 38127Svbart@nginx.com 38227Svbart@nginx.com 38327Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 38427Svbart@nginx.com nxt_aligned(64) = 38527Svbart@nginx.com { 38656Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 38756Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 38856Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 38927Svbart@nginx.com 39056Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 39156Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 39256Sigor@sysoev.ru .timer_data = 60 * 1000, 39356Sigor@sysoev.ru .timer_autoreset = 1, 39427Svbart@nginx.com }; 39527Svbart@nginx.com 39627Svbart@nginx.com 39727Svbart@nginx.com static void 39827Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 39927Svbart@nginx.com { 400107Svbart@nginx.com size_t read; 401107Svbart@nginx.com nxt_buf_t *b; 402107Svbart@nginx.com nxt_conn_t *c; 403107Svbart@nginx.com nxt_controller_request_t *r; 40427Svbart@nginx.com 40527Svbart@nginx.com c = obj; 406107Svbart@nginx.com r = data; 40727Svbart@nginx.com b = c->read; 40827Svbart@nginx.com 409107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 41027Svbart@nginx.com 411107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 412107Svbart@nginx.com read, r->length); 41327Svbart@nginx.com 414107Svbart@nginx.com if (read >= r->length) { 415140Svbart@nginx.com nxt_controller_process_request(task, r); 41627Svbart@nginx.com return; 41727Svbart@nginx.com } 41827Svbart@nginx.com 41962Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 42027Svbart@nginx.com } 42127Svbart@nginx.com 42227Svbart@nginx.com 42327Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 42427Svbart@nginx.com nxt_aligned(64) = 42527Svbart@nginx.com { 42656Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 42756Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 42827Svbart@nginx.com 42956Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 43056Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 43156Sigor@sysoev.ru .timer_data = 60 * 1000, 43256Sigor@sysoev.ru .timer_autoreset = 1, 43327Svbart@nginx.com }; 43427Svbart@nginx.com 43527Svbart@nginx.com 43627Svbart@nginx.com static void 43727Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 43827Svbart@nginx.com { 43962Sigor@sysoev.ru nxt_buf_t *b; 44062Sigor@sysoev.ru nxt_conn_t *c; 44127Svbart@nginx.com 44227Svbart@nginx.com c = obj; 44327Svbart@nginx.com 44427Svbart@nginx.com nxt_debug(task, "controller conn write"); 44527Svbart@nginx.com 44627Svbart@nginx.com b = c->write; 44727Svbart@nginx.com 44827Svbart@nginx.com if (b->mem.pos != b->mem.free) { 44962Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 45027Svbart@nginx.com return; 45127Svbart@nginx.com } 45227Svbart@nginx.com 45327Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 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_error(nxt_task_t *task, void *obj, void *data) 46127Svbart@nginx.com { 46262Sigor@sysoev.ru nxt_conn_t *c; 46327Svbart@nginx.com 46427Svbart@nginx.com c = obj; 46527Svbart@nginx.com 46627Svbart@nginx.com nxt_debug(task, "controller conn write error"); 46727Svbart@nginx.com 46827Svbart@nginx.com nxt_controller_conn_close(task, c, data); 46927Svbart@nginx.com } 47027Svbart@nginx.com 47127Svbart@nginx.com 47227Svbart@nginx.com static void 47327Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 47427Svbart@nginx.com { 47562Sigor@sysoev.ru nxt_conn_t *c; 47662Sigor@sysoev.ru nxt_timer_t *timer; 47727Svbart@nginx.com 47862Sigor@sysoev.ru timer = obj; 47927Svbart@nginx.com 48062Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 48127Svbart@nginx.com c->socket.timedout = 1; 48227Svbart@nginx.com c->socket.closed = 1; 48327Svbart@nginx.com 48427Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 48527Svbart@nginx.com 48627Svbart@nginx.com nxt_controller_conn_close(task, c, data); 48720Sigor@sysoev.ru } 48820Sigor@sysoev.ru 48920Sigor@sysoev.ru 49020Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 49120Sigor@sysoev.ru nxt_aligned(64) = 49220Sigor@sysoev.ru { 49356Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 49420Sigor@sysoev.ru }; 49520Sigor@sysoev.ru 49620Sigor@sysoev.ru 49720Sigor@sysoev.ru static void 49820Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 49920Sigor@sysoev.ru { 50062Sigor@sysoev.ru nxt_conn_t *c; 50120Sigor@sysoev.ru 50220Sigor@sysoev.ru c = obj; 50320Sigor@sysoev.ru 50420Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 50520Sigor@sysoev.ru 50627Svbart@nginx.com nxt_queue_remove(&c->link); 50727Svbart@nginx.com 50820Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 50920Sigor@sysoev.ru 51062Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 51120Sigor@sysoev.ru } 51220Sigor@sysoev.ru 51320Sigor@sysoev.ru 51420Sigor@sysoev.ru static void 51520Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 51620Sigor@sysoev.ru { 51762Sigor@sysoev.ru nxt_conn_t *c; 51820Sigor@sysoev.ru 51920Sigor@sysoev.ru c = obj; 52020Sigor@sysoev.ru 52120Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 52220Sigor@sysoev.ru 52365Sigor@sysoev.ru nxt_mp_destroy(c->mem_pool); 52420Sigor@sysoev.ru 52520Sigor@sysoev.ru //nxt_free(c); 52620Sigor@sysoev.ru } 52727Svbart@nginx.com 52827Svbart@nginx.com 52927Svbart@nginx.com static nxt_int_t 53060Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 53167Svbart@nginx.com nxt_log_t *log) 53227Svbart@nginx.com { 53327Svbart@nginx.com off_t length; 53427Svbart@nginx.com nxt_controller_request_t *r; 53527Svbart@nginx.com 53627Svbart@nginx.com r = ctx; 53727Svbart@nginx.com 53860Svbart@nginx.com length = nxt_off_t_parse(field->value.start, field->value.length); 53927Svbart@nginx.com 54027Svbart@nginx.com if (nxt_fast_path(length > 0)) { 541107Svbart@nginx.com 542107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 543107Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is too big"); 544107Svbart@nginx.com return NXT_ERROR; 545107Svbart@nginx.com } 54627Svbart@nginx.com 54727Svbart@nginx.com r->length = length; 54827Svbart@nginx.com return NXT_OK; 54927Svbart@nginx.com } 55027Svbart@nginx.com 55160Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, log, "Content-Length is invalid"); 55227Svbart@nginx.com 55327Svbart@nginx.com return NXT_ERROR; 55427Svbart@nginx.com } 55527Svbart@nginx.com 55627Svbart@nginx.com 55727Svbart@nginx.com static void 558140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 55927Svbart@nginx.com { 56065Sigor@sysoev.ru nxt_mp_t *mp; 56151Svbart@nginx.com nxt_int_t rc; 56246Svbart@nginx.com nxt_str_t path; 563140Svbart@nginx.com nxt_conn_t *c; 56451Svbart@nginx.com nxt_uint_t status; 56551Svbart@nginx.com nxt_buf_mem_t *mbuf; 566106Svbart@nginx.com nxt_conf_op_t *ops; 567106Svbart@nginx.com nxt_conf_value_t *value; 56844Svbart@nginx.com nxt_controller_response_t resp; 56944Svbart@nginx.com 57051Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 57151Svbart@nginx.com 572140Svbart@nginx.com c = req->conn; 573112Smax.romanov@nginx.com path = req->parser.path; 57451Svbart@nginx.com 57551Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 57651Svbart@nginx.com path.length--; 57751Svbart@nginx.com } 57851Svbart@nginx.com 57944Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 58044Svbart@nginx.com 58144Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 58246Svbart@nginx.com 583106Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, &path); 58451Svbart@nginx.com 58551Svbart@nginx.com if (value == NULL) { 58651Svbart@nginx.com status = 404; 58751Svbart@nginx.com goto done; 58851Svbart@nginx.com } 58951Svbart@nginx.com 590106Svbart@nginx.com resp.conf = value; 59146Svbart@nginx.com 59251Svbart@nginx.com status = 200; 59351Svbart@nginx.com goto done; 59451Svbart@nginx.com } 59551Svbart@nginx.com 59651Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "PUT", 3)) { 59746Svbart@nginx.com 59865Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 59951Svbart@nginx.com 60051Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 60151Svbart@nginx.com status = 500; 60251Svbart@nginx.com goto done; 60346Svbart@nginx.com } 60446Svbart@nginx.com 60551Svbart@nginx.com mbuf = &c->read->mem; 60651Svbart@nginx.com 60791Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free); 60851Svbart@nginx.com 60951Svbart@nginx.com if (value == NULL) { 61065Sigor@sysoev.ru nxt_mp_destroy(mp); 61151Svbart@nginx.com status = 400; 612116Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Invalid JSON.\" }"); 61351Svbart@nginx.com goto done; 61451Svbart@nginx.com } 61551Svbart@nginx.com 61651Svbart@nginx.com if (path.length != 1) { 617106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 618106Svbart@nginx.com nxt_controller_conf.root, 619106Svbart@nginx.com &path, value); 62046Svbart@nginx.com 62151Svbart@nginx.com if (rc != NXT_OK) { 62251Svbart@nginx.com if (rc == NXT_DECLINED) { 62351Svbart@nginx.com status = 404; 62451Svbart@nginx.com goto done; 62551Svbart@nginx.com } 62646Svbart@nginx.com 62751Svbart@nginx.com status = 500; 62851Svbart@nginx.com goto done; 62951Svbart@nginx.com } 63051Svbart@nginx.com 631106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 63251Svbart@nginx.com 63351Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 63465Sigor@sysoev.ru nxt_mp_destroy(mp); 63551Svbart@nginx.com status = 500; 63651Svbart@nginx.com goto done; 63751Svbart@nginx.com } 63846Svbart@nginx.com } 63944Svbart@nginx.com 640116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 641121Svbart@nginx.com nxt_mp_destroy(mp); 642116Svbart@nginx.com status = 400; 643116Svbart@nginx.com nxt_str_set(&resp.json, 644116Svbart@nginx.com "{ \"error\": \"Invalid configuration.\" }"); 645116Svbart@nginx.com goto done; 646116Svbart@nginx.com } 647116Svbart@nginx.com 648140Svbart@nginx.com req->conf.root = value; 649140Svbart@nginx.com req->conf.pool = mp; 650140Svbart@nginx.com 651140Svbart@nginx.com if (nxt_controller_conf_apply(task, req) != NXT_OK) { 652121Svbart@nginx.com nxt_mp_destroy(mp); 653121Svbart@nginx.com status = 500; 654121Svbart@nginx.com goto done; 655121Svbart@nginx.com } 656121Svbart@nginx.com 657140Svbart@nginx.com return; 65851Svbart@nginx.com } 65927Svbart@nginx.com 66051Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { 66151Svbart@nginx.com 66251Svbart@nginx.com if (path.length == 1) { 66365Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 66444Svbart@nginx.com 66551Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 66651Svbart@nginx.com status = 500; 66751Svbart@nginx.com goto done; 66851Svbart@nginx.com } 66951Svbart@nginx.com 670106Svbart@nginx.com value = nxt_conf_json_parse_str(mp, &empty_obj); 67127Svbart@nginx.com 67244Svbart@nginx.com } else { 673106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 674106Svbart@nginx.com nxt_controller_conf.root, 675106Svbart@nginx.com &path, NULL); 67651Svbart@nginx.com 67751Svbart@nginx.com if (rc != NXT_OK) { 67851Svbart@nginx.com if (rc == NXT_DECLINED) { 67951Svbart@nginx.com status = 404; 68051Svbart@nginx.com goto done; 68151Svbart@nginx.com } 68251Svbart@nginx.com 68351Svbart@nginx.com status = 500; 68451Svbart@nginx.com goto done; 68551Svbart@nginx.com } 68651Svbart@nginx.com 68765Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 68851Svbart@nginx.com 68951Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 69051Svbart@nginx.com status = 500; 69151Svbart@nginx.com goto done; 69251Svbart@nginx.com } 69351Svbart@nginx.com 694106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 69551Svbart@nginx.com } 69651Svbart@nginx.com 69751Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 69865Sigor@sysoev.ru nxt_mp_destroy(mp); 69951Svbart@nginx.com status = 500; 70051Svbart@nginx.com goto done; 70144Svbart@nginx.com } 70244Svbart@nginx.com 703116Svbart@nginx.com if (nxt_slow_path(nxt_conf_validate(value) != NXT_OK)) { 704121Svbart@nginx.com nxt_mp_destroy(mp); 705116Svbart@nginx.com status = 400; 706116Svbart@nginx.com nxt_str_set(&resp.json, 707116Svbart@nginx.com "{ \"error\": \"Invalid configuration.\" }"); 708116Svbart@nginx.com goto done; 709116Svbart@nginx.com } 710116Svbart@nginx.com 711140Svbart@nginx.com req->conf.root = value; 712140Svbart@nginx.com req->conf.pool = mp; 713140Svbart@nginx.com 714140Svbart@nginx.com if (nxt_controller_conf_apply(task, req) != NXT_OK) { 715121Svbart@nginx.com nxt_mp_destroy(mp); 716121Svbart@nginx.com status = 500; 717121Svbart@nginx.com goto done; 718121Svbart@nginx.com } 719121Svbart@nginx.com 720140Svbart@nginx.com return; 72151Svbart@nginx.com } 72251Svbart@nginx.com 72351Svbart@nginx.com status = 405; 72451Svbart@nginx.com 72551Svbart@nginx.com done: 72651Svbart@nginx.com 72751Svbart@nginx.com switch (status) { 72851Svbart@nginx.com 72951Svbart@nginx.com case 200: 73051Svbart@nginx.com nxt_str_set(&resp.status_line, "200 OK"); 73151Svbart@nginx.com break; 73251Svbart@nginx.com 73351Svbart@nginx.com case 400: 73451Svbart@nginx.com nxt_str_set(&resp.status_line, "400 Bad Request"); 73551Svbart@nginx.com break; 73651Svbart@nginx.com 73751Svbart@nginx.com case 404: 73851Svbart@nginx.com nxt_str_set(&resp.status_line, "404 Not Found"); 739106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Value doesn't exist.\" }"); 74051Svbart@nginx.com break; 74151Svbart@nginx.com 74251Svbart@nginx.com case 405: 74344Svbart@nginx.com nxt_str_set(&resp.status_line, "405 Method Not Allowed"); 744106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Invalid method.\" }"); 74551Svbart@nginx.com break; 74651Svbart@nginx.com 74751Svbart@nginx.com case 500: 74851Svbart@nginx.com nxt_str_set(&resp.status_line, "500 Internal Server Error"); 749106Svbart@nginx.com nxt_str_set(&resp.json, "{ \"error\": \"Memory allocation failed.\" }"); 75051Svbart@nginx.com break; 75129Svbart@nginx.com } 75227Svbart@nginx.com 753140Svbart@nginx.com nxt_controller_response(task, req, &resp); 75427Svbart@nginx.com } 75527Svbart@nginx.com 75627Svbart@nginx.com 75727Svbart@nginx.com static nxt_int_t 758140Svbart@nginx.com nxt_controller_conf_apply(nxt_task_t *task, nxt_controller_request_t *req) 759140Svbart@nginx.com { 760140Svbart@nginx.com nxt_int_t rc; 761140Svbart@nginx.com 762140Svbart@nginx.com if (nxt_controller_current_request != NULL) { 763140Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 764140Svbart@nginx.com return NXT_OK; 765140Svbart@nginx.com } 766140Svbart@nginx.com 767140Svbart@nginx.com rc = nxt_controller_conf_pass(task, req->conf.root); 768140Svbart@nginx.com 769140Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 770140Svbart@nginx.com return NXT_ERROR; 771140Svbart@nginx.com } 772140Svbart@nginx.com 773140Svbart@nginx.com nxt_controller_current_request = req; 774140Svbart@nginx.com 775140Svbart@nginx.com return NXT_OK; 776140Svbart@nginx.com } 777140Svbart@nginx.com 778140Svbart@nginx.com 779140Svbart@nginx.com void 780140Svbart@nginx.com nxt_port_controller_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 781140Svbart@nginx.com { 782140Svbart@nginx.com size_t size, dump_size; 783140Svbart@nginx.com nxt_buf_t *b; 784140Svbart@nginx.com nxt_controller_request_t *req; 785140Svbart@nginx.com nxt_controller_response_t resp; 786140Svbart@nginx.com 787140Svbart@nginx.com b = msg->buf; 788140Svbart@nginx.com size = b->mem.free - b->mem.pos; 789140Svbart@nginx.com 790140Svbart@nginx.com dump_size = size > 300 ? 300 : size; 791140Svbart@nginx.com 792140Svbart@nginx.com nxt_debug(task, "contoller data: %*s ...", dump_size, b->mem.pos); 793140Svbart@nginx.com 794140Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 795140Svbart@nginx.com 796140Svbart@nginx.com req = nxt_controller_current_request; 797140Svbart@nginx.com nxt_controller_current_request = NULL; 798140Svbart@nginx.com 799140Svbart@nginx.com if (size == 2 && nxt_memcmp(b->mem.pos, "OK", 2) == 0) { 800140Svbart@nginx.com 801140Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 802140Svbart@nginx.com 803140Svbart@nginx.com nxt_controller_conf = req->conf; 804140Svbart@nginx.com 805140Svbart@nginx.com nxt_str_set(&resp.status_line, "200 OK"); 806140Svbart@nginx.com nxt_str_set(&resp.json, "{ \"success\": \"Reconfiguration done.\" }"); 807140Svbart@nginx.com 808140Svbart@nginx.com } else { 809140Svbart@nginx.com nxt_mp_destroy(req->conf.pool); 810140Svbart@nginx.com 811140Svbart@nginx.com nxt_str_set(&resp.status_line, "500 Internal Server Error"); 812140Svbart@nginx.com nxt_str_set(&resp.json, 813140Svbart@nginx.com "{ \"error\": \"Failed to apply new configuration.\" }"); 814140Svbart@nginx.com } 815140Svbart@nginx.com 816140Svbart@nginx.com nxt_controller_response(task, req, &resp); 817140Svbart@nginx.com 818140Svbart@nginx.com nxt_controller_process_waiting(task); 819140Svbart@nginx.com } 820140Svbart@nginx.com 821140Svbart@nginx.com 822140Svbart@nginx.com static void 823140Svbart@nginx.com nxt_controller_process_waiting(nxt_task_t *task) 824140Svbart@nginx.com { 825140Svbart@nginx.com nxt_controller_request_t *req; 826140Svbart@nginx.com nxt_controller_response_t resp; 827140Svbart@nginx.com 828140Svbart@nginx.com nxt_queue_each(req, &nxt_controller_waiting_requests, 829140Svbart@nginx.com nxt_controller_request_t, link) 830140Svbart@nginx.com { 831140Svbart@nginx.com nxt_queue_remove(&req->link); 832140Svbart@nginx.com 833140Svbart@nginx.com if (nxt_fast_path(nxt_controller_conf_apply(task, req) == NXT_OK)) { 834140Svbart@nginx.com return; 835140Svbart@nginx.com } 836140Svbart@nginx.com 837140Svbart@nginx.com nxt_mp_destroy(req->conf.pool); 838140Svbart@nginx.com 839140Svbart@nginx.com nxt_str_set(&resp.status_line, "500 Internal Server Error"); 840140Svbart@nginx.com nxt_str_set(&resp.json, 841140Svbart@nginx.com "{ \"error\": \"Memory allocation failed.\" }"); 842140Svbart@nginx.com 843140Svbart@nginx.com nxt_controller_response(task, req, &resp); 844140Svbart@nginx.com 845140Svbart@nginx.com } nxt_queue_loop; 846140Svbart@nginx.com } 847140Svbart@nginx.com 848140Svbart@nginx.com 849140Svbart@nginx.com static nxt_int_t 850140Svbart@nginx.com nxt_controller_conf_pass(nxt_task_t *task, nxt_conf_value_t *conf) 851121Svbart@nginx.com { 852135Svbart@nginx.com size_t size; 853135Svbart@nginx.com nxt_buf_t *b; 854135Svbart@nginx.com nxt_port_t *port; 855135Svbart@nginx.com nxt_runtime_t *rt; 856121Svbart@nginx.com 857121Svbart@nginx.com rt = task->thread->runtime; 858121Svbart@nginx.com 859*141Smax.romanov@nginx.com port = rt->port_by_type[NXT_PROCESS_ROUTER]; 860121Svbart@nginx.com 861135Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 862121Svbart@nginx.com 863121Svbart@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 864121Svbart@nginx.com 865135Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 866121Svbart@nginx.com 867140Svbart@nginx.com return nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, -1, 0, 0, b); 868121Svbart@nginx.com } 869121Svbart@nginx.com 870121Svbart@nginx.com 871140Svbart@nginx.com 872140Svbart@nginx.com static void 873140Svbart@nginx.com nxt_controller_response(nxt_task_t *task, nxt_controller_request_t *req, 87444Svbart@nginx.com nxt_controller_response_t *resp) 87533Svbart@nginx.com { 876140Svbart@nginx.com size_t size; 877140Svbart@nginx.com nxt_buf_t *b; 878140Svbart@nginx.com nxt_conn_t *c; 879140Svbart@nginx.com 880140Svbart@nginx.com c = req->conn; 88133Svbart@nginx.com 88245Svbart@nginx.com size = sizeof("HTTP/1.0 " "\r\n\r\n") - 1 + resp->status_line.length; 88333Svbart@nginx.com 88444Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 88533Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 886140Svbart@nginx.com nxt_controller_conn_close(task, c, req); 887140Svbart@nginx.com return; 88833Svbart@nginx.com } 88933Svbart@nginx.com 89044Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, "HTTP/1.0 ", sizeof("HTTP/1.0 ") - 1); 89144Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, resp->status_line.start, 89244Svbart@nginx.com resp->status_line.length); 89344Svbart@nginx.com 89444Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, "\r\n\r\n", sizeof("\r\n\r\n") - 1); 89544Svbart@nginx.com 89645Svbart@nginx.com b->next = nxt_controller_response_body(resp, c->mem_pool); 89745Svbart@nginx.com 89845Svbart@nginx.com if (nxt_slow_path(b->next == NULL)) { 899140Svbart@nginx.com nxt_controller_conn_close(task, c, req); 900140Svbart@nginx.com return; 90144Svbart@nginx.com } 90233Svbart@nginx.com 90333Svbart@nginx.com c->write = b; 90444Svbart@nginx.com c->write_state = &nxt_controller_conn_write_state; 90533Svbart@nginx.com 90662Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 90733Svbart@nginx.com } 90845Svbart@nginx.com 90945Svbart@nginx.com 91045Svbart@nginx.com static nxt_buf_t * 91165Sigor@sysoev.ru nxt_controller_response_body(nxt_controller_response_t *resp, nxt_mp_t *pool) 91245Svbart@nginx.com { 91345Svbart@nginx.com size_t size; 91445Svbart@nginx.com nxt_buf_t *b; 915106Svbart@nginx.com nxt_conf_value_t *value; 91645Svbart@nginx.com nxt_conf_json_pretty_t pretty; 91745Svbart@nginx.com 918106Svbart@nginx.com if (resp->conf) { 919106Svbart@nginx.com value = resp->conf; 92045Svbart@nginx.com 92145Svbart@nginx.com } else { 922106Svbart@nginx.com value = nxt_conf_json_parse_str(pool, &resp->json); 92345Svbart@nginx.com 92445Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 92545Svbart@nginx.com return NULL; 92645Svbart@nginx.com } 92745Svbart@nginx.com } 92845Svbart@nginx.com 92945Svbart@nginx.com nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 93045Svbart@nginx.com 931106Svbart@nginx.com size = nxt_conf_json_length(value, &pretty) + 2; 93245Svbart@nginx.com 93345Svbart@nginx.com b = nxt_buf_mem_alloc(pool, size, 0); 93445Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 93545Svbart@nginx.com return NULL; 93645Svbart@nginx.com } 93745Svbart@nginx.com 93845Svbart@nginx.com nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); 93945Svbart@nginx.com 940106Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, value, &pretty); 94145Svbart@nginx.com 94245Svbart@nginx.com *b->mem.free++ = '\r'; 94345Svbart@nginx.com *b->mem.free++ = '\n'; 94445Svbart@nginx.com 94545Svbart@nginx.com return b; 94645Svbart@nginx.com } 947