comparison src/http/v2/ngx_http_v2.c @ 6412:4ba91a4c66a3

HTTP/2: implemented per request timeouts (closes #626). Previously, there were only three timeouts used globally for the whole HTTP/2 connection: 1. Idle timeout for inactivity when there are no streams in processing (the "http2_idle_timeout" directive); 2. Receive timeout for incomplete frames when there are no streams in processing (the "http2_recv_timeout" directive); 3. Send timeout when there are frames waiting in the output queue (the "send_timeout" directive on a server level). Reaching one of these timeouts leads to HTTP/2 connection close. This left a number of scenarios when a connection can get stuck without any processing and timeouts: 1. A client has sent the headers block partially so nginx starts processing a new stream but cannot continue without the rest of HEADERS and/or CONTINUATION frames; 2. When nginx waits for the request body; 3. All streams are stuck on exhausted connection or stream windows. The first idea that was rejected was to detect when the whole connection gets stuck because of these situations and set the global receive timeout. The disadvantage of such approach would be inconsistent behaviour in some typical use cases. For example, if a user never replies to the browser's question about where to save the downloaded file, the stream will be eventually closed by a timeout. On the other hand, this will not happen if there's some activity in other concurrent streams. Now almost all the request timeouts work like in HTTP/1.x connections, so the "client_header_timeout", "client_body_timeout", and "send_timeout" are respected. These timeouts close the request. The global timeouts work as before. Previously, the c->write->delayed flag was abused to avoid setting timeouts on stream events. Now, the "active" and "ready" flags are manipulated instead to control the processing of individual streams.
author Valentin Bartenev <vbart@nginx.com>
date Wed, 24 Feb 2016 15:58:07 +0300
parents 8ec349bb60b2
children 4d1d3c2530e0
comparison
equal deleted inserted replaced
6411:8ec349bb60b2 6412:4ba91a4c66a3
112 u_char *pos, u_char *end); 112 u_char *pos, u_char *end);
113 static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, 113 static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c,
114 u_char *pos, u_char *end); 114 u_char *pos, u_char *end);
115 static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, 115 static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c,
116 u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); 116 u_char *pos, u_char *end, ngx_http_v2_handler_pt handler);
117 static u_char *ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c,
118 u_char *pos, u_char *end, ngx_http_v2_handler_pt handler);
117 static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, 119 static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
118 ngx_uint_t err); 120 ngx_uint_t err);
119 121
120 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, 122 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c,
121 u_char **pos, u_char *end, ngx_uint_t prefix); 123 u_char **pos, u_char *end, ngx_uint_t prefix);
160 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, 162 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
161 ngx_http_v2_header_t *header); 163 ngx_http_v2_header_t *header);
162 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); 164 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
163 static void ngx_http_v2_run_request(ngx_http_request_t *r); 165 static void ngx_http_v2_run_request(ngx_http_request_t *r);
164 static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); 166 static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r);
167 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
165 168
166 static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, 169 static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
167 ngx_http_v2_stream_t *stream, ngx_uint_t status); 170 ngx_http_v2_stream_t *stream, ngx_uint_t status);
168 static void ngx_http_v2_close_stream_handler(ngx_event_t *ev); 171 static void ngx_http_v2_close_stream_handler(ngx_event_t *ev);
169 static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev); 172 static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev);
428 431
429 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 432 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
430 "run http2 stream %ui", stream->node->id); 433 "run http2 stream %ui", stream->node->id);
431 434
432 wev = stream->request->connection->write; 435 wev = stream->request->connection->write;
436
437 wev->active = 0;
438 wev->ready = 1;
439
433 wev->handler(wev); 440 wev->handler(wev);
434 } 441 }
435 442
436 h2c->blocked = 0; 443 h2c->blocked = 0;
437 444
881 size_t size; 888 size_t size;
882 ssize_t n; 889 ssize_t n;
883 ngx_buf_t *buf; 890 ngx_buf_t *buf;
884 ngx_int_t rc; 891 ngx_int_t rc;
885 ngx_temp_file_t *tf; 892 ngx_temp_file_t *tf;
893 ngx_connection_t *fc;
886 ngx_http_request_t *r; 894 ngx_http_request_t *r;
887 ngx_http_v2_stream_t *stream; 895 ngx_http_v2_stream_t *stream;
888 ngx_http_request_body_t *rb; 896 ngx_http_request_body_t *rb;
889 ngx_http_core_loc_conf_t *clcf; 897 ngx_http_core_loc_conf_t *clcf;
890 898
917 { 925 {
918 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; 926 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR;
919 return ngx_http_v2_state_skip_padded(h2c, pos, end); 927 return ngx_http_v2_state_skip_padded(h2c, pos, end);
920 } 928 }
921 929
930 fc = r->connection;
922 rb = r->request_body; 931 rb = r->request_body;
923 tf = rb->temp_file; 932 tf = rb->temp_file;
924 buf = rb->buf; 933 buf = rb->buf;
925 934
926 if (size) { 935 if (size) {
927 rb->rest += size; 936 rb->rest += size;
928 937
929 if (r->headers_in.content_length_n != -1 938 if (r->headers_in.content_length_n != -1
930 && r->headers_in.content_length_n < rb->rest) 939 && r->headers_in.content_length_n < rb->rest)
931 { 940 {
932 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 941 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
933 "client intended to send body data " 942 "client intended to send body data "
934 "larger than declared"); 943 "larger than declared");
935 944
936 stream->skip_data = NGX_HTTP_V2_DATA_ERROR; 945 stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
937 goto error; 946 goto error;
940 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 949 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
941 950
942 if (clcf->client_max_body_size 951 if (clcf->client_max_body_size
943 && clcf->client_max_body_size < rb->rest) 952 && clcf->client_max_body_size < rb->rest)
944 { 953 {
945 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 954 ngx_log_error(NGX_LOG_ERR, fc->log, 0,
946 "client intended to send " 955 "client intended to send "
947 "too large chunked body: %O bytes", rb->rest); 956 "too large chunked body: %O bytes", rb->rest);
948 957
949 stream->skip_data = NGX_HTTP_V2_DATA_ERROR; 958 stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
950 goto error; 959 goto error;
980 989
981 r->request_length += size; 990 r->request_length += size;
982 } 991 }
983 992
984 if (h2c->state.length) { 993 if (h2c->state.length) {
994 if (rb->post_handler) {
995 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
996 ngx_add_timer(fc->read, clcf->client_body_timeout);
997 }
998
985 return ngx_http_v2_state_save(h2c, pos, end, 999 return ngx_http_v2_state_save(h2c, pos, end,
986 ngx_http_v2_state_read_data); 1000 ngx_http_v2_state_read_data);
987 } 1001 }
988 1002
989 if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { 1003 if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) {
991 1005
992 if (r->headers_in.content_length_n < 0) { 1006 if (r->headers_in.content_length_n < 0) {
993 r->headers_in.content_length_n = rb->rest; 1007 r->headers_in.content_length_n = rb->rest;
994 1008
995 } else if (r->headers_in.content_length_n != rb->rest) { 1009 } else if (r->headers_in.content_length_n != rb->rest) {
996 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 1010 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
997 "client prematurely closed stream: " 1011 "client prematurely closed stream: "
998 "only %O out of %O bytes of request body received", 1012 "only %O out of %O bytes of request body received",
999 rb->rest, r->headers_in.content_length_n); 1013 rb->rest, r->headers_in.content_length_n);
1000 1014
1001 stream->skip_data = NGX_HTTP_V2_DATA_ERROR; 1015 stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
1011 1025
1012 rb->buf = NULL; 1026 rb->buf = NULL;
1013 } 1027 }
1014 1028
1015 if (rb->post_handler) { 1029 if (rb->post_handler) {
1030 if (fc->read->timer_set) {
1031 ngx_del_timer(fc->read);
1032 }
1033
1016 r->read_event_handler = ngx_http_block_reading; 1034 r->read_event_handler = ngx_http_block_reading;
1017 rb->post_handler(r); 1035 rb->post_handler(r);
1018 } 1036 }
1037
1038 } else if (rb->post_handler) {
1039 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1040 ngx_add_timer(fc->read, clcf->client_body_timeout);
1019 } 1041 }
1020 1042
1021 if (h2c->state.padding) { 1043 if (h2c->state.padding) {
1022 return ngx_http_v2_state_skip_padded(h2c, pos, end); 1044 return ngx_http_v2_state_skip_padded(h2c, pos, end);
1023 } 1045 }
1025 return ngx_http_v2_state_complete(h2c, pos, end); 1047 return ngx_http_v2_state_complete(h2c, pos, end);
1026 1048
1027 error: 1049 error:
1028 1050
1029 if (rb->post_handler) { 1051 if (rb->post_handler) {
1052 if (fc->read->timer_set) {
1053 ngx_del_timer(fc->read);
1054 }
1030 1055
1031 if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { 1056 if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) {
1032 rc = (r->headers_in.content_length_n == -1) 1057 rc = (r->headers_in.content_length_n == -1)
1033 ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST; 1058 ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST;
1034 1059
1216 u_char ch; 1241 u_char ch;
1217 ngx_int_t value; 1242 ngx_int_t value;
1218 ngx_uint_t indexed, size_update, prefix; 1243 ngx_uint_t indexed, size_update, prefix;
1219 1244
1220 if (end - pos < 1) { 1245 if (end - pos < 1) {
1221 return ngx_http_v2_state_save(h2c, pos, end, 1246 return ngx_http_v2_state_headers_save(h2c, pos, end,
1222 ngx_http_v2_state_header_block); 1247 ngx_http_v2_state_header_block);
1223 } 1248 }
1224 1249
1225 if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) 1250 if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)
1226 && h2c->state.length < NGX_HTTP_V2_INT_OCTETS) 1251 && h2c->state.length < NGX_HTTP_V2_INT_OCTETS)
1227 { 1252 {
1260 1285
1261 value = ngx_http_v2_parse_int(h2c, &pos, end, prefix); 1286 value = ngx_http_v2_parse_int(h2c, &pos, end, prefix);
1262 1287
1263 if (value < 0) { 1288 if (value < 0) {
1264 if (value == NGX_AGAIN) { 1289 if (value == NGX_AGAIN) {
1265 return ngx_http_v2_state_save(h2c, pos, end, 1290 return ngx_http_v2_state_headers_save(h2c, pos, end,
1266 ngx_http_v2_state_header_block); 1291 ngx_http_v2_state_header_block);
1267 } 1292 }
1268 1293
1269 if (value == NGX_DECLINED) { 1294 if (value == NGX_DECLINED) {
1270 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, 1295 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1271 "client sent header block with too long %s value", 1296 "client sent header block with too long %s value",
1331 1356
1332 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); 1357 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1333 } 1358 }
1334 1359
1335 if (end - pos < 1) { 1360 if (end - pos < 1) {
1336 return ngx_http_v2_state_save(h2c, pos, end, 1361 return ngx_http_v2_state_headers_save(h2c, pos, end,
1337 ngx_http_v2_state_field_len); 1362 ngx_http_v2_state_field_len);
1338 } 1363 }
1339 1364
1340 huff = *pos >> 7; 1365 huff = *pos >> 7;
1341 len = ngx_http_v2_parse_int(h2c, &pos, end, ngx_http_v2_prefix(7)); 1366 len = ngx_http_v2_parse_int(h2c, &pos, end, ngx_http_v2_prefix(7));
1342 1367
1343 if (len < 0) { 1368 if (len < 0) {
1344 if (len == NGX_AGAIN) { 1369 if (len == NGX_AGAIN) {
1345 return ngx_http_v2_state_save(h2c, pos, end, 1370 return ngx_http_v2_state_headers_save(h2c, pos, end,
1346 ngx_http_v2_state_field_len); 1371 ngx_http_v2_state_field_len);
1347 } 1372 }
1348 1373
1349 if (len == NGX_DECLINED) { 1374 if (len == NGX_DECLINED) {
1350 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, 1375 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1351 "client sent header field with too long length value"); 1376 "client sent header field with too long length value");
1433 *h2c->state.field_end = '\0'; 1458 *h2c->state.field_end = '\0';
1434 return ngx_http_v2_state_process_header(h2c, pos, end); 1459 return ngx_http_v2_state_process_header(h2c, pos, end);
1435 } 1460 }
1436 1461
1437 if (h2c->state.length) { 1462 if (h2c->state.length) {
1438 return ngx_http_v2_state_save(h2c, pos, end, 1463 return ngx_http_v2_state_headers_save(h2c, pos, end,
1439 ngx_http_v2_state_field_huff); 1464 ngx_http_v2_state_field_huff);
1440 } 1465 }
1441 1466
1442 if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { 1467 if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
1443 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, 1468 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1444 "client sent header field with incorrect length"); 1469 "client sent header field with incorrect length");
1478 *h2c->state.field_end = '\0'; 1503 *h2c->state.field_end = '\0';
1479 return ngx_http_v2_state_process_header(h2c, pos, end); 1504 return ngx_http_v2_state_process_header(h2c, pos, end);
1480 } 1505 }
1481 1506
1482 if (h2c->state.length) { 1507 if (h2c->state.length) {
1483 return ngx_http_v2_state_save(h2c, pos, end, 1508 return ngx_http_v2_state_headers_save(h2c, pos, end,
1484 ngx_http_v2_state_field_raw); 1509 ngx_http_v2_state_field_raw);
1485 } 1510 }
1486 1511
1487 if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { 1512 if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
1488 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, 1513 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1489 "client sent header field with incorrect length"); 1514 "client sent header field with incorrect length");
1752 pos += skip; 1777 pos += skip;
1753 ngx_memmove(pos, p, len); 1778 ngx_memmove(pos, p, len);
1754 } 1779 }
1755 1780
1756 if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) { 1781 if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) {
1757 return ngx_http_v2_state_save(h2c, pos, end, handler); 1782 return ngx_http_v2_state_headers_save(h2c, pos, end, handler);
1758 } 1783 }
1759 1784
1760 p = pos + len; 1785 p = pos + len;
1761 1786
1762 head = ngx_http_v2_parse_uint32(p); 1787 head = ngx_http_v2_parse_uint32(p);
2227 if (stream->exhausted) { 2252 if (stream->exhausted) {
2228 stream->exhausted = 0; 2253 stream->exhausted = 0;
2229 2254
2230 wev = stream->request->connection->write; 2255 wev = stream->request->connection->write;
2231 2256
2232 if (!wev->timer_set) { 2257 wev->active = 0;
2233 wev->delayed = 0; 2258 wev->ready = 1;
2259
2260 if (!wev->delayed) {
2234 wev->handler(wev); 2261 wev->handler(wev);
2235 } 2262 }
2236 } 2263 }
2237 2264
2238 return ngx_http_v2_state_complete(h2c, pos, end); 2265 return ngx_http_v2_state_complete(h2c, pos, end);
2260 2287
2261 stream->handled = 0; 2288 stream->handled = 0;
2262 2289
2263 wev = stream->request->connection->write; 2290 wev = stream->request->connection->write;
2264 2291
2265 if (!wev->timer_set) { 2292 wev->active = 0;
2266 wev->delayed = 0; 2293 wev->ready = 1;
2294
2295 if (!wev->delayed) {
2267 wev->handler(wev); 2296 wev->handler(wev);
2268 2297
2269 if (h2c->send_window == 0) { 2298 if (h2c->send_window == 0) {
2270 break; 2299 break;
2271 } 2300 }
2365 h2c->state.buffer_used = size; 2394 h2c->state.buffer_used = size;
2366 h2c->state.handler = handler; 2395 h2c->state.handler = handler;
2367 h2c->state.incomplete = 1; 2396 h2c->state.incomplete = 1;
2368 2397
2369 return end; 2398 return end;
2399 }
2400
2401
2402 static u_char *
2403 ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, u_char *pos,
2404 u_char *end, ngx_http_v2_handler_pt handler)
2405 {
2406 ngx_event_t *rev;
2407 ngx_http_request_t *r;
2408 ngx_http_core_srv_conf_t *cscf;
2409
2410 if (h2c->state.stream) {
2411 r = h2c->state.stream->request;
2412 rev = r->connection->read;
2413
2414 if (!rev->timer_set) {
2415 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2416 ngx_add_timer(rev, cscf->client_header_timeout);
2417 }
2418 }
2419
2420 return ngx_http_v2_state_save(h2c, pos, end, handler);
2370 } 2421 }
2371 2422
2372 2423
2373 static u_char * 2424 static u_char *
2374 ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, 2425 ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
2746 } 2797 }
2747 2798
2748 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); 2799 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t));
2749 2800
2750 log->data = ctx; 2801 log->data = ctx;
2802 log->action = "reading client request headers";
2751 2803
2752 ngx_memzero(rev, sizeof(ngx_event_t)); 2804 ngx_memzero(rev, sizeof(ngx_event_t));
2753 2805
2754 rev->data = fc; 2806 rev->data = fc;
2755 rev->ready = 1; 2807 rev->ready = 1;
3552 3604
3553 ngx_int_t 3605 ngx_int_t
3554 ngx_http_v2_read_request_body(ngx_http_request_t *r, 3606 ngx_http_v2_read_request_body(ngx_http_request_t *r,
3555 ngx_http_client_body_handler_pt post_handler) 3607 ngx_http_client_body_handler_pt post_handler)
3556 { 3608 {
3557 ngx_http_v2_stream_t *stream; 3609 ngx_http_v2_stream_t *stream;
3610 ngx_http_core_loc_conf_t *clcf;
3558 3611
3559 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 3612 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3560 "http2 read request body"); 3613 "http2 read request body");
3561 3614
3562 stream = r->stream; 3615 stream = r->stream;
3588 return NGX_OK; 3641 return NGX_OK;
3589 } 3642 }
3590 3643
3591 r->request_body->post_handler = post_handler; 3644 r->request_body->post_handler = post_handler;
3592 3645
3593 r->read_event_handler = ngx_http_test_reading; 3646 r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
3594 r->write_event_handler = ngx_http_request_empty_handler; 3647 r->write_event_handler = ngx_http_request_empty_handler;
3595 3648
3649 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3650 ngx_add_timer(r->connection->read, clcf->client_body_timeout);
3651
3596 return NGX_AGAIN; 3652 return NGX_AGAIN;
3653 }
3654
3655
3656 static void
3657 ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
3658 {
3659 ngx_connection_t *fc;
3660
3661 fc = r->connection;
3662
3663 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
3664 "http2 read client request body handler");
3665
3666 if (fc->read->timedout) {
3667 ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out");
3668
3669 fc->timedout = 1;
3670 r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
3671
3672 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
3673 return;
3674 }
3675
3676 if (fc->error) {
3677 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
3678 "client prematurely closed stream");
3679
3680 r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
3681
3682 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
3683 return;
3684 }
3597 } 3685 }
3598 3686
3599 3687
3600 static ngx_int_t 3688 static ngx_int_t
3601 ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, 3689 ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
3645 return; 3733 return;
3646 } 3734 }
3647 3735
3648 if (!stream->out_closed) { 3736 if (!stream->out_closed) {
3649 if (ngx_http_v2_send_rst_stream(h2c, node->id, 3737 if (ngx_http_v2_send_rst_stream(h2c, node->id,
3650 NGX_HTTP_V2_INTERNAL_ERROR) 3738 fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
3739 : NGX_HTTP_V2_INTERNAL_ERROR)
3651 != NGX_OK) 3740 != NGX_OK)
3652 { 3741 {
3653 h2c->connection->error = 1; 3742 h2c->connection->error = 1;
3654 } 3743 }
3655 } 3744 }
3682 h2c->state.keep_pool = 0; 3771 h2c->state.keep_pool = 0;
3683 } 3772 }
3684 3773
3685 ev = fc->read; 3774 ev = fc->read;
3686 3775
3687 if (ev->active || ev->disabled) {
3688 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
3689 "fake read event was activated");
3690 }
3691
3692 if (ev->timer_set) { 3776 if (ev->timer_set) {
3693 ngx_del_timer(ev); 3777 ngx_del_timer(ev);
3694 } 3778 }
3695 3779
3696 if (ev->posted) { 3780 if (ev->posted) {
3697 ngx_delete_posted_event(ev); 3781 ngx_delete_posted_event(ev);
3698 } 3782 }
3699 3783
3700 ev = fc->write; 3784 ev = fc->write;
3701 3785
3702 if (ev->active || ev->disabled) {
3703 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
3704 "fake write event was activated");
3705 }
3706
3707 if (ev->timer_set) { 3786 if (ev->timer_set) {
3708 ngx_del_timer(ev); 3787 ngx_del_timer(ev);
3709 } 3788 }
3710 3789
3711 if (ev->posted) { 3790 if (ev->posted) {
3735 ngx_http_request_t *r; 3814 ngx_http_request_t *r;
3736 3815
3737 fc = ev->data; 3816 fc = ev->data;
3738 r = fc->data; 3817 r = fc->data;
3739 3818
3740 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 3819 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
3741 "http2 close stream handler"); 3820 "http2 close stream handler");
3821
3822 if (ev->timedout) {
3823 ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out");
3824
3825 fc->timedout = 1;
3826
3827 ngx_http_v2_close_stream(r->stream, NGX_HTTP_REQUEST_TIME_OUT);
3828 return;
3829 }
3742 3830
3743 ngx_http_v2_close_stream(r->stream, 0); 3831 ngx_http_v2_close_stream(r->stream, 0);
3744 } 3832 }
3745 3833
3746 3834
3747 static void 3835 static void
3748 ngx_http_v2_handle_connection_handler(ngx_event_t *rev) 3836 ngx_http_v2_handle_connection_handler(ngx_event_t *rev)
3749 { 3837 {
3750 ngx_connection_t *c; 3838 ngx_connection_t *c;
3839 ngx_http_v2_connection_t *h2c;
3840
3841 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
3842 "http2 handle connection handler");
3751 3843
3752 rev->handler = ngx_http_v2_read_handler; 3844 rev->handler = ngx_http_v2_read_handler;
3753 3845
3754 if (rev->ready) { 3846 if (rev->ready) {
3755 ngx_http_v2_read_handler(rev); 3847 ngx_http_v2_read_handler(rev);
3756 return; 3848 return;
3757 } 3849 }
3758 3850
3759 c = rev->data; 3851 c = rev->data;
3852 h2c = c->data;
3853
3854 if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
3855 ngx_http_v2_finalize_connection(h2c, 0);
3856 return;
3857 }
3760 3858
3761 ngx_http_v2_handle_connection(c->data); 3859 ngx_http_v2_handle_connection(c->data);
3762 } 3860 }
3763 3861
3764 3862
3876 3974
3877 fc->error = 1; 3975 fc->error = 1;
3878 3976
3879 if (stream->queued) { 3977 if (stream->queued) {
3880 stream->queued = 0; 3978 stream->queued = 0;
3881
3882 ev = fc->write; 3979 ev = fc->write;
3883 ev->delayed = 0;
3884 3980
3885 } else { 3981 } else {
3886 ev = fc->read; 3982 ev = fc->read;
3887 } 3983 }
3888 3984
3947 if (stream->send_window > 0 && stream->exhausted) { 4043 if (stream->send_window > 0 && stream->exhausted) {
3948 stream->exhausted = 0; 4044 stream->exhausted = 0;
3949 4045
3950 wev = stream->request->connection->write; 4046 wev = stream->request->connection->write;
3951 4047
3952 if (!wev->timer_set) { 4048 wev->active = 0;
3953 wev->delayed = 0; 4049 wev->ready = 1;
4050
4051 if (!wev->delayed) {
3954 wev->handler(wev); 4052 wev->handler(wev);
3955 } 4053 }
3956 } 4054 }
3957 } 4055 }
3958 } 4056 }