xref: /unit/src/nxt_controller.c (revision 29)
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>
11*29Svbart@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;
1727Svbart@nginx.com } nxt_controller_request_t;
1827Svbart@nginx.com 
1927Svbart@nginx.com 
2020Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data);
2120Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data);
2220Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_event_conn_t *c,
2320Sigor@sysoev.ru     uintptr_t data);
2420Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj,
2520Sigor@sysoev.ru     void *data);
2620Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj,
2720Sigor@sysoev.ru     void *data);
2827Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj,
2927Svbart@nginx.com     void *data);
3027Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data);
3127Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj,
3227Svbart@nginx.com     void *data);
3327Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj,
3427Svbart@nginx.com     void *data);
3520Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data);
3620Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data);
3720Sigor@sysoev.ru 
3827Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx,
3927Svbart@nginx.com     nxt_str_t *name, nxt_str_t *value, uintptr_t data);
4027Svbart@nginx.com 
4127Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task,
4227Svbart@nginx.com     nxt_event_conn_t *c, nxt_controller_request_t *r);
43*29Svbart@nginx.com static nxt_int_t nxt_controller_request_body_parse(nxt_task_t *task,
44*29Svbart@nginx.com     nxt_event_conn_t *c);
4527Svbart@nginx.com 
4627Svbart@nginx.com 
4727Svbart@nginx.com static nxt_http_fields_t  nxt_controller_request_fields[] = {
4827Svbart@nginx.com     { nxt_string("Content-Length"),
4927Svbart@nginx.com       &nxt_controller_request_content_length, 0 },
5027Svbart@nginx.com 
5127Svbart@nginx.com     { nxt_null_string, NULL, 0 }
5227Svbart@nginx.com };
5327Svbart@nginx.com 
5427Svbart@nginx.com 
5527Svbart@nginx.com static nxt_http_fields_hash_t  *nxt_controller_request_fields_hash;
5627Svbart@nginx.com 
5720Sigor@sysoev.ru 
5820Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_read_state;
5927Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state;
6027Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_write_state;
6120Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_close_state;
6220Sigor@sysoev.ru 
6320Sigor@sysoev.ru 
6420Sigor@sysoev.ru nxt_int_t
6520Sigor@sysoev.ru nxt_controller_start(nxt_task_t *task, nxt_runtime_t *rt)
6620Sigor@sysoev.ru {
6727Svbart@nginx.com     nxt_http_fields_hash_t  *hash;
6827Svbart@nginx.com 
6927Svbart@nginx.com     hash = nxt_http_fields_hash(nxt_controller_request_fields, rt->mem_pool);
7027Svbart@nginx.com 
7127Svbart@nginx.com     if (nxt_slow_path(hash == NULL)) {
7227Svbart@nginx.com         return NXT_ERROR;
7327Svbart@nginx.com     }
7427Svbart@nginx.com 
7527Svbart@nginx.com     nxt_controller_request_fields_hash = hash;
7627Svbart@nginx.com 
7720Sigor@sysoev.ru     if (nxt_event_conn_listen(task, rt->controller_socket) != NXT_OK) {
7820Sigor@sysoev.ru         return NXT_ERROR;
7920Sigor@sysoev.ru     }
8020Sigor@sysoev.ru 
8120Sigor@sysoev.ru     return NXT_OK;
8220Sigor@sysoev.ru }
8320Sigor@sysoev.ru 
8420Sigor@sysoev.ru 
8520Sigor@sysoev.ru nxt_int_t
8620Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt)
8720Sigor@sysoev.ru {
8820Sigor@sysoev.ru     nxt_sockaddr_t       *sa;
8920Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
9020Sigor@sysoev.ru 
9120Sigor@sysoev.ru     sa = rt->controller_listen;
9220Sigor@sysoev.ru 
9320Sigor@sysoev.ru     if (rt->controller_listen == NULL) {
9420Sigor@sysoev.ru         sa = nxt_sockaddr_alloc(rt->mem_pool, sizeof(struct sockaddr_in),
9520Sigor@sysoev.ru                                 NXT_INET_ADDR_STR_LEN);
9620Sigor@sysoev.ru         if (sa == NULL) {
9720Sigor@sysoev.ru             return NXT_ERROR;
9820Sigor@sysoev.ru         }
9920Sigor@sysoev.ru 
10020Sigor@sysoev.ru         sa->type = SOCK_STREAM;
10120Sigor@sysoev.ru         sa->u.sockaddr_in.sin_family = AF_INET;
10220Sigor@sysoev.ru         sa->u.sockaddr_in.sin_port = htons(8443);
10320Sigor@sysoev.ru 
10420Sigor@sysoev.ru         nxt_sockaddr_text(sa);
10520Sigor@sysoev.ru 
10620Sigor@sysoev.ru         rt->controller_listen = sa;
10720Sigor@sysoev.ru     }
10820Sigor@sysoev.ru 
10920Sigor@sysoev.ru     ls = nxt_mem_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t));
11020Sigor@sysoev.ru     if (ls == NULL) {
11120Sigor@sysoev.ru         return NXT_ERROR;
11220Sigor@sysoev.ru     }
11320Sigor@sysoev.ru 
11420Sigor@sysoev.ru     ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr,
11520Sigor@sysoev.ru                                        sa->socklen, sa->length);
11620Sigor@sysoev.ru     if (ls->sockaddr == NULL) {
11720Sigor@sysoev.ru         return NXT_ERROR;
11820Sigor@sysoev.ru     }
11920Sigor@sysoev.ru 
12020Sigor@sysoev.ru     ls->sockaddr->type = sa->type;
12120Sigor@sysoev.ru 
12220Sigor@sysoev.ru     nxt_sockaddr_text(ls->sockaddr);
12320Sigor@sysoev.ru 
12420Sigor@sysoev.ru     ls->socket = -1;
12520Sigor@sysoev.ru     ls->backlog = NXT_LISTEN_BACKLOG;
12620Sigor@sysoev.ru     ls->read_after_accept = 1;
12720Sigor@sysoev.ru     ls->flags = NXT_NONBLOCK;
12820Sigor@sysoev.ru 
12920Sigor@sysoev.ru #if 0
13020Sigor@sysoev.ru     /* STUB */
13120Sigor@sysoev.ru     wq = nxt_mem_zalloc(cf->mem_pool, sizeof(nxt_work_queue_t));
13220Sigor@sysoev.ru     if (wq == NULL) {
13320Sigor@sysoev.ru         return NXT_ERROR;
13420Sigor@sysoev.ru     }
13520Sigor@sysoev.ru     nxt_work_queue_name(wq, "listen");
13620Sigor@sysoev.ru     /**/
13720Sigor@sysoev.ru 
13820Sigor@sysoev.ru     ls->work_queue = wq;
13920Sigor@sysoev.ru #endif
14020Sigor@sysoev.ru     ls->handler = nxt_controller_conn_init;
14120Sigor@sysoev.ru 
14220Sigor@sysoev.ru     /*
14320Sigor@sysoev.ru      * Connection memory pool chunk size is tunned to
14420Sigor@sysoev.ru      * allocate the most data in one mem_pool chunk.
14520Sigor@sysoev.ru      */
14620Sigor@sysoev.ru     ls->mem_pool_size = nxt_listen_socket_pool_min_size(ls)
14720Sigor@sysoev.ru                         + sizeof(nxt_event_conn_proxy_t)
14820Sigor@sysoev.ru                         + sizeof(nxt_event_conn_t)
14920Sigor@sysoev.ru                         + 4 * sizeof(nxt_buf_t);
15020Sigor@sysoev.ru 
15120Sigor@sysoev.ru     if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) {
15220Sigor@sysoev.ru         return NXT_ERROR;
15320Sigor@sysoev.ru     }
15420Sigor@sysoev.ru 
15520Sigor@sysoev.ru     rt->controller_socket = ls;
15620Sigor@sysoev.ru 
15720Sigor@sysoev.ru     return NXT_OK;
15820Sigor@sysoev.ru }
15920Sigor@sysoev.ru 
16020Sigor@sysoev.ru 
16120Sigor@sysoev.ru static void
16220Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data)
16320Sigor@sysoev.ru {
16427Svbart@nginx.com     nxt_buf_t                 *b;
16527Svbart@nginx.com     nxt_event_conn_t          *c;
16627Svbart@nginx.com     nxt_event_engine_t        *engine;
16727Svbart@nginx.com     nxt_controller_request_t  *r;
16820Sigor@sysoev.ru 
16920Sigor@sysoev.ru     c = obj;
17020Sigor@sysoev.ru 
17120Sigor@sysoev.ru     nxt_debug(task, "controller conn init fd:%d", c->socket.fd);
17220Sigor@sysoev.ru 
17327Svbart@nginx.com     r = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_controller_request_t));
17427Svbart@nginx.com     if (nxt_slow_path(r == NULL)) {
17527Svbart@nginx.com         nxt_controller_conn_free(task, c, NULL);
17627Svbart@nginx.com         return;
17727Svbart@nginx.com     }
17827Svbart@nginx.com 
17927Svbart@nginx.com     r->parser.hash = nxt_controller_request_fields_hash;
18027Svbart@nginx.com     r->parser.ctx = r;
18127Svbart@nginx.com 
18220Sigor@sysoev.ru     b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0);
18320Sigor@sysoev.ru     if (nxt_slow_path(b == NULL)) {
18420Sigor@sysoev.ru         nxt_controller_conn_free(task, c, NULL);
18520Sigor@sysoev.ru         return;
18620Sigor@sysoev.ru     }
18720Sigor@sysoev.ru 
18820Sigor@sysoev.ru     c->read = b;
18927Svbart@nginx.com     c->socket.data = r;
19020Sigor@sysoev.ru     c->socket.read_ready = 1;
19120Sigor@sysoev.ru     c->read_state = &nxt_controller_conn_read_state;
19220Sigor@sysoev.ru 
19320Sigor@sysoev.ru     engine = task->thread->engine;
19420Sigor@sysoev.ru     c->read_work_queue = &engine->read_work_queue;
19527Svbart@nginx.com     c->write_work_queue = &engine->write_work_queue;
19620Sigor@sysoev.ru 
19720Sigor@sysoev.ru     nxt_event_conn_read(engine, c);
19820Sigor@sysoev.ru }
19920Sigor@sysoev.ru 
20020Sigor@sysoev.ru 
20120Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_read_state
20220Sigor@sysoev.ru     nxt_aligned(64) =
20320Sigor@sysoev.ru {
20420Sigor@sysoev.ru     NXT_EVENT_NO_BUF_PROCESS,
20520Sigor@sysoev.ru     NXT_EVENT_TIMER_NO_AUTORESET,
20620Sigor@sysoev.ru 
20720Sigor@sysoev.ru     nxt_controller_conn_read,
20820Sigor@sysoev.ru     nxt_controller_conn_close,
20920Sigor@sysoev.ru     nxt_controller_conn_read_error,
21020Sigor@sysoev.ru 
21120Sigor@sysoev.ru     nxt_controller_conn_read_timeout,
21220Sigor@sysoev.ru     nxt_controller_conn_timeout_value,
21320Sigor@sysoev.ru     60 * 1000,
21420Sigor@sysoev.ru };
21520Sigor@sysoev.ru 
21620Sigor@sysoev.ru 
21720Sigor@sysoev.ru static void
21820Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data)
21920Sigor@sysoev.ru {
22027Svbart@nginx.com     size_t                    preread;
22127Svbart@nginx.com     nxt_buf_t                 *b;
22227Svbart@nginx.com     nxt_int_t                 rc;
22327Svbart@nginx.com     nxt_event_conn_t          *c;
22427Svbart@nginx.com     nxt_controller_request_t  *r;
22520Sigor@sysoev.ru 
22620Sigor@sysoev.ru     c = obj;
22727Svbart@nginx.com     r = data;
22820Sigor@sysoev.ru 
22920Sigor@sysoev.ru     nxt_debug(task, "controller conn read");
23020Sigor@sysoev.ru 
23127Svbart@nginx.com     nxt_queue_remove(&c->link);
23227Svbart@nginx.com     nxt_queue_self(&c->link);
23327Svbart@nginx.com 
23427Svbart@nginx.com     b = c->read;
23527Svbart@nginx.com 
23627Svbart@nginx.com     rc = nxt_http_parse_request(&r->parser, &b->mem);
23727Svbart@nginx.com 
23827Svbart@nginx.com     if (nxt_slow_path(rc != NXT_DONE)) {
23927Svbart@nginx.com 
24027Svbart@nginx.com         if (rc == NXT_AGAIN) {
24127Svbart@nginx.com             if (nxt_buf_mem_free_size(&b->mem) == 0) {
24227Svbart@nginx.com                 nxt_log(task, NXT_LOG_ERR, "too long request headers");
24327Svbart@nginx.com                 nxt_controller_conn_close(task, c, r);
24427Svbart@nginx.com                 return;
24527Svbart@nginx.com             }
24627Svbart@nginx.com 
24727Svbart@nginx.com             nxt_event_conn_read(task->thread->engine, c);
24827Svbart@nginx.com             return;
24927Svbart@nginx.com         }
25027Svbart@nginx.com 
25127Svbart@nginx.com         /* rc == NXT_ERROR */
25227Svbart@nginx.com 
25327Svbart@nginx.com         nxt_log(task, NXT_LOG_ERR, "parsing error");
25427Svbart@nginx.com 
25527Svbart@nginx.com         nxt_controller_conn_close(task, c, r);
25627Svbart@nginx.com         return;
25727Svbart@nginx.com     }
25827Svbart@nginx.com 
25927Svbart@nginx.com     preread = nxt_buf_mem_used_size(&b->mem);
26027Svbart@nginx.com 
26127Svbart@nginx.com     nxt_debug(task, "controller request header parsing complete, "
26227Svbart@nginx.com                     "body length: %O, preread: %uz",
26327Svbart@nginx.com                     r->length, preread);
26427Svbart@nginx.com 
26527Svbart@nginx.com     if (preread >= r->length) {
26627Svbart@nginx.com         nxt_controller_process_request(task, c, r);
26727Svbart@nginx.com         return;
26827Svbart@nginx.com     }
26927Svbart@nginx.com 
27027Svbart@nginx.com     if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) {
27127Svbart@nginx.com         b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0);
27227Svbart@nginx.com         if (nxt_slow_path(b == NULL)) {
27327Svbart@nginx.com             nxt_controller_conn_free(task, c, NULL);
27427Svbart@nginx.com             return;
27527Svbart@nginx.com         }
27627Svbart@nginx.com 
27727Svbart@nginx.com         b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread);
27827Svbart@nginx.com 
27927Svbart@nginx.com         c->read = b;
28027Svbart@nginx.com     }
28127Svbart@nginx.com 
28227Svbart@nginx.com     c->read_state = &nxt_controller_conn_body_read_state;
28327Svbart@nginx.com 
28427Svbart@nginx.com     nxt_event_conn_read(task->thread->engine, c);
28520Sigor@sysoev.ru }
28620Sigor@sysoev.ru 
28720Sigor@sysoev.ru 
28820Sigor@sysoev.ru static nxt_msec_t
28920Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_event_conn_t *c, uintptr_t data)
29020Sigor@sysoev.ru {
29120Sigor@sysoev.ru     return (nxt_msec_t) data;
29220Sigor@sysoev.ru }
29320Sigor@sysoev.ru 
29420Sigor@sysoev.ru 
29520Sigor@sysoev.ru static void
29620Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data)
29720Sigor@sysoev.ru {
29820Sigor@sysoev.ru     nxt_event_conn_t  *c;
29920Sigor@sysoev.ru 
30020Sigor@sysoev.ru     c = obj;
30120Sigor@sysoev.ru 
30220Sigor@sysoev.ru     nxt_debug(task, "controller conn read error");
30320Sigor@sysoev.ru 
30427Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
30520Sigor@sysoev.ru }
30620Sigor@sysoev.ru 
30720Sigor@sysoev.ru 
30820Sigor@sysoev.ru static void
30920Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data)
31020Sigor@sysoev.ru {
31120Sigor@sysoev.ru     nxt_timer_t       *ev;
31220Sigor@sysoev.ru     nxt_event_conn_t  *c;
31320Sigor@sysoev.ru 
31420Sigor@sysoev.ru     ev = obj;
31520Sigor@sysoev.ru 
31620Sigor@sysoev.ru     c = nxt_event_read_timer_conn(ev);
31720Sigor@sysoev.ru     c->socket.timedout = 1;
31820Sigor@sysoev.ru     c->socket.closed = 1;
31920Sigor@sysoev.ru 
32020Sigor@sysoev.ru     nxt_debug(task, "controller conn read timeout");
32120Sigor@sysoev.ru 
32227Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
32327Svbart@nginx.com }
32427Svbart@nginx.com 
32527Svbart@nginx.com 
32627Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state
32727Svbart@nginx.com     nxt_aligned(64) =
32827Svbart@nginx.com {
32927Svbart@nginx.com     NXT_EVENT_NO_BUF_PROCESS,
33027Svbart@nginx.com     NXT_EVENT_TIMER_AUTORESET,
33127Svbart@nginx.com 
33227Svbart@nginx.com     nxt_controller_conn_body_read,
33327Svbart@nginx.com     nxt_controller_conn_close,
33427Svbart@nginx.com     nxt_controller_conn_read_error,
33527Svbart@nginx.com 
33627Svbart@nginx.com     nxt_controller_conn_read_timeout,
33727Svbart@nginx.com     nxt_controller_conn_timeout_value,
33827Svbart@nginx.com     60 * 1000,
33927Svbart@nginx.com };
34027Svbart@nginx.com 
34127Svbart@nginx.com 
34227Svbart@nginx.com static void
34327Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data)
34427Svbart@nginx.com {
34527Svbart@nginx.com     size_t            rest;
34627Svbart@nginx.com     nxt_buf_t         *b;
34727Svbart@nginx.com     nxt_event_conn_t  *c;
34827Svbart@nginx.com 
34927Svbart@nginx.com     c = obj;
35027Svbart@nginx.com 
35127Svbart@nginx.com     nxt_debug(task, "controller conn body read");
35227Svbart@nginx.com 
35327Svbart@nginx.com     b = c->read;
35427Svbart@nginx.com 
35527Svbart@nginx.com     rest = nxt_buf_mem_free_size(&b->mem);
35627Svbart@nginx.com 
35727Svbart@nginx.com     if (rest == 0) {
35827Svbart@nginx.com         nxt_debug(task, "controller conn body read complete");
35927Svbart@nginx.com 
36027Svbart@nginx.com         nxt_controller_process_request(task, c, data);
36127Svbart@nginx.com         return;
36227Svbart@nginx.com     }
36327Svbart@nginx.com 
36427Svbart@nginx.com     nxt_debug(task, "controller conn body read again, rest: %uz", rest);
36527Svbart@nginx.com 
36627Svbart@nginx.com     nxt_event_conn_read(task->thread->engine, c);
36727Svbart@nginx.com }
36827Svbart@nginx.com 
36927Svbart@nginx.com 
37027Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_write_state
37127Svbart@nginx.com     nxt_aligned(64) =
37227Svbart@nginx.com {
37327Svbart@nginx.com     NXT_EVENT_NO_BUF_PROCESS,
37427Svbart@nginx.com     NXT_EVENT_TIMER_AUTORESET,
37527Svbart@nginx.com 
37627Svbart@nginx.com     nxt_controller_conn_write,
37727Svbart@nginx.com     NULL,
37827Svbart@nginx.com     nxt_controller_conn_write_error,
37927Svbart@nginx.com 
38027Svbart@nginx.com     nxt_controller_conn_write_timeout,
38127Svbart@nginx.com     nxt_controller_conn_timeout_value,
38227Svbart@nginx.com     60 * 1000,
38327Svbart@nginx.com };
38427Svbart@nginx.com 
38527Svbart@nginx.com 
38627Svbart@nginx.com static void
38727Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data)
38827Svbart@nginx.com {
38927Svbart@nginx.com     nxt_buf_t         *b;
39027Svbart@nginx.com     nxt_event_conn_t  *c;
39127Svbart@nginx.com 
39227Svbart@nginx.com     c = obj;
39327Svbart@nginx.com 
39427Svbart@nginx.com     nxt_debug(task, "controller conn write");
39527Svbart@nginx.com 
39627Svbart@nginx.com     b = c->write;
39727Svbart@nginx.com 
39827Svbart@nginx.com     if (b->mem.pos != b->mem.free) {
39927Svbart@nginx.com         nxt_event_conn_write(task->thread->engine, c);
40027Svbart@nginx.com         return;
40127Svbart@nginx.com     }
40227Svbart@nginx.com 
40327Svbart@nginx.com     nxt_debug(task, "controller conn write complete");
40427Svbart@nginx.com 
40527Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
40627Svbart@nginx.com }
40727Svbart@nginx.com 
40827Svbart@nginx.com 
40927Svbart@nginx.com static void
41027Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data)
41127Svbart@nginx.com {
41227Svbart@nginx.com     nxt_event_conn_t  *c;
41327Svbart@nginx.com 
41427Svbart@nginx.com     c = obj;
41527Svbart@nginx.com 
41627Svbart@nginx.com     nxt_debug(task, "controller conn write error");
41727Svbart@nginx.com 
41827Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
41927Svbart@nginx.com }
42027Svbart@nginx.com 
42127Svbart@nginx.com 
42227Svbart@nginx.com static void
42327Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data)
42427Svbart@nginx.com {
42527Svbart@nginx.com     nxt_timer_t       *ev;
42627Svbart@nginx.com     nxt_event_conn_t  *c;
42727Svbart@nginx.com 
42827Svbart@nginx.com     ev = obj;
42927Svbart@nginx.com 
43027Svbart@nginx.com     c = nxt_event_write_timer_conn(ev);
43127Svbart@nginx.com     c->socket.timedout = 1;
43227Svbart@nginx.com     c->socket.closed = 1;
43327Svbart@nginx.com 
43427Svbart@nginx.com     nxt_debug(task, "controller conn write timeout");
43527Svbart@nginx.com 
43627Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
43720Sigor@sysoev.ru }
43820Sigor@sysoev.ru 
43920Sigor@sysoev.ru 
44020Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_close_state
44120Sigor@sysoev.ru     nxt_aligned(64) =
44220Sigor@sysoev.ru {
44320Sigor@sysoev.ru     NXT_EVENT_NO_BUF_PROCESS,
44420Sigor@sysoev.ru     NXT_EVENT_TIMER_NO_AUTORESET,
44520Sigor@sysoev.ru 
44620Sigor@sysoev.ru     nxt_controller_conn_free,
44720Sigor@sysoev.ru     NULL,
44820Sigor@sysoev.ru     NULL,
44920Sigor@sysoev.ru 
45020Sigor@sysoev.ru     NULL,
45120Sigor@sysoev.ru     NULL,
45220Sigor@sysoev.ru     0,
45320Sigor@sysoev.ru };
45420Sigor@sysoev.ru 
45520Sigor@sysoev.ru 
45620Sigor@sysoev.ru static void
45720Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data)
45820Sigor@sysoev.ru {
45920Sigor@sysoev.ru     nxt_event_conn_t  *c;
46020Sigor@sysoev.ru 
46120Sigor@sysoev.ru     c = obj;
46220Sigor@sysoev.ru 
46320Sigor@sysoev.ru     nxt_debug(task, "controller conn close");
46420Sigor@sysoev.ru 
46527Svbart@nginx.com     nxt_queue_remove(&c->link);
46627Svbart@nginx.com 
46720Sigor@sysoev.ru     c->write_state = &nxt_controller_conn_close_state;
46820Sigor@sysoev.ru 
46920Sigor@sysoev.ru     nxt_event_conn_close(task->thread->engine, c);
47020Sigor@sysoev.ru }
47120Sigor@sysoev.ru 
47220Sigor@sysoev.ru 
47320Sigor@sysoev.ru static void
47420Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data)
47520Sigor@sysoev.ru {
47620Sigor@sysoev.ru     nxt_event_conn_t  *c;
47720Sigor@sysoev.ru 
47820Sigor@sysoev.ru     c = obj;
47920Sigor@sysoev.ru 
48020Sigor@sysoev.ru     nxt_debug(task, "controller conn free");
48120Sigor@sysoev.ru 
48220Sigor@sysoev.ru     nxt_mem_pool_destroy(c->mem_pool);
48320Sigor@sysoev.ru 
48420Sigor@sysoev.ru     //nxt_free(c);
48520Sigor@sysoev.ru }
48627Svbart@nginx.com 
48727Svbart@nginx.com 
48827Svbart@nginx.com static nxt_int_t
48927Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_str_t *name,
49027Svbart@nginx.com     nxt_str_t *value, uintptr_t data)
49127Svbart@nginx.com {
49227Svbart@nginx.com     off_t                     length;
49327Svbart@nginx.com     nxt_controller_request_t  *r;
49427Svbart@nginx.com 
49527Svbart@nginx.com     r = ctx;
49627Svbart@nginx.com 
49727Svbart@nginx.com     length = nxt_off_t_parse(value->start, value->length);
49827Svbart@nginx.com 
49927Svbart@nginx.com     if (nxt_fast_path(length > 0)) {
50027Svbart@nginx.com         /* TODO length too big */
50127Svbart@nginx.com 
50227Svbart@nginx.com         r->length = length;
50327Svbart@nginx.com         return NXT_OK;
50427Svbart@nginx.com     }
50527Svbart@nginx.com 
50627Svbart@nginx.com     /* TODO logging (task?) */
50727Svbart@nginx.com 
50827Svbart@nginx.com     return NXT_ERROR;
50927Svbart@nginx.com }
51027Svbart@nginx.com 
51127Svbart@nginx.com 
51227Svbart@nginx.com static void
51327Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c,
51427Svbart@nginx.com     nxt_controller_request_t *r)
51527Svbart@nginx.com {
516*29Svbart@nginx.com     nxt_str_t  response;
517*29Svbart@nginx.com     nxt_buf_t  *b;
51827Svbart@nginx.com 
519*29Svbart@nginx.com     static const u_char response_good[]
520*29Svbart@nginx.com         = "HTTP/1.0 200 OK\r\n\r\ndone\r\n";
52127Svbart@nginx.com 
522*29Svbart@nginx.com     static const u_char response_bad[]
523*29Svbart@nginx.com         = "HTTP/1.0 418 I'm a teapot\r\n\r\nerror\r\n";
52427Svbart@nginx.com 
525*29Svbart@nginx.com     if (nxt_controller_request_body_parse(task, c) == NXT_OK) {
526*29Svbart@nginx.com         nxt_str_set(&response, response_good);
52727Svbart@nginx.com 
528*29Svbart@nginx.com     } else {
529*29Svbart@nginx.com         nxt_str_set(&response, response_bad);
530*29Svbart@nginx.com     }
53127Svbart@nginx.com 
532*29Svbart@nginx.com     b = nxt_buf_mem_alloc(c->mem_pool, response.length, 0);
533*29Svbart@nginx.com     if (nxt_slow_path(b == NULL)) {
53427Svbart@nginx.com         nxt_controller_conn_close(task, c, r);
53527Svbart@nginx.com         return;
53627Svbart@nginx.com     }
53727Svbart@nginx.com 
538*29Svbart@nginx.com     b->mem.free = nxt_cpymem(b->mem.free, response.start, response.length);
53927Svbart@nginx.com 
540*29Svbart@nginx.com     c->write = b;
54127Svbart@nginx.com     c->write_state = &nxt_controller_conn_write_state;
54227Svbart@nginx.com 
54327Svbart@nginx.com     nxt_event_conn_write(task->thread->engine, c);
54427Svbart@nginx.com }
54527Svbart@nginx.com 
54627Svbart@nginx.com 
54727Svbart@nginx.com static nxt_int_t
548*29Svbart@nginx.com nxt_controller_request_body_parse(nxt_task_t *task, nxt_event_conn_t *c)
54927Svbart@nginx.com {
550*29Svbart@nginx.com     nxt_buf_t              *b;
551*29Svbart@nginx.com     nxt_conf_json_value_t  *value;
552*29Svbart@nginx.com 
553*29Svbart@nginx.com     b = c->read;
554*29Svbart@nginx.com 
555*29Svbart@nginx.com     value = nxt_conf_json_parse(&b->mem, c->mem_pool);
556*29Svbart@nginx.com 
557*29Svbart@nginx.com     if (value == NULL) {
558*29Svbart@nginx.com         return NXT_ERROR;
559*29Svbart@nginx.com     }
560*29Svbart@nginx.com 
56127Svbart@nginx.com     return NXT_OK;
56227Svbart@nginx.com }
563