Deleted Added
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)
21static ssize_t nxt_http_idle_io_read_handler(nxt_conn_t *c);
22static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data);
23#endif
24static ssize_t nxt_h1p_idle_io_read_handler(nxt_conn_t *c);
25static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data);
26static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data);
27static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj,
28 void *data);
29static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p,
30 nxt_http_request_t *r);
31static 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);
33static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field,
34 uintptr_t data);
35static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field,
36 uintptr_t data);
37static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field,
38 uintptr_t data);
39static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field,
40 uintptr_t data);
41static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field,
42 uintptr_t data);
43static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r);
44static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj,
45 void *data);
46static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r);
47static void nxt_h1p_request_header_send(nxt_task_t *task,
48 nxt_http_request_t *r);

--- 5 unchanged lines hidden (view full) ---

54 nxt_http_proto_t proto);
55static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
56 nxt_buf_t *last);
57static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data);
58static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj,
59 void *data);
60static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj,
61 void *data);
62nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
63 nxt_http_request_t *r);
64static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
65 nxt_socket_conf_joint_t *joint);
66static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data);
67static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data);
68static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data);
69static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data);
70static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p,
71 nxt_conn_t *c);
72static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data);
73static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data);
74static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c);
75static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data);
76static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj,
77 void *data);
78static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c,
79 uintptr_t data);
80static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c);
81static void nxt_h1p_shutdown_(nxt_task_t *task, nxt_conn_t *c);
82static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data);
83static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data);
84static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data);
85
86#if (NXT_TLS)
87static const nxt_conn_state_t nxt_http_idle_state;
88static const nxt_conn_state_t nxt_h1p_shutdown_state;
89#endif
90static const nxt_conn_state_t nxt_h1p_idle_state;
91static const nxt_conn_state_t nxt_h1p_header_parse_state;
92static const nxt_conn_state_t nxt_h1p_read_body_state;
93static const nxt_conn_state_t nxt_h1p_request_send_state;
94static const nxt_conn_state_t nxt_h1p_timeout_response_state;
95static const nxt_conn_state_t nxt_h1p_keepalive_state;
96static const nxt_conn_state_t nxt_h1p_close_state;
97
98
99const 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
116static nxt_lvlhsh_t nxt_h1p_fields_hash;
117
118static 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,

--- 358 unchanged lines hidden (view full) ---

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 }

--- 31 unchanged lines hidden (view full) ---

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
548error:
549
550 h1p->keepalive = 0;
551
552 nxt_http_request_error(task, r, status);
553}
554
555
556static nxt_int_t
557nxt_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
620static nxt_int_t
621nxt_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;

--- 25 unchanged lines hidden (view full) ---

650
651 return NXT_OK;
652}
653
654
655static nxt_int_t
656nxt_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
676static nxt_int_t
677nxt_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
694static nxt_int_t
695nxt_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
709static nxt_int_t
710nxt_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
726static nxt_int_t
727nxt_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

--- 78 unchanged lines hidden (view full) ---

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 }

--- 62 unchanged lines hidden (view full) ---

892
893static void
894nxt_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
903static 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
912static 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"),

--- 40 unchanged lines hidden (view full) ---

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

--- 33 unchanged lines hidden (view full) ---

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) {

--- 15 unchanged lines hidden (view full) ---

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
1176void
1177nxt_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
1224static 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,

--- 131 unchanged lines hidden (view full) ---

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}

--- 19 unchanged lines hidden (view full) ---

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
1420static void
1421nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)

--- 9 unchanged lines hidden (view full) ---

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
1439nxt_msec_t
1440nxt_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}

--- 90 unchanged lines hidden (view full) ---

1538 return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
1539}
1540
1541
1542static void
1543nxt_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);

--- 12 unchanged lines hidden (view full) ---

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
1598const nxt_conn_state_t nxt_h1p_idle_close_state
1599 nxt_aligned(64) =
1600{
1601 .close_handler = nxt_h1p_idle_close,
1602};
1603
1604
1605static void
1606nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)

--- 126 unchanged lines hidden (view full) ---

1733{
1734 return 10 * 1000;
1735}
1736
1737
1738static void
1739nxt_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
1765static void
1766nxt_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);

--- 15 unchanged lines hidden (view full) ---

1791 .close_handler = nxt_h1p_conn_closing,
1792 .error_handler = nxt_h1p_conn_closing,
1793};
1794
1795#endif
1796
1797
1798static void
1799nxt_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
1813static void
1814nxt_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

--- 36 unchanged lines hidden ---