xref: /unit/src/nxt_h1proto.c (revision 1131:ec7d924d8dfb)
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_h1proto.h>
10 #include <nxt_websocket.h>
11 #include <nxt_websocket_header.h>
12 
13 
14 /*
15  * nxt_http_conn_ and nxt_h1p_conn_ prefixes are used for connection handlers.
16  * nxt_h1p_idle_ prefix is used for idle connection handlers.
17  * nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods.
18  */
19 
20 #if (NXT_TLS)
21 static ssize_t nxt_http_idle_io_read_handler(nxt_conn_t *c);
22 static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data);
23 #endif
24 static ssize_t nxt_h1p_idle_io_read_handler(nxt_conn_t *c);
25 static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data);
26 static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data);
27 static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj,
28     void *data);
29 static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p,
30     nxt_http_request_t *r);
31 static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task,
32     nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf);
33 static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field,
34     uintptr_t data);
35 static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field,
36     uintptr_t data);
37 static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field,
38     uintptr_t data);
39 static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field,
40     uintptr_t data);
41 static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field,
42     uintptr_t data);
43 static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r);
44 static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj,
45     void *data);
46 static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r);
47 static void nxt_h1p_request_header_send(nxt_task_t *task,
48     nxt_http_request_t *r);
49 static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r,
50     nxt_buf_t *out);
51 static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r,
52     nxt_buf_t *out);
53 static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task,
54     nxt_http_proto_t proto);
55 static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
56     nxt_buf_t *last);
57 static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data);
58 static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj,
59     void *data);
60 static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj,
61     void *data);
62 nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
63     nxt_http_request_t *r);
64 static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
65     nxt_socket_conf_joint_t *joint);
66 static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data);
67 static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data);
68 static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data);
69 static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data);
70 static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p,
71     nxt_conn_t *c);
72 static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data);
73 static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data);
74 static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c);
75 static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data);
76 static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj,
77     void *data);
78 static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c,
79     uintptr_t data);
80 static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c);
81 static void nxt_h1p_shutdown_(nxt_task_t *task, nxt_conn_t *c);
82 static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data);
83 static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data);
84 static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data);
85 
86 #if (NXT_TLS)
87 static const nxt_conn_state_t  nxt_http_idle_state;
88 static const nxt_conn_state_t  nxt_h1p_shutdown_state;
89 #endif
90 static const nxt_conn_state_t  nxt_h1p_idle_state;
91 static const nxt_conn_state_t  nxt_h1p_header_parse_state;
92 static const nxt_conn_state_t  nxt_h1p_read_body_state;
93 static const nxt_conn_state_t  nxt_h1p_request_send_state;
94 static const nxt_conn_state_t  nxt_h1p_timeout_response_state;
95 static const nxt_conn_state_t  nxt_h1p_keepalive_state;
96 static const nxt_conn_state_t  nxt_h1p_close_state;
97 
98 
99 const nxt_http_proto_table_t  nxt_http_proto[3] = {
100     /* NXT_HTTP_PROTO_H1 */
101     {
102         .body_read        = nxt_h1p_request_body_read,
103         .local_addr       = nxt_h1p_request_local_addr,
104         .header_send      = nxt_h1p_request_header_send,
105         .send             = nxt_h1p_request_send,
106         .body_bytes_sent  = nxt_h1p_request_body_bytes_sent,
107         .discard          = nxt_h1p_request_discard,
108         .close            = nxt_h1p_request_close,
109         .ws_frame_start   = nxt_h1p_websocket_frame_start,
110     },
111     /* NXT_HTTP_PROTO_H2      */
112     /* NXT_HTTP_PROTO_DEVNULL */
113 };
114 
115 
116 static nxt_lvlhsh_t            nxt_h1p_fields_hash;
117 
118 static nxt_http_field_proc_t   nxt_h1p_fields[] = {
119     { nxt_string("Connection"),        &nxt_h1p_connection, 0 },
120     { nxt_string("Upgrade"),           &nxt_h1p_upgrade, 0 },
121     { nxt_string("Sec-WebSocket-Key"), &nxt_h1p_websocket_key, 0 },
122     { nxt_string("Sec-WebSocket-Version"),
123                                        &nxt_h1p_websocket_version, 0 },
124     { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 },
125 
126     { nxt_string("Host"),              &nxt_http_request_host, 0 },
127     { nxt_string("Cookie"),            &nxt_http_request_field,
128         offsetof(nxt_http_request_t, cookie) },
129     { nxt_string("Referer"),           &nxt_http_request_field,
130         offsetof(nxt_http_request_t, referer) },
131     { nxt_string("User-Agent"),        &nxt_http_request_field,
132         offsetof(nxt_http_request_t, user_agent) },
133     { nxt_string("Content-Type"),      &nxt_http_request_field,
134         offsetof(nxt_http_request_t, content_type) },
135     { nxt_string("Content-Length"),    &nxt_http_request_content_length, 0 },
136 };
137 
138 
139 nxt_int_t
140 nxt_h1p_init(nxt_task_t *task, nxt_runtime_t *rt)
141 {
142     return nxt_http_fields_hash(&nxt_h1p_fields_hash, rt->mem_pool,
143                                 nxt_h1p_fields, nxt_nitems(nxt_h1p_fields));
144 }
145 
146 
147 void
148 nxt_http_conn_init(nxt_task_t *task, void *obj, void *data)
149 {
150     nxt_conn_t               *c;
151     nxt_socket_conf_t        *skcf;
152     nxt_event_engine_t       *engine;
153     nxt_listen_event_t       *lev;
154     nxt_socket_conf_joint_t  *joint;
155 
156     c = obj;
157     lev = data;
158 
159     nxt_debug(task, "http conn init");
160 
161     joint = lev->socket.data;
162     skcf = joint->socket_conf;
163     c->local = skcf->sockaddr;
164 
165     engine = task->thread->engine;
166     c->read_work_queue = &engine->fast_work_queue;
167     c->write_work_queue = &engine->fast_work_queue;
168 
169     c->read_state = &nxt_h1p_idle_state;
170 
171 #if (NXT_TLS)
172     if (skcf->tls != NULL) {
173         c->read_state = &nxt_http_idle_state;
174     }
175 #endif
176 
177     nxt_conn_read(engine, c);
178 }
179 
180 
181 #if (NXT_TLS)
182 
183 static const nxt_conn_state_t  nxt_http_idle_state
184     nxt_aligned(64) =
185 {
186     .ready_handler = nxt_http_conn_test,
187     .close_handler = nxt_h1p_conn_close,
188     .error_handler = nxt_h1p_conn_error,
189 
190     .io_read_handler = nxt_http_idle_io_read_handler,
191 
192     .timer_handler = nxt_h1p_idle_timeout,
193     .timer_value = nxt_h1p_conn_timer_value,
194     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
195 };
196 
197 
198 static ssize_t
199 nxt_http_idle_io_read_handler(nxt_conn_t *c)
200 {
201     size_t                   size;
202     ssize_t                  n;
203     nxt_buf_t                *b;
204     nxt_socket_conf_joint_t  *joint;
205 
206     joint = c->listen->socket.data;
207 
208     if (nxt_slow_path(joint == NULL)) {
209         /*
210          * Listening socket had been closed while
211          * connection was in keep-alive state.
212          */
213         c->read_state = &nxt_h1p_idle_close_state;
214         return 0;
215     }
216 
217     size = joint->socket_conf->header_buffer_size;
218 
219     b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
220     if (nxt_slow_path(b == NULL)) {
221         c->socket.error = NXT_ENOMEM;
222         return NXT_ERROR;
223     }
224 
225     /*
226      * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP.
227      * 11 bytes are enough to log supported SSLv3/TLS version.
228      * 16 bytes are just for more optimized kernel copy-out operation.
229      */
230     n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK);
231 
232     if (n > 0) {
233         c->read = b;
234 
235     } else {
236         c->read = NULL;
237         nxt_mp_free(c->mem_pool, b);
238     }
239 
240     return n;
241 }
242 
243 
244 static void
245 nxt_http_conn_test(nxt_task_t *task, void *obj, void *data)
246 {
247     u_char                   *p;
248     nxt_buf_t                *b;
249     nxt_conn_t               *c;
250     nxt_tls_conf_t           *tls;
251     nxt_socket_conf_joint_t  *joint;
252 
253     c = obj;
254 
255     nxt_debug(task, "h1p conn https test");
256 
257     b = c->read;
258     p = b->mem.pos;
259 
260     c->read_state = &nxt_h1p_idle_state;
261 
262     if (p[0] != 0x16) {
263         b->mem.free = b->mem.pos;
264 
265         nxt_conn_read(task->thread->engine, c);
266         return;
267     }
268 
269     /* SSLv3/TLS ClientHello message. */
270 
271 #if (NXT_DEBUG)
272     if (nxt_buf_mem_used_size(&b->mem) >= 11) {
273         u_char      major, minor;
274         const char  *protocol;
275 
276         major = p[9];
277         minor = p[10];
278 
279         if (major == 3) {
280             if (minor == 0) {
281                 protocol = "SSLv";
282 
283             } else {
284                 protocol = "TLSv";
285                 major -= 2;
286                 minor -= 1;
287             }
288 
289             nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor);
290         }
291     }
292 #endif
293 
294     c->read = NULL;
295     nxt_mp_free(c->mem_pool, b);
296 
297     joint = c->listen->socket.data;
298 
299     if (nxt_slow_path(joint == NULL)) {
300         /*
301          * Listening socket had been closed while
302          * connection was in keep-alive state.
303          */
304         nxt_h1p_shutdown(task, c);
305         return;
306     }
307 
308     tls = joint->socket_conf->tls;
309 
310     tls->conn_init(task, tls, c);
311 }
312 
313 #endif
314 
315 
316 static const nxt_conn_state_t  nxt_h1p_idle_state
317     nxt_aligned(64) =
318 {
319     .ready_handler = nxt_h1p_conn_proto_init,
320     .close_handler = nxt_h1p_conn_close,
321     .error_handler = nxt_h1p_conn_error,
322 
323     .io_read_handler = nxt_h1p_idle_io_read_handler,
324 
325     .timer_handler = nxt_h1p_idle_timeout,
326     .timer_value = nxt_h1p_conn_timer_value,
327     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
328     .timer_autoreset = 1,
329 };
330 
331 
332 static ssize_t
333 nxt_h1p_idle_io_read_handler(nxt_conn_t *c)
334 {
335     size_t                   size;
336     ssize_t                  n;
337     nxt_buf_t                *b;
338     nxt_socket_conf_joint_t  *joint;
339 
340     joint = c->listen->socket.data;
341 
342     if (nxt_slow_path(joint == NULL)) {
343         /*
344          * Listening socket had been closed while
345          * connection was in keep-alive state.
346          */
347         c->read_state = &nxt_h1p_idle_close_state;
348         return 0;
349     }
350 
351     b = c->read;
352 
353     if (b == NULL) {
354         size = joint->socket_conf->header_buffer_size;
355 
356         b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
357         if (nxt_slow_path(b == NULL)) {
358             c->socket.error = NXT_ENOMEM;
359             return NXT_ERROR;
360         }
361     }
362 
363     n = c->io->recvbuf(c, b);
364 
365     if (n > 0) {
366         c->read = b;
367 
368     } else {
369         c->read = NULL;
370         nxt_mp_free(c->mem_pool, b);
371     }
372 
373     return n;
374 }
375 
376 
377 static void
378 nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data)
379 {
380     nxt_conn_t     *c;
381     nxt_h1proto_t  *h1p;
382 
383     c = obj;
384 
385     nxt_debug(task, "h1p conn proto init");
386 
387     h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t));
388     if (nxt_slow_path(h1p == NULL)) {
389         nxt_h1p_shutdown(task, c);
390         return;
391     }
392 
393     c->socket.data = h1p;
394     h1p->conn = c;
395 
396     nxt_h1p_conn_request_init(task, c, h1p);
397 }
398 
399 
400 static void
401 nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
402 {
403     nxt_int_t                ret;
404     nxt_conn_t               *c;
405     nxt_h1proto_t            *h1p;
406     nxt_http_request_t       *r;
407     nxt_socket_conf_joint_t  *joint;
408 
409     c = obj;
410     h1p = data;
411 
412     nxt_debug(task, "h1p conn request init");
413 
414     r = nxt_http_request_create(task);
415 
416     if (nxt_fast_path(r != NULL)) {
417         h1p->request = r;
418         r->proto.h1 = h1p;
419 
420         /* r->protocol = NXT_HTTP_PROTO_H1 is done by zeroing. */
421         r->remote = c->remote;
422 
423 #if (NXT_TLS)
424         r->tls = c->u.tls;
425 #endif
426 
427         ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool);
428 
429         if (nxt_fast_path(ret == NXT_OK)) {
430             joint = c->listen->socket.data;
431             joint->count++;
432 
433             r->conf = joint;
434             c->local = joint->socket_conf->sockaddr;
435 
436             nxt_h1p_conn_request_header_parse(task, c, h1p);
437             return;
438         }
439 
440         /*
441          * The request is very incomplete here,
442          * so "internal server error" useless here.
443          */
444         nxt_mp_release(r->mem_pool);
445     }
446 
447     nxt_h1p_shutdown(task, c);
448 }
449 
450 
451 static const nxt_conn_state_t  nxt_h1p_header_parse_state
452     nxt_aligned(64) =
453 {
454     .ready_handler = nxt_h1p_conn_request_header_parse,
455     .close_handler = nxt_h1p_conn_request_error,
456     .error_handler = nxt_h1p_conn_request_error,
457 
458     .timer_handler = nxt_h1p_conn_request_timeout,
459     .timer_value = nxt_h1p_conn_request_timer_value,
460     .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout),
461 };
462 
463 
464 static void
465 nxt_h1p_conn_request_header_parse(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_status_t   status;
471     nxt_http_request_t  *r;
472 
473     c = obj;
474     h1p = data;
475 
476     nxt_debug(task, "h1p conn header parse");
477 
478     ret = nxt_http_parse_request(&h1p->parser, &c->read->mem);
479 
480     ret = nxt_expect(NXT_DONE, ret);
481 
482     if (ret != NXT_AGAIN) {
483         nxt_timer_disable(task->thread->engine, &c->read_timer);
484     }
485 
486     r = h1p->request;
487 
488     switch (ret) {
489 
490     case NXT_DONE:
491         /*
492          * By default the keepalive mode is disabled in HTTP/1.0 and
493          * enabled in HTTP/1.1.  The mode can be overridden later by
494          * the "Connection" field processed in nxt_h1p_connection().
495          */
496         h1p->keepalive = (h1p->parser.version.s.minor != '0');
497 
498         ret = nxt_h1p_header_process(task, h1p, r);
499 
500         if (nxt_fast_path(ret == NXT_OK)) {
501 
502 #if (NXT_TLS)
503             if (c->u.tls == NULL && r->conf->socket_conf->tls != NULL) {
504                 status = NXT_HTTP_TO_HTTPS;
505                 goto error;
506             }
507 #endif
508 
509             r->state->ready_handler(task, r, NULL);
510             return;
511         }
512 
513         status = ret;
514         goto error;
515 
516     case NXT_AGAIN:
517         status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf);
518 
519         if (nxt_fast_path(status == NXT_OK)) {
520             c->read_state = &nxt_h1p_header_parse_state;
521 
522             nxt_conn_read(task->thread->engine, c);
523             return;
524         }
525 
526         break;
527 
528     case NXT_HTTP_PARSE_INVALID:
529         status = NXT_HTTP_BAD_REQUEST;
530         break;
531 
532     case NXT_HTTP_PARSE_UNSUPPORTED_VERSION:
533         status = NXT_HTTP_VERSION_NOT_SUPPORTED;
534         break;
535 
536     case NXT_HTTP_PARSE_TOO_LARGE_FIELD:
537         status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
538         break;
539 
540     default:
541     case NXT_ERROR:
542         status = NXT_HTTP_INTERNAL_SERVER_ERROR;
543         break;
544     }
545 
546     (void) nxt_h1p_header_process(task, h1p, r);
547 
548 error:
549 
550     h1p->keepalive = 0;
551 
552     nxt_http_request_error(task, r, status);
553 }
554 
555 
556 static nxt_int_t
557 nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p,
558     nxt_http_request_t *r)
559 {
560     u_char     *m;
561     nxt_int_t  ret;
562 
563     r->target.start = h1p->parser.target_start;
564     r->target.length = h1p->parser.target_end - h1p->parser.target_start;
565 
566     if (h1p->parser.version.ui64 != 0) {
567         r->version.start = h1p->parser.version.str;
568         r->version.length = sizeof(h1p->parser.version.str);
569     }
570 
571     r->method = &h1p->parser.method;
572     r->path = &h1p->parser.path;
573     r->args = &h1p->parser.args;
574 
575     r->fields = h1p->parser.fields;
576 
577     ret = nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r);
578     if (nxt_slow_path(ret != NXT_OK)) {
579         return ret;
580     }
581 
582     if (h1p->connection_upgrade && h1p->upgrade_websocket) {
583         m = h1p->parser.method.start;
584 
585         if (nxt_slow_path(h1p->parser.method.length != 3
586                           || m[0] != 'G'
587                           || m[1] != 'E'
588                           || m[2] != 'T'))
589         {
590             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad method");
591 
592             return NXT_HTTP_BAD_REQUEST;
593         }
594 
595         if (nxt_slow_path(h1p->parser.version.s.minor != '1')) {
596             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad protocol version");
597 
598             return NXT_HTTP_BAD_REQUEST;
599         }
600 
601         if (nxt_slow_path(h1p->websocket_key == NULL)) {
602             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad or absent websocket key");
603 
604             return NXT_HTTP_BAD_REQUEST;
605         }
606 
607         if (nxt_slow_path(h1p->websocket_version_ok == 0)) {
608             nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad or absent websocket version");
609 
610             return NXT_HTTP_UPGRADE_REQUIRED;
611         }
612 
613         r->websocket_handshake = 1;
614     }
615 
616     return ret;
617 }
618 
619 
620 static nxt_int_t
621 nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c,
622     nxt_socket_conf_t *skcf)
623 {
624     size_t     size, used;
625     nxt_buf_t  *in, *b;
626 
627     in = c->read;
628 
629     if (nxt_buf_mem_free_size(&in->mem) == 0) {
630         size = skcf->large_header_buffer_size;
631         used = nxt_buf_mem_used_size(&in->mem);
632 
633         if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) {
634             return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
635         }
636 
637         b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
638         if (nxt_slow_path(b == NULL)) {
639             return NXT_HTTP_INTERNAL_SERVER_ERROR;
640         }
641 
642         b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used);
643 
644         in->next = h1p->buffers;
645         h1p->buffers = in;
646         h1p->nbuffers++;
647 
648         c->read = b;
649     }
650 
651     return NXT_OK;
652 }
653 
654 
655 static nxt_int_t
656 nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data)
657 {
658     nxt_http_request_t   *r;
659     static const u_char  *upgrade = (const u_char *) "upgrade";
660 
661     r = ctx;
662 
663     if (field->value_length == 5 && nxt_memcmp(field->value, "close", 5) == 0) {
664         r->proto.h1->keepalive = 0;
665 
666     } else if (field->value_length == 7
667                && nxt_memcasecmp(field->value, upgrade, 7) == 0)
668     {
669         r->proto.h1->connection_upgrade = 1;
670     }
671 
672     return NXT_OK;
673 }
674 
675 
676 static nxt_int_t
677 nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, uintptr_t data)
678 {
679     nxt_http_request_t   *r;
680     static const u_char  *websocket = (const u_char *) "websocket";
681 
682     r = ctx;
683 
684     if (field->value_length == 9
685         && nxt_memcasecmp(field->value, websocket, 9) == 0)
686     {
687         r->proto.h1->upgrade_websocket = 1;
688     }
689 
690     return NXT_OK;
691 }
692 
693 
694 static nxt_int_t
695 nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, uintptr_t data)
696 {
697     nxt_http_request_t  *r;
698 
699     r = ctx;
700 
701     if (field->value_length == 24) {
702         r->proto.h1->websocket_key = field;
703     }
704 
705     return NXT_OK;
706 }
707 
708 
709 static nxt_int_t
710 nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, uintptr_t data)
711 {
712     nxt_http_request_t  *r;
713 
714     r = ctx;
715 
716     if (field->value_length == 2
717         && field->value[0] == '1' && field->value[1] == '3')
718     {
719         r->proto.h1->websocket_version_ok = 1;
720     }
721 
722     return NXT_OK;
723 }
724 
725 
726 static nxt_int_t
727 nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data)
728 {
729     nxt_http_te_t       te;
730     nxt_http_request_t  *r;
731 
732     r = ctx;
733 
734     if (field->value_length == 7
735         && nxt_memcmp(field->value, "chunked", 7) == 0)
736     {
737         te = NXT_HTTP_TE_CHUNKED;
738 
739     } else {
740         te = NXT_HTTP_TE_UNSUPPORTED;
741     }
742 
743     r->proto.h1->transfer_encoding = te;
744 
745     return NXT_OK;
746 }
747 
748 
749 static void
750 nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r)
751 {
752     size_t             size, body_length;
753     nxt_buf_t          *in, *b;
754     nxt_conn_t         *c;
755     nxt_h1proto_t      *h1p;
756     nxt_http_status_t  status;
757 
758     h1p = r->proto.h1;
759 
760     nxt_debug(task, "h1p request body read %O te:%d",
761               r->content_length_n, h1p->transfer_encoding);
762 
763     switch (h1p->transfer_encoding) {
764 
765     case NXT_HTTP_TE_CHUNKED:
766         status = NXT_HTTP_LENGTH_REQUIRED;
767         goto error;
768 
769     case NXT_HTTP_TE_UNSUPPORTED:
770         status = NXT_HTTP_NOT_IMPLEMENTED;
771         goto error;
772 
773     default:
774     case NXT_HTTP_TE_NONE:
775         break;
776     }
777 
778     if (r->content_length_n == -1 || r->content_length_n == 0) {
779         goto ready;
780     }
781 
782     if (r->content_length_n > (nxt_off_t) r->conf->socket_conf->max_body_size) {
783         status = NXT_HTTP_PAYLOAD_TOO_LARGE;
784         goto error;
785     }
786 
787     body_length = (size_t) r->content_length_n;
788 
789     b = r->body;
790 
791     if (b == NULL) {
792         b = nxt_buf_mem_alloc(r->mem_pool, body_length, 0);
793         if (nxt_slow_path(b == NULL)) {
794             status = NXT_HTTP_INTERNAL_SERVER_ERROR;
795             goto error;
796         }
797 
798         r->body = b;
799     }
800 
801     in = h1p->conn->read;
802 
803     size = nxt_buf_mem_used_size(&in->mem);
804 
805     if (size != 0) {
806         if (size > body_length) {
807             size = body_length;
808         }
809 
810         b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size);
811         in->mem.pos += size;
812     }
813 
814     size = nxt_buf_mem_free_size(&b->mem);
815 
816     nxt_debug(task, "h1p body rest: %uz", size);
817 
818     if (size != 0) {
819         in->next = h1p->buffers;
820         h1p->buffers = in;
821         h1p->nbuffers++;
822 
823         c = h1p->conn;
824         c->read = b;
825         c->read_state = &nxt_h1p_read_body_state;
826 
827         nxt_conn_read(task->thread->engine, c);
828         return;
829     }
830 
831 ready:
832 
833     nxt_work_queue_add(&task->thread->engine->fast_work_queue,
834                        r->state->ready_handler, task, r, NULL);
835 
836     return;
837 
838 error:
839 
840     h1p->keepalive = 0;
841 
842     nxt_http_request_error(task, r, status);
843 }
844 
845 
846 static const nxt_conn_state_t  nxt_h1p_read_body_state
847     nxt_aligned(64) =
848 {
849     .ready_handler = nxt_h1p_conn_request_body_read,
850     .close_handler = nxt_h1p_conn_request_error,
851     .error_handler = nxt_h1p_conn_request_error,
852 
853     .timer_handler = nxt_h1p_conn_request_timeout,
854     .timer_value = nxt_h1p_conn_request_timer_value,
855     .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout),
856     .timer_autoreset = 1,
857 };
858 
859 
860 static void
861 nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data)
862 {
863     size_t              size;
864     nxt_conn_t          *c;
865     nxt_h1proto_t       *h1p;
866     nxt_http_request_t  *r;
867     nxt_event_engine_t  *engine;
868 
869     c = obj;
870     h1p = data;
871 
872     nxt_debug(task, "h1p conn request body read");
873 
874     size = nxt_buf_mem_free_size(&c->read->mem);
875 
876     nxt_debug(task, "h1p body rest: %uz", size);
877 
878     engine = task->thread->engine;
879 
880     if (size != 0) {
881         nxt_conn_read(engine, c);
882 
883     } else {
884         c->read = NULL;
885         r = h1p->request;
886 
887         nxt_work_queue_add(&engine->fast_work_queue, r->state->ready_handler,
888                            task, r, NULL);
889     }
890 }
891 
892 
893 static void
894 nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r)
895 {
896     r->local = nxt_conn_local_addr(task, r->proto.h1->conn);
897 }
898 
899 
900 #define NXT_HTTP_LAST_INFORMATIONAL                                           \
901     (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1)
902 
903 static const nxt_str_t  nxt_http_informational[] = {
904     nxt_string("HTTP/1.1 100 Continue\r\n"),
905     nxt_string("HTTP/1.1 101 Switching Protocols\r\n"),
906 };
907 
908 
909 #define NXT_HTTP_LAST_SUCCESS                                                 \
910     (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1)
911 
912 static const nxt_str_t  nxt_http_success[] = {
913     nxt_string("HTTP/1.1 200 OK\r\n"),
914     nxt_string("HTTP/1.1 201 Created\r\n"),
915     nxt_string("HTTP/1.1 202 Accepted\r\n"),
916     nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"),
917     nxt_string("HTTP/1.1 204 No Content\r\n"),
918     nxt_string("HTTP/1.1 205 Reset Content\r\n"),
919     nxt_string("HTTP/1.1 206 Partial Content\r\n"),
920 };
921 
922 
923 #define NXT_HTTP_LAST_REDIRECTION                                             \
924     (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1)
925 
926 static const nxt_str_t  nxt_http_redirection[] = {
927     nxt_string("HTTP/1.1 300 Multiple Choices\r\n"),
928     nxt_string("HTTP/1.1 301 Moved Permanently\r\n"),
929     nxt_string("HTTP/1.1 302 Found\r\n"),
930     nxt_string("HTTP/1.1 303 See Other\r\n"),
931     nxt_string("HTTP/1.1 304 Not Modified\r\n"),
932 };
933 
934 
935 #define NXT_HTTP_LAST_CLIENT_ERROR                                            \
936     (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1)
937 
938 static const nxt_str_t  nxt_http_client_error[] = {
939     nxt_string("HTTP/1.1 400 Bad Request\r\n"),
940     nxt_string("HTTP/1.1 401 Unauthorized\r\n"),
941     nxt_string("HTTP/1.1 402 Payment Required\r\n"),
942     nxt_string("HTTP/1.1 403 Forbidden\r\n"),
943     nxt_string("HTTP/1.1 404 Not Found\r\n"),
944     nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"),
945     nxt_string("HTTP/1.1 406 Not Acceptable\r\n"),
946     nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"),
947     nxt_string("HTTP/1.1 408 Request Timeout\r\n"),
948     nxt_string("HTTP/1.1 409 Conflict\r\n"),
949     nxt_string("HTTP/1.1 410 Gone\r\n"),
950     nxt_string("HTTP/1.1 411 Length Required\r\n"),
951     nxt_string("HTTP/1.1 412 Precondition Failed\r\n"),
952     nxt_string("HTTP/1.1 413 Payload Too Large\r\n"),
953     nxt_string("HTTP/1.1 414 URI Too Long\r\n"),
954     nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"),
955     nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"),
956     nxt_string("HTTP/1.1 417 Expectation Failed\r\n"),
957     nxt_string("HTTP/1.1 418\r\n"),
958     nxt_string("HTTP/1.1 419\r\n"),
959     nxt_string("HTTP/1.1 420\r\n"),
960     nxt_string("HTTP/1.1 421\r\n"),
961     nxt_string("HTTP/1.1 422\r\n"),
962     nxt_string("HTTP/1.1 423\r\n"),
963     nxt_string("HTTP/1.1 424\r\n"),
964     nxt_string("HTTP/1.1 425\r\n"),
965     nxt_string("HTTP/1.1 426 Upgrade Required\r\n"),
966     nxt_string("HTTP/1.1 427\r\n"),
967     nxt_string("HTTP/1.1 428\r\n"),
968     nxt_string("HTTP/1.1 429\r\n"),
969     nxt_string("HTTP/1.1 430\r\n"),
970     nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"),
971 };
972 
973 
974 #define NXT_HTTP_LAST_NGINX_ERROR                                             \
975     (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1)
976 
977 static const nxt_str_t  nxt_http_nginx_error[] = {
978     nxt_string("HTTP/1.1 400 "
979                "The plain HTTP request was sent to HTTPS port\r\n"),
980 };
981 
982 
983 #define NXT_HTTP_LAST_SERVER_ERROR                                            \
984     (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1)
985 
986 static const nxt_str_t  nxt_http_server_error[] = {
987     nxt_string("HTTP/1.1 500 Internal Server Error\r\n"),
988     nxt_string("HTTP/1.1 501 Not Implemented\r\n"),
989     nxt_string("HTTP/1.1 502 Bad Gateway\r\n"),
990     nxt_string("HTTP/1.1 503 Service Unavailable\r\n"),
991     nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"),
992     nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"),
993 };
994 
995 
996 #define UNKNOWN_STATUS_LENGTH  nxt_length("HTTP/1.1 65536\r\n")
997 
998 static void
999 nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r)
1000 {
1001     u_char              *p;
1002     size_t              size;
1003     nxt_buf_t           *header;
1004     nxt_str_t           unknown_status;
1005     nxt_int_t           conn;
1006     nxt_uint_t          n;
1007     nxt_bool_t          http11;
1008     nxt_conn_t          *c;
1009     nxt_h1proto_t       *h1p;
1010     const nxt_str_t     *status;
1011     nxt_http_field_t    *field;
1012     u_char              buf[UNKNOWN_STATUS_LENGTH];
1013 
1014     static const char   chunked[] = "Transfer-Encoding: chunked\r\n";
1015     static const char   websocket_version[] = "Sec-WebSocket-Version: 13\r\n";
1016 
1017     static const nxt_str_t  connection[3] = {
1018         nxt_string("Connection: close\r\n"),
1019         nxt_string("Connection: keep-alive\r\n"),
1020         nxt_string("Upgrade: websocket\r\n"
1021                    "Connection: Upgrade\r\n"
1022                    "Sec-WebSocket-Accept: "),
1023     };
1024 
1025     nxt_debug(task, "h1p request header send");
1026 
1027     r->header_sent = 1;
1028     h1p = r->proto.h1;
1029     n = r->status;
1030 
1031     if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) {
1032         status = &nxt_http_informational[n - NXT_HTTP_CONTINUE];
1033 
1034     } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) {
1035         status = &nxt_http_success[n - NXT_HTTP_OK];
1036 
1037     } else if (n >= NXT_HTTP_MULTIPLE_CHOICES
1038                && n <= NXT_HTTP_LAST_REDIRECTION)
1039     {
1040         status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES];
1041 
1042     } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) {
1043         status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST];
1044 
1045     } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) {
1046         status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS];
1047 
1048     } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR
1049                && n <= NXT_HTTP_LAST_SERVER_ERROR)
1050     {
1051         status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR];
1052 
1053     } else {
1054         p = nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH,
1055                         "HTTP/1.1 %03d\r\n", n);
1056 
1057         unknown_status.length = p - buf;
1058         unknown_status.start = buf;
1059         status = &unknown_status;
1060     }
1061 
1062     size = status->length;
1063     /* Trailing CRLF at the end of header. */
1064     size += nxt_length("\r\n");
1065 
1066     conn = -1;
1067 
1068     if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) {
1069         h1p->websocket = 1;
1070         h1p->keepalive = 0;
1071         conn = 2;
1072         size += NXT_WEBSOCKET_ACCEPT_SIZE + 2;
1073 
1074     } else {
1075         http11 = (h1p->parser.version.s.minor != '0');
1076 
1077         if (r->resp.content_length == NULL || r->resp.content_length->skip) {
1078 
1079             if (http11) {
1080                 if (n != NXT_HTTP_NOT_MODIFIED
1081                     && n != NXT_HTTP_NO_CONTENT
1082                     && !h1p->websocket)
1083                 {
1084                     h1p->chunked = 1;
1085                     size += nxt_length(chunked);
1086                     /* Trailing CRLF will be added by the first chunk header. */
1087                     size -= nxt_length("\r\n");
1088                 }
1089 
1090             } else {
1091                 h1p->keepalive = 0;
1092             }
1093         }
1094 
1095         if (http11 ^ h1p->keepalive) {
1096             conn = h1p->keepalive;
1097         }
1098     }
1099 
1100     if (conn >= 0) {
1101         size += connection[conn].length;
1102     }
1103 
1104     nxt_list_each(field, r->resp.fields) {
1105 
1106         if (!field->skip) {
1107             size += field->name_length + field->value_length;
1108             size += nxt_length(": \r\n");
1109         }
1110 
1111     } nxt_list_loop;
1112 
1113     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1114         size += nxt_length(websocket_version);
1115     }
1116 
1117     header = nxt_http_buf_mem(task, r, size);
1118     if (nxt_slow_path(header == NULL)) {
1119         nxt_h1p_request_error(task, h1p, r);
1120         return;
1121     }
1122 
1123     p = nxt_cpymem(header->mem.free, status->start, status->length);
1124 
1125     nxt_list_each(field, r->resp.fields) {
1126 
1127         if (!field->skip) {
1128             p = nxt_cpymem(p, field->name, field->name_length);
1129             *p++ = ':'; *p++ = ' ';
1130             p = nxt_cpymem(p, field->value, field->value_length);
1131             *p++ = '\r'; *p++ = '\n';
1132         }
1133 
1134     } nxt_list_loop;
1135 
1136     if (conn >= 0) {
1137         p = nxt_cpymem(p, connection[conn].start, connection[conn].length);
1138     }
1139 
1140     if (h1p->websocket) {
1141         nxt_websocket_accept(p, h1p->websocket_key->value);
1142         p += NXT_WEBSOCKET_ACCEPT_SIZE;
1143 
1144         *p++ = '\r'; *p++ = '\n';
1145     }
1146 
1147     if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) {
1148         p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version));
1149     }
1150 
1151     if (h1p->chunked) {
1152         p = nxt_cpymem(p, chunked, nxt_length(chunked));
1153         /* Trailing CRLF will be added by the first chunk header. */
1154 
1155     } else {
1156         *p++ = '\r'; *p++ = '\n';
1157     }
1158 
1159     header->mem.free = p;
1160 
1161     h1p->header_size = nxt_buf_mem_used_size(&header->mem);
1162 
1163     c = h1p->conn;
1164 
1165     c->write = header;
1166     c->write_state = &nxt_h1p_request_send_state;
1167 
1168     nxt_conn_write(task->thread->engine, c);
1169 
1170     if (h1p->websocket) {
1171         nxt_h1p_websocket_first_frame_start(task, r, c->read);
1172     }
1173 }
1174 
1175 
1176 void
1177 nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p)
1178 {
1179     size_t         size;
1180     nxt_buf_t      *b, *in, *next;
1181     nxt_conn_t     *c;
1182 
1183     nxt_debug(task, "h1p complete buffers");
1184 
1185     b = h1p->buffers;
1186     c = h1p->conn;
1187     in = c->read;
1188 
1189     if (b != NULL) {
1190         if (in == NULL) {
1191             /* A request with large body. */
1192             in = b;
1193             c->read = in;
1194 
1195             b = in->next;
1196             in->next = NULL;
1197         }
1198 
1199         while (b != NULL) {
1200             next = b->next;
1201 
1202             nxt_work_queue_add(&task->thread->engine->fast_work_queue,
1203                                b->completion_handler, task, b, b->parent);
1204 
1205             b = next;
1206         }
1207 
1208         h1p->buffers = NULL;
1209         h1p->nbuffers = 0;
1210     }
1211 
1212     if (in != NULL) {
1213         size = nxt_buf_mem_used_size(&in->mem);
1214 
1215         if (size == 0) {
1216             nxt_mp_free(c->mem_pool, in);
1217 
1218             c->read = NULL;
1219         }
1220     }
1221 }
1222 
1223 
1224 static const nxt_conn_state_t  nxt_h1p_request_send_state
1225     nxt_aligned(64) =
1226 {
1227     .ready_handler = nxt_h1p_conn_sent,
1228     .error_handler = nxt_h1p_conn_request_error,
1229 
1230     .timer_handler = nxt_h1p_conn_request_send_timeout,
1231     .timer_value = nxt_h1p_conn_request_timer_value,
1232     .timer_data = offsetof(nxt_socket_conf_t, send_timeout),
1233     .timer_autoreset = 1,
1234 };
1235 
1236 
1237 static void
1238 nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1239 {
1240     nxt_conn_t     *c;
1241     nxt_h1proto_t  *h1p;
1242 
1243     nxt_debug(task, "h1p request send");
1244 
1245     h1p = r->proto.h1;
1246     c = h1p->conn;
1247 
1248     if (h1p->chunked) {
1249         out = nxt_h1p_chunk_create(task, r, out);
1250         if (nxt_slow_path(out == NULL)) {
1251             nxt_h1p_request_error(task, h1p, r);
1252             return;
1253         }
1254     }
1255 
1256     if (c->write == NULL) {
1257         c->write = out;
1258         c->write_state = &nxt_h1p_request_send_state;
1259 
1260         nxt_conn_write(task->thread->engine, c);
1261 
1262     } else {
1263         nxt_buf_chain_add(&c->write, out);
1264     }
1265 }
1266 
1267 
1268 static nxt_buf_t *
1269 nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
1270 {
1271     nxt_off_t          size;
1272     nxt_buf_t          *b, **prev, *header, *tail;
1273 
1274     const size_t       chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN;
1275     static const char  tail_chunk[] = "\r\n0\r\n\r\n";
1276 
1277     size = 0;
1278     prev = &out;
1279 
1280     for (b = out; b != NULL; b = b->next) {
1281 
1282         if (nxt_buf_is_last(b)) {
1283             tail = nxt_http_buf_mem(task, r, chunk_size);
1284             if (nxt_slow_path(tail == NULL)) {
1285                 return NULL;
1286             }
1287 
1288             *prev = tail;
1289             tail->next = b;
1290             /*
1291              * The tail_chunk size with trailing zero is 8 bytes, so
1292              * memcpy may be inlined with just single 8 byte move operation.
1293              */
1294             nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk));
1295             tail->mem.free += nxt_length(tail_chunk);
1296 
1297             break;
1298         }
1299 
1300         size += nxt_buf_used_size(b);
1301         prev = &b->next;
1302     }
1303 
1304     if (size == 0) {
1305         return out;
1306     }
1307 
1308     header = nxt_http_buf_mem(task, r, chunk_size);
1309     if (nxt_slow_path(header == NULL)) {
1310         return NULL;
1311     }
1312 
1313     header->next = out;
1314     header->mem.free = nxt_sprintf(header->mem.free, header->mem.end,
1315                                    "\r\n%xO\r\n", size);
1316     return header;
1317 }
1318 
1319 
1320 static nxt_off_t
1321 nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto)
1322 {
1323     nxt_off_t      sent;
1324     nxt_h1proto_t  *h1p;
1325 
1326     h1p = proto.h1;
1327 
1328     sent = h1p->conn->sent - h1p->header_size;
1329 
1330     return (sent > 0) ? sent : 0;
1331 }
1332 
1333 
1334 static void
1335 nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
1336     nxt_buf_t *last)
1337 {
1338     nxt_buf_t         *b;
1339     nxt_conn_t        *c;
1340     nxt_h1proto_t     *h1p;
1341     nxt_work_queue_t  *wq;
1342 
1343     nxt_debug(task, "h1p request discard");
1344 
1345     h1p = r->proto.h1;
1346     h1p->keepalive = 0;
1347 
1348     c = h1p->conn;
1349     b = c->write;
1350     c->write = NULL;
1351 
1352     wq = &task->thread->engine->fast_work_queue;
1353 
1354     nxt_sendbuf_drain(task, wq, b);
1355     nxt_sendbuf_drain(task, wq, last);
1356 }
1357 
1358 
1359 static void
1360 nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data)
1361 {
1362     nxt_h1proto_t       *h1p;
1363     nxt_http_request_t  *r;
1364 
1365     h1p = data;
1366 
1367     nxt_debug(task, "h1p conn request error");
1368 
1369     r = h1p->request;
1370 
1371     if (nxt_slow_path(r == NULL)) {
1372         nxt_h1p_shutdown(task, h1p->conn);
1373         return;
1374     }
1375 
1376     if (r->fields == NULL) {
1377         (void) nxt_h1p_header_process(task, h1p, r);
1378     }
1379 
1380     if (r->status == 0) {
1381         r->status = NXT_HTTP_BAD_REQUEST;
1382     }
1383 
1384     nxt_h1p_request_error(task, h1p, r);
1385 }
1386 
1387 
1388 static void
1389 nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
1390 {
1391     nxt_conn_t          *c;
1392     nxt_timer_t         *timer;
1393     nxt_h1proto_t       *h1p;
1394     nxt_http_request_t  *r;
1395 
1396     timer = obj;
1397 
1398     nxt_debug(task, "h1p conn request timeout");
1399 
1400     c = nxt_read_timer_conn(timer);
1401     c->block_read = 1;
1402     /*
1403      * Disable SO_LINGER off during socket closing
1404      * to send "408 Request Timeout" error response.
1405      */
1406     c->socket.timedout = 0;
1407 
1408     h1p = c->socket.data;
1409     h1p->keepalive = 0;
1410     r = h1p->request;
1411 
1412     if (r->fields == NULL) {
1413         (void) nxt_h1p_header_process(task, h1p, r);
1414     }
1415 
1416     nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT);
1417 }
1418 
1419 
1420 static void
1421 nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)
1422 {
1423     nxt_conn_t     *c;
1424     nxt_timer_t    *timer;
1425     nxt_h1proto_t  *h1p;
1426 
1427     timer = obj;
1428 
1429     nxt_debug(task, "h1p conn request send timeout");
1430 
1431     c = nxt_write_timer_conn(timer);
1432     c->block_write = 1;
1433     h1p = c->socket.data;
1434 
1435     nxt_h1p_request_error(task, h1p, h1p->request);
1436 }
1437 
1438 
1439 nxt_msec_t
1440 nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data)
1441 {
1442     nxt_h1proto_t  *h1p;
1443 
1444     h1p = c->socket.data;
1445 
1446     return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data);
1447 }
1448 
1449 
1450 nxt_inline void
1451 nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
1452     nxt_http_request_t *r)
1453 {
1454     h1p->keepalive = 0;
1455 
1456     r->state->error_handler(task, r, h1p);
1457 }
1458 
1459 
1460 static void
1461 nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
1462     nxt_socket_conf_joint_t *joint)
1463 {
1464     nxt_conn_t     *c;
1465     nxt_h1proto_t  *h1p;
1466 
1467     nxt_debug(task, "h1p request close");
1468 
1469     h1p = proto.h1;
1470     h1p->request = NULL;
1471 
1472     nxt_router_conf_release(task, joint);
1473 
1474     c = h1p->conn;
1475 
1476     if (h1p->keepalive) {
1477         nxt_h1p_keepalive(task, h1p, c);
1478 
1479     } else {
1480         nxt_h1p_shutdown(task, c);
1481     }
1482 }
1483 
1484 
1485 static void
1486 nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data)
1487 {
1488     nxt_conn_t          *c;
1489     nxt_event_engine_t  *engine;
1490 
1491     c = obj;
1492 
1493     nxt_debug(task, "h1p conn sent");
1494 
1495     engine = task->thread->engine;
1496 
1497     c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
1498 
1499     if (c->write != NULL) {
1500         nxt_conn_write(engine, c);
1501     }
1502 }
1503 
1504 
1505 static void
1506 nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
1507 {
1508     nxt_conn_t  *c;
1509 
1510     c = obj;
1511 
1512     nxt_debug(task, "h1p conn close");
1513 
1514     nxt_h1p_shutdown(task, c);
1515 }
1516 
1517 
1518 static void
1519 nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
1520 {
1521     nxt_conn_t  *c;
1522 
1523     c = obj;
1524 
1525     nxt_debug(task, "h1p conn error");
1526 
1527     nxt_h1p_shutdown(task, c);
1528 }
1529 
1530 
1531 static nxt_msec_t
1532 nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data)
1533 {
1534     nxt_socket_conf_joint_t  *joint;
1535 
1536     joint = c->listen->socket.data;
1537 
1538     return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
1539 }
1540 
1541 
1542 static void
1543 nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
1544 {
1545     size_t     size;
1546     nxt_buf_t  *in;
1547 
1548     nxt_debug(task, "h1p keepalive");
1549 
1550     if (!c->tcp_nodelay) {
1551         nxt_conn_tcp_nodelay_on(task, c);
1552     }
1553 
1554     nxt_h1p_complete_buffers(task, h1p);
1555 
1556     in = c->read;
1557 
1558     nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn));
1559 
1560     c->sent = 0;
1561 
1562     if (in == NULL) {
1563         c->read_state = &nxt_h1p_keepalive_state;
1564 
1565         nxt_conn_read(task->thread->engine, c);
1566 
1567     } else {
1568         size = nxt_buf_mem_used_size(&in->mem);
1569 
1570         nxt_debug(task, "h1p pipelining");
1571 
1572         nxt_memmove(in->mem.start, in->mem.pos, size);
1573 
1574         in->mem.pos = in->mem.start;
1575         in->mem.free = in->mem.start + size;
1576 
1577         nxt_h1p_conn_request_init(task, c, c->socket.data);
1578     }
1579 }
1580 
1581 
1582 static const nxt_conn_state_t  nxt_h1p_keepalive_state
1583     nxt_aligned(64) =
1584 {
1585     .ready_handler = nxt_h1p_conn_request_init,
1586     .close_handler = nxt_h1p_conn_close,
1587     .error_handler = nxt_h1p_conn_error,
1588 
1589     .io_read_handler = nxt_h1p_idle_io_read_handler,
1590 
1591     .timer_handler = nxt_h1p_idle_timeout,
1592     .timer_value = nxt_h1p_conn_timer_value,
1593     .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
1594     .timer_autoreset = 1,
1595 };
1596 
1597 
1598 const nxt_conn_state_t  nxt_h1p_idle_close_state
1599     nxt_aligned(64) =
1600 {
1601     .close_handler = nxt_h1p_idle_close,
1602 };
1603 
1604 
1605 static void
1606 nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
1607 {
1608     nxt_conn_t  *c;
1609 
1610     c = obj;
1611 
1612     nxt_debug(task, "h1p idle close");
1613 
1614     nxt_h1p_idle_response(task, c);
1615 }
1616 
1617 
1618 static void
1619 nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
1620 {
1621     nxt_conn_t   *c;
1622     nxt_timer_t  *timer;
1623 
1624     timer = obj;
1625 
1626     nxt_debug(task, "h1p idle timeout");
1627 
1628     c = nxt_read_timer_conn(timer);
1629     c->block_read = 1;
1630 
1631     nxt_h1p_idle_response(task, c);
1632 }
1633 
1634 
1635 #define NXT_H1P_IDLE_TIMEOUT                                                  \
1636      "HTTP/1.1 408 Request Timeout\r\n"                                       \
1637      "Server: " NXT_SERVER "\r\n"                                             \
1638      "Connection: close\r\n"                                                  \
1639      "Content-Length: 0\r\n"                                                  \
1640      "Date: "
1641 
1642 
1643 static void
1644 nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c)
1645 {
1646     u_char     *p;
1647     size_t     size;
1648     nxt_buf_t  *out, *last;
1649 
1650     size = nxt_length(NXT_H1P_IDLE_TIMEOUT)
1651            + nxt_http_date_cache.size
1652            + nxt_length("\r\n\r\n");
1653 
1654     out = nxt_buf_mem_alloc(c->mem_pool, size, 0);
1655     if (nxt_slow_path(out == NULL)) {
1656         goto fail;
1657     }
1658 
1659     p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT,
1660                    nxt_length(NXT_H1P_IDLE_TIMEOUT));
1661 
1662     p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p);
1663 
1664     out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4);
1665 
1666     last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE);
1667     if (nxt_slow_path(last == NULL)) {
1668         goto fail;
1669     }
1670 
1671     out->next = last;
1672     nxt_buf_set_sync(last);
1673     nxt_buf_set_last(last);
1674 
1675     last->completion_handler = nxt_h1p_idle_response_sent;
1676     last->parent = c;
1677 
1678     c->write = out;
1679     c->write_state = &nxt_h1p_timeout_response_state;
1680 
1681     nxt_conn_write(task->thread->engine, c);
1682     return;
1683 
1684 fail:
1685 
1686     nxt_h1p_shutdown(task, c);
1687 }
1688 
1689 
1690 static const nxt_conn_state_t  nxt_h1p_timeout_response_state
1691     nxt_aligned(64) =
1692 {
1693     .ready_handler = nxt_h1p_conn_sent,
1694     .error_handler = nxt_h1p_conn_error,
1695 
1696     .timer_handler = nxt_h1p_idle_response_timeout,
1697     .timer_value = nxt_h1p_idle_response_timer_value,
1698 };
1699 
1700 
1701 static void
1702 nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data)
1703 {
1704     nxt_conn_t  *c;
1705 
1706     c = data;
1707 
1708     nxt_debug(task, "h1p idle timeout response sent");
1709 
1710     nxt_h1p_shutdown(task, c);
1711 }
1712 
1713 
1714 static void
1715 nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data)
1716 {
1717     nxt_conn_t   *c;
1718     nxt_timer_t  *timer;
1719 
1720     timer = obj;
1721 
1722     nxt_debug(task, "h1p idle timeout response timeout");
1723 
1724     c = nxt_read_timer_conn(timer);
1725     c->block_write = 1;
1726 
1727     nxt_h1p_shutdown(task, c);
1728 }
1729 
1730 
1731 static nxt_msec_t
1732 nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data)
1733 {
1734     return 10 * 1000;
1735 }
1736 
1737 
1738 static void
1739 nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c)
1740 {
1741     nxt_timer_t    *timer;
1742     nxt_h1proto_t  *h1p;
1743 
1744     nxt_debug(task, "h1p shutdown");
1745 
1746     h1p = c->socket.data;
1747 
1748     if (nxt_slow_path(h1p != NULL && h1p->websocket_timer != NULL)) {
1749         timer = &h1p->websocket_timer->timer;
1750 
1751         if (timer->handler != nxt_h1p_conn_ws_shutdown) {
1752             timer->handler = nxt_h1p_conn_ws_shutdown;
1753             nxt_timer_add(task->thread->engine, timer, 0);
1754 
1755         } else {
1756             nxt_debug(task, "h1p already scheduled ws shutdown");
1757         }
1758 
1759     } else {
1760         nxt_h1p_shutdown_(task, c);
1761     }
1762 }
1763 
1764 
1765 static void
1766 nxt_h1p_shutdown_(nxt_task_t *task, nxt_conn_t *c)
1767 {
1768     c->socket.data = NULL;
1769 
1770 #if (NXT_TLS)
1771 
1772     if (c->u.tls != NULL) {
1773         c->write_state = &nxt_h1p_shutdown_state;
1774 
1775         c->io->shutdown(task, c, NULL);
1776         return;
1777     }
1778 
1779 #endif
1780 
1781     nxt_h1p_conn_closing(task, c, NULL);
1782 }
1783 
1784 
1785 #if (NXT_TLS)
1786 
1787 static const nxt_conn_state_t  nxt_h1p_shutdown_state
1788     nxt_aligned(64) =
1789 {
1790     .ready_handler = nxt_h1p_conn_closing,
1791     .close_handler = nxt_h1p_conn_closing,
1792     .error_handler = nxt_h1p_conn_closing,
1793 };
1794 
1795 #endif
1796 
1797 
1798 static void
1799 nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data)
1800 {
1801     nxt_timer_t                *timer;
1802     nxt_h1p_websocket_timer_t  *ws_timer;
1803 
1804     nxt_debug(task, "h1p conn ws shutdown");
1805 
1806     timer = obj;
1807     ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer);
1808 
1809     nxt_h1p_shutdown_(task, ws_timer->h1p->conn);
1810 }
1811 
1812 
1813 static void
1814 nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data)
1815 {
1816     nxt_conn_t  *c;
1817 
1818     c = obj;
1819 
1820     nxt_debug(task, "h1p conn closing");
1821 
1822     c->write_state = &nxt_h1p_close_state;
1823 
1824     nxt_conn_close(task->thread->engine, c);
1825 }
1826 
1827 
1828 static const nxt_conn_state_t  nxt_h1p_close_state
1829     nxt_aligned(64) =
1830 {
1831     .ready_handler = nxt_h1p_conn_free,
1832 };
1833 
1834 
1835 static void
1836 nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data)
1837 {
1838     nxt_conn_t          *c;
1839     nxt_listen_event_t  *lev;
1840     nxt_event_engine_t  *engine;
1841 
1842     c = obj;
1843 
1844     nxt_debug(task, "h1p conn free");
1845 
1846     nxt_queue_remove(&c->link);
1847 
1848     engine = task->thread->engine;
1849 
1850     nxt_sockaddr_cache_free(engine, c);
1851 
1852     lev = c->listen;
1853 
1854     nxt_conn_free(task, c);
1855 
1856     nxt_router_listen_event_release(&engine->task, lev, NULL);
1857 }
1858