Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 7201:641306096f5b
HTTP/2: server push.
Resources to be pushed are configured with the "http2_push" directive.
Also, preload links from the Link response headers, as described in
https://www.w3.org/TR/preload/#server-push-http-2, can be pushed, if
enabled with the "http2_push_preload" directive.
Only relative URIs with absolute paths can be pushed.
The number of concurrent pushes is normally limited by a client, but
cannot exceed a hard limit set by the "http2_max_concurrent_pushes"
directive.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Thu, 08 Feb 2018 09:55:03 +0300 |
parents | cadb43014c7c |
children | e44c297a6b95 |
comparison
equal
deleted
inserted
replaced
7200:cadb43014c7c | 7201:641306096f5b |
---|---|
33 #define NGX_HTTP_V2_PRIORITY_SIZE 5 | 33 #define NGX_HTTP_V2_PRIORITY_SIZE 5 |
34 #define NGX_HTTP_V2_PING_SIZE 8 | 34 #define NGX_HTTP_V2_PING_SIZE 8 |
35 #define NGX_HTTP_V2_GOAWAY_SIZE 8 | 35 #define NGX_HTTP_V2_GOAWAY_SIZE 8 |
36 #define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4 | 36 #define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4 |
37 | 37 |
38 #define NGX_HTTP_V2_STREAM_ID_SIZE 4 | |
39 | |
40 #define NGX_HTTP_V2_SETTINGS_PARAM_SIZE 6 | 38 #define NGX_HTTP_V2_SETTINGS_PARAM_SIZE 6 |
41 | 39 |
42 /* settings fields */ | 40 /* settings fields */ |
43 #define NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING 0x1 | 41 #define NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING 0x1 |
42 #define NGX_HTTP_V2_ENABLE_PUSH_SETTING 0x2 | |
44 #define NGX_HTTP_V2_MAX_STREAMS_SETTING 0x3 | 43 #define NGX_HTTP_V2_MAX_STREAMS_SETTING 0x3 |
45 #define NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING 0x4 | 44 #define NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING 0x4 |
46 #define NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING 0x5 | 45 #define NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING 0x5 |
47 | 46 |
48 #define NGX_HTTP_V2_FRAME_BUFFER_SIZE 24 | 47 #define NGX_HTTP_V2_FRAME_BUFFER_SIZE 24 |
119 | 118 |
120 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, | 119 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); | 120 u_char **pos, u_char *end, ngx_uint_t prefix); |
122 | 121 |
123 static ngx_http_v2_stream_t *ngx_http_v2_create_stream( | 122 static ngx_http_v2_stream_t *ngx_http_v2_create_stream( |
124 ngx_http_v2_connection_t *h2c); | 123 ngx_http_v2_connection_t *h2c, ngx_uint_t push); |
125 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( | 124 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( |
126 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); | 125 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); |
127 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( | 126 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( |
128 ngx_http_v2_connection_t *h2c); | 127 ngx_http_v2_connection_t *h2c); |
129 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) | 128 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) |
160 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); | 159 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); |
161 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, | 160 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, |
162 ngx_http_v2_header_t *header); | 161 ngx_http_v2_header_t *header); |
163 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); | 162 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); |
164 static void ngx_http_v2_run_request(ngx_http_request_t *r); | 163 static void ngx_http_v2_run_request(ngx_http_request_t *r); |
164 static void ngx_http_v2_run_request_handler(ngx_event_t *ev); | |
165 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, | 165 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, |
166 u_char *pos, size_t size, ngx_uint_t last); | 166 u_char *pos, size_t size, ngx_uint_t last); |
167 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); | 167 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); |
168 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); | 168 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); |
169 | 169 |
247 | 247 |
248 h2c->table_update = 1; | 248 h2c->table_update = 1; |
249 | 249 |
250 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); | 250 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); |
251 | 251 |
252 h2c->concurrent_pushes = h2scf->concurrent_pushes; | |
253 | |
252 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); | 254 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); |
253 if (h2c->pool == NULL) { | 255 if (h2c->pool == NULL) { |
254 ngx_http_close_connection(c); | 256 ngx_http_close_connection(c); |
255 return; | 257 return; |
256 } | 258 } |
364 | 366 |
365 if (n == NGX_AGAIN) { | 367 if (n == NGX_AGAIN) { |
366 break; | 368 break; |
367 } | 369 } |
368 | 370 |
369 if (n == 0 && (h2c->state.incomplete || h2c->processing)) { | 371 if (n == 0 |
372 && (h2c->state.incomplete || h2c->processing || h2c->pushing)) | |
373 { | |
370 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 374 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
371 "client prematurely closed connection"); | 375 "client prematurely closed connection"); |
372 } | 376 } |
373 | 377 |
374 if (n == 0 || n == NGX_ERROR) { | 378 if (n == 0 || n == NGX_ERROR) { |
403 return; | 407 return; |
404 } | 408 } |
405 | 409 |
406 h2c->blocked = 0; | 410 h2c->blocked = 0; |
407 | 411 |
408 if (h2c->processing) { | 412 if (h2c->processing || h2c->pushing) { |
409 if (rev->timer_set) { | 413 if (rev->timer_set) { |
410 ngx_del_timer(rev); | 414 ngx_del_timer(rev); |
411 } | 415 } |
412 | 416 |
413 return; | 417 return; |
587 { | 591 { |
588 ngx_int_t rc; | 592 ngx_int_t rc; |
589 ngx_connection_t *c; | 593 ngx_connection_t *c; |
590 ngx_http_v2_srv_conf_t *h2scf; | 594 ngx_http_v2_srv_conf_t *h2scf; |
591 | 595 |
592 if (h2c->last_out || h2c->processing) { | 596 if (h2c->last_out || h2c->processing || h2c->pushing) { |
593 return; | 597 return; |
594 } | 598 } |
595 | 599 |
596 c = h2c->connection; | 600 c = h2c->connection; |
597 | 601 |
1121 if (node->parent) { | 1125 if (node->parent) { |
1122 ngx_queue_remove(&node->reuse); | 1126 ngx_queue_remove(&node->reuse); |
1123 h2c->closed_nodes--; | 1127 h2c->closed_nodes--; |
1124 } | 1128 } |
1125 | 1129 |
1126 stream = ngx_http_v2_create_stream(h2c); | 1130 stream = ngx_http_v2_create_stream(h2c, 0); |
1127 if (stream == NULL) { | 1131 if (stream == NULL) { |
1128 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | 1132 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); |
1129 } | 1133 } |
1130 | 1134 |
1131 h2c->state.stream = stream; | 1135 h2c->state.stream = stream; |
1907 case NGX_HTTP_V2_CANCEL: | 1911 case NGX_HTTP_V2_CANCEL: |
1908 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | 1912 ngx_log_error(NGX_LOG_INFO, fc->log, 0, |
1909 "client canceled stream %ui", h2c->state.sid); | 1913 "client canceled stream %ui", h2c->state.sid); |
1910 break; | 1914 break; |
1911 | 1915 |
1916 case NGX_HTTP_V2_REFUSED_STREAM: | |
1917 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | |
1918 "client refused stream %ui", h2c->state.sid); | |
1919 break; | |
1920 | |
1912 case NGX_HTTP_V2_INTERNAL_ERROR: | 1921 case NGX_HTTP_V2_INTERNAL_ERROR: |
1913 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | 1922 ngx_log_error(NGX_LOG_INFO, fc->log, 0, |
1914 "client terminated stream %ui due to internal error", | 1923 "client terminated stream %ui due to internal error", |
1915 h2c->state.sid); | 1924 h2c->state.sid); |
1916 break; | 1925 break; |
1964 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, | 1973 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, |
1965 u_char *end) | 1974 u_char *end) |
1966 { | 1975 { |
1967 ssize_t window_delta; | 1976 ssize_t window_delta; |
1968 ngx_uint_t id, value; | 1977 ngx_uint_t id, value; |
1978 ngx_http_v2_srv_conf_t *h2scf; | |
1969 ngx_http_v2_out_frame_t *frame; | 1979 ngx_http_v2_out_frame_t *frame; |
1970 | 1980 |
1971 window_delta = 0; | 1981 window_delta = 0; |
1972 | 1982 |
1973 while (h2c->state.length) { | 1983 while (h2c->state.length) { |
2012 return ngx_http_v2_connection_error(h2c, | 2022 return ngx_http_v2_connection_error(h2c, |
2013 NGX_HTTP_V2_PROTOCOL_ERROR); | 2023 NGX_HTTP_V2_PROTOCOL_ERROR); |
2014 } | 2024 } |
2015 | 2025 |
2016 h2c->frame_size = value; | 2026 h2c->frame_size = value; |
2027 break; | |
2028 | |
2029 case NGX_HTTP_V2_ENABLE_PUSH_SETTING: | |
2030 | |
2031 if (value > 1) { | |
2032 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, | |
2033 "client sent SETTINGS frame with incorrect " | |
2034 "ENABLE_PUSH value %ui", value); | |
2035 | |
2036 return ngx_http_v2_connection_error(h2c, | |
2037 NGX_HTTP_V2_PROTOCOL_ERROR); | |
2038 } | |
2039 | |
2040 h2c->push_disabled = !value; | |
2041 break; | |
2042 | |
2043 case NGX_HTTP_V2_MAX_STREAMS_SETTING: | |
2044 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, | |
2045 ngx_http_v2_module); | |
2046 | |
2047 h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); | |
2017 break; | 2048 break; |
2018 | 2049 |
2019 default: | 2050 default: |
2020 break; | 2051 break; |
2021 } | 2052 } |
2481 | 2512 |
2482 return NGX_AGAIN; | 2513 return NGX_AGAIN; |
2483 } | 2514 } |
2484 | 2515 |
2485 | 2516 |
2517 ngx_int_t | |
2518 ngx_http_v2_push_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t depend, | |
2519 size_t request_length, ngx_str_t *path, ngx_str_t *authority) | |
2520 { | |
2521 ngx_int_t rc; | |
2522 ngx_str_t value; | |
2523 ngx_connection_t *fc; | |
2524 ngx_http_request_t *r; | |
2525 ngx_http_v2_node_t *node; | |
2526 ngx_http_v2_stream_t *stream; | |
2527 | |
2528 node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); | |
2529 | |
2530 if (node == NULL) { | |
2531 return NGX_ERROR; | |
2532 } | |
2533 | |
2534 if (node->parent) { | |
2535 ngx_queue_remove(&node->reuse); | |
2536 h2c->closed_nodes--; | |
2537 } | |
2538 | |
2539 stream = ngx_http_v2_create_stream(h2c, 1); | |
2540 if (stream == NULL) { | |
2541 return NGX_ERROR; | |
2542 } | |
2543 | |
2544 stream->pool = ngx_create_pool(1024, h2c->connection->log); | |
2545 if (stream->pool == NULL) { | |
2546 return NGX_ERROR; | |
2547 } | |
2548 | |
2549 r = stream->request; | |
2550 fc = r->connection; | |
2551 | |
2552 r->request_length = request_length; | |
2553 | |
2554 stream->in_closed = 1; | |
2555 stream->node = node; | |
2556 | |
2557 node->stream = stream; | |
2558 | |
2559 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, | |
2560 "http2 push stream sid:%ui " | |
2561 "depends on %ui excl:0 weight:16", | |
2562 h2c->last_push, depend); | |
2563 | |
2564 node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; | |
2565 ngx_http_v2_set_dependency(h2c, node, depend, 0); | |
2566 | |
2567 r->method_name = ngx_http_core_get_method; | |
2568 r->method = NGX_HTTP_GET; | |
2569 | |
2570 r->schema_start = (u_char *) "https"; | |
2571 | |
2572 #if (NGX_HTTP_SSL) | |
2573 if (fc->ssl) { | |
2574 r->schema_end = r->schema_start + 5; | |
2575 | |
2576 } else | |
2577 #endif | |
2578 { | |
2579 r->schema_end = r->schema_start + 4; | |
2580 } | |
2581 | |
2582 value.len = authority->len; | |
2583 | |
2584 value.data = ngx_pstrdup(stream->pool, authority); | |
2585 if (value.data == NULL) { | |
2586 return NGX_ERROR; | |
2587 } | |
2588 | |
2589 rc = ngx_http_v2_parse_authority(r, &value); | |
2590 | |
2591 if (rc != NGX_OK) { | |
2592 goto error; | |
2593 } | |
2594 | |
2595 value.len = path->len; | |
2596 | |
2597 value.data = ngx_pstrdup(stream->pool, path); | |
2598 if (value.data == NULL) { | |
2599 return NGX_ERROR; | |
2600 } | |
2601 | |
2602 rc = ngx_http_v2_parse_path(r, &value); | |
2603 | |
2604 if (rc != NGX_OK) { | |
2605 goto error; | |
2606 } | |
2607 | |
2608 fc->write->handler = ngx_http_v2_run_request_handler; | |
2609 ngx_post_event(fc->write, &ngx_posted_events); | |
2610 | |
2611 return NGX_OK; | |
2612 | |
2613 error: | |
2614 | |
2615 if (rc == NGX_ABORT) { | |
2616 return NGX_ERROR; | |
2617 } | |
2618 | |
2619 if (rc == NGX_DECLINED) { | |
2620 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
2621 return NGX_ERROR; | |
2622 } | |
2623 | |
2624 (void) ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | |
2625 | |
2626 return NGX_ERROR; | |
2627 } | |
2628 | |
2629 | |
2486 static ngx_int_t | 2630 static ngx_int_t |
2487 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) | 2631 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) |
2488 { | 2632 { |
2489 size_t len; | 2633 size_t len; |
2490 ngx_buf_t *buf; | 2634 ngx_buf_t *buf; |
2741 return NGX_OK; | 2885 return NGX_OK; |
2742 } | 2886 } |
2743 | 2887 |
2744 | 2888 |
2745 static ngx_http_v2_stream_t * | 2889 static ngx_http_v2_stream_t * |
2746 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) | 2890 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) |
2747 { | 2891 { |
2748 ngx_log_t *log; | 2892 ngx_log_t *log; |
2749 ngx_event_t *rev, *wev; | 2893 ngx_event_t *rev, *wev; |
2750 ngx_connection_t *fc; | 2894 ngx_connection_t *fc; |
2751 ngx_http_log_ctx_t *ctx; | 2895 ngx_http_log_ctx_t *ctx; |
2796 } | 2940 } |
2797 | 2941 |
2798 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); | 2942 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); |
2799 | 2943 |
2800 log->data = ctx; | 2944 log->data = ctx; |
2801 log->action = "reading client request headers"; | 2945 |
2946 if (push) { | |
2947 log->action = "processing pushed request headers"; | |
2948 | |
2949 } else { | |
2950 log->action = "reading client request headers"; | |
2951 } | |
2802 | 2952 |
2803 ngx_memzero(rev, sizeof(ngx_event_t)); | 2953 ngx_memzero(rev, sizeof(ngx_event_t)); |
2804 | 2954 |
2805 rev->data = fc; | 2955 rev->data = fc; |
2806 rev->ready = 1; | 2956 rev->ready = 1; |
2868 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); | 3018 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); |
2869 | 3019 |
2870 stream->send_window = h2c->init_window; | 3020 stream->send_window = h2c->init_window; |
2871 stream->recv_window = h2scf->preread_size; | 3021 stream->recv_window = h2scf->preread_size; |
2872 | 3022 |
2873 h2c->processing++; | 3023 if (push) { |
3024 h2c->pushing++; | |
3025 | |
3026 } else { | |
3027 h2c->processing++; | |
3028 } | |
2874 | 3029 |
2875 return stream; | 3030 return stream; |
2876 } | 3031 } |
2877 | 3032 |
2878 | 3033 |
3530 | 3685 |
3531 ngx_http_process_request(r); | 3686 ngx_http_process_request(r); |
3532 } | 3687 } |
3533 | 3688 |
3534 | 3689 |
3690 static void | |
3691 ngx_http_v2_run_request_handler(ngx_event_t *ev) | |
3692 { | |
3693 ngx_connection_t *fc; | |
3694 ngx_http_request_t *r; | |
3695 | |
3696 fc = ev->data; | |
3697 r = fc->data; | |
3698 | |
3699 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, | |
3700 "http2 run request handler"); | |
3701 | |
3702 ngx_http_v2_run_request(r); | |
3703 } | |
3704 | |
3705 | |
3535 ngx_int_t | 3706 ngx_int_t |
3536 ngx_http_v2_read_request_body(ngx_http_request_t *r) | 3707 ngx_http_v2_read_request_body(ngx_http_request_t *r) |
3537 { | 3708 { |
3538 off_t len; | 3709 off_t len; |
3539 size_t size; | 3710 size_t size; |
4001 | 4172 |
4002 void | 4173 void |
4003 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) | 4174 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) |
4004 { | 4175 { |
4005 ngx_pool_t *pool; | 4176 ngx_pool_t *pool; |
4177 ngx_uint_t push; | |
4006 ngx_event_t *ev; | 4178 ngx_event_t *ev; |
4007 ngx_connection_t *fc; | 4179 ngx_connection_t *fc; |
4008 ngx_http_v2_node_t *node; | 4180 ngx_http_v2_node_t *node; |
4009 ngx_http_v2_connection_t *h2c; | 4181 ngx_http_v2_connection_t *h2c; |
4010 | 4182 |
4011 h2c = stream->connection; | 4183 h2c = stream->connection; |
4012 node = stream->node; | 4184 node = stream->node; |
4013 | 4185 |
4014 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, | 4186 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, |
4015 "http2 close stream %ui, queued %ui, processing %ui", | 4187 "http2 close stream %ui, queued %ui, " |
4016 node->id, stream->queued, h2c->processing); | 4188 "processing %ui, pushing %ui", |
4189 node->id, stream->queued, h2c->processing, h2c->pushing); | |
4017 | 4190 |
4018 fc = stream->request->connection; | 4191 fc = stream->request->connection; |
4019 | 4192 |
4020 if (stream->queued) { | 4193 if (stream->queued) { |
4021 fc->write->handler = ngx_http_v2_close_stream_handler; | 4194 fc->write->handler = ngx_http_v2_close_stream_handler; |
4067 | 4240 |
4068 if (h2c->state.stream == stream) { | 4241 if (h2c->state.stream == stream) { |
4069 h2c->state.stream = NULL; | 4242 h2c->state.stream = NULL; |
4070 } | 4243 } |
4071 | 4244 |
4245 push = stream->node->id % 2 == 0; | |
4246 | |
4072 node->stream = NULL; | 4247 node->stream = NULL; |
4073 | 4248 |
4074 ngx_queue_insert_tail(&h2c->closed, &node->reuse); | 4249 ngx_queue_insert_tail(&h2c->closed, &node->reuse); |
4075 h2c->closed_nodes++; | 4250 h2c->closed_nodes++; |
4076 | 4251 |
4114 } | 4289 } |
4115 | 4290 |
4116 fc->data = h2c->free_fake_connections; | 4291 fc->data = h2c->free_fake_connections; |
4117 h2c->free_fake_connections = fc; | 4292 h2c->free_fake_connections = fc; |
4118 | 4293 |
4119 h2c->processing--; | 4294 if (push) { |
4120 | 4295 h2c->pushing--; |
4121 if (h2c->processing || h2c->blocked) { | 4296 |
4297 } else { | |
4298 h2c->processing--; | |
4299 } | |
4300 | |
4301 if (h2c->processing || h2c->pushing || h2c->blocked) { | |
4122 return; | 4302 return; |
4123 } | 4303 } |
4124 | 4304 |
4125 ev = h2c->connection->read; | 4305 ev = h2c->connection->read; |
4126 | 4306 |
4265 } | 4445 } |
4266 } | 4446 } |
4267 | 4447 |
4268 c->error = 1; | 4448 c->error = 1; |
4269 | 4449 |
4270 if (!h2c->processing) { | 4450 if (!h2c->processing && !h2c->pushing) { |
4271 ngx_http_close_connection(c); | 4451 ngx_http_close_connection(c); |
4272 return; | 4452 return; |
4273 } | 4453 } |
4274 | 4454 |
4275 c->read->handler = ngx_http_empty_handler; | 4455 c->read->handler = ngx_http_empty_handler; |
4314 } | 4494 } |
4315 } | 4495 } |
4316 | 4496 |
4317 h2c->blocked = 0; | 4497 h2c->blocked = 0; |
4318 | 4498 |
4319 if (h2c->processing) { | 4499 if (h2c->processing || h2c->pushing) { |
4320 return; | 4500 return; |
4321 } | 4501 } |
4322 | 4502 |
4323 ngx_http_close_connection(c); | 4503 ngx_http_close_connection(c); |
4324 } | 4504 } |