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