xref: /unit/src/nxt_h1proto.c (revision 1614:ecbc08abe2cc)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_router.h>
8 #include <nxt_http.h>
9 #include <nxt_upstream.h>
10 #include <nxt_h1proto.h>
11 #include <nxt_websocket.h>
12 #include <nxt_websocket_header.h>
13 
14 
15 /*
16  * nxt_http_conn_ and nxt_h1p_conn_ prefixes are used for connection handlers.
17  * nxt_h1p_idle_ prefix is used for idle connection handlers.
18  * nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods.
19  */
20 
21 #if (NXT_TLS)
22 static ssize_t nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c);
23 static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data);
24 #endif
25 static ssize_t nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c);
26 static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data);
27 static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data);
28 static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj,
29     void *data);
30 static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p,
31     nxt_http_request_t *r);
32 static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task,
33     nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf);
34 static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field,
35     uintptr_t data);
36 static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field,
37     uintptr_t data);
38 static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field,
39     uintptr_t data);
40 static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field,
41     uintptr_t data);
42 static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field,
43     uintptr_t data);
44 static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r);
45 static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj,
46     void *data);
47 static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r);
48 static void nxt_h1p_request_header_send(nxt_task_t *task,
49     nxt_http_request_t *r, nxt_work_handler_t body_handler, void *data);
50 static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r,
51     nxt_buf_t *out);
52 static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r,
53     nxt_buf_t *out);
54 static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task,
55     nxt_http_proto_t proto);
56 static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
57     nxt_buf_t *last);
58 static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data);
59 static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj,
60     void *data);
61 static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj,
62     void *data);
63 nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
64     nxt_http_request_t *r);
65 static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
66     nxt_socket_conf_joint_t *joint);
67 static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data);
68 static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data);
69 static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data);
70 static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data);
71 static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p,
72     nxt_conn_t *c);
73 static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data);
74 static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data);
75 static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c);
76 static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data);
77 static void nxt_h1p_idle_response_error(nxt_task_t *task, void *obj,
78     void *data);
79 static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj,
80     void *data);
81 static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c,
82     uintptr_t data);
83 static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c);
84 static void nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c);
85 static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data);
86 static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data);
87 static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data);
88 
89 static void nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer);
90 static void nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data);
91 static void nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data);
92 static void nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer);
93 static void nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data);
94 static void nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer);
95 static ssize_t nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c);
96 static void nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj,
97     void *data);
98 static nxt_int_t nxt_h1p_peer_header_parse(nxt_http_peer_t *peer,
99     nxt_buf_mem_t *bm);
100 static void nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer);
101 static void nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data);
102 static void nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, nxt_buf_t *out);
103 static void nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data);
104 static void nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data);
105 static void nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data);
106 static void nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data);
107 static nxt_msec_t nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data);
108 static void nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer);
109 static void nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data);
110 static nxt_int_t nxt_h1p_peer_transfer_encoding(void *ctx,
111     nxt_http_field_t *field, uintptr_t data);
112 
113 #if (NXT_TLS)
114 static const nxt_conn_state_t  nxt_http_idle_state;
115 static const nxt_conn_state_t  nxt_h1p_shutdown_state;
116 #endif
117 static const nxt_conn_state_t  nxt_h1p_idle_state;
118 static const nxt_conn_state_t  nxt_h1p_header_parse_state;
119 static const nxt_conn_state_t  nxt_h1p_read_body_state;
120 static const nxt_conn_state_t  nxt_h1p_request_send_state;
121 static const nxt_conn_state_t  nxt_h1p_timeout_response_state;
122 static const nxt_conn_state_t  nxt_h1p_keepalive_state;
123 static const nxt_conn_state_t  nxt_h1p_close_state;
124 static const nxt_conn_state_t  nxt_h1p_peer_connect_state;
125 static const nxt_conn_state_t  nxt_h1p_peer_header_send_state;
126 static const nxt_conn_state_t  nxt_h1p_peer_header_body_send_state;
127 static const nxt_conn_state_t  nxt_h1p_peer_header_read_state;
128 static const nxt_conn_state_t  nxt_h1p_peer_header_read_timer_state;
129 static const nxt_conn_state_t  nxt_h1p_peer_read_state;
130 static const nxt_conn_state_t  nxt_h1p_peer_close_state;
131 
132 
133 const nxt_http_proto_table_t  nxt_http_proto[3] = {
134     /* NXT_HTTP_PROTO_H1 */
135     {
136         .body_read        = nxt_h1p_request_body_read,
137         .local_addr       = nxt_h1p_request_local_addr,
138         .header_send      = nxt_h1p_request_header_send,
139         .send             = nxt_h1p_request_send,
140         .body_bytes_sent  = nxt_h1p_request_body_bytes_sent,
141         .discard          = nxt_h1p_request_discard,
142         .close            = nxt_h1p_request_close,
143 
144         .peer_connect     = nxt_h1p_peer_connect,
145         .peer_header_send = nxt_h1p_peer_header_send,
146         .peer_header_read = nxt_h1p_peer_header_read,
147         .peer_read        = nxt_h1p_peer_read,
148         .peer_close       = nxt_h1p_peer_close,
149 
150         .ws_frame_start   = nxt_h1p_websocket_frame_start,
151     },
152     /* NXT_HTTP_PROTO_H2      */
153     /* NXT_HTTP_PROTO_DEVNULL */
154 };
155 
156 
157 static nxt_lvlhsh_t                    nxt_h1p_fields_hash;
158 
159 static nxt_http_field_proc_t           nxt_h1p_fields[] = {
160     { nxt_string("Connection"),        &nxt_h1p_connection, 0 },
161     { nxt_string("Upgrade"),           &nxt_h1p_upgrade, 0 },
162     { nxt_string("Sec-WebSocket-Key"), &nxt_h1p_websocket_key, 0 },
163     { nxt_string("Sec-WebSocket-Version"),
164                                        &nxt_h1p_websocket_version, 0 },
165     { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 },
166 
167     { nxt_string("Host"),              &nxt_http_request_host, 0 },
168     { nxt_string("Cookie"),            &nxt_http_request_field,
169         offsetof(nxt_http_request_t, cookie) },
170     { nxt_string("Referer"),           &nxt_http_request_field,
171         offsetof(nxt_http_request_t, referer) },
172     { nxt_string("User-Agent"),        &nxt_http_request_field,
173         offsetof(nxt_http_request_t, user_agent) },
174     { nxt_string("Content-Type"),      &nxt_http_request_field,
175         offsetof(nxt_http_request_t, content_type) },
176     { nxt_string("Content-Length"),    &nxt_http_request_content_length, 0 },
177 };
178 
179 
180 static nxt_lvlhsh_t                    nxt_h1p_peer_fields_hash;
181 
182 static nxt_http_field_proc_t           nxt_h1p_peer_fields[] = {
183     { nxt_string("Connection"),        &nxt_http_proxy_skip, 0 },
184     { nxt_string("Transfer-Encoding"), &nxt_h1p_peer_transfer_encoding, 0 },
185     { nxt_string("Server"),            &nxt_http_proxy_skip, 0 },
186     { nxt_string("Date"),              &nxt_http_proxy_date, 0 },
187     { nxt_string("Content-Length"),    &nxt_http_proxy_content_length, 0 },
188 };
189 
190 
191 nxt_int_t
192 nxt_h1p_init(nxt_task_t *task)
193 {
194     nxt_int_t  ret;
195 
196     ret = nxt_http_fields_hash(&nxt_h1p_fields_hash,
197                                nxt_h1p_fields, nxt_nitems(nxt_h1p_fields));
198 
199     if (nxt_fast_path(ret == NXT_OK)) {
200         ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash,
201                                    nxt_h1p_peer_fields,
202                                    nxt_nitems(nxt_h1p_peer_fields));
203     }
204 
205     return ret;
206 }
207 
208 
209 void
210 nxt_http_conn_init(nxt_task_t *task, void *obj, void *data)
211 {
212     nxt_conn_t               *c;
213     nxt_socket_conf_t        *skcf;
214     nxt_event_engine_t       *engine;
215     nxt_listen_event_t       *lev;
216     nxt_socket_conf_joint_t  *joint;
217 
218     c = obj;
219     lev = data;
220 
221     nxt_debug(task, "http conn init");
222 
223     joint = lev->socket.data;
224     skcf = joint->socket_conf;
225     c->local = skcf->sockaddr;
226 
227     engine = task->thread->engine;
228     c->read_work_queue = &engine->fast_work_queue;
229     c->write_work_queue = &engine->fast_work_queue;
230 
231     c->read_state = &nxt_h1p_idle_state;
232 
233 #if (NXT_TLS)
234     if (skcf->tls != NULL) {
235         c->read_state = &nxt_http_idle_state;
236     }
237 #endif
238 
239     nxt_conn_read(engine, c);
240 }
241 
242 
243 #if (NXT_TLS)
244 
245 static const nxt_conn_state_t  nxt_http_idle_state
246     nxt_aligned(64) =
247 {
248     .ready_handler = nxt_http_conn_test,
249     .close_handler = nxt_h1p_conn_close,
250     .error_handler = nxt_h1p_conn_error,
251 
252     .io_read_handler = nxt_http_idle_io_read_handler,
253 
254     .timer_handler = nxt_h1p_idle_timeout,
255     .timer_value = nxt_h1p_conn_timer_value,
256     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
257 };
258 
259 
260 static ssize_t
261 nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c)
262 {
263     size_t                   size;
264     ssize_t                  n;
265     nxt_buf_t                *b;
266     nxt_socket_conf_joint_t  *joint;
267 
268     joint = c->listen->socket.data;
269 
270     if (nxt_slow_path(joint == NULL)) {
271         /*
272          * Listening socket had been closed while
273          * connection was in keep-alive state.
274          */
275         c->read_state = &nxt_h1p_idle_close_state;
276         return 0;
277     }
278 
279     size = joint->socket_conf->header_buffer_size;
280 
281     b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size);
282     if (nxt_slow_path(b == NULL)) {
283         c->socket.error = NXT_ENOMEM;
284         return NXT_ERROR;
285     }
286 
287     /*
288      * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP.
289      * 11 bytes are enough to log supported SSLv3/TLS version.
290      * 16 bytes are just for more optimized kernel copy-out operation.
291      */
292     n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK);
293 
294     if (n > 0) {
295         c->read = b;
296 
297     } else {
298         c->read = NULL;
299         nxt_event_engine_buf_mem_free(task->thread->engine, b);
300     }
301 
302     return n;
303 }
304 
305 
306 static void
307 nxt_http_conn_test(nxt_task_t *task, void *obj, void *data)
308 {
309     u_char                   *p;
310     nxt_buf_t                *b;
311     nxt_conn_t               *c;
312     nxt_tls_conf_t           *tls;
313     nxt_event_engine_t       *engine;
314     nxt_socket_conf_joint_t  *joint;
315 
316     c = obj;
317 
318     nxt_debug(task, "h1p conn https test");
319 
320     engine = task->thread->engine;
321     b = c->read;
322     p = b->mem.pos;
323 
324     c->read_state = &nxt_h1p_idle_state;
325 
326     if (p[0] != 0x16) {
327         b->mem.free = b->mem.pos;
328 
329         nxt_conn_read(engine, c);
330         return;
331     }
332 
333     /* SSLv3/TLS ClientHello message. */
334 
335 #if (NXT_DEBUG)
336     if (nxt_buf_mem_used_size(&b->mem) >= 11) {
337         u_char      major, minor;
338         const char  *protocol;
339 
340         major = p[9];
341         minor = p[10];
342 
343         if (major == 3) {
344             if (minor == 0) {
345                 protocol = "SSLv";
346 
347             } else {
348                 protocol = "TLSv";
349                 major -= 2;
350                 minor -= 1;
351             }
352 
353             nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor);
354         }
355     }
356 #endif
357 
358     c->read = NULL;
359     nxt_event_engine_buf_mem_free(engine, b);
360 
361     joint = c->listen->socket.data;
362 
363     if (nxt_slow_path(joint == NULL)) {
364         /*
365          * Listening socket had been closed while
366          * connection was in keep-alive state.
367          */
368         nxt_h1p_closing(task, c);
369         return;
370     }
371 
372     tls = joint->socket_conf->tls;
373 
374     tls->conn_init(task, tls, c);
375 }
376 
377 #endif
378 
379 
380 static const nxt_conn_state_t  nxt_h1p_idle_state
381     nxt_aligned(64) =
382 {
383     .ready_handler = nxt_h1p_conn_proto_init,
384     .close_handler = nxt_h1p_conn_close,
385     .error_handler = nxt_h1p_conn_error,
386 
387     .io_read_handler = nxt_h1p_idle_io_read_handler,
388 
389     .timer_handler = nxt_h1p_idle_timeout,
390     .timer_value = nxt_h1p_conn_timer_value,
391     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
392     .timer_autoreset = 1,
393 };
394 
395 
396 static ssize_t
397 nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c)
398 {
399     size_t                   size;
400     ssize_t                  n;
401     nxt_buf_t                *b;
402     nxt_socket_conf_joint_t  *joint;
403 
404     joint = c->listen->socket.data;
405 
406     if (nxt_slow_path(joint == NULL)) {
407         /*
408          * Listening socket had been closed while
409          * connection was in keep-alive state.
410          */
411         c->read_state = &nxt_h1p_idle_close_state;
412         return 0;
413     }
414 
415     b = c->read;
416 
417     if (b == NULL) {
418         size = joint->socket_conf->header_buffer_size;
419 
420         b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size);
421         if (nxt_slow_path(b == NULL)) {
422             c->socket.error = NXT_ENOMEM;
423             return NXT_ERROR;
424         }
425     }
426 
427     n = c->io->recvbuf(c, b);
428 
429     if (n > 0) {
430         c->read = b;
431 
432     } else {
433         c->read = NULL;
434         nxt_event_engine_buf_mem_free(task->thread->engine, b);
435     }
436 
437     return n;
438 }
439 
440 
441 static void
442 nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data)
443 {
444     nxt_conn_t     *c;
445     nxt_h1proto_t  *h1p;
446 
447     c = obj;
448 
449     nxt_debug(task, "h1p conn proto init");
450 
451     h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t));
452     if (nxt_slow_path(h1p == NULL)) {
453         nxt_h1p_closing(task, c);
454         return;
455     }
456 
457     c->socket.data = h1p;
458     h1p->conn = c;
459 
460     nxt_h1p_conn_request_init(task, c, h1p);
461 }
462 
463 
464 static void
465 nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
466 {
467     nxt_int_t                ret;
468     nxt_conn_t               *c;
469     nxt_h1proto_t            *h1p;
470     nxt_http_request_t       *r;
471     nxt_socket_conf_joint_t  *joint;
472 
473     c = obj;
474     h1p = data;
475 
476     nxt_debug(task, "h1p conn request init");
477 
478     nxt_queue_remove(&c->link);
479 
480     r = nxt_http_request_create(task);
481 
482     if (nxt_fast_path(r != NULL)) {
483         h1p->request = r;
484         r->proto.h1 = h1p;
485 
486         /* r->protocol = NXT_HTTP_PROTO_H1 is done by zeroing. */
487         r->remote = c->remote;
488 
489 #if (NXT_TLS)
490         r->tls = c->u.tls;
491 #endif
492 
493         r->task = c->task;
494         task = &r->task;
495         c->socket.task = task;
496         c->read_timer.task = task;
497         c->write_timer.task = task;
498 
499         ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool);
500 
501         if (nxt_fast_path(ret == NXT_OK)) {
502             joint = c->listen->socket.data;
503             joint->count++;
504 
505             r->conf = joint;
506             c->local = joint->socket_conf->sockaddr;
507 
508             nxt_h1p_conn_request_header_parse(task, c, h1p);
509             return;
510         }
511 
512         /*
513          * The request is very incomplete here,
514          * so "internal server error" useless here.
515          */
516         nxt_mp_release(r->mem_pool);
517     }
518 
519     nxt_h1p_closing(task, c);
520 }
521 
522 
523 static const nxt_conn_state_t  nxt_h1p_header_parse_state
524     nxt_aligned(64) =
525 {
526     .ready_handler = nxt_h1p_conn_request_header_parse,
527     .close_handler = nxt_h1p_conn_request_error,
528     .error_handler = nxt_h1p_conn_request_error,
529 
530     .timer_handler = nxt_h1p_conn_request_timeout,
531     .timer_value = nxt_h1p_conn_request_timer_value,
532     .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout),
533 };
534 
535 
536 static void
537 nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, void *data)
538 {
539     nxt_int_t           ret;
540     nxt_conn_t          *c;
541     nxt_h1proto_t       *h1p;
542     nxt_http_status_t   status;
543     nxt_http_request_t  *r;
544 
545     c = obj;
546     h1p = data;
547 
548     nxt_debug(task, "h1p conn header parse");
549 
550     ret = nxt_http_parse_request(&h1p->parser, &c->read->mem);
551 
552     ret = nxt_expect(NXT_DONE, ret);
553 
554     if (ret != NXT_AGAIN) {
555         nxt_timer_disable(task->thread->engine, &c->read_timer);
556     }
557 
558     r = h1p->request;
559 
560     switch (ret) {
561 
562     case NXT_DONE:
563         /*
564          * By default the keepalive mode is disabled in HTTP/1.0 and
565          * enabled in HTTP/1.1.  The mode can be overridden later by
566          * the "Connection" field processed in nxt_h1p_connection().
567          */
568         h1p->keepalive = (h1p->parser.version.s.minor != '0');
569 
570         ret = nxt_h1p_header_process(task, h1p, r);
571 
572         if (nxt_fast_path(ret == NXT_OK)) {
573 
574 #if (NXT_TLS)
575             if (c->u.tls == NULL && r->conf->socket_conf->tls != NULL) {
576                 status = NXT_HTTP_TO_HTTPS;
577                 goto error;
578             }
579 #endif
580 
581             r->state->ready_handler(task, r, NULL);
582             return;
583         }
584 
585         status = ret;
586         goto error;
587 
588     case NXT_AGAIN:
589         status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf);
590 
591         if (nxt_fast_path(status == NXT_OK)) {
592             c->read_state = &nxt_h1p_header_parse_state;
593 
594             nxt_conn_read(task->thread->engine, c);
595             return;
596         }
597 
598         break;
599 
600     case NXT_HTTP_PARSE_INVALID:
601         status = NXT_HTTP_BAD_REQUEST;
602         break;
603 
604     case NXT_HTTP_PARSE_UNSUPPORTED_VERSION:
605         status = NXT_HTTP_VERSION_NOT_SUPPORTED;
606         break;
607 
608     case NXT_HTTP_PARSE_TOO_LARGE_FIELD:
609         status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
610         break;
611 
612     default:
613     case NXT_ERROR:
614         status = NXT_HTTP_INTERNAL_SERVER_ERROR;
615         break;
616     }
617 
618     (void) nxt_h1p_header_process(task, h1p, r);
619 
620 error:
621 
622     h1p->keepalive = 0;
623 
624     nxt_http_request_error(task, r, status);
625 }
626 
627 
628 static nxt_int_t
629 nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p,
630     nxt_http_request_t *r)
631 {
632     u_char     *m;
633     nxt_int_t  ret;
634 
635     r->target.start = h1p->parser.target_start;
636     r->target.length = h1p->parser.target_end - h1p->parser.target_start;
637 
638     if (h1p->parser.version.ui64 != 0) {
639         r->version.start = h1p->parser.version.str;
640         r->version.length = sizeof(h1p->parser.version.str);
641     }
642 
643     r->method = &h1p->parser.method;
644     r->path = &h1p->parser.path;
645     r->args = &h1p->parser.args;
646 
647     r->fields = h1p->parser.fields;
648 
649     ret = nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r);
650     if (nxt_slow_path(ret != NXT_OK)) {
651         return ret;
652     }
653 
654     if (h1p->connection_upgrade && h1p->upgrade_websocket) {
655         m = h1p->parser.method.start;
656 
657         if (nxt_slow_path(h1p->parser.method.length != 3
658                           || m[0] != 'G'
659                           || m[1] != 'E'
660                           || m[2] != 'T'))
661         {
662             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad method");
663 
664             return NXT_HTTP_BAD_REQUEST;
665         }
666 
667         if (nxt_slow_path(h1p->parser.version.s.minor != '1')) {
668             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad protocol version");
669 
670             return NXT_HTTP_BAD_REQUEST;
671         }
672 
673         if (nxt_slow_path(h1p->websocket_key == NULL)) {
674             nxt_log(task, NXT_LOG_INFO,
675                     "h1p upgrade: bad or absent websocket key");
676 
677             return NXT_HTTP_BAD_REQUEST;
678         }
679 
680         if (nxt_slow_path(h1p->websocket_version_ok == 0)) {
681             nxt_log(task, NXT_LOG_INFO,
682                     "h1p upgrade: bad or absent websocket version");
683 
684             return NXT_HTTP_UPGRADE_REQUIRED;
685         }
686 
687         r->websocket_handshake = 1;
688     }
689 
690     return ret;
691 }
692 
693 
694 static nxt_int_t
695 nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c,
696     nxt_socket_conf_t *skcf)
697 {
698     size_t     size, used;
699     nxt_buf_t  *in, *b;
700 
701     in = c->read;
702 
703     if (nxt_buf_mem_free_size(&in->mem) == 0) {
704         size = skcf->large_header_buffer_size;
705         used = nxt_buf_mem_used_size(&in->mem);
706 
707         if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) {
708             return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
709         }
710 
711         b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
712         if (nxt_slow_path(b == NULL)) {
713             return NXT_HTTP_INTERNAL_SERVER_ERROR;
714         }
715 
716         b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used);
717 
718         in->next = h1p->buffers;
719         h1p->buffers = in;
720         h1p->nbuffers++;
721 
722         c->read = b;
723     }
724 
725     return NXT_OK;
726 }
727 
728 
729 static nxt_int_t
730 nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data)
731 {
732     nxt_http_request_t  *r;
733 
734     r = ctx;
735     field->hopbyhop = 1;
736 
737     if (field->value_length == 5
738         && nxt_memcasecmp(field->value, "close", 5) == 0)
739     {
740         r->proto.h1->keepalive = 0;
741 
742     } else if (field->value_length == 10
743                && nxt_memcasecmp(field->value, "keep-alive", 10) == 0)
744     {
745         r->proto.h1->keepalive = 1;
746 
747     } else if (field->value_length == 7
748                && nxt_memcasecmp(field->value, "upgrade", 7) == 0)
749     {
750         r->proto.h1->connection_upgrade = 1;
751     }
752 
753     return NXT_OK;
754 }
755 
756 
757 static nxt_int_t
758 nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, uintptr_t data)
759 {
760     nxt_http_request_t  *r;
761 
762     r = ctx;
763 
764     if (field->value_length == 9
765         && nxt_memcasecmp(field->value, "websocket", 9) == 0)
766     {
767         r->proto.h1->upgrade_websocket = 1;
768     }
769 
770     return NXT_OK;
771 }
772 
773 
774 static nxt_int_t
775 nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, uintptr_t data)
776 {
777     nxt_http_request_t  *r;
778 
779     r = ctx;
780 
781     if (field->value_length == 24) {
782         r->proto.h1->websocket_key = field;
783     }
784 
785     return NXT_OK;
786 }
787 
788 
789 static nxt_int_t
790 nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, uintptr_t data)
791 {
792     nxt_http_request_t  *r;
793 
794     r = ctx;
795 
796     if (field->value_length == 2
797         && field->value[0] == '1' && field->value[1] == '3')
798     {
799         r->proto.h1->websocket_version_ok = 1;
800     }
801 
802     return NXT_OK;
803 }
804 
805 
806 static nxt_int_t
807 nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data)
808 {
809     nxt_http_te_t       te;
810     nxt_http_request_t  *r;
811 
812     r = ctx;
813     field->skip = 1;
814     field->hopbyhop = 1;
815 
816     if (field->value_length == 7
817         && nxt_memcmp(field->value, "chunked", 7) == 0)
818     {
819         te = NXT_HTTP_TE_CHUNKED;
820 
821     } else {
822         te = NXT_HTTP_TE_UNSUPPORTED;
823     }
824 
825     r->proto.h1->transfer_encoding = te;
826 
827     return NXT_OK;
828 }
829 
830 
831 static void
832 nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r)
833 {
834     size_t             size, body_length, body_buffer_size, body_rest;
835     ssize_t            res;
836     nxt_str_t          *tmp_path, tmp_name;
837     nxt_buf_t          *in, *b;
838     nxt_conn_t         *c;
839     nxt_h1proto_t      *h1p;
840     nxt_http_status_t  status;
841 
842     static const nxt_str_t tmp_name_pattern = nxt_string("/req-XXXXXXXX");
843 
844     h1p = r->proto.h1;
845 
846     nxt_debug(task, "h1p request body read %O te:%d",
847               r->content_length_n, h1p->transfer_encoding);
848 
849     switch (h1p->transfer_encoding) {
850 
851     case NXT_HTTP_TE_CHUNKED:
852         status = NXT_HTTP_LENGTH_REQUIRED;
853         goto error;
854 
855     case NXT_HTTP_TE_UNSUPPORTED:
856         status = NXT_HTTP_NOT_IMPLEMENTED;
857         goto error;
858 
859     default:
860     case NXT_HTTP_TE_NONE:
861         break;
862     }
863 
864     if (r->content_length_n == -1 || r->content_length_n == 0) {
865         goto ready;
866     }
867 
868     body_length = (size_t) r->content_length_n;
869 
870     body_buffer_size = nxt_min(r->conf->socket_conf->body_buffer_size,
871                                body_length);
872 
873     if (body_length > body_buffer_size) {
874         tmp_path = &r->conf->socket_conf->body_temp_path;
875 
876         tmp_name.length = tmp_path->length + tmp_name_pattern.length;
877 
878         b = nxt_buf_file_alloc(r->mem_pool,
879                                body_buffer_size + sizeof(nxt_file_t)
880                                + tmp_name.length + 1, 0);
881 
882     } else {
883         /* This initialization required for CentOS 6, gcc 4.4.7. */
884         tmp_path = NULL;
885         tmp_name.length = 0;
886 
887         b = nxt_buf_mem_alloc(r->mem_pool, body_buffer_size, 0);
888     }
889 
890     if (nxt_slow_path(b == NULL)) {
891         status = NXT_HTTP_INTERNAL_SERVER_ERROR;
892         goto error;
893     }
894 
895     r->body = b;
896 
897     if (body_length > body_buffer_size) {
898         tmp_name.start = nxt_pointer_to(b->mem.start, sizeof(nxt_file_t));
899 
900         memcpy(tmp_name.start, tmp_path->start, tmp_path->length);
901         memcpy(tmp_name.start + tmp_path->length, tmp_name_pattern.start,
902                tmp_name_pattern.length);
903         tmp_name.start[tmp_name.length] = '\0';
904 
905         b->file = (nxt_file_t *) b->mem.start;
906         nxt_memzero(b->file, sizeof(nxt_file_t));
907         b->file->fd = -1;
908         b->file->size = body_length;
909 
910         b->mem.start += sizeof(nxt_file_t) + tmp_name.length + 1;
911         b->mem.pos = b->mem.start;
912         b->mem.free = b->mem.start;
913 
914         b->file->fd = mkstemp((char *) tmp_name.start);
915         if (nxt_slow_path(b->file->fd == -1)) {
916             nxt_alert(task, "mkstemp(%s) failed %E", tmp_name.start, nxt_errno);
917 
918             status = NXT_HTTP_INTERNAL_SERVER_ERROR;
919             goto error;
920         }
921 
922         nxt_debug(task, "create body tmp file \"%V\", %d",
923                   &tmp_name, b->file->fd);
924 
925         unlink((char *) tmp_name.start);
926     }
927 
928     body_rest = body_length;
929 
930     in = h1p->conn->read;
931 
932     size = nxt_buf_mem_used_size(&in->mem);
933 
934     if (size != 0) {
935         size = nxt_min(size, body_length);
936 
937         if (nxt_buf_is_file(b)) {
938             res = nxt_fd_write(b->file->fd, in->mem.pos, size);
939             if (nxt_slow_path(res < (ssize_t) size)) {
940                 status = NXT_HTTP_INTERNAL_SERVER_ERROR;
941                 goto error;
942             }
943 
944             b->file_end += size;
945 
946         } else {
947             size = nxt_min(body_buffer_size, size);
948             b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size);
949             body_buffer_size -= size;
950         }
951 
952         in->mem.pos += size;
953         body_rest -= size;
954     }
955 
956     nxt_debug(task, "h1p body rest: %uz", body_rest);
957 
958     if (body_rest != 0) {
959         in->next = h1p->buffers;
960         h1p->buffers = in;
961         h1p->nbuffers++;
962 
963         c = h1p->conn;
964         c->read = b;
965         c->read_state = &nxt_h1p_read_body_state;
966 
967         nxt_conn_read(task->thread->engine, c);
968         return;
969     }
970 
971     if (nxt_buf_is_file(b)) {
972         b->mem.start = NULL;
973         b->mem.end = NULL;
974         b->mem.pos = NULL;
975         b->mem.free = NULL;
976     }
977 
978 ready:
979 
980     r->state->ready_handler(task, r, NULL);
981 
982     return;
983 
984 error:
985 
986     h1p->keepalive = 0;
987 
988     nxt_http_request_error(task, r, status);
989 }
990 
991 
992 static const nxt_conn_state_t  nxt_h1p_read_body_state
993     nxt_aligned(64) =
994 {
995     .ready_handler = nxt_h1p_conn_request_body_read,
996     .close_handler = nxt_h1p_conn_request_error,
997     .error_handler = nxt_h1p_conn_request_error,
998 
999     .timer_handler = nxt_h1p_conn_request_timeout,
1000     .timer_value = nxt_h1p_conn_request_timer_value,
1001     .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout),
1002     .timer_autoreset = 1,
1003 };
1004 
1005 
1006 static void
1007 nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data)
1008 {
1009     size_t              size, body_rest;
1010     ssize_t             res;
1011     nxt_buf_t           *b;
1012     nxt_conn_t          *c;
1013     nxt_h1proto_t       *h1p;
1014     nxt_http_request_t  *r;
1015     nxt_event_engine_t  *engine;
1016 
1017     c = obj;
1018     h1p = data;
1019 
1020     nxt_debug(task, "h1p conn request body read");
1021 
1022     r = h1p->request;
1023 
1024     engine = task->thread->engine;
1025 
1026     b = c->read;
1027 
1028     if (nxt_buf_is_file(b)) {
1029         body_rest = b->file->size - b->file_end;
1030 
1031         size = nxt_buf_mem_used_size(&b->mem);
1032         size = nxt_min(size, body_rest);
1033 
1034         res = nxt_fd_write(b->file->fd, b->mem.pos, size);
1035         if (nxt_slow_path(res < (ssize_t) size)) {
1036             nxt_h1p_request_error(task, h1p, r);
1037             return;
1038         }
1039 
1040         b->file_end += size;
1041         body_rest -= res;
1042 
1043         b->mem.pos += size;
1044 
1045         if (b->mem.pos == b->mem.free) {
1046             if (body_rest >= (size_t) nxt_buf_mem_size(&b->mem)) {
1047                 b->mem.free = b->mem.start;
1048 
1049             } else {
1050                 /* This required to avoid reading next request. */
1051                 b->mem.free = b->mem.end - body_rest;
1052             }
1053 
1054             b->mem.pos = b->mem.free;
1055         }
1056 
1057     } else {
1058         body_rest = nxt_buf_mem_free_size(&c->read->mem);
1059     }
1060 
1061     nxt_debug(task, "h1p body rest: %uz", body_rest);
1062 
1063     if (body_rest != 0) {
1064         nxt_conn_read(engine, c);
1065 
1066     } else {
1067         if (nxt_buf_is_file(b)) {
1068             b->mem.start = NULL;
1069             b->mem.end = NULL;
1070             b->mem.pos = NULL;
1071             b->mem.free = NULL;
1072         }
1073 
1074         c->read = NULL;
1075 
1076         r->state->ready_handler(task, r, NULL);
1077     }
1078 }
1079 
1080 
1081 static void
1082 nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r)
1083 {
1084     r->local = nxt_conn_local_addr(task, r->proto.h1->conn);
1085 }
1086 
1087 
1088 #define NXT_HTTP_LAST_INFORMATIONAL                                           \
1089     (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1)
1090 
1091 static const nxt_str_t  nxt_http_informational[] = {
1092     nxt_string("HTTP/1.1 100 Continue\r\n"),
1093     nxt_string("HTTP/1.1 101 Switching Protocols\r\n"),
1094 };
1095 
1096 
1097 #define NXT_HTTP_LAST_SUCCESS                                                 \
1098     (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1)
1099 
1100 static const nxt_str_t  nxt_http_success[] = {
1101     nxt_string("HTTP/1.1 200 OK\r\n"),
1102     nxt_string("HTTP/1.1 201 Created\r\n"),
1103     nxt_string("HTTP/1.1 202 Accepted\r\n"),
1104     nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"),
1105     nxt_string("HTTP/1.1 204 No Content\r\n"),
1106     nxt_string("HTTP/1.1 205 Reset Content\r\n"),
1107     nxt_string("HTTP/1.1 206 Partial Content\r\n"),
1108 };
1109 
1110 
1111 #define NXT_HTTP_LAST_REDIRECTION                                             \
1112     (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1)
1113 
1114 static const nxt_str_t  nxt_http_redirection[] = {
1115     nxt_string("HTTP/1.1 300 Multiple Choices\r\n"),
1116     nxt_string("HTTP/1.1 301 Moved Permanently\r\n"),
1117     nxt_string("HTTP/1.1 302 Found\r\n"),
1118     nxt_string("HTTP/1.1 303 See Other\r\n"),
1119     nxt_string("HTTP/1.1 304 Not Modified\r\n"),
1120     nxt_string("HTTP/1.1 307 Temporary Redirect\r\n"),
1121     nxt_string("HTTP/1.1 308 Permanent Redirect\r\n"),
1122 };
1123 
1124 
1125 #define NXT_HTTP_LAST_CLIENT_ERROR                                            \
1126     (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1)
1127 
1128 static const nxt_str_t  nxt_http_client_error[] = {
1129     nxt_string("HTTP/1.1 400 Bad Request\r\n"),
1130     nxt_string("HTTP/1.1 401 Unauthorized\r\n"),
1131     nxt_string("HTTP/1.1 402 Payment Required\r\n"),
1132     nxt_string("HTTP/1.1 403 Forbidden\r\n"),
1133     nxt_string("HTTP/1.1 404 Not Found\r\n"),
1134     nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"),
1135     nxt_string("HTTP/1.1 406 Not Acceptable\r\n"),
1136     nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1137     nxt_string("HTTP/1.1 408 Request Timeout\r\n"),
1138     nxt_string("HTTP/1.1 409 Conflict\r\n"),
1139     nxt_string("HTTP/1.1 410 Gone\r\n"),
1140     nxt_string("HTTP/1.1 411 Length Required\r\n"),
1141     nxt_string("HTTP/1.1 412 Precondition Failed\r\n"),
1142     nxt_string("HTTP/1.1 413 Payload Too Large\r\n"),
1143     nxt_string("HTTP/1.1 414 URI Too Long\r\n"),
1144     nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"),
1145     nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"),
1146     nxt_string("HTTP/1.1 417 Expectation Failed\r\n"),
1147     nxt_string("HTTP/1.1 418\r\n"),
1148     nxt_string("HTTP/1.1 419\r\n"),
1149     nxt_string("HTTP/1.1 420\r\n"),
1150     nxt_string("HTTP/1.1 421\r\n"),
1151     nxt_string("HTTP/1.1 422\r\n"),
1152     nxt_string("HTTP/1.1 423\r\n"),
1153     nxt_string("HTTP/1.1 424\r\n"),
1154     nxt_string("HTTP/1.1 425\r\n"),
1155     nxt_string("HTTP/1.1 426 Upgrade Required\r\n"),
1156     nxt_string("HTTP/1.1 427\r\n"),
1157     nxt_string("HTTP/1.1 428\r\n"),
1158     nxt_string("HTTP/1.1 429\r\n"),
1159     nxt_string("HTTP/1.1 430\r\n"),
1160     nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"),
1161 };
1162 
1163 
1164 #define NXT_HTTP_LAST_NGINX_ERROR                                             \
1165     (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1)
1166 
1167 static const nxt_str_t  nxt_http_nginx_error[] = {
1168     nxt_string("HTTP/1.1 400 "
1169                "The plain HTTP request was sent to HTTPS port\r\n"),
1170 };
1171 
1172 
1173 #define NXT_HTTP_LAST_SERVER_ERROR                                            \
1174     (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1)
1175 
1176 static const nxt_str_t  nxt_http_server_error[] = {
1177     nxt_string("HTTP/1.1 500 Internal Server Error\r\n"),
1178     nxt_string("HTTP/1.1 501 Not Implemented\r\n"),
1179     nxt_string("HTTP/1.1 502 Bad Gateway\r\n"),
1180     nxt_string("HTTP/1.1 503 Service Unavailable\r\n"),
1181     nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"),
1182     nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"),
1183 };
1184 
1185 
1186 #define UNKNOWN_STATUS_LENGTH  nxt_length("HTTP/1.1 65536\r\n")
1187 
1188 static void
1189 nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r,
1190     nxt_work_handler_t body_handler, void *data)
1191 {
1192     u_char              *p;
1193     size_t              size;
1194     nxt_buf_t           *header;
1195     nxt_str_t           unknown_status;
1196     nxt_int_t           conn;
1197     nxt_uint_t          n;
1198     nxt_bool_t          http11;
1199     nxt_conn_t          *c;
1200     nxt_h1proto_t       *h1p;
1201     const nxt_str_t     *status;
1202     nxt_http_field_t    *field;
1203     u_char              buf[UNKNOWN_STATUS_LENGTH];
1204 
1205     static const char   chunked[] = "Transfer-Encoding: chunked\r\n";
1206     static const char   websocket_version[] = "Sec-WebSocket-Version: 13\r\n";
1207 
1208     static const nxt_str_t  connection[3] = {
1209         nxt_string("Connection: close\r\n"),
1210         nxt_string("Connection: keep-alive\r\n"),
1211         nxt_string("Upgrade: websocket\r\n"
1212                    "Connection: Upgrade\r\n"
1213                    "Sec-WebSocket-Accept: "),
1214     };
1215 
1216     nxt_debug(task, "h1p request header send");
1217 
1218     r->header_sent = 1;
1219     h1p = r->proto.h1;
1220     n = r->status;
1221 
1222     if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) {
1223         status = &nxt_http_informational[n - NXT_HTTP_CONTINUE];
1224 
1225     } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) {
1226         status = &nxt_http_success[n - NXT_HTTP_OK];
1227 
1228     } else if (n >= NXT_HTTP_MULTIPLE_CHOICES
1229                && n <= NXT_HTTP_LAST_REDIRECTION)
1230     {
1231         status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES];
1232 
1233     } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) {
1234         status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST];
1235 
1236     } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) {
1237         status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS];
1238 
1239     } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR
1240                && n <= NXT_HTTP_LAST_SERVER_ERROR)
1241     {
1242         status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR];
1243 
1244     } else {
1245         p = nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH,
1246                         "HTTP/1.1 %03d\r\n", n);
1247 
1248         unknown_status.length = p - buf;
1249         unknown_status.start = buf;
1250         status = &unknown_status;
1251     }
1252 
1253     size = status->length;
1254     /* Trailing CRLF at the end of header. */
1255     size += nxt_length("\r\n");
1256 
1257     conn = -1;
1258 
1259     if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) {
1260         h1p->websocket = 1;
1261         h1p->keepalive = 0;
1262         conn = 2;
1263         size += NXT_WEBSOCKET_ACCEPT_SIZE + 2;
1264 
1265     } else {
1266         http11 = (h1p->parser.version.s.minor != '0');
1267 
1268         if (r->resp.content_length == NULL || r->resp.content_length->skip) {
1269 
1270             if (http11) {
1271                 if (n != NXT_HTTP_NOT_MODIFIED
1272                     && n != NXT_HTTP_NO_CONTENT
1273                     && body_handler != NULL
1274                     && !h1p->websocket)
1275                 {
1276                     h1p->chunked = 1;
1277                     size += nxt_length(chunked);
1278                     /* Trailing CRLF will be added by the first chunk header. */
1279                     size -= nxt_length("\r\n");
1280                 }
1281 
1282             } else {
1283                 h1p->keepalive = 0;
1284             }
1285         }
1286 
1287         if (http11 ^ h1p->keepalive) {
1288             conn = h1p->keepalive;
1289         }
1290     }
1291 
1292     if (conn >= 0) {
1293         size += connection[conn].length;
1294     }
1295 
1296     nxt_list_each(field, r->resp.fields) {
1297 
1298         if (!field->skip) {
1299             size += field->name_length + field->value_length;
1300             size += nxt_length(": \r\n");
1301         }
1302 
1303     } nxt_list_loop;
1304 
1305     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1306         size += nxt_length(websocket_version);
1307     }
1308 
1309     header = nxt_http_buf_mem(task, r, size);
1310     if (nxt_slow_path(header == NULL)) {
1311         nxt_h1p_request_error(task, h1p, r);
1312         return;
1313     }
1314 
1315     p = nxt_cpymem(header->mem.free, status->start, status->length);
1316 
1317     nxt_list_each(field, r->resp.fields) {
1318 
1319         if (!field->skip) {
1320             p = nxt_cpymem(p, field->name, field->name_length);
1321             *p++ = ':'; *p++ = ' ';
1322             p = nxt_cpymem(p, field->value, field->value_length);
1323             *p++ = '\r'; *p++ = '\n';
1324         }
1325 
1326     } nxt_list_loop;
1327 
1328     if (conn >= 0) {
1329         p = nxt_cpymem(p, connection[conn].start, connection[conn].length);
1330     }
1331 
1332     if (h1p->websocket) {
1333         nxt_websocket_accept(p, h1p->websocket_key->value);
1334         p += NXT_WEBSOCKET_ACCEPT_SIZE;
1335 
1336         *p++ = '\r'; *p++ = '\n';
1337     }
1338 
1339     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1340         p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version));
1341     }
1342 
1343     if (h1p->chunked) {
1344         p = nxt_cpymem(p, chunked, nxt_length(chunked));
1345         /* Trailing CRLF will be added by the first chunk header. */
1346 
1347     } else {
1348         *p++ = '\r'; *p++ = '\n';
1349     }
1350 
1351     header->mem.free = p;
1352 
1353     h1p->header_size = nxt_buf_mem_used_size(&header->mem);
1354 
1355     c = h1p->conn;
1356 
1357     c->write = header;
1358     h1p->conn_write_tail = &header->next;
1359     c->write_state = &nxt_h1p_request_send_state;
1360 
1361     if (body_handler != NULL) {
1362         /*
1363          * The body handler will run before c->io->write() handler,
1364          * because the latter was inqueued by nxt_conn_write()
1365          * in engine->write_work_queue.
1366          */
1367         nxt_work_queue_add(&task->thread->engine->fast_work_queue,
1368                            body_handler, task, r, data);
1369 
1370     } else {
1371         header->next = nxt_http_buf_last(r);
1372     }
1373 
1374     nxt_conn_write(task->thread->engine, c);
1375 
1376     if (h1p->websocket) {
1377         nxt_h1p_websocket_first_frame_start(task, r, c->read);
1378     }
1379 }
1380 
1381 
1382 void
1383 nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_bool_t all)
1384 {
1385     size_t            size;
1386     nxt_buf_t         *b, *in, *next;
1387     nxt_conn_t        *c;
1388 
1389     nxt_debug(task, "h1p complete buffers");
1390 
1391     b = h1p->buffers;
1392     c = h1p->conn;
1393     in = c->read;
1394 
1395     if (b != NULL) {
1396         if (in == NULL) {
1397             /* A request with large body. */
1398             in = b;
1399             c->read = in;
1400 
1401             b = in->next;
1402             in->next = NULL;
1403         }
1404 
1405         while (b != NULL) {
1406             next = b->next;
1407             b->next = NULL;
1408 
1409             b->completion_handler(task, b, b->parent);
1410 
1411             b = next;
1412         }
1413 
1414         h1p->buffers = NULL;
1415         h1p->nbuffers = 0;
1416     }
1417 
1418     if (in != NULL) {
1419         size = nxt_buf_mem_used_size(&in->mem);
1420 
1421         if (size == 0 || all) {
1422             in->completion_handler(task, in, in->parent);
1423 
1424             c->read = NULL;
1425         }
1426     }
1427 }
1428 
1429 
1430 static const nxt_conn_state_t  nxt_h1p_request_send_state
1431     nxt_aligned(64) =
1432 {
1433     .ready_handler = nxt_h1p_conn_sent,
1434     .error_handler = nxt_h1p_conn_request_error,
1435 
1436     .timer_handler = nxt_h1p_conn_request_send_timeout,
1437     .timer_value = nxt_h1p_conn_request_timer_value,
1438     .timer_data = offsetof(nxt_socket_conf_t, send_timeout),
1439     .timer_autoreset = 1,
1440 };
1441 
1442 
1443 static void
1444 nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1445 {
1446     nxt_conn_t     *c;
1447     nxt_h1proto_t  *h1p;
1448 
1449     nxt_debug(task, "h1p request send");
1450 
1451     h1p = r->proto.h1;
1452     c = h1p->conn;
1453 
1454     if (h1p->chunked) {
1455         out = nxt_h1p_chunk_create(task, r, out);
1456         if (nxt_slow_path(out == NULL)) {
1457             nxt_h1p_request_error(task, h1p, r);
1458             return;
1459         }
1460     }
1461 
1462     if (c->write == NULL) {
1463         c->write = out;
1464         c->write_state = &nxt_h1p_request_send_state;
1465 
1466         nxt_conn_write(task->thread->engine, c);
1467 
1468     } else {
1469         *h1p->conn_write_tail = out;
1470     }
1471 
1472     while (out->next != NULL) {
1473         out = out->next;
1474     }
1475 
1476     h1p->conn_write_tail = &out->next;
1477 }
1478 
1479 
1480 static nxt_buf_t *
1481 nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1482 {
1483     nxt_off_t          size;
1484     nxt_buf_t          *b, **prev, *header, *tail;
1485 
1486     const size_t       chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN;
1487     static const char  tail_chunk[] = "\r\n0\r\n\r\n";
1488 
1489     size = 0;
1490     prev = &out;
1491 
1492     for (b = out; b != NULL; b = b->next) {
1493 
1494         if (nxt_buf_is_last(b)) {
1495             tail = nxt_http_buf_mem(task, r, sizeof(tail_chunk));
1496             if (nxt_slow_path(tail == NULL)) {
1497                 return NULL;
1498             }
1499 
1500             *prev = tail;
1501             tail->next = b;
1502             /*
1503              * The tail_chunk size with trailing zero is 8 bytes, so
1504              * memcpy may be inlined with just single 8 byte move operation.
1505              */
1506             nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk));
1507             tail->mem.free += nxt_length(tail_chunk);
1508 
1509             break;
1510         }
1511 
1512         size += nxt_buf_used_size(b);
1513         prev = &b->next;
1514     }
1515 
1516     if (size == 0) {
1517         return out;
1518     }
1519 
1520     header = nxt_http_buf_mem(task, r, chunk_size);
1521     if (nxt_slow_path(header == NULL)) {
1522         return NULL;
1523     }
1524 
1525     header->next = out;
1526     header->mem.free = nxt_sprintf(header->mem.free, header->mem.end,
1527                                    "\r\n%xO\r\n", size);
1528     return header;
1529 }
1530 
1531 
1532 static nxt_off_t
1533 nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto)
1534 {
1535     nxt_off_t      sent;
1536     nxt_h1proto_t  *h1p;
1537 
1538     h1p = proto.h1;
1539 
1540     sent = h1p->conn->sent - h1p->header_size;
1541 
1542     return (sent > 0) ? sent : 0;
1543 }
1544 
1545 
1546 static void
1547 nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
1548     nxt_buf_t *last)
1549 {
1550     nxt_buf_t         *b;
1551     nxt_conn_t        *c;
1552     nxt_h1proto_t     *h1p;
1553     nxt_work_queue_t  *wq;
1554 
1555     nxt_debug(task, "h1p request discard");
1556 
1557     h1p = r->proto.h1;
1558     h1p->keepalive = 0;
1559 
1560     c = h1p->conn;
1561     b = c->write;
1562     c->write = NULL;
1563 
1564     wq = &task->thread->engine->fast_work_queue;
1565 
1566     nxt_sendbuf_drain(task, wq, b);
1567     nxt_sendbuf_drain(task, wq, last);
1568 }
1569 
1570 
1571 static void
1572 nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data)
1573 {
1574     nxt_h1proto_t       *h1p;
1575     nxt_http_request_t  *r;
1576 
1577     h1p = data;
1578 
1579     nxt_debug(task, "h1p conn request error");
1580 
1581     r = h1p->request;
1582 
1583     if (nxt_slow_path(r == NULL)) {
1584         nxt_h1p_shutdown(task, h1p->conn);
1585         return;
1586     }
1587 
1588     if (r->fields == NULL) {
1589         (void) nxt_h1p_header_process(task, h1p, r);
1590     }
1591 
1592     if (r->status == 0) {
1593         r->status = NXT_HTTP_BAD_REQUEST;
1594     }
1595 
1596     nxt_h1p_request_error(task, h1p, r);
1597 }
1598 
1599 
1600 static void
1601 nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
1602 {
1603     nxt_conn_t          *c;
1604     nxt_timer_t         *timer;
1605     nxt_h1proto_t       *h1p;
1606     nxt_http_request_t  *r;
1607 
1608     timer = obj;
1609 
1610     nxt_debug(task, "h1p conn request timeout");
1611 
1612     c = nxt_read_timer_conn(timer);
1613     c->block_read = 1;
1614     /*
1615      * Disable SO_LINGER off during socket closing
1616      * to send "408 Request Timeout" error response.
1617      */
1618     c->socket.timedout = 0;
1619 
1620     h1p = c->socket.data;
1621     h1p->keepalive = 0;
1622     r = h1p->request;
1623 
1624     if (r->fields == NULL) {
1625         (void) nxt_h1p_header_process(task, h1p, r);
1626     }
1627 
1628     nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT);
1629 }
1630 
1631 
1632 static void
1633 nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)
1634 {
1635     nxt_conn_t     *c;
1636     nxt_timer_t    *timer;
1637     nxt_h1proto_t  *h1p;
1638 
1639     timer = obj;
1640 
1641     nxt_debug(task, "h1p conn request send timeout");
1642 
1643     c = nxt_write_timer_conn(timer);
1644     c->block_write = 1;
1645     h1p = c->socket.data;
1646 
1647     nxt_h1p_request_error(task, h1p, h1p->request);
1648 }
1649 
1650 
1651 nxt_msec_t
1652 nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data)
1653 {
1654     nxt_h1proto_t  *h1p;
1655 
1656     h1p = c->socket.data;
1657 
1658     return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data);
1659 }
1660 
1661 
1662 nxt_inline void
1663 nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
1664     nxt_http_request_t *r)
1665 {
1666     h1p->keepalive = 0;
1667 
1668     r->state->error_handler(task, r, h1p);
1669 }
1670 
1671 
1672 static void
1673 nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
1674     nxt_socket_conf_joint_t *joint)
1675 {
1676     nxt_conn_t     *c;
1677     nxt_h1proto_t  *h1p;
1678 
1679     nxt_debug(task, "h1p request close");
1680 
1681     h1p = proto.h1;
1682     h1p->keepalive &= !h1p->request->inconsistent;
1683     h1p->request = NULL;
1684 
1685     nxt_router_conf_release(task, joint);
1686 
1687     c = h1p->conn;
1688     task = &c->task;
1689     c->socket.task = task;
1690     c->read_timer.task = task;
1691     c->write_timer.task = task;
1692 
1693     if (h1p->keepalive) {
1694         nxt_h1p_keepalive(task, h1p, c);
1695 
1696     } else {
1697         nxt_h1p_shutdown(task, c);
1698     }
1699 }
1700 
1701 
1702 static void
1703 nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data)
1704 {
1705     nxt_conn_t          *c;
1706     nxt_event_engine_t  *engine;
1707 
1708     c = obj;
1709 
1710     nxt_debug(task, "h1p conn sent");
1711 
1712     engine = task->thread->engine;
1713 
1714     c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
1715 
1716     if (c->write != NULL) {
1717         nxt_conn_write(engine, c);
1718     }
1719 }
1720 
1721 
1722 static void
1723 nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
1724 {
1725     nxt_conn_t  *c;
1726 
1727     c = obj;
1728 
1729     nxt_debug(task, "h1p conn close");
1730 
1731     nxt_queue_remove(&c->link);
1732 
1733     nxt_h1p_shutdown(task, c);
1734 }
1735 
1736 
1737 static void
1738 nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
1739 {
1740     nxt_conn_t  *c;
1741 
1742     c = obj;
1743 
1744     nxt_debug(task, "h1p conn error");
1745 
1746     nxt_queue_remove(&c->link);
1747 
1748     nxt_h1p_shutdown(task, c);
1749 }
1750 
1751 
1752 static nxt_msec_t
1753 nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data)
1754 {
1755     nxt_socket_conf_joint_t  *joint;
1756 
1757     joint = c->listen->socket.data;
1758 
1759     if (nxt_fast_path(joint != NULL)) {
1760         return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
1761     }
1762 
1763     /*
1764      * Listening socket had been closed while
1765      * connection was in keep-alive state.
1766      */
1767     return 1;
1768 }
1769 
1770 
1771 static void
1772 nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
1773 {
1774     size_t              size;
1775     nxt_buf_t           *in;
1776     nxt_event_engine_t  *engine;
1777 
1778     nxt_debug(task, "h1p keepalive");
1779 
1780     if (!c->tcp_nodelay) {
1781         nxt_conn_tcp_nodelay_on(task, c);
1782     }
1783 
1784     nxt_h1p_complete_buffers(task, h1p, 0);
1785 
1786     in = c->read;
1787 
1788     nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn));
1789 
1790     c->sent = 0;
1791 
1792     engine = task->thread->engine;
1793     nxt_queue_insert_head(&engine->idle_connections, &c->link);
1794 
1795     if (in == NULL) {
1796         c->read_state = &nxt_h1p_keepalive_state;
1797 
1798         nxt_conn_read(engine, c);
1799 
1800     } else {
1801         size = nxt_buf_mem_used_size(&in->mem);
1802 
1803         nxt_debug(task, "h1p pipelining");
1804 
1805         nxt_memmove(in->mem.start, in->mem.pos, size);
1806 
1807         in->mem.pos = in->mem.start;
1808         in->mem.free = in->mem.start + size;
1809 
1810         nxt_h1p_conn_request_init(task, c, c->socket.data);
1811     }
1812 }
1813 
1814 
1815 static const nxt_conn_state_t  nxt_h1p_keepalive_state
1816     nxt_aligned(64) =
1817 {
1818     .ready_handler = nxt_h1p_conn_request_init,
1819     .close_handler = nxt_h1p_conn_close,
1820     .error_handler = nxt_h1p_conn_error,
1821 
1822     .io_read_handler = nxt_h1p_idle_io_read_handler,
1823 
1824     .timer_handler = nxt_h1p_idle_timeout,
1825     .timer_value = nxt_h1p_conn_timer_value,
1826     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
1827     .timer_autoreset = 1,
1828 };
1829 
1830 
1831 const nxt_conn_state_t  nxt_h1p_idle_close_state
1832     nxt_aligned(64) =
1833 {
1834     .close_handler = nxt_h1p_idle_close,
1835 };
1836 
1837 
1838 static void
1839 nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
1840 {
1841     nxt_conn_t  *c;
1842 
1843     c = obj;
1844 
1845     nxt_debug(task, "h1p idle close");
1846 
1847     nxt_queue_remove(&c->link);
1848 
1849     nxt_h1p_idle_response(task, c);
1850 }
1851 
1852 
1853 static void
1854 nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
1855 {
1856     nxt_conn_t   *c;
1857     nxt_timer_t  *timer;
1858 
1859     timer = obj;
1860 
1861     nxt_debug(task, "h1p idle timeout");
1862 
1863     c = nxt_read_timer_conn(timer);
1864     c->block_read = 1;
1865 
1866     nxt_queue_remove(&c->link);
1867 
1868     nxt_h1p_idle_response(task, c);
1869 }
1870 
1871 
1872 #define NXT_H1P_IDLE_TIMEOUT                                                  \
1873      "HTTP/1.1 408 Request Timeout\r\n"                                       \
1874      "Server: " NXT_SERVER "\r\n"                                             \
1875      "Connection: close\r\n"                                                  \
1876      "Content-Length: 0\r\n"                                                  \
1877      "Date: "
1878 
1879 
1880 static void
1881 nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c)
1882 {
1883     u_char     *p;
1884     size_t     size;
1885     nxt_buf_t  *out, *last;
1886 
1887     size = nxt_length(NXT_H1P_IDLE_TIMEOUT)
1888            + nxt_http_date_cache.size
1889            + nxt_length("\r\n\r\n");
1890 
1891     out = nxt_buf_mem_alloc(c->mem_pool, size, 0);
1892     if (nxt_slow_path(out == NULL)) {
1893         goto fail;
1894     }
1895 
1896     p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT,
1897                    nxt_length(NXT_H1P_IDLE_TIMEOUT));
1898 
1899     p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p);
1900 
1901     out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4);
1902 
1903     last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE);
1904     if (nxt_slow_path(last == NULL)) {
1905         goto fail;
1906     }
1907 
1908     out->next = last;
1909     nxt_buf_set_sync(last);
1910     nxt_buf_set_last(last);
1911 
1912     last->completion_handler = nxt_h1p_idle_response_sent;
1913     last->parent = c;
1914 
1915     c->write = out;
1916     c->write_state = &nxt_h1p_timeout_response_state;
1917 
1918     nxt_conn_write(task->thread->engine, c);
1919     return;
1920 
1921 fail:
1922 
1923     nxt_h1p_shutdown(task, c);
1924 }
1925 
1926 
1927 static const nxt_conn_state_t  nxt_h1p_timeout_response_state
1928     nxt_aligned(64) =
1929 {
1930     .ready_handler = nxt_h1p_conn_sent,
1931     .error_handler = nxt_h1p_idle_response_error,
1932 
1933     .timer_handler = nxt_h1p_idle_response_timeout,
1934     .timer_value = nxt_h1p_idle_response_timer_value,
1935 };
1936 
1937 
1938 static void
1939 nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data)
1940 {
1941     nxt_conn_t  *c;
1942 
1943     c = data;
1944 
1945     nxt_debug(task, "h1p idle timeout response sent");
1946 
1947     nxt_h1p_shutdown(task, c);
1948 }
1949 
1950 
1951 static void
1952 nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, void *data)
1953 {
1954     nxt_conn_t  *c;
1955 
1956     c = obj;
1957 
1958     nxt_debug(task, "h1p response error");
1959 
1960     nxt_h1p_shutdown(task, c);
1961 }
1962 
1963 
1964 static void
1965 nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data)
1966 {
1967     nxt_conn_t   *c;
1968     nxt_timer_t  *timer;
1969 
1970     timer = obj;
1971 
1972     nxt_debug(task, "h1p idle timeout response timeout");
1973 
1974     c = nxt_read_timer_conn(timer);
1975     c->block_write = 1;
1976 
1977     nxt_h1p_shutdown(task, c);
1978 }
1979 
1980 
1981 static nxt_msec_t
1982 nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data)
1983 {
1984     return 10 * 1000;
1985 }
1986 
1987 
1988 static void
1989 nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c)
1990 {
1991     nxt_timer_t    *timer;
1992     nxt_h1proto_t  *h1p;
1993 
1994     nxt_debug(task, "h1p shutdown");
1995 
1996     h1p = c->socket.data;
1997 
1998     if (h1p != NULL) {
1999         nxt_h1p_complete_buffers(task, h1p, 1);
2000 
2001         if (nxt_slow_path(h1p->websocket_timer != NULL)) {
2002             timer = &h1p->websocket_timer->timer;
2003 
2004             if (timer->handler != nxt_h1p_conn_ws_shutdown) {
2005                 timer->handler = nxt_h1p_conn_ws_shutdown;
2006                 nxt_timer_add(task->thread->engine, timer, 0);
2007 
2008             } else {
2009                 nxt_debug(task, "h1p already scheduled ws shutdown");
2010             }
2011 
2012             return;
2013         }
2014     }
2015 
2016     nxt_h1p_closing(task, c);
2017 }
2018 
2019 
2020 static void
2021 nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data)
2022 {
2023     nxt_timer_t                *timer;
2024     nxt_h1p_websocket_timer_t  *ws_timer;
2025 
2026     nxt_debug(task, "h1p conn ws shutdown");
2027 
2028     timer = obj;
2029     ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer);
2030 
2031     nxt_h1p_closing(task, ws_timer->h1p->conn);
2032 }
2033 
2034 
2035 static void
2036 nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c)
2037 {
2038     nxt_debug(task, "h1p closing");
2039 
2040     c->socket.data = NULL;
2041 
2042 #if (NXT_TLS)
2043 
2044     if (c->u.tls != NULL) {
2045         c->write_state = &nxt_h1p_shutdown_state;
2046 
2047         c->io->shutdown(task, c, NULL);
2048         return;
2049     }
2050 
2051 #endif
2052 
2053     nxt_h1p_conn_closing(task, c, NULL);
2054 }
2055 
2056 
2057 #if (NXT_TLS)
2058 
2059 static const nxt_conn_state_t  nxt_h1p_shutdown_state
2060     nxt_aligned(64) =
2061 {
2062     .ready_handler = nxt_h1p_conn_closing,
2063     .close_handler = nxt_h1p_conn_closing,
2064     .error_handler = nxt_h1p_conn_closing,
2065 };
2066 
2067 #endif
2068 
2069 
2070 static void
2071 nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data)
2072 {
2073     nxt_conn_t  *c;
2074 
2075     c = obj;
2076 
2077     nxt_debug(task, "h1p conn closing");
2078 
2079     c->write_state = &nxt_h1p_close_state;
2080 
2081     nxt_conn_close(task->thread->engine, c);
2082 }
2083 
2084 
2085 static const nxt_conn_state_t  nxt_h1p_close_state
2086     nxt_aligned(64) =
2087 {
2088     .ready_handler = nxt_h1p_conn_free,
2089 };
2090 
2091 
2092 static void
2093 nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data)
2094 {
2095     nxt_conn_t          *c;
2096     nxt_listen_event_t  *lev;
2097     nxt_event_engine_t  *engine;
2098 
2099     c = obj;
2100 
2101     nxt_debug(task, "h1p conn free");
2102 
2103     engine = task->thread->engine;
2104 
2105     nxt_sockaddr_cache_free(engine, c);
2106 
2107     lev = c->listen;
2108 
2109     nxt_conn_free(task, c);
2110 
2111     nxt_router_listen_event_release(&engine->task, lev, NULL);
2112 }
2113 
2114 
2115 static void
2116 nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer)
2117 {
2118     nxt_mp_t            *mp;
2119     nxt_int_t           ret;
2120     nxt_conn_t          *c, *client;
2121     nxt_h1proto_t       *h1p;
2122     nxt_fd_event_t      *socket;
2123     nxt_work_queue_t    *wq;
2124     nxt_http_request_t  *r;
2125 
2126     nxt_debug(task, "h1p peer connect");
2127 
2128     peer->status = NXT_HTTP_UNSET;
2129     r = peer->request;
2130 
2131     mp = nxt_mp_create(1024, 128, 256, 32);
2132 
2133     if (nxt_slow_path(mp == NULL)) {
2134         goto fail;
2135     }
2136 
2137     h1p = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t));
2138     if (nxt_slow_path(h1p == NULL)) {
2139         goto fail;
2140     }
2141 
2142     ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool);
2143     if (nxt_slow_path(ret != NXT_OK)) {
2144         goto fail;
2145     }
2146 
2147     c = nxt_conn_create(mp, task);
2148     if (nxt_slow_path(c == NULL)) {
2149         goto fail;
2150     }
2151 
2152     c->mem_pool = mp;
2153     h1p->conn = c;
2154 
2155     peer->proto.h1 = h1p;
2156     h1p->request = r;
2157 
2158     c->socket.data = peer;
2159     c->remote = peer->server->sockaddr;
2160 
2161     c->socket.write_ready = 1;
2162     c->write_state = &nxt_h1p_peer_connect_state;
2163 
2164     /*
2165      * TODO: queues should be implemented via client proto interface.
2166      */
2167     client = r->proto.h1->conn;
2168 
2169     socket = &client->socket;
2170     wq = socket->read_work_queue;
2171     c->read_work_queue = wq;
2172     c->socket.read_work_queue = wq;
2173     c->read_timer.work_queue = wq;
2174 
2175     wq = socket->write_work_queue;
2176     c->write_work_queue = wq;
2177     c->socket.write_work_queue = wq;
2178     c->write_timer.work_queue = wq;
2179     /* TODO END */
2180 
2181     nxt_conn_connect(task->thread->engine, c);
2182 
2183     return;
2184 
2185 fail:
2186 
2187     peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR;
2188 
2189     r->state->error_handler(task, r, peer);
2190 }
2191 
2192 
2193 static const nxt_conn_state_t  nxt_h1p_peer_connect_state
2194     nxt_aligned(64) =
2195 {
2196     .ready_handler = nxt_h1p_peer_connected,
2197     .close_handler = nxt_h1p_peer_refused,
2198     .error_handler = nxt_h1p_peer_error,
2199 
2200     .timer_handler = nxt_h1p_peer_send_timeout,
2201     .timer_value = nxt_h1p_peer_timer_value,
2202     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2203 };
2204 
2205 
2206 static void
2207 nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data)
2208 {
2209     nxt_http_peer_t     *peer;
2210     nxt_http_request_t  *r;
2211 
2212     peer = data;
2213 
2214     nxt_debug(task, "h1p peer connected");
2215 
2216     r = peer->request;
2217     r->state->ready_handler(task, r, peer);
2218 }
2219 
2220 
2221 static void
2222 nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data)
2223 {
2224     nxt_http_peer_t     *peer;
2225     nxt_http_request_t  *r;
2226 
2227     peer = data;
2228 
2229     nxt_debug(task, "h1p peer refused");
2230 
2231     //peer->status = NXT_HTTP_SERVICE_UNAVAILABLE;
2232     peer->status = NXT_HTTP_BAD_GATEWAY;
2233 
2234     r = peer->request;
2235     r->state->error_handler(task, r, peer);
2236 }
2237 
2238 
2239 static void
2240 nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer)
2241 {
2242     u_char              *p;
2243     size_t              size;
2244     nxt_buf_t           *header, *body;
2245     nxt_conn_t          *c;
2246     nxt_http_field_t    *field;
2247     nxt_http_request_t  *r;
2248 
2249     nxt_debug(task, "h1p peer header send");
2250 
2251     r = peer->request;
2252 
2253     size = r->method->length + sizeof(" ") + r->target.length
2254            + sizeof(" HTTP/1.1\r\n")
2255            + sizeof("Connection: close\r\n")
2256            + sizeof("\r\n");
2257 
2258     nxt_list_each(field, r->fields) {
2259 
2260         if (!field->hopbyhop) {
2261             size += field->name_length + field->value_length;
2262             size += nxt_length(": \r\n");
2263         }
2264 
2265     } nxt_list_loop;
2266 
2267     header = nxt_http_buf_mem(task, r, size);
2268     if (nxt_slow_path(header == NULL)) {
2269         r->state->error_handler(task, r, peer);
2270         return;
2271     }
2272 
2273     p = header->mem.free;
2274 
2275     p = nxt_cpymem(p, r->method->start, r->method->length);
2276     *p++ = ' ';
2277     p = nxt_cpymem(p, r->target.start, r->target.length);
2278     p = nxt_cpymem(p, " HTTP/1.1\r\n", 11);
2279     p = nxt_cpymem(p, "Connection: close\r\n", 19);
2280 
2281     nxt_list_each(field, r->fields) {
2282 
2283         if (!field->hopbyhop) {
2284             p = nxt_cpymem(p, field->name, field->name_length);
2285             *p++ = ':'; *p++ = ' ';
2286             p = nxt_cpymem(p, field->value, field->value_length);
2287             *p++ = '\r'; *p++ = '\n';
2288         }
2289 
2290     } nxt_list_loop;
2291 
2292     *p++ = '\r'; *p++ = '\n';
2293     header->mem.free = p;
2294     size = p - header->mem.pos;
2295 
2296     c = peer->proto.h1->conn;
2297     c->write = header;
2298     c->write_state = &nxt_h1p_peer_header_send_state;
2299 
2300     if (r->body != NULL) {
2301         if (nxt_buf_is_file(r->body)) {
2302             body = nxt_buf_file_alloc(r->mem_pool, 0, 0);
2303 
2304         } else {
2305             body = nxt_buf_mem_alloc(r->mem_pool, 0, 0);
2306         }
2307 
2308         if (nxt_slow_path(body == NULL)) {
2309             r->state->error_handler(task, r, peer);
2310             return;
2311         }
2312 
2313         header->next = body;
2314 
2315         if (nxt_buf_is_file(r->body)) {
2316             body->file = r->body->file;
2317             body->file_end = r->body->file_end;
2318 
2319         } else {
2320             body->mem = r->body->mem;
2321         }
2322 
2323         size += nxt_buf_used_size(body);
2324 
2325 //        nxt_mp_retain(r->mem_pool);
2326     }
2327 
2328     if (size > 16384) {
2329         /* Use proxy_send_timeout instead of proxy_timeout. */
2330         c->write_state = &nxt_h1p_peer_header_body_send_state;
2331     }
2332 
2333     nxt_conn_write(task->thread->engine, c);
2334 }
2335 
2336 
2337 static const nxt_conn_state_t  nxt_h1p_peer_header_send_state
2338     nxt_aligned(64) =
2339 {
2340     .ready_handler = nxt_h1p_peer_header_sent,
2341     .error_handler = nxt_h1p_peer_error,
2342 
2343     .timer_handler = nxt_h1p_peer_send_timeout,
2344     .timer_value = nxt_h1p_peer_timer_value,
2345     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2346 };
2347 
2348 
2349 static const nxt_conn_state_t  nxt_h1p_peer_header_body_send_state
2350     nxt_aligned(64) =
2351 {
2352     .ready_handler = nxt_h1p_peer_header_sent,
2353     .error_handler = nxt_h1p_peer_error,
2354 
2355     .timer_handler = nxt_h1p_peer_send_timeout,
2356     .timer_value = nxt_h1p_peer_timer_value,
2357     .timer_data = offsetof(nxt_socket_conf_t, proxy_send_timeout),
2358     .timer_autoreset = 1,
2359 };
2360 
2361 
2362 static void
2363 nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data)
2364 {
2365     nxt_conn_t          *c;
2366     nxt_http_peer_t     *peer;
2367     nxt_http_request_t  *r;
2368     nxt_event_engine_t  *engine;
2369 
2370     c = obj;
2371     peer = data;
2372 
2373     nxt_debug(task, "h1p peer header sent");
2374 
2375     engine = task->thread->engine;
2376 
2377     c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
2378 
2379     if (c->write != NULL) {
2380         nxt_conn_write(engine, c);
2381         return;
2382     }
2383 
2384     r = peer->request;
2385     r->state->ready_handler(task, r, peer);
2386 }
2387 
2388 
2389 static void
2390 nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer)
2391 {
2392     nxt_conn_t  *c;
2393 
2394     nxt_debug(task, "h1p peer header read");
2395 
2396     c = peer->proto.h1->conn;
2397 
2398     if (c->write_timer.enabled) {
2399         c->read_state = &nxt_h1p_peer_header_read_state;
2400 
2401     } else {
2402         c->read_state = &nxt_h1p_peer_header_read_timer_state;
2403     }
2404 
2405     nxt_conn_read(task->thread->engine, c);
2406 }
2407 
2408 
2409 static const nxt_conn_state_t  nxt_h1p_peer_header_read_state
2410     nxt_aligned(64) =
2411 {
2412     .ready_handler = nxt_h1p_peer_header_read_done,
2413     .close_handler = nxt_h1p_peer_closed,
2414     .error_handler = nxt_h1p_peer_error,
2415 
2416     .io_read_handler = nxt_h1p_peer_io_read_handler,
2417 };
2418 
2419 
2420 static const nxt_conn_state_t  nxt_h1p_peer_header_read_timer_state
2421     nxt_aligned(64) =
2422 {
2423     .ready_handler = nxt_h1p_peer_header_read_done,
2424     .close_handler = nxt_h1p_peer_closed,
2425     .error_handler = nxt_h1p_peer_error,
2426 
2427     .io_read_handler = nxt_h1p_peer_io_read_handler,
2428 
2429     .timer_handler = nxt_h1p_peer_read_timeout,
2430     .timer_value = nxt_h1p_peer_timer_value,
2431     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2432 };
2433 
2434 
2435 static ssize_t
2436 nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c)
2437 {
2438     size_t              size;
2439     ssize_t             n;
2440     nxt_buf_t           *b;
2441     nxt_http_peer_t     *peer;
2442     nxt_socket_conf_t   *skcf;
2443     nxt_http_request_t  *r;
2444 
2445     peer = c->socket.data;
2446     r = peer->request;
2447     b = c->read;
2448 
2449     if (b == NULL) {
2450         skcf = r->conf->socket_conf;
2451 
2452         size = (peer->header_received) ? skcf->proxy_buffer_size
2453                                        : skcf->proxy_header_buffer_size;
2454 
2455         nxt_debug(task, "h1p peer io read: %z", size);
2456 
2457         b = nxt_http_proxy_buf_mem_alloc(task, r, size);
2458         if (nxt_slow_path(b == NULL)) {
2459             c->socket.error = NXT_ENOMEM;
2460             return NXT_ERROR;
2461         }
2462     }
2463 
2464     n = c->io->recvbuf(c, b);
2465 
2466     if (n > 0) {
2467         c->read = b;
2468 
2469     } else {
2470         c->read = NULL;
2471         nxt_http_proxy_buf_mem_free(task, r, b);
2472     }
2473 
2474     return n;
2475 }
2476 
2477 
2478 static void
2479 nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, void *data)
2480 {
2481     nxt_int_t           ret;
2482     nxt_buf_t           *b;
2483     nxt_conn_t          *c;
2484     nxt_h1proto_t       *h1p;
2485     nxt_http_peer_t     *peer;
2486     nxt_http_request_t  *r;
2487     nxt_event_engine_t  *engine;
2488 
2489     c = obj;
2490     peer = data;
2491 
2492     nxt_debug(task, "h1p peer header read done");
2493 
2494     b = c->read;
2495 
2496     ret = nxt_h1p_peer_header_parse(peer, &b->mem);
2497 
2498     r = peer->request;
2499 
2500     ret = nxt_expect(NXT_DONE, ret);
2501 
2502     if (ret != NXT_AGAIN) {
2503         engine = task->thread->engine;
2504         nxt_timer_disable(engine, &c->write_timer);
2505         nxt_timer_disable(engine, &c->read_timer);
2506     }
2507 
2508     switch (ret) {
2509 
2510     case NXT_DONE:
2511         peer->fields = peer->proto.h1->parser.fields;
2512 
2513         ret = nxt_http_fields_process(peer->fields,
2514                                       &nxt_h1p_peer_fields_hash, r);
2515         if (nxt_slow_path(ret != NXT_OK)) {
2516             peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR;
2517             break;
2518         }
2519 
2520         c->read = NULL;
2521 
2522         peer->header_received = 1;
2523 
2524         h1p = peer->proto.h1;
2525 
2526         if (h1p->chunked) {
2527             if (r->resp.content_length != NULL) {
2528                 peer->status = NXT_HTTP_BAD_GATEWAY;
2529                 break;
2530             }
2531 
2532             h1p->chunked_parse.mem_pool = c->mem_pool;
2533 
2534         } else if (r->resp.content_length_n > 0) {
2535             h1p->remainder = r->resp.content_length_n;
2536         }
2537 
2538         if (nxt_buf_mem_used_size(&b->mem) != 0) {
2539             nxt_h1p_peer_body_process(task, peer, b);
2540             return;
2541         }
2542 
2543         r->state->ready_handler(task, r, peer);
2544         return;
2545 
2546     case NXT_AGAIN:
2547         if (nxt_buf_mem_free_size(&b->mem) != 0) {
2548             nxt_conn_read(task->thread->engine, c);
2549             return;
2550         }
2551 
2552         /* Fall through. */
2553 
2554     default:
2555     case NXT_ERROR:
2556     case NXT_HTTP_PARSE_INVALID:
2557     case NXT_HTTP_PARSE_UNSUPPORTED_VERSION:
2558     case NXT_HTTP_PARSE_TOO_LARGE_FIELD:
2559         peer->status = NXT_HTTP_BAD_GATEWAY;
2560         break;
2561     }
2562 
2563     nxt_http_proxy_buf_mem_free(task, r, b);
2564 
2565     r->state->error_handler(task, r, peer);
2566 }
2567 
2568 
2569 static nxt_int_t
2570 nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm)
2571 {
2572     u_char     *p;
2573     size_t     length;
2574     nxt_int_t  status;
2575 
2576     if (peer->status < 0) {
2577         length = nxt_buf_mem_used_size(bm);
2578 
2579         if (nxt_slow_path(length < 12)) {
2580             return NXT_AGAIN;
2581         }
2582 
2583         p = bm->pos;
2584 
2585         if (nxt_slow_path(nxt_memcmp(p, "HTTP/1.", 7) != 0
2586                           || (p[7] != '0' && p[7] != '1')))
2587         {
2588             return NXT_ERROR;
2589         }
2590 
2591         status = nxt_int_parse(&p[9], 3);
2592 
2593         if (nxt_slow_path(status < 0)) {
2594             return NXT_ERROR;
2595         }
2596 
2597         p += 12;
2598         length -= 12;
2599 
2600         p = nxt_memchr(p, '\n', length);
2601 
2602         if (nxt_slow_path(p == NULL)) {
2603             return NXT_AGAIN;
2604         }
2605 
2606         bm->pos = p + 1;
2607         peer->status = status;
2608     }
2609 
2610     return nxt_http_parse_fields(&peer->proto.h1->parser, bm);
2611 }
2612 
2613 
2614 static void
2615 nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer)
2616 {
2617     nxt_conn_t  *c;
2618 
2619     nxt_debug(task, "h1p peer read");
2620 
2621     c = peer->proto.h1->conn;
2622     c->read_state = &nxt_h1p_peer_read_state;
2623 
2624     nxt_conn_read(task->thread->engine, c);
2625 }
2626 
2627 
2628 static const nxt_conn_state_t  nxt_h1p_peer_read_state
2629     nxt_aligned(64) =
2630 {
2631     .ready_handler = nxt_h1p_peer_read_done,
2632     .close_handler = nxt_h1p_peer_closed,
2633     .error_handler = nxt_h1p_peer_error,
2634 
2635     .io_read_handler = nxt_h1p_peer_io_read_handler,
2636 
2637     .timer_handler = nxt_h1p_peer_read_timeout,
2638     .timer_value = nxt_h1p_peer_timer_value,
2639     .timer_data = offsetof(nxt_socket_conf_t, proxy_read_timeout),
2640     .timer_autoreset = 1,
2641 };
2642 
2643 
2644 static void
2645 nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data)
2646 {
2647     nxt_buf_t        *out;
2648     nxt_conn_t       *c;
2649     nxt_http_peer_t  *peer;
2650 
2651     c = obj;
2652     peer = data;
2653 
2654     nxt_debug(task, "h1p peer read done");
2655 
2656     out = c->read;
2657     c->read = NULL;
2658 
2659     nxt_h1p_peer_body_process(task, peer, out);
2660 }
2661 
2662 
2663 static void
2664 nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer,
2665     nxt_buf_t *out)
2666 {
2667     size_t              length;
2668     nxt_h1proto_t       *h1p;
2669     nxt_http_request_t  *r;
2670 
2671     h1p = peer->proto.h1;
2672 
2673     if (h1p->chunked) {
2674         out = nxt_http_chunk_parse(task, &h1p->chunked_parse, out);
2675 
2676         if (h1p->chunked_parse.chunk_error || h1p->chunked_parse.error) {
2677             peer->status = NXT_HTTP_BAD_GATEWAY;
2678             r = peer->request;
2679             r->state->error_handler(task, r, peer);
2680             return;
2681         }
2682 
2683         if (h1p->chunked_parse.last) {
2684             nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request));
2685             peer->closed = 1;
2686         }
2687 
2688     } else if (h1p->remainder > 0) {
2689         length = nxt_buf_chain_length(out);
2690         h1p->remainder -= length;
2691     }
2692 
2693     peer->body = out;
2694 
2695     r = peer->request;
2696     r->state->ready_handler(task, r, peer);
2697 }
2698 
2699 
2700 static void
2701 nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data)
2702 {
2703     nxt_http_peer_t     *peer;
2704     nxt_http_request_t  *r;
2705 
2706     peer = data;
2707 
2708     nxt_debug(task, "h1p peer closed");
2709 
2710     r = peer->request;
2711 
2712     if (peer->header_received) {
2713         peer->body = nxt_http_buf_last(r);
2714         peer->closed = 1;
2715         r->inconsistent = (peer->proto.h1->remainder != 0);
2716 
2717         r->state->ready_handler(task, r, peer);
2718 
2719     } else {
2720         peer->status = NXT_HTTP_BAD_GATEWAY;
2721 
2722         r->state->error_handler(task, r, peer);
2723     }
2724 }
2725 
2726 
2727 static void
2728 nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data)
2729 {
2730     nxt_http_peer_t     *peer;
2731     nxt_http_request_t  *r;
2732 
2733     peer = data;
2734 
2735     nxt_debug(task, "h1p peer error");
2736 
2737     peer->status = NXT_HTTP_BAD_GATEWAY;
2738 
2739     r = peer->request;
2740     r->state->error_handler(task, r, peer);
2741 }
2742 
2743 
2744 static void
2745 nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data)
2746 {
2747     nxt_conn_t          *c;
2748     nxt_timer_t         *timer;
2749     nxt_http_peer_t     *peer;
2750     nxt_http_request_t  *r;
2751 
2752     timer = obj;
2753 
2754     nxt_debug(task, "h1p peer send timeout");
2755 
2756     c = nxt_write_timer_conn(timer);
2757     c->block_write = 1;
2758     c->block_read = 1;
2759 
2760     peer = c->socket.data;
2761     peer->status = NXT_HTTP_GATEWAY_TIMEOUT;
2762 
2763     r = peer->request;
2764     r->state->error_handler(task, r, peer);
2765 }
2766 
2767 
2768 static void
2769 nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data)
2770 {
2771     nxt_conn_t          *c;
2772     nxt_timer_t         *timer;
2773     nxt_http_peer_t     *peer;
2774     nxt_http_request_t  *r;
2775 
2776     timer = obj;
2777 
2778     nxt_debug(task, "h1p peer read timeout");
2779 
2780     c = nxt_read_timer_conn(timer);
2781     c->block_write = 1;
2782     c->block_read = 1;
2783 
2784     peer = c->socket.data;
2785     peer->status = NXT_HTTP_GATEWAY_TIMEOUT;
2786 
2787     r = peer->request;
2788     r->state->error_handler(task, r, peer);
2789 }
2790 
2791 
2792 static nxt_msec_t
2793 nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data)
2794 {
2795     nxt_http_peer_t  *peer;
2796 
2797     peer = c->socket.data;
2798 
2799     return nxt_value_at(nxt_msec_t, peer->request->conf->socket_conf, data);
2800 }
2801 
2802 
2803 static void
2804 nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer)
2805 {
2806     nxt_conn_t  *c;
2807 
2808     nxt_debug(task, "h1p peer close");
2809 
2810     peer->closed = 1;
2811 
2812     c = peer->proto.h1->conn;
2813     task = &c->task;
2814     c->socket.task = task;
2815     c->read_timer.task = task;
2816     c->write_timer.task = task;
2817 
2818     if (c->socket.fd != -1) {
2819         c->write_state = &nxt_h1p_peer_close_state;
2820 
2821         nxt_conn_close(task->thread->engine, c);
2822 
2823     } else {
2824         nxt_h1p_peer_free(task, c, NULL);
2825     }
2826 }
2827 
2828 
2829 static const nxt_conn_state_t  nxt_h1p_peer_close_state
2830     nxt_aligned(64) =
2831 {
2832     .ready_handler = nxt_h1p_peer_free,
2833 };
2834 
2835 
2836 static void
2837 nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data)
2838 {
2839     nxt_conn_t  *c;
2840 
2841     c = obj;
2842 
2843     nxt_debug(task, "h1p peer free");
2844 
2845     nxt_conn_free(task, c);
2846 }
2847 
2848 
2849 static nxt_int_t
2850 nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field,
2851     uintptr_t data)
2852 {
2853     nxt_http_request_t  *r;
2854 
2855     r = ctx;
2856     field->skip = 1;
2857 
2858     if (field->value_length == 7
2859         && nxt_memcmp(field->value, "chunked", 7) == 0)
2860     {
2861         r->peer->proto.h1->chunked = 1;
2862     }
2863 
2864     return NXT_OK;
2865 }
2866