xref: /unit/src/nxt_controller.c (revision 27)
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>
1120Sigor@sysoev.ru 
1220Sigor@sysoev.ru 
13*27Svbart@nginx.com typedef struct {
14*27Svbart@nginx.com     nxt_http_request_parse_t  parser;
15*27Svbart@nginx.com     size_t                    length;
16*27Svbart@nginx.com } nxt_controller_request_t;
17*27Svbart@nginx.com 
18*27Svbart@nginx.com 
1920Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data);
2020Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data);
2120Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_event_conn_t *c,
2220Sigor@sysoev.ru     uintptr_t data);
2320Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj,
2420Sigor@sysoev.ru     void *data);
2520Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj,
2620Sigor@sysoev.ru     void *data);
27*27Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj,
28*27Svbart@nginx.com     void *data);
29*27Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data);
30*27Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj,
31*27Svbart@nginx.com     void *data);
32*27Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj,
33*27Svbart@nginx.com     void *data);
3420Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data);
3520Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data);
3620Sigor@sysoev.ru 
37*27Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx,
38*27Svbart@nginx.com     nxt_str_t *name, nxt_str_t *value, uintptr_t data);
39*27Svbart@nginx.com 
40*27Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task,
41*27Svbart@nginx.com     nxt_event_conn_t *c, nxt_controller_request_t *r);
42*27Svbart@nginx.com static nxt_int_t nxt_controller_request_body_parse(nxt_buf_mem_t *b);
43*27Svbart@nginx.com 
44*27Svbart@nginx.com 
45*27Svbart@nginx.com static nxt_http_fields_t  nxt_controller_request_fields[] = {
46*27Svbart@nginx.com     { nxt_string("Content-Length"),
47*27Svbart@nginx.com       &nxt_controller_request_content_length, 0 },
48*27Svbart@nginx.com 
49*27Svbart@nginx.com     { nxt_null_string, NULL, 0 }
50*27Svbart@nginx.com };
51*27Svbart@nginx.com 
52*27Svbart@nginx.com 
53*27Svbart@nginx.com static nxt_http_fields_hash_t  *nxt_controller_request_fields_hash;
54*27Svbart@nginx.com 
5520Sigor@sysoev.ru 
5620Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_read_state;
57*27Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state;
58*27Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_write_state;
5920Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_close_state;
6020Sigor@sysoev.ru 
6120Sigor@sysoev.ru 
6220Sigor@sysoev.ru nxt_int_t
6320Sigor@sysoev.ru nxt_controller_start(nxt_task_t *task, nxt_runtime_t *rt)
6420Sigor@sysoev.ru {
65*27Svbart@nginx.com     nxt_http_fields_hash_t  *hash;
66*27Svbart@nginx.com 
67*27Svbart@nginx.com     hash = nxt_http_fields_hash(nxt_controller_request_fields, rt->mem_pool);
68*27Svbart@nginx.com 
69*27Svbart@nginx.com     if (nxt_slow_path(hash == NULL)) {
70*27Svbart@nginx.com         return NXT_ERROR;
71*27Svbart@nginx.com     }
72*27Svbart@nginx.com 
73*27Svbart@nginx.com     nxt_controller_request_fields_hash = hash;
74*27Svbart@nginx.com 
7520Sigor@sysoev.ru     if (nxt_event_conn_listen(task, rt->controller_socket) != NXT_OK) {
7620Sigor@sysoev.ru         return NXT_ERROR;
7720Sigor@sysoev.ru     }
7820Sigor@sysoev.ru 
7920Sigor@sysoev.ru     return NXT_OK;
8020Sigor@sysoev.ru }
8120Sigor@sysoev.ru 
8220Sigor@sysoev.ru 
8320Sigor@sysoev.ru nxt_int_t
8420Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt)
8520Sigor@sysoev.ru {
8620Sigor@sysoev.ru     nxt_sockaddr_t       *sa;
8720Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
8820Sigor@sysoev.ru 
8920Sigor@sysoev.ru     sa = rt->controller_listen;
9020Sigor@sysoev.ru 
9120Sigor@sysoev.ru     if (rt->controller_listen == NULL) {
9220Sigor@sysoev.ru         sa = nxt_sockaddr_alloc(rt->mem_pool, sizeof(struct sockaddr_in),
9320Sigor@sysoev.ru                                 NXT_INET_ADDR_STR_LEN);
9420Sigor@sysoev.ru         if (sa == NULL) {
9520Sigor@sysoev.ru             return NXT_ERROR;
9620Sigor@sysoev.ru         }
9720Sigor@sysoev.ru 
9820Sigor@sysoev.ru         sa->type = SOCK_STREAM;
9920Sigor@sysoev.ru         sa->u.sockaddr_in.sin_family = AF_INET;
10020Sigor@sysoev.ru         sa->u.sockaddr_in.sin_port = htons(8443);
10120Sigor@sysoev.ru 
10220Sigor@sysoev.ru         nxt_sockaddr_text(sa);
10320Sigor@sysoev.ru 
10420Sigor@sysoev.ru         rt->controller_listen = sa;
10520Sigor@sysoev.ru     }
10620Sigor@sysoev.ru 
10720Sigor@sysoev.ru     ls = nxt_mem_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t));
10820Sigor@sysoev.ru     if (ls == NULL) {
10920Sigor@sysoev.ru         return NXT_ERROR;
11020Sigor@sysoev.ru     }
11120Sigor@sysoev.ru 
11220Sigor@sysoev.ru     ls->sockaddr = nxt_sockaddr_create(rt->mem_pool, &sa->u.sockaddr,
11320Sigor@sysoev.ru                                        sa->socklen, sa->length);
11420Sigor@sysoev.ru     if (ls->sockaddr == NULL) {
11520Sigor@sysoev.ru         return NXT_ERROR;
11620Sigor@sysoev.ru     }
11720Sigor@sysoev.ru 
11820Sigor@sysoev.ru     ls->sockaddr->type = sa->type;
11920Sigor@sysoev.ru 
12020Sigor@sysoev.ru     nxt_sockaddr_text(ls->sockaddr);
12120Sigor@sysoev.ru 
12220Sigor@sysoev.ru     ls->socket = -1;
12320Sigor@sysoev.ru     ls->backlog = NXT_LISTEN_BACKLOG;
12420Sigor@sysoev.ru     ls->read_after_accept = 1;
12520Sigor@sysoev.ru     ls->flags = NXT_NONBLOCK;
12620Sigor@sysoev.ru 
12720Sigor@sysoev.ru #if 0
12820Sigor@sysoev.ru     /* STUB */
12920Sigor@sysoev.ru     wq = nxt_mem_zalloc(cf->mem_pool, sizeof(nxt_work_queue_t));
13020Sigor@sysoev.ru     if (wq == NULL) {
13120Sigor@sysoev.ru         return NXT_ERROR;
13220Sigor@sysoev.ru     }
13320Sigor@sysoev.ru     nxt_work_queue_name(wq, "listen");
13420Sigor@sysoev.ru     /**/
13520Sigor@sysoev.ru 
13620Sigor@sysoev.ru     ls->work_queue = wq;
13720Sigor@sysoev.ru #endif
13820Sigor@sysoev.ru     ls->handler = nxt_controller_conn_init;
13920Sigor@sysoev.ru 
14020Sigor@sysoev.ru     /*
14120Sigor@sysoev.ru      * Connection memory pool chunk size is tunned to
14220Sigor@sysoev.ru      * allocate the most data in one mem_pool chunk.
14320Sigor@sysoev.ru      */
14420Sigor@sysoev.ru     ls->mem_pool_size = nxt_listen_socket_pool_min_size(ls)
14520Sigor@sysoev.ru                         + sizeof(nxt_event_conn_proxy_t)
14620Sigor@sysoev.ru                         + sizeof(nxt_event_conn_t)
14720Sigor@sysoev.ru                         + 4 * sizeof(nxt_buf_t);
14820Sigor@sysoev.ru 
14920Sigor@sysoev.ru     if (nxt_listen_socket_create(task, ls, 0) != NXT_OK) {
15020Sigor@sysoev.ru         return NXT_ERROR;
15120Sigor@sysoev.ru     }
15220Sigor@sysoev.ru 
15320Sigor@sysoev.ru     rt->controller_socket = ls;
15420Sigor@sysoev.ru 
15520Sigor@sysoev.ru     return NXT_OK;
15620Sigor@sysoev.ru }
15720Sigor@sysoev.ru 
15820Sigor@sysoev.ru 
15920Sigor@sysoev.ru static void
16020Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data)
16120Sigor@sysoev.ru {
162*27Svbart@nginx.com     nxt_buf_t                 *b;
163*27Svbart@nginx.com     nxt_event_conn_t          *c;
164*27Svbart@nginx.com     nxt_event_engine_t        *engine;
165*27Svbart@nginx.com     nxt_controller_request_t  *r;
16620Sigor@sysoev.ru 
16720Sigor@sysoev.ru     c = obj;
16820Sigor@sysoev.ru 
16920Sigor@sysoev.ru     nxt_debug(task, "controller conn init fd:%d", c->socket.fd);
17020Sigor@sysoev.ru 
171*27Svbart@nginx.com     r = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_controller_request_t));
172*27Svbart@nginx.com     if (nxt_slow_path(r == NULL)) {
173*27Svbart@nginx.com         nxt_controller_conn_free(task, c, NULL);
174*27Svbart@nginx.com         return;
175*27Svbart@nginx.com     }
176*27Svbart@nginx.com 
177*27Svbart@nginx.com     r->parser.hash = nxt_controller_request_fields_hash;
178*27Svbart@nginx.com     r->parser.ctx = r;
179*27Svbart@nginx.com 
18020Sigor@sysoev.ru     b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0);
18120Sigor@sysoev.ru     if (nxt_slow_path(b == NULL)) {
18220Sigor@sysoev.ru         nxt_controller_conn_free(task, c, NULL);
18320Sigor@sysoev.ru         return;
18420Sigor@sysoev.ru     }
18520Sigor@sysoev.ru 
18620Sigor@sysoev.ru     c->read = b;
187*27Svbart@nginx.com     c->socket.data = r;
18820Sigor@sysoev.ru     c->socket.read_ready = 1;
18920Sigor@sysoev.ru     c->read_state = &nxt_controller_conn_read_state;
19020Sigor@sysoev.ru 
19120Sigor@sysoev.ru     engine = task->thread->engine;
19220Sigor@sysoev.ru     c->read_work_queue = &engine->read_work_queue;
193*27Svbart@nginx.com     c->write_work_queue = &engine->write_work_queue;
19420Sigor@sysoev.ru 
19520Sigor@sysoev.ru     nxt_event_conn_read(engine, c);
19620Sigor@sysoev.ru }
19720Sigor@sysoev.ru 
19820Sigor@sysoev.ru 
19920Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_read_state
20020Sigor@sysoev.ru     nxt_aligned(64) =
20120Sigor@sysoev.ru {
20220Sigor@sysoev.ru     NXT_EVENT_NO_BUF_PROCESS,
20320Sigor@sysoev.ru     NXT_EVENT_TIMER_NO_AUTORESET,
20420Sigor@sysoev.ru 
20520Sigor@sysoev.ru     nxt_controller_conn_read,
20620Sigor@sysoev.ru     nxt_controller_conn_close,
20720Sigor@sysoev.ru     nxt_controller_conn_read_error,
20820Sigor@sysoev.ru 
20920Sigor@sysoev.ru     nxt_controller_conn_read_timeout,
21020Sigor@sysoev.ru     nxt_controller_conn_timeout_value,
21120Sigor@sysoev.ru     60 * 1000,
21220Sigor@sysoev.ru };
21320Sigor@sysoev.ru 
21420Sigor@sysoev.ru 
21520Sigor@sysoev.ru static void
21620Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data)
21720Sigor@sysoev.ru {
218*27Svbart@nginx.com     size_t                    preread;
219*27Svbart@nginx.com     nxt_buf_t                 *b;
220*27Svbart@nginx.com     nxt_int_t                 rc;
221*27Svbart@nginx.com     nxt_event_conn_t          *c;
222*27Svbart@nginx.com     nxt_controller_request_t  *r;
22320Sigor@sysoev.ru 
22420Sigor@sysoev.ru     c = obj;
225*27Svbart@nginx.com     r = data;
22620Sigor@sysoev.ru 
22720Sigor@sysoev.ru     nxt_debug(task, "controller conn read");
22820Sigor@sysoev.ru 
229*27Svbart@nginx.com     nxt_queue_remove(&c->link);
230*27Svbart@nginx.com     nxt_queue_self(&c->link);
231*27Svbart@nginx.com 
232*27Svbart@nginx.com     b = c->read;
233*27Svbart@nginx.com 
234*27Svbart@nginx.com     rc = nxt_http_parse_request(&r->parser, &b->mem);
235*27Svbart@nginx.com 
236*27Svbart@nginx.com     if (nxt_slow_path(rc != NXT_DONE)) {
237*27Svbart@nginx.com 
238*27Svbart@nginx.com         if (rc == NXT_AGAIN) {
239*27Svbart@nginx.com             if (nxt_buf_mem_free_size(&b->mem) == 0) {
240*27Svbart@nginx.com                 nxt_log(task, NXT_LOG_ERR, "too long request headers");
241*27Svbart@nginx.com                 nxt_controller_conn_close(task, c, r);
242*27Svbart@nginx.com                 return;
243*27Svbart@nginx.com             }
244*27Svbart@nginx.com 
245*27Svbart@nginx.com             nxt_event_conn_read(task->thread->engine, c);
246*27Svbart@nginx.com             return;
247*27Svbart@nginx.com         }
248*27Svbart@nginx.com 
249*27Svbart@nginx.com         /* rc == NXT_ERROR */
250*27Svbart@nginx.com 
251*27Svbart@nginx.com         nxt_log(task, NXT_LOG_ERR, "parsing error");
252*27Svbart@nginx.com 
253*27Svbart@nginx.com         nxt_controller_conn_close(task, c, r);
254*27Svbart@nginx.com         return;
255*27Svbart@nginx.com     }
256*27Svbart@nginx.com 
257*27Svbart@nginx.com     preread = nxt_buf_mem_used_size(&b->mem);
258*27Svbart@nginx.com 
259*27Svbart@nginx.com     nxt_debug(task, "controller request header parsing complete, "
260*27Svbart@nginx.com                     "body length: %O, preread: %uz",
261*27Svbart@nginx.com                     r->length, preread);
262*27Svbart@nginx.com 
263*27Svbart@nginx.com     if (preread >= r->length) {
264*27Svbart@nginx.com         nxt_controller_process_request(task, c, r);
265*27Svbart@nginx.com         return;
266*27Svbart@nginx.com     }
267*27Svbart@nginx.com 
268*27Svbart@nginx.com     if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) {
269*27Svbart@nginx.com         b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0);
270*27Svbart@nginx.com         if (nxt_slow_path(b == NULL)) {
271*27Svbart@nginx.com             nxt_controller_conn_free(task, c, NULL);
272*27Svbart@nginx.com             return;
273*27Svbart@nginx.com         }
274*27Svbart@nginx.com 
275*27Svbart@nginx.com         b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread);
276*27Svbart@nginx.com 
277*27Svbart@nginx.com         c->read = b;
278*27Svbart@nginx.com     }
279*27Svbart@nginx.com 
280*27Svbart@nginx.com     c->read_state = &nxt_controller_conn_body_read_state;
281*27Svbart@nginx.com 
282*27Svbart@nginx.com     nxt_event_conn_read(task->thread->engine, c);
28320Sigor@sysoev.ru }
28420Sigor@sysoev.ru 
28520Sigor@sysoev.ru 
28620Sigor@sysoev.ru static nxt_msec_t
28720Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_event_conn_t *c, uintptr_t data)
28820Sigor@sysoev.ru {
28920Sigor@sysoev.ru     return (nxt_msec_t) data;
29020Sigor@sysoev.ru }
29120Sigor@sysoev.ru 
29220Sigor@sysoev.ru 
29320Sigor@sysoev.ru static void
29420Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data)
29520Sigor@sysoev.ru {
29620Sigor@sysoev.ru     nxt_event_conn_t  *c;
29720Sigor@sysoev.ru 
29820Sigor@sysoev.ru     c = obj;
29920Sigor@sysoev.ru 
30020Sigor@sysoev.ru     nxt_debug(task, "controller conn read error");
30120Sigor@sysoev.ru 
302*27Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
30320Sigor@sysoev.ru }
30420Sigor@sysoev.ru 
30520Sigor@sysoev.ru 
30620Sigor@sysoev.ru static void
30720Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data)
30820Sigor@sysoev.ru {
30920Sigor@sysoev.ru     nxt_timer_t       *ev;
31020Sigor@sysoev.ru     nxt_event_conn_t  *c;
31120Sigor@sysoev.ru 
31220Sigor@sysoev.ru     ev = obj;
31320Sigor@sysoev.ru 
31420Sigor@sysoev.ru     c = nxt_event_read_timer_conn(ev);
31520Sigor@sysoev.ru     c->socket.timedout = 1;
31620Sigor@sysoev.ru     c->socket.closed = 1;
31720Sigor@sysoev.ru 
31820Sigor@sysoev.ru     nxt_debug(task, "controller conn read timeout");
31920Sigor@sysoev.ru 
320*27Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
321*27Svbart@nginx.com }
322*27Svbart@nginx.com 
323*27Svbart@nginx.com 
324*27Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_body_read_state
325*27Svbart@nginx.com     nxt_aligned(64) =
326*27Svbart@nginx.com {
327*27Svbart@nginx.com     NXT_EVENT_NO_BUF_PROCESS,
328*27Svbart@nginx.com     NXT_EVENT_TIMER_AUTORESET,
329*27Svbart@nginx.com 
330*27Svbart@nginx.com     nxt_controller_conn_body_read,
331*27Svbart@nginx.com     nxt_controller_conn_close,
332*27Svbart@nginx.com     nxt_controller_conn_read_error,
333*27Svbart@nginx.com 
334*27Svbart@nginx.com     nxt_controller_conn_read_timeout,
335*27Svbart@nginx.com     nxt_controller_conn_timeout_value,
336*27Svbart@nginx.com     60 * 1000,
337*27Svbart@nginx.com };
338*27Svbart@nginx.com 
339*27Svbart@nginx.com 
340*27Svbart@nginx.com static void
341*27Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data)
342*27Svbart@nginx.com {
343*27Svbart@nginx.com     size_t            rest;
344*27Svbart@nginx.com     nxt_buf_t         *b;
345*27Svbart@nginx.com     nxt_event_conn_t  *c;
346*27Svbart@nginx.com 
347*27Svbart@nginx.com     c = obj;
348*27Svbart@nginx.com 
349*27Svbart@nginx.com     nxt_debug(task, "controller conn body read");
350*27Svbart@nginx.com 
351*27Svbart@nginx.com     b = c->read;
352*27Svbart@nginx.com 
353*27Svbart@nginx.com     rest = nxt_buf_mem_free_size(&b->mem);
354*27Svbart@nginx.com 
355*27Svbart@nginx.com     if (rest == 0) {
356*27Svbart@nginx.com         nxt_debug(task, "controller conn body read complete");
357*27Svbart@nginx.com 
358*27Svbart@nginx.com         nxt_controller_process_request(task, c, data);
359*27Svbart@nginx.com         return;
360*27Svbart@nginx.com     }
361*27Svbart@nginx.com 
362*27Svbart@nginx.com     nxt_debug(task, "controller conn body read again, rest: %uz", rest);
363*27Svbart@nginx.com 
364*27Svbart@nginx.com     nxt_event_conn_read(task->thread->engine, c);
365*27Svbart@nginx.com }
366*27Svbart@nginx.com 
367*27Svbart@nginx.com 
368*27Svbart@nginx.com static const nxt_event_conn_state_t  nxt_controller_conn_write_state
369*27Svbart@nginx.com     nxt_aligned(64) =
370*27Svbart@nginx.com {
371*27Svbart@nginx.com     NXT_EVENT_NO_BUF_PROCESS,
372*27Svbart@nginx.com     NXT_EVENT_TIMER_AUTORESET,
373*27Svbart@nginx.com 
374*27Svbart@nginx.com     nxt_controller_conn_write,
375*27Svbart@nginx.com     NULL,
376*27Svbart@nginx.com     nxt_controller_conn_write_error,
377*27Svbart@nginx.com 
378*27Svbart@nginx.com     nxt_controller_conn_write_timeout,
379*27Svbart@nginx.com     nxt_controller_conn_timeout_value,
380*27Svbart@nginx.com     60 * 1000,
381*27Svbart@nginx.com };
382*27Svbart@nginx.com 
383*27Svbart@nginx.com 
384*27Svbart@nginx.com static void
385*27Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data)
386*27Svbart@nginx.com {
387*27Svbart@nginx.com     nxt_buf_t         *b;
388*27Svbart@nginx.com     nxt_event_conn_t  *c;
389*27Svbart@nginx.com 
390*27Svbart@nginx.com     c = obj;
391*27Svbart@nginx.com 
392*27Svbart@nginx.com     nxt_debug(task, "controller conn write");
393*27Svbart@nginx.com 
394*27Svbart@nginx.com     b = c->write;
395*27Svbart@nginx.com 
396*27Svbart@nginx.com     if (b->mem.pos != b->mem.free) {
397*27Svbart@nginx.com         nxt_event_conn_write(task->thread->engine, c);
398*27Svbart@nginx.com         return;
399*27Svbart@nginx.com     }
400*27Svbart@nginx.com 
401*27Svbart@nginx.com     nxt_debug(task, "controller conn write complete");
402*27Svbart@nginx.com 
403*27Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
404*27Svbart@nginx.com }
405*27Svbart@nginx.com 
406*27Svbart@nginx.com 
407*27Svbart@nginx.com static void
408*27Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data)
409*27Svbart@nginx.com {
410*27Svbart@nginx.com     nxt_event_conn_t  *c;
411*27Svbart@nginx.com 
412*27Svbart@nginx.com     c = obj;
413*27Svbart@nginx.com 
414*27Svbart@nginx.com     nxt_debug(task, "controller conn write error");
415*27Svbart@nginx.com 
416*27Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
417*27Svbart@nginx.com }
418*27Svbart@nginx.com 
419*27Svbart@nginx.com 
420*27Svbart@nginx.com static void
421*27Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data)
422*27Svbart@nginx.com {
423*27Svbart@nginx.com     nxt_timer_t       *ev;
424*27Svbart@nginx.com     nxt_event_conn_t  *c;
425*27Svbart@nginx.com 
426*27Svbart@nginx.com     ev = obj;
427*27Svbart@nginx.com 
428*27Svbart@nginx.com     c = nxt_event_write_timer_conn(ev);
429*27Svbart@nginx.com     c->socket.timedout = 1;
430*27Svbart@nginx.com     c->socket.closed = 1;
431*27Svbart@nginx.com 
432*27Svbart@nginx.com     nxt_debug(task, "controller conn write timeout");
433*27Svbart@nginx.com 
434*27Svbart@nginx.com     nxt_controller_conn_close(task, c, data);
43520Sigor@sysoev.ru }
43620Sigor@sysoev.ru 
43720Sigor@sysoev.ru 
43820Sigor@sysoev.ru static const nxt_event_conn_state_t  nxt_controller_conn_close_state
43920Sigor@sysoev.ru     nxt_aligned(64) =
44020Sigor@sysoev.ru {
44120Sigor@sysoev.ru     NXT_EVENT_NO_BUF_PROCESS,
44220Sigor@sysoev.ru     NXT_EVENT_TIMER_NO_AUTORESET,
44320Sigor@sysoev.ru 
44420Sigor@sysoev.ru     nxt_controller_conn_free,
44520Sigor@sysoev.ru     NULL,
44620Sigor@sysoev.ru     NULL,
44720Sigor@sysoev.ru 
44820Sigor@sysoev.ru     NULL,
44920Sigor@sysoev.ru     NULL,
45020Sigor@sysoev.ru     0,
45120Sigor@sysoev.ru };
45220Sigor@sysoev.ru 
45320Sigor@sysoev.ru 
45420Sigor@sysoev.ru static void
45520Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data)
45620Sigor@sysoev.ru {
45720Sigor@sysoev.ru     nxt_event_conn_t  *c;
45820Sigor@sysoev.ru 
45920Sigor@sysoev.ru     c = obj;
46020Sigor@sysoev.ru 
46120Sigor@sysoev.ru     nxt_debug(task, "controller conn close");
46220Sigor@sysoev.ru 
463*27Svbart@nginx.com     nxt_queue_remove(&c->link);
464*27Svbart@nginx.com 
46520Sigor@sysoev.ru     c->write_state = &nxt_controller_conn_close_state;
46620Sigor@sysoev.ru 
46720Sigor@sysoev.ru     nxt_event_conn_close(task->thread->engine, c);
46820Sigor@sysoev.ru }
46920Sigor@sysoev.ru 
47020Sigor@sysoev.ru 
47120Sigor@sysoev.ru static void
47220Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data)
47320Sigor@sysoev.ru {
47420Sigor@sysoev.ru     nxt_event_conn_t  *c;
47520Sigor@sysoev.ru 
47620Sigor@sysoev.ru     c = obj;
47720Sigor@sysoev.ru 
47820Sigor@sysoev.ru     nxt_debug(task, "controller conn free");
47920Sigor@sysoev.ru 
48020Sigor@sysoev.ru     nxt_mem_pool_destroy(c->mem_pool);
48120Sigor@sysoev.ru 
48220Sigor@sysoev.ru     //nxt_free(c);
48320Sigor@sysoev.ru }
484*27Svbart@nginx.com 
485*27Svbart@nginx.com 
486*27Svbart@nginx.com static nxt_int_t
487*27Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_str_t *name,
488*27Svbart@nginx.com     nxt_str_t *value, uintptr_t data)
489*27Svbart@nginx.com {
490*27Svbart@nginx.com     off_t                     length;
491*27Svbart@nginx.com     nxt_controller_request_t  *r;
492*27Svbart@nginx.com 
493*27Svbart@nginx.com     r = ctx;
494*27Svbart@nginx.com 
495*27Svbart@nginx.com     length = nxt_off_t_parse(value->start, value->length);
496*27Svbart@nginx.com 
497*27Svbart@nginx.com     if (nxt_fast_path(length > 0)) {
498*27Svbart@nginx.com         /* TODO length too big */
499*27Svbart@nginx.com 
500*27Svbart@nginx.com         r->length = length;
501*27Svbart@nginx.com         return NXT_OK;
502*27Svbart@nginx.com     }
503*27Svbart@nginx.com 
504*27Svbart@nginx.com     /* TODO logging (task?) */
505*27Svbart@nginx.com 
506*27Svbart@nginx.com     return NXT_ERROR;
507*27Svbart@nginx.com }
508*27Svbart@nginx.com 
509*27Svbart@nginx.com 
510*27Svbart@nginx.com static void
511*27Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c,
512*27Svbart@nginx.com     nxt_controller_request_t *r)
513*27Svbart@nginx.com {
514*27Svbart@nginx.com     size_t     size;
515*27Svbart@nginx.com     nxt_buf_t  *b, *wb;
516*27Svbart@nginx.com 
517*27Svbart@nginx.com     static const u_char response[] = "HTTP/1.0 200 OK\r\n\r\n";
518*27Svbart@nginx.com 
519*27Svbart@nginx.com     b = c->read;
520*27Svbart@nginx.com 
521*27Svbart@nginx.com     nxt_controller_request_body_parse(&b->mem);
522*27Svbart@nginx.com 
523*27Svbart@nginx.com     size = nxt_buf_mem_used_size(&b->mem);
524*27Svbart@nginx.com 
525*27Svbart@nginx.com     wb = nxt_buf_mem_alloc(c->mem_pool, sizeof(response) - 1 + size, 0);
526*27Svbart@nginx.com     if (nxt_slow_path(wb == NULL)) {
527*27Svbart@nginx.com         nxt_controller_conn_close(task, c, r);
528*27Svbart@nginx.com         return;
529*27Svbart@nginx.com     }
530*27Svbart@nginx.com 
531*27Svbart@nginx.com     wb->mem.free = nxt_cpymem(wb->mem.free, response, sizeof(response) - 1);
532*27Svbart@nginx.com     wb->mem.free = nxt_cpymem(wb->mem.free, b->mem.pos, size);
533*27Svbart@nginx.com 
534*27Svbart@nginx.com     c->write = wb;
535*27Svbart@nginx.com     c->write_state = &nxt_controller_conn_write_state;
536*27Svbart@nginx.com 
537*27Svbart@nginx.com     nxt_event_conn_write(task->thread->engine, c);
538*27Svbart@nginx.com }
539*27Svbart@nginx.com 
540*27Svbart@nginx.com 
541*27Svbart@nginx.com static nxt_int_t
542*27Svbart@nginx.com nxt_controller_request_body_parse(nxt_buf_mem_t *b)
543*27Svbart@nginx.com {
544*27Svbart@nginx.com     /* TODO */
545*27Svbart@nginx.com     return NXT_OK;
546*27Svbart@nginx.com }
547