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 { 1527Svbart@nginx.com nxt_http_request_parse_t parser; 1627Svbart@nginx.com size_t length; 17*33Svbart@nginx.com 18*33Svbart@nginx.com nxt_conf_json_value_t *conf; 1927Svbart@nginx.com } nxt_controller_request_t; 2027Svbart@nginx.com 2127Svbart@nginx.com 2220Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 2320Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 2420Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_event_conn_t *c, 2520Sigor@sysoev.ru uintptr_t data); 2620Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 2720Sigor@sysoev.ru void *data); 2820Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 2920Sigor@sysoev.ru void *data); 3027Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 3127Svbart@nginx.com void *data); 3227Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 3327Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 3427Svbart@nginx.com void *data); 3527Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 3627Svbart@nginx.com void *data); 3720Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 3820Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 3920Sigor@sysoev.ru 4027Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 4127Svbart@nginx.com nxt_str_t *name, nxt_str_t *value, uintptr_t data); 4227Svbart@nginx.com 4327Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 4427Svbart@nginx.com nxt_event_conn_t *c, nxt_controller_request_t *r); 4529Svbart@nginx.com static nxt_int_t nxt_controller_request_body_parse(nxt_task_t *task, 46*33Svbart@nginx.com nxt_event_conn_t *c, nxt_controller_request_t *r); 47*33Svbart@nginx.com static void nxt_controller_conf_output(nxt_task_t *task, nxt_event_conn_t *c, 48*33Svbart@nginx.com nxt_controller_request_t *r); 4927Svbart@nginx.com 5027Svbart@nginx.com 5127Svbart@nginx.com static nxt_http_fields_t nxt_controller_request_fields[] = { 5227Svbart@nginx.com { nxt_string("Content-Length"), 5327Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 5427Svbart@nginx.com 5527Svbart@nginx.com { nxt_null_string, NULL, 0 } 5627Svbart@nginx.com }; 5727Svbart@nginx.com 5827Svbart@nginx.com 5927Svbart@nginx.com static nxt_http_fields_hash_t *nxt_controller_request_fields_hash; 6027Svbart@nginx.com 6120Sigor@sysoev.ru 6220Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 6327Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 6427Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 6520Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 6620Sigor@sysoev.ru 6720Sigor@sysoev.ru 6820Sigor@sysoev.ru nxt_int_t 6920Sigor@sysoev.ru nxt_controller_start(nxt_task_t *task, nxt_runtime_t *rt) 7020Sigor@sysoev.ru { 7127Svbart@nginx.com nxt_http_fields_hash_t *hash; 7227Svbart@nginx.com 7327Svbart@nginx.com hash = nxt_http_fields_hash(nxt_controller_request_fields, rt->mem_pool); 7427Svbart@nginx.com 7527Svbart@nginx.com if (nxt_slow_path(hash == NULL)) { 7627Svbart@nginx.com return NXT_ERROR; 7727Svbart@nginx.com } 7827Svbart@nginx.com 7927Svbart@nginx.com nxt_controller_request_fields_hash = hash; 8027Svbart@nginx.com 8120Sigor@sysoev.ru if (nxt_event_conn_listen(task, rt->controller_socket) != NXT_OK) { 8220Sigor@sysoev.ru return NXT_ERROR; 8320Sigor@sysoev.ru } 8420Sigor@sysoev.ru 8520Sigor@sysoev.ru return NXT_OK; 8620Sigor@sysoev.ru } 8720Sigor@sysoev.ru 8820Sigor@sysoev.ru 8920Sigor@sysoev.ru nxt_int_t 9020Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 9120Sigor@sysoev.ru { 9220Sigor@sysoev.ru nxt_sockaddr_t *sa; 9320Sigor@sysoev.ru nxt_listen_socket_t *ls; 9420Sigor@sysoev.ru 9520Sigor@sysoev.ru sa = rt->controller_listen; 9620Sigor@sysoev.ru 9720Sigor@sysoev.ru if (rt->controller_listen == NULL) { 9820Sigor@sysoev.ru sa = nxt_sockaddr_alloc(rt->mem_pool, sizeof(struct sockaddr_in), 9920Sigor@sysoev.ru NXT_INET_ADDR_STR_LEN); 10020Sigor@sysoev.ru if (sa == NULL) { 10120Sigor@sysoev.ru return NXT_ERROR; 10220Sigor@sysoev.ru } 10320Sigor@sysoev.ru 10420Sigor@sysoev.ru sa->type = SOCK_STREAM; 10520Sigor@sysoev.ru sa->u.sockaddr_in.sin_family = AF_INET; 10620Sigor@sysoev.ru sa->u.sockaddr_in.sin_port = htons(8443); 10720Sigor@sysoev.ru 10820Sigor@sysoev.ru nxt_sockaddr_text(sa); 10920Sigor@sysoev.ru 11020Sigor@sysoev.ru rt->controller_listen = sa; 11120Sigor@sysoev.ru } 11220Sigor@sysoev.ru 11320Sigor@sysoev.ru ls = nxt_mem_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 11420Sigor@sysoev.ru if (ls == NULL) { 11520Sigor@sysoev.ru return NXT_ERROR; 11620Sigor@sysoev.ru } 11720Sigor@sysoev.ru 11820Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr, 11920Sigor@sysoev.ru sa->socklen, sa->length); 12020Sigor@sysoev.ru if (ls->sockaddr == NULL) { 12120Sigor@sysoev.ru return NXT_ERROR; 12220Sigor@sysoev.ru } 12320Sigor@sysoev.ru 12420Sigor@sysoev.ru ls->sockaddr->type = sa->type; 12520Sigor@sysoev.ru 12620Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 12720Sigor@sysoev.ru 12820Sigor@sysoev.ru ls->socket = -1; 12920Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 13020Sigor@sysoev.ru ls->read_after_accept = 1; 13120Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 13220Sigor@sysoev.ru 13320Sigor@sysoev.ru #if 0 13420Sigor@sysoev.ru /* STUB */ 13520Sigor@sysoev.ru wq = nxt_mem_zalloc(cf->mem_pool, sizeof(nxt_work_queue_t)); 13620Sigor@sysoev.ru if (wq == NULL) { 13720Sigor@sysoev.ru return NXT_ERROR; 13820Sigor@sysoev.ru } 13920Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 14020Sigor@sysoev.ru /**/ 14120Sigor@sysoev.ru 14220Sigor@sysoev.ru ls->work_queue = wq; 14320Sigor@sysoev.ru #endif 14420Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 14520Sigor@sysoev.ru 14620Sigor@sysoev.ru /* 14720Sigor@sysoev.ru * Connection memory pool chunk size is tunned to 14820Sigor@sysoev.ru * allocate the most data in one mem_pool chunk. 14920Sigor@sysoev.ru */ 15020Sigor@sysoev.ru ls->mem_pool_size = nxt_listen_socket_pool_min_size(ls) 15120Sigor@sysoev.ru + sizeof(nxt_event_conn_proxy_t) 15220Sigor@sysoev.ru + sizeof(nxt_event_conn_t) 15320Sigor@sysoev.ru + 4 * sizeof(nxt_buf_t); 15420Sigor@sysoev.ru 15520Sigor@sysoev.ru if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) { 15620Sigor@sysoev.ru return NXT_ERROR; 15720Sigor@sysoev.ru } 15820Sigor@sysoev.ru 15920Sigor@sysoev.ru rt->controller_socket = ls; 16020Sigor@sysoev.ru 16120Sigor@sysoev.ru return NXT_OK; 16220Sigor@sysoev.ru } 16320Sigor@sysoev.ru 16420Sigor@sysoev.ru 16520Sigor@sysoev.ru static void 16620Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 16720Sigor@sysoev.ru { 16827Svbart@nginx.com nxt_buf_t *b; 16927Svbart@nginx.com nxt_event_conn_t *c; 17027Svbart@nginx.com nxt_event_engine_t *engine; 17127Svbart@nginx.com nxt_controller_request_t *r; 17220Sigor@sysoev.ru 17320Sigor@sysoev.ru c = obj; 17420Sigor@sysoev.ru 17520Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 17620Sigor@sysoev.ru 17727Svbart@nginx.com r = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_controller_request_t)); 17827Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 17927Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 18027Svbart@nginx.com return; 18127Svbart@nginx.com } 18227Svbart@nginx.com 18327Svbart@nginx.com r->parser.hash = nxt_controller_request_fields_hash; 18427Svbart@nginx.com r->parser.ctx = r; 18527Svbart@nginx.com 18620Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 18720Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 18820Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 18920Sigor@sysoev.ru return; 19020Sigor@sysoev.ru } 19120Sigor@sysoev.ru 19220Sigor@sysoev.ru c->read = b; 19327Svbart@nginx.com c->socket.data = r; 19420Sigor@sysoev.ru c->socket.read_ready = 1; 19520Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 19620Sigor@sysoev.ru 19720Sigor@sysoev.ru engine = task->thread->engine; 19820Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 19927Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 20020Sigor@sysoev.ru 20120Sigor@sysoev.ru nxt_event_conn_read(engine, c); 20220Sigor@sysoev.ru } 20320Sigor@sysoev.ru 20420Sigor@sysoev.ru 20520Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 20620Sigor@sysoev.ru nxt_aligned(64) = 20720Sigor@sysoev.ru { 20820Sigor@sysoev.ru NXT_EVENT_NO_BUF_PROCESS, 20920Sigor@sysoev.ru NXT_EVENT_TIMER_NO_AUTORESET, 21020Sigor@sysoev.ru 21120Sigor@sysoev.ru nxt_controller_conn_read, 21220Sigor@sysoev.ru nxt_controller_conn_close, 21320Sigor@sysoev.ru nxt_controller_conn_read_error, 21420Sigor@sysoev.ru 21520Sigor@sysoev.ru nxt_controller_conn_read_timeout, 21620Sigor@sysoev.ru nxt_controller_conn_timeout_value, 21720Sigor@sysoev.ru 60 * 1000, 21820Sigor@sysoev.ru }; 21920Sigor@sysoev.ru 22020Sigor@sysoev.ru 22120Sigor@sysoev.ru static void 22220Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 22320Sigor@sysoev.ru { 22427Svbart@nginx.com size_t preread; 22527Svbart@nginx.com nxt_buf_t *b; 22627Svbart@nginx.com nxt_int_t rc; 22727Svbart@nginx.com nxt_event_conn_t *c; 22827Svbart@nginx.com nxt_controller_request_t *r; 22920Sigor@sysoev.ru 23020Sigor@sysoev.ru c = obj; 23127Svbart@nginx.com r = data; 23220Sigor@sysoev.ru 23320Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 23420Sigor@sysoev.ru 23527Svbart@nginx.com nxt_queue_remove(&c->link); 23627Svbart@nginx.com nxt_queue_self(&c->link); 23727Svbart@nginx.com 23827Svbart@nginx.com b = c->read; 23927Svbart@nginx.com 24027Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 24127Svbart@nginx.com 24227Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 24327Svbart@nginx.com 24427Svbart@nginx.com if (rc == NXT_AGAIN) { 24527Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 24627Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 24727Svbart@nginx.com nxt_controller_conn_close(task, c, r); 24827Svbart@nginx.com return; 24927Svbart@nginx.com } 25027Svbart@nginx.com 25127Svbart@nginx.com nxt_event_conn_read(task->thread->engine, c); 25227Svbart@nginx.com return; 25327Svbart@nginx.com } 25427Svbart@nginx.com 25527Svbart@nginx.com /* rc == NXT_ERROR */ 25627Svbart@nginx.com 25727Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 25827Svbart@nginx.com 25927Svbart@nginx.com nxt_controller_conn_close(task, c, r); 26027Svbart@nginx.com return; 26127Svbart@nginx.com } 26227Svbart@nginx.com 26327Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 26427Svbart@nginx.com 26527Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 26627Svbart@nginx.com "body length: %O, preread: %uz", 26727Svbart@nginx.com r->length, preread); 26827Svbart@nginx.com 26927Svbart@nginx.com if (preread >= r->length) { 27027Svbart@nginx.com nxt_controller_process_request(task, c, r); 27127Svbart@nginx.com return; 27227Svbart@nginx.com } 27327Svbart@nginx.com 27427Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 27527Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 27627Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 27727Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 27827Svbart@nginx.com return; 27927Svbart@nginx.com } 28027Svbart@nginx.com 28127Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 28227Svbart@nginx.com 28327Svbart@nginx.com c->read = b; 28427Svbart@nginx.com } 28527Svbart@nginx.com 28627Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 28727Svbart@nginx.com 28827Svbart@nginx.com nxt_event_conn_read(task->thread->engine, c); 28920Sigor@sysoev.ru } 29020Sigor@sysoev.ru 29120Sigor@sysoev.ru 29220Sigor@sysoev.ru static nxt_msec_t 29320Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_event_conn_t *c, uintptr_t data) 29420Sigor@sysoev.ru { 29520Sigor@sysoev.ru return (nxt_msec_t) data; 29620Sigor@sysoev.ru } 29720Sigor@sysoev.ru 29820Sigor@sysoev.ru 29920Sigor@sysoev.ru static void 30020Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 30120Sigor@sysoev.ru { 30220Sigor@sysoev.ru nxt_event_conn_t *c; 30320Sigor@sysoev.ru 30420Sigor@sysoev.ru c = obj; 30520Sigor@sysoev.ru 30620Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 30720Sigor@sysoev.ru 30827Svbart@nginx.com nxt_controller_conn_close(task, c, data); 30920Sigor@sysoev.ru } 31020Sigor@sysoev.ru 31120Sigor@sysoev.ru 31220Sigor@sysoev.ru static void 31320Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 31420Sigor@sysoev.ru { 31520Sigor@sysoev.ru nxt_timer_t *ev; 31620Sigor@sysoev.ru nxt_event_conn_t *c; 31720Sigor@sysoev.ru 31820Sigor@sysoev.ru ev = obj; 31920Sigor@sysoev.ru 32020Sigor@sysoev.ru c = nxt_event_read_timer_conn(ev); 32120Sigor@sysoev.ru c->socket.timedout = 1; 32220Sigor@sysoev.ru c->socket.closed = 1; 32320Sigor@sysoev.ru 32420Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 32520Sigor@sysoev.ru 32627Svbart@nginx.com nxt_controller_conn_close(task, c, data); 32727Svbart@nginx.com } 32827Svbart@nginx.com 32927Svbart@nginx.com 33027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 33127Svbart@nginx.com nxt_aligned(64) = 33227Svbart@nginx.com { 33327Svbart@nginx.com NXT_EVENT_NO_BUF_PROCESS, 33427Svbart@nginx.com NXT_EVENT_TIMER_AUTORESET, 33527Svbart@nginx.com 33627Svbart@nginx.com nxt_controller_conn_body_read, 33727Svbart@nginx.com nxt_controller_conn_close, 33827Svbart@nginx.com nxt_controller_conn_read_error, 33927Svbart@nginx.com 34027Svbart@nginx.com nxt_controller_conn_read_timeout, 34127Svbart@nginx.com nxt_controller_conn_timeout_value, 34227Svbart@nginx.com 60 * 1000, 34327Svbart@nginx.com }; 34427Svbart@nginx.com 34527Svbart@nginx.com 34627Svbart@nginx.com static void 34727Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 34827Svbart@nginx.com { 34927Svbart@nginx.com size_t rest; 35027Svbart@nginx.com nxt_buf_t *b; 35127Svbart@nginx.com nxt_event_conn_t *c; 35227Svbart@nginx.com 35327Svbart@nginx.com c = obj; 35427Svbart@nginx.com 35527Svbart@nginx.com nxt_debug(task, "controller conn body read"); 35627Svbart@nginx.com 35727Svbart@nginx.com b = c->read; 35827Svbart@nginx.com 35927Svbart@nginx.com rest = nxt_buf_mem_free_size(&b->mem); 36027Svbart@nginx.com 36127Svbart@nginx.com if (rest == 0) { 36227Svbart@nginx.com nxt_debug(task, "controller conn body read complete"); 36327Svbart@nginx.com 36427Svbart@nginx.com nxt_controller_process_request(task, c, data); 36527Svbart@nginx.com return; 36627Svbart@nginx.com } 36727Svbart@nginx.com 36827Svbart@nginx.com nxt_debug(task, "controller conn body read again, rest: %uz", rest); 36927Svbart@nginx.com 37027Svbart@nginx.com nxt_event_conn_read(task->thread->engine, c); 37127Svbart@nginx.com } 37227Svbart@nginx.com 37327Svbart@nginx.com 37427Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 37527Svbart@nginx.com nxt_aligned(64) = 37627Svbart@nginx.com { 37727Svbart@nginx.com NXT_EVENT_NO_BUF_PROCESS, 37827Svbart@nginx.com NXT_EVENT_TIMER_AUTORESET, 37927Svbart@nginx.com 38027Svbart@nginx.com nxt_controller_conn_write, 38127Svbart@nginx.com NULL, 38227Svbart@nginx.com nxt_controller_conn_write_error, 38327Svbart@nginx.com 38427Svbart@nginx.com nxt_controller_conn_write_timeout, 38527Svbart@nginx.com nxt_controller_conn_timeout_value, 38627Svbart@nginx.com 60 * 1000, 38727Svbart@nginx.com }; 38827Svbart@nginx.com 38927Svbart@nginx.com 39027Svbart@nginx.com static void 39127Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 39227Svbart@nginx.com { 39327Svbart@nginx.com nxt_buf_t *b; 39427Svbart@nginx.com nxt_event_conn_t *c; 39527Svbart@nginx.com 39627Svbart@nginx.com c = obj; 39727Svbart@nginx.com 39827Svbart@nginx.com nxt_debug(task, "controller conn write"); 39927Svbart@nginx.com 40027Svbart@nginx.com b = c->write; 40127Svbart@nginx.com 40227Svbart@nginx.com if (b->mem.pos != b->mem.free) { 40327Svbart@nginx.com nxt_event_conn_write(task->thread->engine, c); 40427Svbart@nginx.com return; 40527Svbart@nginx.com } 40627Svbart@nginx.com 40727Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 40827Svbart@nginx.com 40927Svbart@nginx.com nxt_controller_conn_close(task, c, data); 41027Svbart@nginx.com } 41127Svbart@nginx.com 41227Svbart@nginx.com 41327Svbart@nginx.com static void 41427Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 41527Svbart@nginx.com { 41627Svbart@nginx.com nxt_event_conn_t *c; 41727Svbart@nginx.com 41827Svbart@nginx.com c = obj; 41927Svbart@nginx.com 42027Svbart@nginx.com nxt_debug(task, "controller conn write error"); 42127Svbart@nginx.com 42227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 42327Svbart@nginx.com } 42427Svbart@nginx.com 42527Svbart@nginx.com 42627Svbart@nginx.com static void 42727Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 42827Svbart@nginx.com { 42927Svbart@nginx.com nxt_timer_t *ev; 43027Svbart@nginx.com nxt_event_conn_t *c; 43127Svbart@nginx.com 43227Svbart@nginx.com ev = obj; 43327Svbart@nginx.com 43427Svbart@nginx.com c = nxt_event_write_timer_conn(ev); 43527Svbart@nginx.com c->socket.timedout = 1; 43627Svbart@nginx.com c->socket.closed = 1; 43727Svbart@nginx.com 43827Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 43927Svbart@nginx.com 44027Svbart@nginx.com nxt_controller_conn_close(task, c, data); 44120Sigor@sysoev.ru } 44220Sigor@sysoev.ru 44320Sigor@sysoev.ru 44420Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 44520Sigor@sysoev.ru nxt_aligned(64) = 44620Sigor@sysoev.ru { 44720Sigor@sysoev.ru NXT_EVENT_NO_BUF_PROCESS, 44820Sigor@sysoev.ru NXT_EVENT_TIMER_NO_AUTORESET, 44920Sigor@sysoev.ru 45020Sigor@sysoev.ru nxt_controller_conn_free, 45120Sigor@sysoev.ru NULL, 45220Sigor@sysoev.ru NULL, 45320Sigor@sysoev.ru 45420Sigor@sysoev.ru NULL, 45520Sigor@sysoev.ru NULL, 45620Sigor@sysoev.ru 0, 45720Sigor@sysoev.ru }; 45820Sigor@sysoev.ru 45920Sigor@sysoev.ru 46020Sigor@sysoev.ru static void 46120Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 46220Sigor@sysoev.ru { 46320Sigor@sysoev.ru nxt_event_conn_t *c; 46420Sigor@sysoev.ru 46520Sigor@sysoev.ru c = obj; 46620Sigor@sysoev.ru 46720Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 46820Sigor@sysoev.ru 46927Svbart@nginx.com nxt_queue_remove(&c->link); 47027Svbart@nginx.com 47120Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 47220Sigor@sysoev.ru 47320Sigor@sysoev.ru nxt_event_conn_close(task->thread->engine, c); 47420Sigor@sysoev.ru } 47520Sigor@sysoev.ru 47620Sigor@sysoev.ru 47720Sigor@sysoev.ru static void 47820Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 47920Sigor@sysoev.ru { 48020Sigor@sysoev.ru nxt_event_conn_t *c; 48120Sigor@sysoev.ru 48220Sigor@sysoev.ru c = obj; 48320Sigor@sysoev.ru 48420Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 48520Sigor@sysoev.ru 48620Sigor@sysoev.ru nxt_mem_pool_destroy(c->mem_pool); 48720Sigor@sysoev.ru 48820Sigor@sysoev.ru //nxt_free(c); 48920Sigor@sysoev.ru } 49027Svbart@nginx.com 49127Svbart@nginx.com 49227Svbart@nginx.com static nxt_int_t 49327Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_str_t *name, 49427Svbart@nginx.com nxt_str_t *value, uintptr_t data) 49527Svbart@nginx.com { 49627Svbart@nginx.com off_t length; 49727Svbart@nginx.com nxt_controller_request_t *r; 49827Svbart@nginx.com 49927Svbart@nginx.com r = ctx; 50027Svbart@nginx.com 50127Svbart@nginx.com length = nxt_off_t_parse(value->start, value->length); 50227Svbart@nginx.com 50327Svbart@nginx.com if (nxt_fast_path(length > 0)) { 50427Svbart@nginx.com /* TODO length too big */ 50527Svbart@nginx.com 50627Svbart@nginx.com r->length = length; 50727Svbart@nginx.com return NXT_OK; 50827Svbart@nginx.com } 50927Svbart@nginx.com 51027Svbart@nginx.com /* TODO logging (task?) */ 51127Svbart@nginx.com 51227Svbart@nginx.com return NXT_ERROR; 51327Svbart@nginx.com } 51427Svbart@nginx.com 51527Svbart@nginx.com 51627Svbart@nginx.com static void 51727Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c, 51827Svbart@nginx.com nxt_controller_request_t *r) 51927Svbart@nginx.com { 52029Svbart@nginx.com nxt_buf_t *b; 52127Svbart@nginx.com 522*33Svbart@nginx.com static const nxt_str_t resp418 523*33Svbart@nginx.com = nxt_string("HTTP/1.0 418 I'm a teapot\r\n\r\nerror\r\n"); 52427Svbart@nginx.com 525*33Svbart@nginx.com if (nxt_controller_request_body_parse(task, c, r) != NXT_OK) { 526*33Svbart@nginx.com goto error; 52729Svbart@nginx.com } 52827Svbart@nginx.com 529*33Svbart@nginx.com nxt_controller_conf_output(task, c, r); 530*33Svbart@nginx.com 531*33Svbart@nginx.com return; 532*33Svbart@nginx.com 533*33Svbart@nginx.com error: 534*33Svbart@nginx.com 535*33Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, resp418.length, 0); 53629Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 53727Svbart@nginx.com nxt_controller_conn_close(task, c, r); 53827Svbart@nginx.com return; 53927Svbart@nginx.com } 54027Svbart@nginx.com 541*33Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, resp418.start, resp418.length); 54227Svbart@nginx.com 54329Svbart@nginx.com c->write = b; 54427Svbart@nginx.com c->write_state = &nxt_controller_conn_write_state; 54527Svbart@nginx.com 54627Svbart@nginx.com nxt_event_conn_write(task->thread->engine, c); 54727Svbart@nginx.com } 54827Svbart@nginx.com 54927Svbart@nginx.com 55027Svbart@nginx.com static nxt_int_t 551*33Svbart@nginx.com nxt_controller_request_body_parse(nxt_task_t *task, nxt_event_conn_t *c, 552*33Svbart@nginx.com nxt_controller_request_t *r) 55327Svbart@nginx.com { 55429Svbart@nginx.com nxt_buf_t *b; 55529Svbart@nginx.com nxt_conf_json_value_t *value; 55629Svbart@nginx.com 55729Svbart@nginx.com b = c->read; 55829Svbart@nginx.com 55929Svbart@nginx.com value = nxt_conf_json_parse(&b->mem, c->mem_pool); 56029Svbart@nginx.com 56129Svbart@nginx.com if (value == NULL) { 56229Svbart@nginx.com return NXT_ERROR; 56329Svbart@nginx.com } 56429Svbart@nginx.com 565*33Svbart@nginx.com r->conf = value; 566*33Svbart@nginx.com 56727Svbart@nginx.com return NXT_OK; 56827Svbart@nginx.com } 569*33Svbart@nginx.com 570*33Svbart@nginx.com 571*33Svbart@nginx.com static void 572*33Svbart@nginx.com nxt_controller_conf_output(nxt_task_t *task, nxt_event_conn_t *c, 573*33Svbart@nginx.com nxt_controller_request_t *r) 574*33Svbart@nginx.com { 575*33Svbart@nginx.com nxt_buf_t *b; 576*33Svbart@nginx.com 577*33Svbart@nginx.com static const nxt_str_t head = nxt_string("HTTP/1.0 200 OK\r\n\r\n"); 578*33Svbart@nginx.com 579*33Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, head.length, 0); 580*33Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 581*33Svbart@nginx.com nxt_controller_conn_close(task, c, r); 582*33Svbart@nginx.com return; 583*33Svbart@nginx.com } 584*33Svbart@nginx.com 585*33Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, head.start, head.length); 586*33Svbart@nginx.com 587*33Svbart@nginx.com c->write = b; 588*33Svbart@nginx.com 589*33Svbart@nginx.com b = nxt_conf_json_print(r->conf, c->mem_pool); 590*33Svbart@nginx.com 591*33Svbart@nginx.com if (b == NULL) { 592*33Svbart@nginx.com nxt_controller_conn_close(task, c, r); 593*33Svbart@nginx.com return; 594*33Svbart@nginx.com } 595*33Svbart@nginx.com 596*33Svbart@nginx.com c->write->next = b; 597*33Svbart@nginx.com c->write_state = &nxt_controller_conn_write_state; 598*33Svbart@nginx.com 599*33Svbart@nginx.com nxt_event_conn_write(task->thread->engine, c); 600*33Svbart@nginx.com return; 601*33Svbart@nginx.com } 602