xref: /unit/src/nxt_h1proto.c (revision 1534:dd6867b3a02e)
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 && nxt_memcmp(field->value, "close", 5) == 0) {
738         r->proto.h1->keepalive = 0;
739 
740     } else if (field->value_length == 7
741                && nxt_memcasecmp(field->value, "upgrade", 7) == 0)
742     {
743         r->proto.h1->connection_upgrade = 1;
744     }
745 
746     return NXT_OK;
747 }
748 
749 
750 static nxt_int_t
751 nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, uintptr_t data)
752 {
753     nxt_http_request_t  *r;
754 
755     r = ctx;
756 
757     if (field->value_length == 9
758         && nxt_memcasecmp(field->value, "websocket", 9) == 0)
759     {
760         r->proto.h1->upgrade_websocket = 1;
761     }
762 
763     return NXT_OK;
764 }
765 
766 
767 static nxt_int_t
768 nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, uintptr_t data)
769 {
770     nxt_http_request_t  *r;
771 
772     r = ctx;
773 
774     if (field->value_length == 24) {
775         r->proto.h1->websocket_key = field;
776     }
777 
778     return NXT_OK;
779 }
780 
781 
782 static nxt_int_t
783 nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, uintptr_t data)
784 {
785     nxt_http_request_t  *r;
786 
787     r = ctx;
788 
789     if (field->value_length == 2
790         && field->value[0] == '1' && field->value[1] == '3')
791     {
792         r->proto.h1->websocket_version_ok = 1;
793     }
794 
795     return NXT_OK;
796 }
797 
798 
799 static nxt_int_t
800 nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data)
801 {
802     nxt_http_te_t       te;
803     nxt_http_request_t  *r;
804 
805     r = ctx;
806     field->skip = 1;
807     field->hopbyhop = 1;
808 
809     if (field->value_length == 7
810         && nxt_memcmp(field->value, "chunked", 7) == 0)
811     {
812         te = NXT_HTTP_TE_CHUNKED;
813 
814     } else {
815         te = NXT_HTTP_TE_UNSUPPORTED;
816     }
817 
818     r->proto.h1->transfer_encoding = te;
819 
820     return NXT_OK;
821 }
822 
823 
824 static void
825 nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r)
826 {
827     size_t             size, body_length, body_buffer_size, body_rest;
828     ssize_t            res;
829     nxt_str_t          *tmp_path, tmp_name;
830     nxt_buf_t          *in, *b;
831     nxt_conn_t         *c;
832     nxt_h1proto_t      *h1p;
833     nxt_http_status_t  status;
834 
835     static const nxt_str_t tmp_name_pattern = nxt_string("/req-XXXXXXXX");
836 
837     h1p = r->proto.h1;
838 
839     nxt_debug(task, "h1p request body read %O te:%d",
840               r->content_length_n, h1p->transfer_encoding);
841 
842     switch (h1p->transfer_encoding) {
843 
844     case NXT_HTTP_TE_CHUNKED:
845         status = NXT_HTTP_LENGTH_REQUIRED;
846         goto error;
847 
848     case NXT_HTTP_TE_UNSUPPORTED:
849         status = NXT_HTTP_NOT_IMPLEMENTED;
850         goto error;
851 
852     default:
853     case NXT_HTTP_TE_NONE:
854         break;
855     }
856 
857     if (r->content_length_n == -1 || r->content_length_n == 0) {
858         goto ready;
859     }
860 
861     body_length = (size_t) r->content_length_n;
862 
863     body_buffer_size = nxt_min(r->conf->socket_conf->body_buffer_size,
864                                body_length);
865 
866     if (body_length > body_buffer_size) {
867         tmp_path = &r->conf->socket_conf->body_temp_path;
868 
869         tmp_name.length = tmp_path->length + tmp_name_pattern.length;
870 
871         b = nxt_buf_file_alloc(r->mem_pool,
872                                body_buffer_size + sizeof(nxt_file_t)
873                                + tmp_name.length + 1, 0);
874 
875     } else {
876         /* This initialization required for CentOS 6, gcc 4.4.7. */
877         tmp_path = NULL;
878         tmp_name.length = 0;
879 
880         b = nxt_buf_mem_alloc(r->mem_pool, body_buffer_size, 0);
881     }
882 
883     if (nxt_slow_path(b == NULL)) {
884         status = NXT_HTTP_INTERNAL_SERVER_ERROR;
885         goto error;
886     }
887 
888     r->body = b;
889 
890     if (body_length > body_buffer_size) {
891         tmp_name.start = nxt_pointer_to(b->mem.start, sizeof(nxt_file_t));
892 
893         memcpy(tmp_name.start, tmp_path->start, tmp_path->length);
894         memcpy(tmp_name.start + tmp_path->length, tmp_name_pattern.start,
895                tmp_name_pattern.length);
896         tmp_name.start[tmp_name.length] = '\0';
897 
898         b->file = (nxt_file_t *) b->mem.start;
899         nxt_memzero(b->file, sizeof(nxt_file_t));
900         b->file->fd = -1;
901         b->file->size = body_length;
902 
903         b->mem.start += sizeof(nxt_file_t) + tmp_name.length + 1;
904         b->mem.pos = b->mem.start;
905         b->mem.free = b->mem.start;
906 
907         b->file->fd = mkstemp((char *) tmp_name.start);
908         if (nxt_slow_path(b->file->fd == -1)) {
909             nxt_alert(task, "mkstemp(%s) failed %E", tmp_name.start, nxt_errno);
910 
911             status = NXT_HTTP_INTERNAL_SERVER_ERROR;
912             goto error;
913         }
914 
915         nxt_debug(task, "create body tmp file \"%V\", %d",
916                   &tmp_name, b->file->fd);
917 
918         unlink((char *) tmp_name.start);
919     }
920 
921     body_rest = body_length;
922 
923     in = h1p->conn->read;
924 
925     size = nxt_buf_mem_used_size(&in->mem);
926 
927     if (size != 0) {
928         size = nxt_min(size, body_length);
929 
930         if (nxt_buf_is_file(b)) {
931             res = nxt_fd_write(b->file->fd, in->mem.pos, size);
932             if (nxt_slow_path(res < (ssize_t) size)) {
933                 status = NXT_HTTP_INTERNAL_SERVER_ERROR;
934                 goto error;
935             }
936 
937             b->file_end += size;
938 
939         } else {
940             size = nxt_min(body_buffer_size, size);
941             b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size);
942             body_buffer_size -= size;
943         }
944 
945         in->mem.pos += size;
946         body_rest -= size;
947     }
948 
949     nxt_debug(task, "h1p body rest: %uz", body_rest);
950 
951     if (body_rest != 0) {
952         in->next = h1p->buffers;
953         h1p->buffers = in;
954         h1p->nbuffers++;
955 
956         c = h1p->conn;
957         c->read = b;
958         c->read_state = &nxt_h1p_read_body_state;
959 
960         nxt_conn_read(task->thread->engine, c);
961         return;
962     }
963 
964     if (nxt_buf_is_file(b)) {
965         b->mem.start = NULL;
966         b->mem.end = NULL;
967         b->mem.pos = NULL;
968         b->mem.free = NULL;
969     }
970 
971 ready:
972 
973     r->state->ready_handler(task, r, NULL);
974 
975     return;
976 
977 error:
978 
979     h1p->keepalive = 0;
980 
981     nxt_http_request_error(task, r, status);
982 }
983 
984 
985 static const nxt_conn_state_t  nxt_h1p_read_body_state
986     nxt_aligned(64) =
987 {
988     .ready_handler = nxt_h1p_conn_request_body_read,
989     .close_handler = nxt_h1p_conn_request_error,
990     .error_handler = nxt_h1p_conn_request_error,
991 
992     .timer_handler = nxt_h1p_conn_request_timeout,
993     .timer_value = nxt_h1p_conn_request_timer_value,
994     .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout),
995     .timer_autoreset = 1,
996 };
997 
998 
999 static void
1000 nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data)
1001 {
1002     size_t              size, body_rest;
1003     ssize_t             res;
1004     nxt_buf_t           *b;
1005     nxt_conn_t          *c;
1006     nxt_h1proto_t       *h1p;
1007     nxt_http_request_t  *r;
1008     nxt_event_engine_t  *engine;
1009 
1010     c = obj;
1011     h1p = data;
1012 
1013     nxt_debug(task, "h1p conn request body read");
1014 
1015     r = h1p->request;
1016 
1017     engine = task->thread->engine;
1018 
1019     b = c->read;
1020 
1021     if (nxt_buf_is_file(b)) {
1022         body_rest = b->file->size - b->file_end;
1023 
1024         size = nxt_buf_mem_used_size(&b->mem);
1025         size = nxt_min(size, body_rest);
1026 
1027         res = nxt_fd_write(b->file->fd, b->mem.pos, size);
1028         if (nxt_slow_path(res < (ssize_t) size)) {
1029             nxt_h1p_request_error(task, h1p, r);
1030             return;
1031         }
1032 
1033         b->file_end += size;
1034         body_rest -= res;
1035 
1036         b->mem.pos += size;
1037 
1038         if (b->mem.pos == b->mem.free) {
1039             if (body_rest >= (size_t) nxt_buf_mem_size(&b->mem)) {
1040                 b->mem.free = b->mem.start;
1041 
1042             } else {
1043                 /* This required to avoid reading next request. */
1044                 b->mem.free = b->mem.end - body_rest;
1045             }
1046 
1047             b->mem.pos = b->mem.free;
1048         }
1049 
1050     } else {
1051         body_rest = nxt_buf_mem_free_size(&c->read->mem);
1052     }
1053 
1054     nxt_debug(task, "h1p body rest: %uz", body_rest);
1055 
1056     if (body_rest != 0) {
1057         nxt_conn_read(engine, c);
1058 
1059     } else {
1060         if (nxt_buf_is_file(b)) {
1061             b->mem.start = NULL;
1062             b->mem.end = NULL;
1063             b->mem.pos = NULL;
1064             b->mem.free = NULL;
1065         }
1066 
1067         c->read = NULL;
1068 
1069         r->state->ready_handler(task, r, NULL);
1070     }
1071 }
1072 
1073 
1074 static void
1075 nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r)
1076 {
1077     r->local = nxt_conn_local_addr(task, r->proto.h1->conn);
1078 }
1079 
1080 
1081 #define NXT_HTTP_LAST_INFORMATIONAL                                           \
1082     (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1)
1083 
1084 static const nxt_str_t  nxt_http_informational[] = {
1085     nxt_string("HTTP/1.1 100 Continue\r\n"),
1086     nxt_string("HTTP/1.1 101 Switching Protocols\r\n"),
1087 };
1088 
1089 
1090 #define NXT_HTTP_LAST_SUCCESS                                                 \
1091     (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1)
1092 
1093 static const nxt_str_t  nxt_http_success[] = {
1094     nxt_string("HTTP/1.1 200 OK\r\n"),
1095     nxt_string("HTTP/1.1 201 Created\r\n"),
1096     nxt_string("HTTP/1.1 202 Accepted\r\n"),
1097     nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"),
1098     nxt_string("HTTP/1.1 204 No Content\r\n"),
1099     nxt_string("HTTP/1.1 205 Reset Content\r\n"),
1100     nxt_string("HTTP/1.1 206 Partial Content\r\n"),
1101 };
1102 
1103 
1104 #define NXT_HTTP_LAST_REDIRECTION                                             \
1105     (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1)
1106 
1107 static const nxt_str_t  nxt_http_redirection[] = {
1108     nxt_string("HTTP/1.1 300 Multiple Choices\r\n"),
1109     nxt_string("HTTP/1.1 301 Moved Permanently\r\n"),
1110     nxt_string("HTTP/1.1 302 Found\r\n"),
1111     nxt_string("HTTP/1.1 303 See Other\r\n"),
1112     nxt_string("HTTP/1.1 304 Not Modified\r\n"),
1113     nxt_string("HTTP/1.1 307 Temporary Redirect\r\n"),
1114     nxt_string("HTTP/1.1 308 Permanent Redirect\r\n"),
1115 };
1116 
1117 
1118 #define NXT_HTTP_LAST_CLIENT_ERROR                                            \
1119     (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1)
1120 
1121 static const nxt_str_t  nxt_http_client_error[] = {
1122     nxt_string("HTTP/1.1 400 Bad Request\r\n"),
1123     nxt_string("HTTP/1.1 401 Unauthorized\r\n"),
1124     nxt_string("HTTP/1.1 402 Payment Required\r\n"),
1125     nxt_string("HTTP/1.1 403 Forbidden\r\n"),
1126     nxt_string("HTTP/1.1 404 Not Found\r\n"),
1127     nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"),
1128     nxt_string("HTTP/1.1 406 Not Acceptable\r\n"),
1129     nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1130     nxt_string("HTTP/1.1 408 Request Timeout\r\n"),
1131     nxt_string("HTTP/1.1 409 Conflict\r\n"),
1132     nxt_string("HTTP/1.1 410 Gone\r\n"),
1133     nxt_string("HTTP/1.1 411 Length Required\r\n"),
1134     nxt_string("HTTP/1.1 412 Precondition Failed\r\n"),
1135     nxt_string("HTTP/1.1 413 Payload Too Large\r\n"),
1136     nxt_string("HTTP/1.1 414 URI Too Long\r\n"),
1137     nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"),
1138     nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"),
1139     nxt_string("HTTP/1.1 417 Expectation Failed\r\n"),
1140     nxt_string("HTTP/1.1 418\r\n"),
1141     nxt_string("HTTP/1.1 419\r\n"),
1142     nxt_string("HTTP/1.1 420\r\n"),
1143     nxt_string("HTTP/1.1 421\r\n"),
1144     nxt_string("HTTP/1.1 422\r\n"),
1145     nxt_string("HTTP/1.1 423\r\n"),
1146     nxt_string("HTTP/1.1 424\r\n"),
1147     nxt_string("HTTP/1.1 425\r\n"),
1148     nxt_string("HTTP/1.1 426 Upgrade Required\r\n"),
1149     nxt_string("HTTP/1.1 427\r\n"),
1150     nxt_string("HTTP/1.1 428\r\n"),
1151     nxt_string("HTTP/1.1 429\r\n"),
1152     nxt_string("HTTP/1.1 430\r\n"),
1153     nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"),
1154 };
1155 
1156 
1157 #define NXT_HTTP_LAST_NGINX_ERROR                                             \
1158     (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1)
1159 
1160 static const nxt_str_t  nxt_http_nginx_error[] = {
1161     nxt_string("HTTP/1.1 400 "
1162                "The plain HTTP request was sent to HTTPS port\r\n"),
1163 };
1164 
1165 
1166 #define NXT_HTTP_LAST_SERVER_ERROR                                            \
1167     (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1)
1168 
1169 static const nxt_str_t  nxt_http_server_error[] = {
1170     nxt_string("HTTP/1.1 500 Internal Server Error\r\n"),
1171     nxt_string("HTTP/1.1 501 Not Implemented\r\n"),
1172     nxt_string("HTTP/1.1 502 Bad Gateway\r\n"),
1173     nxt_string("HTTP/1.1 503 Service Unavailable\r\n"),
1174     nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"),
1175     nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"),
1176 };
1177 
1178 
1179 #define UNKNOWN_STATUS_LENGTH  nxt_length("HTTP/1.1 65536\r\n")
1180 
1181 static void
1182 nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r,
1183     nxt_work_handler_t body_handler, void *data)
1184 {
1185     u_char              *p;
1186     size_t              size;
1187     nxt_buf_t           *header;
1188     nxt_str_t           unknown_status;
1189     nxt_int_t           conn;
1190     nxt_uint_t          n;
1191     nxt_bool_t          http11;
1192     nxt_conn_t          *c;
1193     nxt_h1proto_t       *h1p;
1194     const nxt_str_t     *status;
1195     nxt_http_field_t    *field;
1196     u_char              buf[UNKNOWN_STATUS_LENGTH];
1197 
1198     static const char   chunked[] = "Transfer-Encoding: chunked\r\n";
1199     static const char   websocket_version[] = "Sec-WebSocket-Version: 13\r\n";
1200 
1201     static const nxt_str_t  connection[3] = {
1202         nxt_string("Connection: close\r\n"),
1203         nxt_string("Connection: keep-alive\r\n"),
1204         nxt_string("Upgrade: websocket\r\n"
1205                    "Connection: Upgrade\r\n"
1206                    "Sec-WebSocket-Accept: "),
1207     };
1208 
1209     nxt_debug(task, "h1p request header send");
1210 
1211     r->header_sent = 1;
1212     h1p = r->proto.h1;
1213     n = r->status;
1214 
1215     if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) {
1216         status = &nxt_http_informational[n - NXT_HTTP_CONTINUE];
1217 
1218     } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) {
1219         status = &nxt_http_success[n - NXT_HTTP_OK];
1220 
1221     } else if (n >= NXT_HTTP_MULTIPLE_CHOICES
1222                && n <= NXT_HTTP_LAST_REDIRECTION)
1223     {
1224         status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES];
1225 
1226     } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) {
1227         status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST];
1228 
1229     } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) {
1230         status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS];
1231 
1232     } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR
1233                && n <= NXT_HTTP_LAST_SERVER_ERROR)
1234     {
1235         status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR];
1236 
1237     } else {
1238         p = nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH,
1239                         "HTTP/1.1 %03d\r\n", n);
1240 
1241         unknown_status.length = p - buf;
1242         unknown_status.start = buf;
1243         status = &unknown_status;
1244     }
1245 
1246     size = status->length;
1247     /* Trailing CRLF at the end of header. */
1248     size += nxt_length("\r\n");
1249 
1250     conn = -1;
1251 
1252     if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) {
1253         h1p->websocket = 1;
1254         h1p->keepalive = 0;
1255         conn = 2;
1256         size += NXT_WEBSOCKET_ACCEPT_SIZE + 2;
1257 
1258     } else {
1259         http11 = (h1p->parser.version.s.minor != '0');
1260 
1261         if (r->resp.content_length == NULL || r->resp.content_length->skip) {
1262 
1263             if (http11) {
1264                 if (n != NXT_HTTP_NOT_MODIFIED
1265                     && n != NXT_HTTP_NO_CONTENT
1266                     && body_handler != NULL
1267                     && !h1p->websocket)
1268                 {
1269                     h1p->chunked = 1;
1270                     size += nxt_length(chunked);
1271                     /* Trailing CRLF will be added by the first chunk header. */
1272                     size -= nxt_length("\r\n");
1273                 }
1274 
1275             } else {
1276                 h1p->keepalive = 0;
1277             }
1278         }
1279 
1280         if (http11 ^ h1p->keepalive) {
1281             conn = h1p->keepalive;
1282         }
1283     }
1284 
1285     if (conn >= 0) {
1286         size += connection[conn].length;
1287     }
1288 
1289     nxt_list_each(field, r->resp.fields) {
1290 
1291         if (!field->skip) {
1292             size += field->name_length + field->value_length;
1293             size += nxt_length(": \r\n");
1294         }
1295 
1296     } nxt_list_loop;
1297 
1298     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1299         size += nxt_length(websocket_version);
1300     }
1301 
1302     header = nxt_http_buf_mem(task, r, size);
1303     if (nxt_slow_path(header == NULL)) {
1304         nxt_h1p_request_error(task, h1p, r);
1305         return;
1306     }
1307 
1308     p = nxt_cpymem(header->mem.free, status->start, status->length);
1309 
1310     nxt_list_each(field, r->resp.fields) {
1311 
1312         if (!field->skip) {
1313             p = nxt_cpymem(p, field->name, field->name_length);
1314             *p++ = ':'; *p++ = ' ';
1315             p = nxt_cpymem(p, field->value, field->value_length);
1316             *p++ = '\r'; *p++ = '\n';
1317         }
1318 
1319     } nxt_list_loop;
1320 
1321     if (conn >= 0) {
1322         p = nxt_cpymem(p, connection[conn].start, connection[conn].length);
1323     }
1324 
1325     if (h1p->websocket) {
1326         nxt_websocket_accept(p, h1p->websocket_key->value);
1327         p += NXT_WEBSOCKET_ACCEPT_SIZE;
1328 
1329         *p++ = '\r'; *p++ = '\n';
1330     }
1331 
1332     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1333         p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version));
1334     }
1335 
1336     if (h1p->chunked) {
1337         p = nxt_cpymem(p, chunked, nxt_length(chunked));
1338         /* Trailing CRLF will be added by the first chunk header. */
1339 
1340     } else {
1341         *p++ = '\r'; *p++ = '\n';
1342     }
1343 
1344     header->mem.free = p;
1345 
1346     h1p->header_size = nxt_buf_mem_used_size(&header->mem);
1347 
1348     c = h1p->conn;
1349 
1350     c->write = header;
1351     h1p->conn_write_tail = &header->next;
1352     c->write_state = &nxt_h1p_request_send_state;
1353 
1354     if (body_handler != NULL) {
1355         /*
1356          * The body handler will run before c->io->write() handler,
1357          * because the latter was inqueued by nxt_conn_write()
1358          * in engine->write_work_queue.
1359          */
1360         nxt_work_queue_add(&task->thread->engine->fast_work_queue,
1361                            body_handler, task, r, data);
1362 
1363     } else {
1364         header->next = nxt_http_buf_last(r);
1365     }
1366 
1367     nxt_conn_write(task->thread->engine, c);
1368 
1369     if (h1p->websocket) {
1370         nxt_h1p_websocket_first_frame_start(task, r, c->read);
1371     }
1372 }
1373 
1374 
1375 void
1376 nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_bool_t all)
1377 {
1378     size_t            size;
1379     nxt_buf_t         *b, *in, *next;
1380     nxt_conn_t        *c;
1381 
1382     nxt_debug(task, "h1p complete buffers");
1383 
1384     b = h1p->buffers;
1385     c = h1p->conn;
1386     in = c->read;
1387 
1388     if (b != NULL) {
1389         if (in == NULL) {
1390             /* A request with large body. */
1391             in = b;
1392             c->read = in;
1393 
1394             b = in->next;
1395             in->next = NULL;
1396         }
1397 
1398         while (b != NULL) {
1399             next = b->next;
1400             b->next = NULL;
1401 
1402             b->completion_handler(task, b, b->parent);
1403 
1404             b = next;
1405         }
1406 
1407         h1p->buffers = NULL;
1408         h1p->nbuffers = 0;
1409     }
1410 
1411     if (in != NULL) {
1412         size = nxt_buf_mem_used_size(&in->mem);
1413 
1414         if (size == 0 || all) {
1415             in->completion_handler(task, in, in->parent);
1416 
1417             c->read = NULL;
1418         }
1419     }
1420 }
1421 
1422 
1423 static const nxt_conn_state_t  nxt_h1p_request_send_state
1424     nxt_aligned(64) =
1425 {
1426     .ready_handler = nxt_h1p_conn_sent,
1427     .error_handler = nxt_h1p_conn_request_error,
1428 
1429     .timer_handler = nxt_h1p_conn_request_send_timeout,
1430     .timer_value = nxt_h1p_conn_request_timer_value,
1431     .timer_data = offsetof(nxt_socket_conf_t, send_timeout),
1432     .timer_autoreset = 1,
1433 };
1434 
1435 
1436 static void
1437 nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1438 {
1439     nxt_conn_t     *c;
1440     nxt_h1proto_t  *h1p;
1441 
1442     nxt_debug(task, "h1p request send");
1443 
1444     h1p = r->proto.h1;
1445     c = h1p->conn;
1446 
1447     if (h1p->chunked) {
1448         out = nxt_h1p_chunk_create(task, r, out);
1449         if (nxt_slow_path(out == NULL)) {
1450             nxt_h1p_request_error(task, h1p, r);
1451             return;
1452         }
1453     }
1454 
1455     if (c->write == NULL) {
1456         c->write = out;
1457         c->write_state = &nxt_h1p_request_send_state;
1458 
1459         nxt_conn_write(task->thread->engine, c);
1460 
1461     } else {
1462         *h1p->conn_write_tail = out;
1463     }
1464 
1465     while (out->next != NULL) {
1466         out = out->next;
1467     }
1468 
1469     h1p->conn_write_tail = &out->next;
1470 }
1471 
1472 
1473 static nxt_buf_t *
1474 nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1475 {
1476     nxt_off_t          size;
1477     nxt_buf_t          *b, **prev, *header, *tail;
1478 
1479     const size_t       chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN;
1480     static const char  tail_chunk[] = "\r\n0\r\n\r\n";
1481 
1482     size = 0;
1483     prev = &out;
1484 
1485     for (b = out; b != NULL; b = b->next) {
1486 
1487         if (nxt_buf_is_last(b)) {
1488             tail = nxt_http_buf_mem(task, r, sizeof(tail_chunk));
1489             if (nxt_slow_path(tail == NULL)) {
1490                 return NULL;
1491             }
1492 
1493             *prev = tail;
1494             tail->next = b;
1495             /*
1496              * The tail_chunk size with trailing zero is 8 bytes, so
1497              * memcpy may be inlined with just single 8 byte move operation.
1498              */
1499             nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk));
1500             tail->mem.free += nxt_length(tail_chunk);
1501 
1502             break;
1503         }
1504 
1505         size += nxt_buf_used_size(b);
1506         prev = &b->next;
1507     }
1508 
1509     if (size == 0) {
1510         return out;
1511     }
1512 
1513     header = nxt_http_buf_mem(task, r, chunk_size);
1514     if (nxt_slow_path(header == NULL)) {
1515         return NULL;
1516     }
1517 
1518     header->next = out;
1519     header->mem.free = nxt_sprintf(header->mem.free, header->mem.end,
1520                                    "\r\n%xO\r\n", size);
1521     return header;
1522 }
1523 
1524 
1525 static nxt_off_t
1526 nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto)
1527 {
1528     nxt_off_t      sent;
1529     nxt_h1proto_t  *h1p;
1530 
1531     h1p = proto.h1;
1532 
1533     sent = h1p->conn->sent - h1p->header_size;
1534 
1535     return (sent > 0) ? sent : 0;
1536 }
1537 
1538 
1539 static void
1540 nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
1541     nxt_buf_t *last)
1542 {
1543     nxt_buf_t         *b;
1544     nxt_conn_t        *c;
1545     nxt_h1proto_t     *h1p;
1546     nxt_work_queue_t  *wq;
1547 
1548     nxt_debug(task, "h1p request discard");
1549 
1550     h1p = r->proto.h1;
1551     h1p->keepalive = 0;
1552 
1553     c = h1p->conn;
1554     b = c->write;
1555     c->write = NULL;
1556 
1557     wq = &task->thread->engine->fast_work_queue;
1558 
1559     nxt_sendbuf_drain(task, wq, b);
1560     nxt_sendbuf_drain(task, wq, last);
1561 }
1562 
1563 
1564 static void
1565 nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data)
1566 {
1567     nxt_h1proto_t       *h1p;
1568     nxt_http_request_t  *r;
1569 
1570     h1p = data;
1571 
1572     nxt_debug(task, "h1p conn request error");
1573 
1574     r = h1p->request;
1575 
1576     if (nxt_slow_path(r == NULL)) {
1577         nxt_h1p_shutdown(task, h1p->conn);
1578         return;
1579     }
1580 
1581     if (r->fields == NULL) {
1582         (void) nxt_h1p_header_process(task, h1p, r);
1583     }
1584 
1585     if (r->status == 0) {
1586         r->status = NXT_HTTP_BAD_REQUEST;
1587     }
1588 
1589     nxt_h1p_request_error(task, h1p, r);
1590 }
1591 
1592 
1593 static void
1594 nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
1595 {
1596     nxt_conn_t          *c;
1597     nxt_timer_t         *timer;
1598     nxt_h1proto_t       *h1p;
1599     nxt_http_request_t  *r;
1600 
1601     timer = obj;
1602 
1603     nxt_debug(task, "h1p conn request timeout");
1604 
1605     c = nxt_read_timer_conn(timer);
1606     c->block_read = 1;
1607     /*
1608      * Disable SO_LINGER off during socket closing
1609      * to send "408 Request Timeout" error response.
1610      */
1611     c->socket.timedout = 0;
1612 
1613     h1p = c->socket.data;
1614     h1p->keepalive = 0;
1615     r = h1p->request;
1616 
1617     if (r->fields == NULL) {
1618         (void) nxt_h1p_header_process(task, h1p, r);
1619     }
1620 
1621     nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT);
1622 }
1623 
1624 
1625 static void
1626 nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)
1627 {
1628     nxt_conn_t     *c;
1629     nxt_timer_t    *timer;
1630     nxt_h1proto_t  *h1p;
1631 
1632     timer = obj;
1633 
1634     nxt_debug(task, "h1p conn request send timeout");
1635 
1636     c = nxt_write_timer_conn(timer);
1637     c->block_write = 1;
1638     h1p = c->socket.data;
1639 
1640     nxt_h1p_request_error(task, h1p, h1p->request);
1641 }
1642 
1643 
1644 nxt_msec_t
1645 nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data)
1646 {
1647     nxt_h1proto_t  *h1p;
1648 
1649     h1p = c->socket.data;
1650 
1651     return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data);
1652 }
1653 
1654 
1655 nxt_inline void
1656 nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
1657     nxt_http_request_t *r)
1658 {
1659     h1p->keepalive = 0;
1660 
1661     r->state->error_handler(task, r, h1p);
1662 }
1663 
1664 
1665 static void
1666 nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
1667     nxt_socket_conf_joint_t *joint)
1668 {
1669     nxt_conn_t     *c;
1670     nxt_h1proto_t  *h1p;
1671 
1672     nxt_debug(task, "h1p request close");
1673 
1674     h1p = proto.h1;
1675     h1p->keepalive &= !h1p->request->inconsistent;
1676     h1p->request = NULL;
1677 
1678     nxt_router_conf_release(task, joint);
1679 
1680     c = h1p->conn;
1681     task = &c->task;
1682     c->socket.task = task;
1683     c->read_timer.task = task;
1684     c->write_timer.task = task;
1685 
1686     if (h1p->keepalive) {
1687         nxt_h1p_keepalive(task, h1p, c);
1688 
1689     } else {
1690         nxt_h1p_shutdown(task, c);
1691     }
1692 }
1693 
1694 
1695 static void
1696 nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data)
1697 {
1698     nxt_conn_t          *c;
1699     nxt_event_engine_t  *engine;
1700 
1701     c = obj;
1702 
1703     nxt_debug(task, "h1p conn sent");
1704 
1705     engine = task->thread->engine;
1706 
1707     c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
1708 
1709     if (c->write != NULL) {
1710         nxt_conn_write(engine, c);
1711     }
1712 }
1713 
1714 
1715 static void
1716 nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
1717 {
1718     nxt_conn_t  *c;
1719 
1720     c = obj;
1721 
1722     nxt_debug(task, "h1p conn close");
1723 
1724     nxt_queue_remove(&c->link);
1725 
1726     nxt_h1p_shutdown(task, c);
1727 }
1728 
1729 
1730 static void
1731 nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
1732 {
1733     nxt_conn_t  *c;
1734 
1735     c = obj;
1736 
1737     nxt_debug(task, "h1p conn error");
1738 
1739     nxt_queue_remove(&c->link);
1740 
1741     nxt_h1p_shutdown(task, c);
1742 }
1743 
1744 
1745 static nxt_msec_t
1746 nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data)
1747 {
1748     nxt_socket_conf_joint_t  *joint;
1749 
1750     joint = c->listen->socket.data;
1751 
1752     return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
1753 }
1754 
1755 
1756 static void
1757 nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
1758 {
1759     size_t              size;
1760     nxt_buf_t           *in;
1761     nxt_event_engine_t  *engine;
1762 
1763     nxt_debug(task, "h1p keepalive");
1764 
1765     if (!c->tcp_nodelay) {
1766         nxt_conn_tcp_nodelay_on(task, c);
1767     }
1768 
1769     nxt_h1p_complete_buffers(task, h1p, 0);
1770 
1771     in = c->read;
1772 
1773     nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn));
1774 
1775     c->sent = 0;
1776 
1777     engine = task->thread->engine;
1778     nxt_queue_insert_head(&engine->idle_connections, &c->link);
1779 
1780     if (in == NULL) {
1781         c->read_state = &nxt_h1p_keepalive_state;
1782 
1783         nxt_conn_read(engine, c);
1784 
1785     } else {
1786         size = nxt_buf_mem_used_size(&in->mem);
1787 
1788         nxt_debug(task, "h1p pipelining");
1789 
1790         nxt_memmove(in->mem.start, in->mem.pos, size);
1791 
1792         in->mem.pos = in->mem.start;
1793         in->mem.free = in->mem.start + size;
1794 
1795         nxt_h1p_conn_request_init(task, c, c->socket.data);
1796     }
1797 }
1798 
1799 
1800 static const nxt_conn_state_t  nxt_h1p_keepalive_state
1801     nxt_aligned(64) =
1802 {
1803     .ready_handler = nxt_h1p_conn_request_init,
1804     .close_handler = nxt_h1p_conn_close,
1805     .error_handler = nxt_h1p_conn_error,
1806 
1807     .io_read_handler = nxt_h1p_idle_io_read_handler,
1808 
1809     .timer_handler = nxt_h1p_idle_timeout,
1810     .timer_value = nxt_h1p_conn_timer_value,
1811     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
1812     .timer_autoreset = 1,
1813 };
1814 
1815 
1816 const nxt_conn_state_t  nxt_h1p_idle_close_state
1817     nxt_aligned(64) =
1818 {
1819     .close_handler = nxt_h1p_idle_close,
1820 };
1821 
1822 
1823 static void
1824 nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
1825 {
1826     nxt_conn_t  *c;
1827 
1828     c = obj;
1829 
1830     nxt_debug(task, "h1p idle close");
1831 
1832     nxt_h1p_idle_response(task, c);
1833 }
1834 
1835 
1836 static void
1837 nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
1838 {
1839     nxt_conn_t   *c;
1840     nxt_timer_t  *timer;
1841 
1842     timer = obj;
1843 
1844     nxt_debug(task, "h1p idle timeout");
1845 
1846     c = nxt_read_timer_conn(timer);
1847     c->block_read = 1;
1848 
1849     nxt_queue_remove(&c->link);
1850 
1851     nxt_h1p_idle_response(task, c);
1852 }
1853 
1854 
1855 #define NXT_H1P_IDLE_TIMEOUT                                                  \
1856      "HTTP/1.1 408 Request Timeout\r\n"                                       \
1857      "Server: " NXT_SERVER "\r\n"                                             \
1858      "Connection: close\r\n"                                                  \
1859      "Content-Length: 0\r\n"                                                  \
1860      "Date: "
1861 
1862 
1863 static void
1864 nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c)
1865 {
1866     u_char         *p;
1867     size_t         size;
1868     nxt_buf_t      *out, *last;
1869     nxt_h1proto_t  *h1p;
1870 
1871     size = nxt_length(NXT_H1P_IDLE_TIMEOUT)
1872            + nxt_http_date_cache.size
1873            + nxt_length("\r\n\r\n");
1874 
1875     out = nxt_buf_mem_alloc(c->mem_pool, size, 0);
1876     if (nxt_slow_path(out == NULL)) {
1877         goto fail;
1878     }
1879 
1880     p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT,
1881                    nxt_length(NXT_H1P_IDLE_TIMEOUT));
1882 
1883     p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p);
1884 
1885     out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4);
1886 
1887     last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE);
1888     if (nxt_slow_path(last == NULL)) {
1889         goto fail;
1890     }
1891 
1892     out->next = last;
1893     nxt_buf_set_sync(last);
1894     nxt_buf_set_last(last);
1895 
1896     last->completion_handler = nxt_h1p_idle_response_sent;
1897     last->parent = c;
1898 
1899     h1p = c->socket.data;
1900     h1p->conn_write_tail = &last->next;
1901 
1902     c->write = out;
1903     c->write_state = &nxt_h1p_timeout_response_state;
1904 
1905     nxt_conn_write(task->thread->engine, c);
1906     return;
1907 
1908 fail:
1909 
1910     nxt_h1p_shutdown(task, c);
1911 }
1912 
1913 
1914 static const nxt_conn_state_t  nxt_h1p_timeout_response_state
1915     nxt_aligned(64) =
1916 {
1917     .ready_handler = nxt_h1p_conn_sent,
1918     .error_handler = nxt_h1p_idle_response_error,
1919 
1920     .timer_handler = nxt_h1p_idle_response_timeout,
1921     .timer_value = nxt_h1p_idle_response_timer_value,
1922 };
1923 
1924 
1925 static void
1926 nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data)
1927 {
1928     nxt_conn_t  *c;
1929 
1930     c = data;
1931 
1932     nxt_debug(task, "h1p idle timeout response sent");
1933 
1934     nxt_h1p_shutdown(task, c);
1935 }
1936 
1937 
1938 static void
1939 nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, void *data)
1940 {
1941     nxt_conn_t  *c;
1942 
1943     c = obj;
1944 
1945     nxt_debug(task, "h1p response error");
1946 
1947     nxt_h1p_shutdown(task, c);
1948 }
1949 
1950 
1951 static void
1952 nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data)
1953 {
1954     nxt_conn_t   *c;
1955     nxt_timer_t  *timer;
1956 
1957     timer = obj;
1958 
1959     nxt_debug(task, "h1p idle timeout response timeout");
1960 
1961     c = nxt_read_timer_conn(timer);
1962     c->block_write = 1;
1963 
1964     nxt_h1p_shutdown(task, c);
1965 }
1966 
1967 
1968 static nxt_msec_t
1969 nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data)
1970 {
1971     return 10 * 1000;
1972 }
1973 
1974 
1975 static void
1976 nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c)
1977 {
1978     nxt_timer_t    *timer;
1979     nxt_h1proto_t  *h1p;
1980 
1981     nxt_debug(task, "h1p shutdown");
1982 
1983     h1p = c->socket.data;
1984 
1985     if (h1p != NULL) {
1986         nxt_h1p_complete_buffers(task, h1p, 1);
1987 
1988         if (nxt_slow_path(h1p->websocket_timer != NULL)) {
1989             timer = &h1p->websocket_timer->timer;
1990 
1991             if (timer->handler != nxt_h1p_conn_ws_shutdown) {
1992                 timer->handler = nxt_h1p_conn_ws_shutdown;
1993                 nxt_timer_add(task->thread->engine, timer, 0);
1994 
1995             } else {
1996                 nxt_debug(task, "h1p already scheduled ws shutdown");
1997             }
1998 
1999             return;
2000         }
2001     }
2002 
2003     nxt_h1p_closing(task, c);
2004 }
2005 
2006 
2007 static void
2008 nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data)
2009 {
2010     nxt_timer_t                *timer;
2011     nxt_h1p_websocket_timer_t  *ws_timer;
2012 
2013     nxt_debug(task, "h1p conn ws shutdown");
2014 
2015     timer = obj;
2016     ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer);
2017 
2018     nxt_h1p_closing(task, ws_timer->h1p->conn);
2019 }
2020 
2021 
2022 static void
2023 nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c)
2024 {
2025     nxt_debug(task, "h1p closing");
2026 
2027     c->socket.data = NULL;
2028 
2029 #if (NXT_TLS)
2030 
2031     if (c->u.tls != NULL) {
2032         c->write_state = &nxt_h1p_shutdown_state;
2033 
2034         c->io->shutdown(task, c, NULL);
2035         return;
2036     }
2037 
2038 #endif
2039 
2040     nxt_h1p_conn_closing(task, c, NULL);
2041 }
2042 
2043 
2044 #if (NXT_TLS)
2045 
2046 static const nxt_conn_state_t  nxt_h1p_shutdown_state
2047     nxt_aligned(64) =
2048 {
2049     .ready_handler = nxt_h1p_conn_closing,
2050     .close_handler = nxt_h1p_conn_closing,
2051     .error_handler = nxt_h1p_conn_closing,
2052 };
2053 
2054 #endif
2055 
2056 
2057 static void
2058 nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data)
2059 {
2060     nxt_conn_t  *c;
2061 
2062     c = obj;
2063 
2064     nxt_debug(task, "h1p conn closing");
2065 
2066     c->write_state = &nxt_h1p_close_state;
2067 
2068     nxt_conn_close(task->thread->engine, c);
2069 }
2070 
2071 
2072 static const nxt_conn_state_t  nxt_h1p_close_state
2073     nxt_aligned(64) =
2074 {
2075     .ready_handler = nxt_h1p_conn_free,
2076 };
2077 
2078 
2079 static void
2080 nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data)
2081 {
2082     nxt_conn_t          *c;
2083     nxt_listen_event_t  *lev;
2084     nxt_event_engine_t  *engine;
2085 
2086     c = obj;
2087 
2088     nxt_debug(task, "h1p conn free");
2089 
2090     engine = task->thread->engine;
2091 
2092     nxt_sockaddr_cache_free(engine, c);
2093 
2094     lev = c->listen;
2095 
2096     nxt_conn_free(task, c);
2097 
2098     nxt_router_listen_event_release(&engine->task, lev, NULL);
2099 }
2100 
2101 
2102 static void
2103 nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer)
2104 {
2105     nxt_mp_t            *mp;
2106     nxt_int_t           ret;
2107     nxt_conn_t          *c, *client;
2108     nxt_h1proto_t       *h1p;
2109     nxt_fd_event_t      *socket;
2110     nxt_work_queue_t    *wq;
2111     nxt_http_request_t  *r;
2112 
2113     nxt_debug(task, "h1p peer connect");
2114 
2115     peer->status = NXT_HTTP_UNSET;
2116     r = peer->request;
2117 
2118     mp = nxt_mp_create(1024, 128, 256, 32);
2119 
2120     if (nxt_slow_path(mp == NULL)) {
2121         goto fail;
2122     }
2123 
2124     h1p = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t));
2125     if (nxt_slow_path(h1p == NULL)) {
2126         goto fail;
2127     }
2128 
2129     ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool);
2130     if (nxt_slow_path(ret != NXT_OK)) {
2131         goto fail;
2132     }
2133 
2134     c = nxt_conn_create(mp, task);
2135     if (nxt_slow_path(c == NULL)) {
2136         goto fail;
2137     }
2138 
2139     c->mem_pool = mp;
2140     h1p->conn = c;
2141 
2142     peer->proto.h1 = h1p;
2143     h1p->request = r;
2144 
2145     c->socket.data = peer;
2146     c->remote = peer->server->sockaddr;
2147 
2148     c->socket.write_ready = 1;
2149     c->write_state = &nxt_h1p_peer_connect_state;
2150 
2151     /*
2152      * TODO: queues should be implemented via client proto interface.
2153      */
2154     client = r->proto.h1->conn;
2155 
2156     socket = &client->socket;
2157     wq = socket->read_work_queue;
2158     c->read_work_queue = wq;
2159     c->socket.read_work_queue = wq;
2160     c->read_timer.work_queue = wq;
2161 
2162     wq = socket->write_work_queue;
2163     c->write_work_queue = wq;
2164     c->socket.write_work_queue = wq;
2165     c->write_timer.work_queue = wq;
2166     /* TODO END */
2167 
2168     nxt_conn_connect(task->thread->engine, c);
2169 
2170     return;
2171 
2172 fail:
2173 
2174     peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR;
2175 
2176     r->state->error_handler(task, r, peer);
2177 }
2178 
2179 
2180 static const nxt_conn_state_t  nxt_h1p_peer_connect_state
2181     nxt_aligned(64) =
2182 {
2183     .ready_handler = nxt_h1p_peer_connected,
2184     .close_handler = nxt_h1p_peer_refused,
2185     .error_handler = nxt_h1p_peer_error,
2186 
2187     .timer_handler = nxt_h1p_peer_send_timeout,
2188     .timer_value = nxt_h1p_peer_timer_value,
2189     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2190 };
2191 
2192 
2193 static void
2194 nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data)
2195 {
2196     nxt_http_peer_t     *peer;
2197     nxt_http_request_t  *r;
2198 
2199     peer = data;
2200 
2201     nxt_debug(task, "h1p peer connected");
2202 
2203     r = peer->request;
2204     r->state->ready_handler(task, r, peer);
2205 }
2206 
2207 
2208 static void
2209 nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data)
2210 {
2211     nxt_http_peer_t     *peer;
2212     nxt_http_request_t  *r;
2213 
2214     peer = data;
2215 
2216     nxt_debug(task, "h1p peer refused");
2217 
2218     //peer->status = NXT_HTTP_SERVICE_UNAVAILABLE;
2219     peer->status = NXT_HTTP_BAD_GATEWAY;
2220 
2221     r = peer->request;
2222     r->state->error_handler(task, r, peer);
2223 }
2224 
2225 
2226 static void
2227 nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer)
2228 {
2229     u_char              *p;
2230     size_t              size;
2231     nxt_buf_t           *header, *body;
2232     nxt_conn_t          *c;
2233     nxt_http_field_t    *field;
2234     nxt_http_request_t  *r;
2235 
2236     nxt_debug(task, "h1p peer header send");
2237 
2238     r = peer->request;
2239 
2240     size = r->method->length + sizeof(" ") + r->target.length
2241            + sizeof(" HTTP/1.1\r\n")
2242            + sizeof("Connection: close\r\n")
2243            + sizeof("\r\n");
2244 
2245     nxt_list_each(field, r->fields) {
2246 
2247         if (!field->hopbyhop) {
2248             size += field->name_length + field->value_length;
2249             size += nxt_length(": \r\n");
2250         }
2251 
2252     } nxt_list_loop;
2253 
2254     header = nxt_http_buf_mem(task, r, size);
2255     if (nxt_slow_path(header == NULL)) {
2256         r->state->error_handler(task, r, peer);
2257         return;
2258     }
2259 
2260     p = header->mem.free;
2261 
2262     p = nxt_cpymem(p, r->method->start, r->method->length);
2263     *p++ = ' ';
2264     p = nxt_cpymem(p, r->target.start, r->target.length);
2265     p = nxt_cpymem(p, " HTTP/1.1\r\n", 11);
2266     p = nxt_cpymem(p, "Connection: close\r\n", 19);
2267 
2268     nxt_list_each(field, r->fields) {
2269 
2270         if (!field->hopbyhop) {
2271             p = nxt_cpymem(p, field->name, field->name_length);
2272             *p++ = ':'; *p++ = ' ';
2273             p = nxt_cpymem(p, field->value, field->value_length);
2274             *p++ = '\r'; *p++ = '\n';
2275         }
2276 
2277     } nxt_list_loop;
2278 
2279     *p++ = '\r'; *p++ = '\n';
2280     header->mem.free = p;
2281     size = p - header->mem.pos;
2282 
2283     c = peer->proto.h1->conn;
2284     c->write = header;
2285     c->write_state = &nxt_h1p_peer_header_send_state;
2286 
2287     if (r->body != NULL) {
2288         if (nxt_buf_is_file(r->body)) {
2289             body = nxt_buf_file_alloc(r->mem_pool, 0, 0);
2290 
2291         } else {
2292             body = nxt_buf_mem_alloc(r->mem_pool, 0, 0);
2293         }
2294 
2295         if (nxt_slow_path(body == NULL)) {
2296             r->state->error_handler(task, r, peer);
2297             return;
2298         }
2299 
2300         header->next = body;
2301 
2302         if (nxt_buf_is_file(r->body)) {
2303             body->file = r->body->file;
2304             body->file_end = r->body->file_end;
2305 
2306         } else {
2307             body->mem = r->body->mem;
2308         }
2309 
2310         size += nxt_buf_used_size(body);
2311 
2312 //        nxt_mp_retain(r->mem_pool);
2313     }
2314 
2315     if (size > 16384) {
2316         /* Use proxy_send_timeout instead of proxy_timeout. */
2317         c->write_state = &nxt_h1p_peer_header_body_send_state;
2318     }
2319 
2320     nxt_conn_write(task->thread->engine, c);
2321 }
2322 
2323 
2324 static const nxt_conn_state_t  nxt_h1p_peer_header_send_state
2325     nxt_aligned(64) =
2326 {
2327     .ready_handler = nxt_h1p_peer_header_sent,
2328     .error_handler = nxt_h1p_peer_error,
2329 
2330     .timer_handler = nxt_h1p_peer_send_timeout,
2331     .timer_value = nxt_h1p_peer_timer_value,
2332     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2333 };
2334 
2335 
2336 static const nxt_conn_state_t  nxt_h1p_peer_header_body_send_state
2337     nxt_aligned(64) =
2338 {
2339     .ready_handler = nxt_h1p_peer_header_sent,
2340     .error_handler = nxt_h1p_peer_error,
2341 
2342     .timer_handler = nxt_h1p_peer_send_timeout,
2343     .timer_value = nxt_h1p_peer_timer_value,
2344     .timer_data = offsetof(nxt_socket_conf_t, proxy_send_timeout),
2345     .timer_autoreset = 1,
2346 };
2347 
2348 
2349 static void
2350 nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data)
2351 {
2352     nxt_conn_t          *c;
2353     nxt_http_peer_t     *peer;
2354     nxt_http_request_t  *r;
2355     nxt_event_engine_t  *engine;
2356 
2357     c = obj;
2358     peer = data;
2359 
2360     nxt_debug(task, "h1p peer header sent");
2361 
2362     engine = task->thread->engine;
2363 
2364     c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
2365 
2366     if (c->write != NULL) {
2367         nxt_conn_write(engine, c);
2368         return;
2369     }
2370 
2371     r = peer->request;
2372     r->state->ready_handler(task, r, peer);
2373 }
2374 
2375 
2376 static void
2377 nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer)
2378 {
2379     nxt_conn_t  *c;
2380 
2381     nxt_debug(task, "h1p peer header read");
2382 
2383     c = peer->proto.h1->conn;
2384 
2385     if (c->write_timer.enabled) {
2386         c->read_state = &nxt_h1p_peer_header_read_state;
2387 
2388     } else {
2389         c->read_state = &nxt_h1p_peer_header_read_timer_state;
2390     }
2391 
2392     nxt_conn_read(task->thread->engine, c);
2393 }
2394 
2395 
2396 static const nxt_conn_state_t  nxt_h1p_peer_header_read_state
2397     nxt_aligned(64) =
2398 {
2399     .ready_handler = nxt_h1p_peer_header_read_done,
2400     .close_handler = nxt_h1p_peer_closed,
2401     .error_handler = nxt_h1p_peer_error,
2402 
2403     .io_read_handler = nxt_h1p_peer_io_read_handler,
2404 };
2405 
2406 
2407 static const nxt_conn_state_t  nxt_h1p_peer_header_read_timer_state
2408     nxt_aligned(64) =
2409 {
2410     .ready_handler = nxt_h1p_peer_header_read_done,
2411     .close_handler = nxt_h1p_peer_closed,
2412     .error_handler = nxt_h1p_peer_error,
2413 
2414     .io_read_handler = nxt_h1p_peer_io_read_handler,
2415 
2416     .timer_handler = nxt_h1p_peer_read_timeout,
2417     .timer_value = nxt_h1p_peer_timer_value,
2418     .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout),
2419 };
2420 
2421 
2422 static ssize_t
2423 nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c)
2424 {
2425     size_t              size;
2426     ssize_t             n;
2427     nxt_buf_t           *b;
2428     nxt_http_peer_t     *peer;
2429     nxt_socket_conf_t   *skcf;
2430     nxt_http_request_t  *r;
2431 
2432     peer = c->socket.data;
2433     r = peer->request;
2434     b = c->read;
2435 
2436     if (b == NULL) {
2437         skcf = r->conf->socket_conf;
2438 
2439         size = (peer->header_received) ? skcf->proxy_buffer_size
2440                                        : skcf->proxy_header_buffer_size;
2441 
2442         nxt_debug(task, "h1p peer io read: %z", size);
2443 
2444         b = nxt_http_proxy_buf_mem_alloc(task, r, size);
2445         if (nxt_slow_path(b == NULL)) {
2446             c->socket.error = NXT_ENOMEM;
2447             return NXT_ERROR;
2448         }
2449     }
2450 
2451     n = c->io->recvbuf(c, b);
2452 
2453     if (n > 0) {
2454         c->read = b;
2455 
2456     } else {
2457         c->read = NULL;
2458         nxt_http_proxy_buf_mem_free(task, r, b);
2459     }
2460 
2461     return n;
2462 }
2463 
2464 
2465 static void
2466 nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, void *data)
2467 {
2468     nxt_int_t           ret;
2469     nxt_buf_t           *b;
2470     nxt_conn_t          *c;
2471     nxt_h1proto_t       *h1p;
2472     nxt_http_peer_t     *peer;
2473     nxt_http_request_t  *r;
2474     nxt_event_engine_t  *engine;
2475 
2476     c = obj;
2477     peer = data;
2478 
2479     nxt_debug(task, "h1p peer header read done");
2480 
2481     b = c->read;
2482 
2483     ret = nxt_h1p_peer_header_parse(peer, &b->mem);
2484 
2485     r = peer->request;
2486 
2487     ret = nxt_expect(NXT_DONE, ret);
2488 
2489     if (ret != NXT_AGAIN) {
2490         engine = task->thread->engine;
2491         nxt_timer_disable(engine, &c->write_timer);
2492         nxt_timer_disable(engine, &c->read_timer);
2493     }
2494 
2495     switch (ret) {
2496 
2497     case NXT_DONE:
2498         peer->fields = peer->proto.h1->parser.fields;
2499 
2500         ret = nxt_http_fields_process(peer->fields,
2501                                       &nxt_h1p_peer_fields_hash, r);
2502         if (nxt_slow_path(ret != NXT_OK)) {
2503             peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR;
2504             break;
2505         }
2506 
2507         c->read = NULL;
2508 
2509         peer->header_received = 1;
2510 
2511         h1p = peer->proto.h1;
2512 
2513         if (h1p->chunked) {
2514             if (r->resp.content_length != NULL) {
2515                 peer->status = NXT_HTTP_BAD_GATEWAY;
2516                 break;
2517             }
2518 
2519             h1p->chunked_parse.mem_pool = c->mem_pool;
2520 
2521         } else if (r->resp.content_length_n > 0) {
2522             h1p->remainder = r->resp.content_length_n;
2523         }
2524 
2525         if (nxt_buf_mem_used_size(&b->mem) != 0) {
2526             nxt_h1p_peer_body_process(task, peer, b);
2527             return;
2528         }
2529 
2530         r->state->ready_handler(task, r, peer);
2531         return;
2532 
2533     case NXT_AGAIN:
2534         if (nxt_buf_mem_free_size(&b->mem) != 0) {
2535             nxt_conn_read(task->thread->engine, c);
2536             return;
2537         }
2538 
2539         /* Fall through. */
2540 
2541     default:
2542     case NXT_ERROR:
2543     case NXT_HTTP_PARSE_INVALID:
2544     case NXT_HTTP_PARSE_UNSUPPORTED_VERSION:
2545     case NXT_HTTP_PARSE_TOO_LARGE_FIELD:
2546         peer->status = NXT_HTTP_BAD_GATEWAY;
2547         break;
2548     }
2549 
2550     nxt_http_proxy_buf_mem_free(task, r, b);
2551 
2552     r->state->error_handler(task, r, peer);
2553 }
2554 
2555 
2556 static nxt_int_t
2557 nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm)
2558 {
2559     u_char     *p;
2560     size_t     length;
2561     nxt_int_t  status;
2562 
2563     if (peer->status < 0) {
2564         length = nxt_buf_mem_used_size(bm);
2565 
2566         if (nxt_slow_path(length < 12)) {
2567             return NXT_AGAIN;
2568         }
2569 
2570         p = bm->pos;
2571 
2572         if (nxt_slow_path(nxt_memcmp(p, "HTTP/1.", 7) != 0
2573                           || (p[7] != '0' && p[7] != '1')))
2574         {
2575             return NXT_ERROR;
2576         }
2577 
2578         status = nxt_int_parse(&p[9], 3);
2579 
2580         if (nxt_slow_path(status < 0)) {
2581             return NXT_ERROR;
2582         }
2583 
2584         p += 12;
2585         length -= 12;
2586 
2587         p = nxt_memchr(p, '\n', length);
2588 
2589         if (nxt_slow_path(p == NULL)) {
2590             return NXT_AGAIN;
2591         }
2592 
2593         bm->pos = p + 1;
2594         peer->status = status;
2595     }
2596 
2597     return nxt_http_parse_fields(&peer->proto.h1->parser, bm);
2598 }
2599 
2600 
2601 static void
2602 nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer)
2603 {
2604     nxt_conn_t  *c;
2605 
2606     nxt_debug(task, "h1p peer read");
2607 
2608     c = peer->proto.h1->conn;
2609     c->read_state = &nxt_h1p_peer_read_state;
2610 
2611     nxt_conn_read(task->thread->engine, c);
2612 }
2613 
2614 
2615 static const nxt_conn_state_t  nxt_h1p_peer_read_state
2616     nxt_aligned(64) =
2617 {
2618     .ready_handler = nxt_h1p_peer_read_done,
2619     .close_handler = nxt_h1p_peer_closed,
2620     .error_handler = nxt_h1p_peer_error,
2621 
2622     .io_read_handler = nxt_h1p_peer_io_read_handler,
2623 
2624     .timer_handler = nxt_h1p_peer_read_timeout,
2625     .timer_value = nxt_h1p_peer_timer_value,
2626     .timer_data = offsetof(nxt_socket_conf_t, proxy_read_timeout),
2627     .timer_autoreset = 1,
2628 };
2629 
2630 
2631 static void
2632 nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data)
2633 {
2634     nxt_buf_t        *out;
2635     nxt_conn_t       *c;
2636     nxt_http_peer_t  *peer;
2637 
2638     c = obj;
2639     peer = data;
2640 
2641     nxt_debug(task, "h1p peer read done");
2642 
2643     out = c->read;
2644     c->read = NULL;
2645 
2646     nxt_h1p_peer_body_process(task, peer, out);
2647 }
2648 
2649 
2650 static void
2651 nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer,
2652     nxt_buf_t *out)
2653 {
2654     size_t              length;
2655     nxt_h1proto_t       *h1p;
2656     nxt_http_request_t  *r;
2657 
2658     h1p = peer->proto.h1;
2659 
2660     if (h1p->chunked) {
2661         out = nxt_http_chunk_parse(task, &h1p->chunked_parse, out);
2662 
2663         if (h1p->chunked_parse.chunk_error || h1p->chunked_parse.error) {
2664             peer->status = NXT_HTTP_BAD_GATEWAY;
2665             r = peer->request;
2666             r->state->error_handler(task, r, peer);
2667             return;
2668         }
2669 
2670         if (h1p->chunked_parse.last) {
2671             nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request));
2672             peer->closed = 1;
2673         }
2674 
2675     } else if (h1p->remainder > 0) {
2676         length = nxt_buf_chain_length(out);
2677         h1p->remainder -= length;
2678     }
2679 
2680     peer->body = out;
2681 
2682     r = peer->request;
2683     r->state->ready_handler(task, r, peer);
2684 }
2685 
2686 
2687 static void
2688 nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data)
2689 {
2690     nxt_http_peer_t     *peer;
2691     nxt_http_request_t  *r;
2692 
2693     peer = data;
2694 
2695     nxt_debug(task, "h1p peer closed");
2696 
2697     r = peer->request;
2698 
2699     if (peer->header_received) {
2700         peer->body = nxt_http_buf_last(r);
2701         peer->closed = 1;
2702         r->inconsistent = (peer->proto.h1->remainder != 0);
2703 
2704         r->state->ready_handler(task, r, peer);
2705 
2706     } else {
2707         peer->status = NXT_HTTP_BAD_GATEWAY;
2708 
2709         r->state->error_handler(task, r, peer);
2710     }
2711 }
2712 
2713 
2714 static void
2715 nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data)
2716 {
2717     nxt_http_peer_t     *peer;
2718     nxt_http_request_t  *r;
2719 
2720     peer = data;
2721 
2722     nxt_debug(task, "h1p peer error");
2723 
2724     peer->status = NXT_HTTP_BAD_GATEWAY;
2725 
2726     r = peer->request;
2727     r->state->error_handler(task, r, peer);
2728 }
2729 
2730 
2731 static void
2732 nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data)
2733 {
2734     nxt_conn_t          *c;
2735     nxt_timer_t         *timer;
2736     nxt_http_peer_t     *peer;
2737     nxt_http_request_t  *r;
2738 
2739     timer = obj;
2740 
2741     nxt_debug(task, "h1p peer send timeout");
2742 
2743     c = nxt_write_timer_conn(timer);
2744     c->block_write = 1;
2745     c->block_read = 1;
2746 
2747     peer = c->socket.data;
2748     peer->status = NXT_HTTP_GATEWAY_TIMEOUT;
2749 
2750     r = peer->request;
2751     r->state->error_handler(task, r, peer);
2752 }
2753 
2754 
2755 static void
2756 nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data)
2757 {
2758     nxt_conn_t          *c;
2759     nxt_timer_t         *timer;
2760     nxt_http_peer_t     *peer;
2761     nxt_http_request_t  *r;
2762 
2763     timer = obj;
2764 
2765     nxt_debug(task, "h1p peer read timeout");
2766 
2767     c = nxt_read_timer_conn(timer);
2768     c->block_write = 1;
2769     c->block_read = 1;
2770 
2771     peer = c->socket.data;
2772     peer->status = NXT_HTTP_GATEWAY_TIMEOUT;
2773 
2774     r = peer->request;
2775     r->state->error_handler(task, r, peer);
2776 }
2777 
2778 
2779 static nxt_msec_t
2780 nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data)
2781 {
2782     nxt_http_peer_t  *peer;
2783 
2784     peer = c->socket.data;
2785 
2786     return nxt_value_at(nxt_msec_t, peer->request->conf->socket_conf, data);
2787 }
2788 
2789 
2790 static void
2791 nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer)
2792 {
2793     nxt_conn_t  *c;
2794 
2795     nxt_debug(task, "h1p peer close");
2796 
2797     peer->closed = 1;
2798 
2799     c = peer->proto.h1->conn;
2800     task = &c->task;
2801     c->socket.task = task;
2802     c->read_timer.task = task;
2803     c->write_timer.task = task;
2804 
2805     if (c->socket.fd != -1) {
2806         c->write_state = &nxt_h1p_peer_close_state;
2807 
2808         nxt_conn_close(task->thread->engine, c);
2809 
2810     } else {
2811         nxt_h1p_peer_free(task, c, NULL);
2812     }
2813 }
2814 
2815 
2816 static const nxt_conn_state_t  nxt_h1p_peer_close_state
2817     nxt_aligned(64) =
2818 {
2819     .ready_handler = nxt_h1p_peer_free,
2820 };
2821 
2822 
2823 static void
2824 nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data)
2825 {
2826     nxt_conn_t  *c;
2827 
2828     c = obj;
2829 
2830     nxt_debug(task, "h1p peer free");
2831 
2832     nxt_conn_free(task, c);
2833 }
2834 
2835 
2836 static nxt_int_t
2837 nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field,
2838     uintptr_t data)
2839 {
2840     nxt_http_request_t  *r;
2841 
2842     r = ctx;
2843     field->skip = 1;
2844 
2845     if (field->value_length == 7
2846         && nxt_memcmp(field->value, "chunked", 7) == 0)
2847     {
2848         r->peer->proto.h1->chunked = 1;
2849     }
2850 
2851     return NXT_OK;
2852 }
2853