comparison src/http/v2/ngx_http_v2.c @ 9121:262c01782566

HTTP/2: removed server push (ticket #2432). Although it has better implementation status than HTTP/3 server push, it remains of limited use, with adoption numbers seen as negligible. Per IETF 102 materials, server push was used only in 0.04% of sessions. It was considered to be "difficult to use effectively" in RFC 9113. Its use is further limited by badly matching to fetch/cache/connection models in browsers, see related discussions linked from [1]. Server push was disabled in Chrome 106 [2]. The http2_push, http2_push_preload, and http2_max_concurrent_pushes directives are made obsolete. In particular, this essentially reverts 7201:641306096f5b and 7207:3d2b0b02bd3d. [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ [2] https://chromestatus.com/feature/6302414934114304
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 08 Jun 2023 16:56:46 +0400
parents 08ef02ad5c54
children cdda286c0f1b
comparison
equal deleted inserted replaced
9120:0aaa09927703 9121:262c01782566
7 7
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 #include <ngx_http_v2_module.h> 11 #include <ngx_http_v2_module.h>
12
13
14 typedef struct {
15 ngx_str_t name;
16 ngx_uint_t offset;
17 ngx_uint_t hash;
18 ngx_http_header_t *hh;
19 } ngx_http_v2_parse_header_t;
20 12
21 13
22 /* errors */ 14 /* errors */
23 #define NGX_HTTP_V2_NO_ERROR 0x0 15 #define NGX_HTTP_V2_NO_ERROR 0x0
24 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 16 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1
124 116
125 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, 117 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c,
126 u_char **pos, u_char *end, ngx_uint_t prefix); 118 u_char **pos, u_char *end, ngx_uint_t prefix);
127 119
128 static ngx_http_v2_stream_t *ngx_http_v2_create_stream( 120 static ngx_http_v2_stream_t *ngx_http_v2_create_stream(
129 ngx_http_v2_connection_t *h2c, ngx_uint_t push); 121 ngx_http_v2_connection_t *h2c);
130 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( 122 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id(
131 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); 123 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc);
132 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( 124 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node(
133 ngx_http_v2_connection_t *h2c); 125 ngx_http_v2_connection_t *h2c);
134 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) 126 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1)
160 ngx_str_t *value); 152 ngx_str_t *value);
161 static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r, 153 static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r,
162 ngx_str_t *value); 154 ngx_str_t *value);
163 static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, 155 static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r,
164 ngx_str_t *value); 156 ngx_str_t *value);
165 static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r,
166 ngx_http_v2_parse_header_t *header, ngx_str_t *value);
167 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); 157 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r);
168 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, 158 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
169 ngx_http_v2_header_t *header); 159 ngx_http_v2_header_t *header);
170 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); 160 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
171 static void ngx_http_v2_run_request(ngx_http_request_t *r); 161 static void ngx_http_v2_run_request(ngx_http_request_t *r);
172 static void ngx_http_v2_run_request_handler(ngx_event_t *ev);
173 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, 162 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
174 u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); 163 u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush);
175 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); 164 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r);
176 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); 165 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
177 166
208 197
209 #define NGX_HTTP_V2_FRAME_STATES \ 198 #define NGX_HTTP_V2_FRAME_STATES \
210 (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) 199 (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt))
211 200
212 201
213 static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = {
214 { ngx_string("host"),
215 offsetof(ngx_http_headers_in_t, host), 0, NULL },
216
217 { ngx_string("accept-encoding"),
218 offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL },
219
220 { ngx_string("accept-language"),
221 offsetof(ngx_http_headers_in_t, accept_language), 0, NULL },
222
223 { ngx_string("user-agent"),
224 offsetof(ngx_http_headers_in_t, user_agent), 0, NULL },
225
226 { ngx_null_string, 0, 0, NULL }
227 };
228
229
230 void 202 void
231 ngx_http_v2_init(ngx_event_t *rev) 203 ngx_http_v2_init(ngx_event_t *rev)
232 { 204 {
233 u_char *p, *end; 205 u_char *p, *end;
234 ngx_connection_t *c; 206 ngx_connection_t *c;
273 245
274 h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; 246 h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
275 247
276 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); 248 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
277 249
278 h2c->concurrent_pushes = h2scf->concurrent_pushes;
279 h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); 250 h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100);
280 251
281 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); 252 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
282 if (h2c->pool == NULL) { 253 if (h2c->pool == NULL) {
283 ngx_http_close_connection(c); 254 ngx_http_close_connection(c);
383 if (c->error) { 354 if (c->error) {
384 ngx_http_v2_finalize_connection(h2c, 0); 355 ngx_http_v2_finalize_connection(h2c, 0);
385 return; 356 return;
386 } 357 }
387 358
388 if (!h2c->processing && !h2c->pushing) { 359 if (!h2c->processing) {
389 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); 360 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
390 return; 361 return;
391 } 362 }
392 363
393 if (!h2c->goaway) { 364 if (!h2c->goaway) {
426 397
427 if (n == NGX_AGAIN) { 398 if (n == NGX_AGAIN) {
428 break; 399 break;
429 } 400 }
430 401
431 if (n == 0 402 if (n == 0 && (h2c->state.incomplete || h2c->processing)) {
432 && (h2c->state.incomplete || h2c->processing || h2c->pushing))
433 {
434 ngx_log_error(NGX_LOG_INFO, c->log, 0, 403 ngx_log_error(NGX_LOG_INFO, c->log, 0,
435 "client prematurely closed connection"); 404 "client prematurely closed connection");
436 } 405 }
437 406
438 if (n == 0 || n == NGX_ERROR) { 407 if (n == 0 || n == NGX_ERROR) {
651 { 620 {
652 ngx_int_t rc; 621 ngx_int_t rc;
653 ngx_connection_t *c; 622 ngx_connection_t *c;
654 ngx_http_core_loc_conf_t *clcf; 623 ngx_http_core_loc_conf_t *clcf;
655 624
656 if (h2c->last_out || h2c->processing || h2c->pushing) { 625 if (h2c->last_out || h2c->processing) {
657 return; 626 return;
658 } 627 }
659 628
660 c = h2c->connection; 629 c = h2c->connection;
661 630
1336 if (node->parent) { 1305 if (node->parent) {
1337 ngx_queue_remove(&node->reuse); 1306 ngx_queue_remove(&node->reuse);
1338 h2c->closed_nodes--; 1307 h2c->closed_nodes--;
1339 } 1308 }
1340 1309
1341 stream = ngx_http_v2_create_stream(h2c, 0); 1310 stream = ngx_http_v2_create_stream(h2c);
1342 if (stream == NULL) { 1311 if (stream == NULL) {
1343 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); 1312 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1344 } 1313 }
1345 1314
1346 h2c->state.stream = stream; 1315 h2c->state.stream = stream;
2125 case NGX_HTTP_V2_CANCEL: 2094 case NGX_HTTP_V2_CANCEL:
2126 ngx_log_error(NGX_LOG_INFO, fc->log, 0, 2095 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
2127 "client canceled stream %ui", h2c->state.sid); 2096 "client canceled stream %ui", h2c->state.sid);
2128 break; 2097 break;
2129 2098
2130 case NGX_HTTP_V2_REFUSED_STREAM:
2131 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
2132 "client refused stream %ui", h2c->state.sid);
2133 break;
2134
2135 case NGX_HTTP_V2_INTERNAL_ERROR: 2099 case NGX_HTTP_V2_INTERNAL_ERROR:
2136 ngx_log_error(NGX_LOG_INFO, fc->log, 0, 2100 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
2137 "client terminated stream %ui due to internal error", 2101 "client terminated stream %ui due to internal error",
2138 h2c->state.sid); 2102 h2c->state.sid);
2139 break; 2103 break;
2197 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, 2161 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
2198 u_char *end) 2162 u_char *end)
2199 { 2163 {
2200 ssize_t window_delta; 2164 ssize_t window_delta;
2201 ngx_uint_t id, value; 2165 ngx_uint_t id, value;
2202 ngx_http_v2_srv_conf_t *h2scf;
2203 ngx_http_v2_out_frame_t *frame; 2166 ngx_http_v2_out_frame_t *frame;
2204 2167
2205 window_delta = 0; 2168 window_delta = 0;
2206 2169
2207 while (h2c->state.length) { 2170 while (h2c->state.length) {
2259 2222
2260 return ngx_http_v2_connection_error(h2c, 2223 return ngx_http_v2_connection_error(h2c,
2261 NGX_HTTP_V2_PROTOCOL_ERROR); 2224 NGX_HTTP_V2_PROTOCOL_ERROR);
2262 } 2225 }
2263 2226
2264 h2c->push_disabled = !value;
2265 break;
2266
2267 case NGX_HTTP_V2_MAX_STREAMS_SETTING:
2268 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2269 ngx_http_v2_module);
2270
2271 h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes);
2272 break; 2227 break;
2273 2228
2274 case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: 2229 case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING:
2275 2230
2276 h2c->table_update = 1; 2231 h2c->table_update = 1;
2718 if (end == start + NGX_HTTP_V2_INT_OCTETS) { 2673 if (end == start + NGX_HTTP_V2_INT_OCTETS) {
2719 return NGX_DECLINED; 2674 return NGX_DECLINED;
2720 } 2675 }
2721 2676
2722 return NGX_AGAIN; 2677 return NGX_AGAIN;
2723 }
2724
2725
2726 ngx_http_v2_stream_t *
2727 ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path)
2728 {
2729 ngx_int_t rc;
2730 ngx_str_t value;
2731 ngx_pool_t *pool;
2732 ngx_uint_t index;
2733 ngx_table_elt_t **h;
2734 ngx_connection_t *fc;
2735 ngx_http_request_t *r;
2736 ngx_http_v2_node_t *node;
2737 ngx_http_v2_stream_t *stream;
2738 ngx_http_v2_srv_conf_t *h2scf;
2739 ngx_http_v2_connection_t *h2c;
2740 ngx_http_v2_parse_header_t *header;
2741
2742 h2c = parent->connection;
2743
2744 pool = ngx_create_pool(1024, h2c->connection->log);
2745 if (pool == NULL) {
2746 goto rst_stream;
2747 }
2748
2749 node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1);
2750
2751 if (node == NULL) {
2752 ngx_destroy_pool(pool);
2753 goto rst_stream;
2754 }
2755
2756 stream = ngx_http_v2_create_stream(h2c, 1);
2757 if (stream == NULL) {
2758
2759 if (node->parent == NULL) {
2760 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2761 ngx_http_v2_module);
2762
2763 index = ngx_http_v2_index(h2scf, h2c->last_push);
2764 h2c->streams_index[index] = node->index;
2765
2766 ngx_queue_insert_tail(&h2c->closed, &node->reuse);
2767 h2c->closed_nodes++;
2768 }
2769
2770 ngx_destroy_pool(pool);
2771 goto rst_stream;
2772 }
2773
2774 if (node->parent) {
2775 ngx_queue_remove(&node->reuse);
2776 h2c->closed_nodes--;
2777 }
2778
2779 stream->pool = pool;
2780
2781 r = stream->request;
2782 fc = r->connection;
2783
2784 stream->in_closed = 1;
2785 stream->node = node;
2786
2787 node->stream = stream;
2788
2789 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2790 "http2 push stream sid:%ui "
2791 "depends on %ui excl:0 weight:16",
2792 h2c->last_push, parent->node->id);
2793
2794 node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT;
2795 ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0);
2796
2797 r->method_name = ngx_http_core_get_method;
2798 r->method = NGX_HTTP_GET;
2799
2800 r->schema.data = ngx_pstrdup(pool, &parent->request->schema);
2801 if (r->schema.data == NULL) {
2802 goto close;
2803 }
2804
2805 r->schema.len = parent->request->schema.len;
2806
2807 value.data = ngx_pstrdup(pool, path);
2808 if (value.data == NULL) {
2809 goto close;
2810 }
2811
2812 value.len = path->len;
2813
2814 rc = ngx_http_v2_parse_path(r, &value);
2815
2816 if (rc != NGX_OK) {
2817 goto error;
2818 }
2819
2820 for (header = ngx_http_v2_parse_headers; header->name.len; header++) {
2821 h = (ngx_table_elt_t **)
2822 ((char *) &parent->request->headers_in + header->offset);
2823
2824 if (*h == NULL) {
2825 continue;
2826 }
2827
2828 value.len = (*h)->value.len;
2829
2830 value.data = ngx_pnalloc(pool, value.len + 1);
2831 if (value.data == NULL) {
2832 goto close;
2833 }
2834
2835 ngx_memcpy(value.data, (*h)->value.data, value.len);
2836 value.data[value.len] = '\0';
2837
2838 rc = ngx_http_v2_parse_header(r, header, &value);
2839
2840 if (rc != NGX_OK) {
2841 goto error;
2842 }
2843 }
2844
2845 fc->write->handler = ngx_http_v2_run_request_handler;
2846 ngx_post_event(fc->write, &ngx_posted_events);
2847
2848 return stream;
2849
2850 error:
2851
2852 if (rc == NGX_ABORT) {
2853 /* header handler has already finalized request */
2854 ngx_http_run_posted_requests(fc);
2855 return NULL;
2856 }
2857
2858 if (rc == NGX_DECLINED) {
2859 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
2860 ngx_http_run_posted_requests(fc);
2861 return NULL;
2862 }
2863
2864 close:
2865
2866 ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
2867
2868 return NULL;
2869
2870 rst_stream:
2871
2872 if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push,
2873 NGX_HTTP_INTERNAL_SERVER_ERROR)
2874 != NGX_OK)
2875 {
2876 h2c->connection->error = 1;
2877 }
2878
2879 return NULL;
2880 } 2678 }
2881 2679
2882 2680
2883 static ngx_int_t 2681 static ngx_int_t
2884 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) 2682 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c)
3149 return NGX_OK; 2947 return NGX_OK;
3150 } 2948 }
3151 2949
3152 2950
3153 static ngx_http_v2_stream_t * 2951 static ngx_http_v2_stream_t *
3154 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) 2952 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c)
3155 { 2953 {
3156 ngx_log_t *log; 2954 ngx_log_t *log;
3157 ngx_event_t *rev, *wev; 2955 ngx_event_t *rev, *wev;
3158 ngx_connection_t *fc; 2956 ngx_connection_t *fc;
3159 ngx_http_log_ctx_t *ctx; 2957 ngx_http_log_ctx_t *ctx;
3204 } 3002 }
3205 3003
3206 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); 3004 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t));
3207 3005
3208 log->data = ctx; 3006 log->data = ctx;
3209 3007 log->action = "reading client request headers";
3210 if (push) {
3211 log->action = "processing pushed request headers";
3212
3213 } else {
3214 log->action = "reading client request headers";
3215 }
3216 3008
3217 ngx_memzero(rev, sizeof(ngx_event_t)); 3009 ngx_memzero(rev, sizeof(ngx_event_t));
3218 3010
3219 rev->data = fc; 3011 rev->data = fc;
3220 rev->ready = 1; 3012 rev->ready = 1;
3282 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); 3074 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
3283 3075
3284 stream->send_window = h2c->init_window; 3076 stream->send_window = h2c->init_window;
3285 stream->recv_window = h2scf->preread_size; 3077 stream->recv_window = h2scf->preread_size;
3286 3078
3287 if (push) { 3079 h2c->processing++;
3288 h2c->pushing++;
3289
3290 } else {
3291 h2c->processing++;
3292 }
3293 3080
3294 h2c->priority_limit += h2scf->concurrent_streams; 3081 h2c->priority_limit += h2scf->concurrent_streams;
3295 3082
3296 if (h2c->connection->read->timer_set) { 3083 if (h2c->connection->read->timer_set) {
3297 ngx_del_timer(h2c->connection->read); 3084 ngx_del_timer(h2c->connection->read);
3710 3497
3711 3498
3712 static ngx_int_t 3499 static ngx_int_t
3713 ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) 3500 ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
3714 { 3501 {
3715 return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value);
3716 }
3717
3718
3719 static ngx_int_t
3720 ngx_http_v2_parse_header(ngx_http_request_t *r,
3721 ngx_http_v2_parse_header_t *header, ngx_str_t *value)
3722 {
3723 ngx_table_elt_t *h; 3502 ngx_table_elt_t *h;
3503 ngx_http_header_t *hh;
3724 ngx_http_core_main_conf_t *cmcf; 3504 ngx_http_core_main_conf_t *cmcf;
3505
3506 static ngx_str_t host = ngx_string("host");
3725 3507
3726 h = ngx_list_push(&r->headers_in.headers); 3508 h = ngx_list_push(&r->headers_in.headers);
3727 if (h == NULL) { 3509 if (h == NULL) {
3728 return NGX_ERROR; 3510 return NGX_ERROR;
3729 } 3511 }
3730 3512
3731 h->key.len = header->name.len; 3513 h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't');
3732 h->key.data = header->name.data; 3514
3733 h->lowcase_key = header->name.data; 3515 h->key.len = host.len;
3734 3516 h->key.data = host.data;
3735 if (header->hh == NULL) {
3736 header->hash = ngx_hash_key(header->name.data, header->name.len);
3737
3738 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3739
3740 header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash,
3741 h->lowcase_key, h->key.len);
3742 if (header->hh == NULL) {
3743 return NGX_ERROR;
3744 }
3745 }
3746
3747 h->hash = header->hash;
3748 3517
3749 h->value.len = value->len; 3518 h->value.len = value->len;
3750 h->value.data = value->data; 3519 h->value.data = value->data;
3751 3520
3752 if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { 3521 h->lowcase_key = host.data;
3753 /* header handler has already finalized request */ 3522
3523 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3524
3525 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
3526 h->lowcase_key, h->key.len);
3527
3528 if (hh == NULL) {
3529 return NGX_ERROR;
3530 }
3531
3532 if (hh->handler(r, h, hh->offset) != NGX_OK) {
3533 /*
3534 * request has been finalized already
3535 * in ngx_http_process_host()
3536 */
3754 return NGX_ABORT; 3537 return NGX_ABORT;
3755 } 3538 }
3756 3539
3757 return NGX_OK; 3540 return NGX_OK;
3758 } 3541 }
3988 ngx_http_process_request(r); 3771 ngx_http_process_request(r);
3989 3772
3990 failed: 3773 failed:
3991 3774
3992 ngx_http_run_posted_requests(fc); 3775 ngx_http_run_posted_requests(fc);
3993 }
3994
3995
3996 static void
3997 ngx_http_v2_run_request_handler(ngx_event_t *ev)
3998 {
3999 ngx_connection_t *fc;
4000 ngx_http_request_t *r;
4001
4002 fc = ev->data;
4003 r = fc->data;
4004
4005 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
4006 "http2 run request handler");
4007
4008 ngx_http_v2_run_request(r);
4009 } 3776 }
4010 3777
4011 3778
4012 ngx_int_t 3779 ngx_int_t
4013 ngx_http_v2_read_request_body(ngx_http_request_t *r) 3780 ngx_http_v2_read_request_body(ngx_http_request_t *r)
4610 4377
4611 void 4378 void
4612 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) 4379 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc)
4613 { 4380 {
4614 ngx_pool_t *pool; 4381 ngx_pool_t *pool;
4615 ngx_uint_t push;
4616 ngx_event_t *ev; 4382 ngx_event_t *ev;
4617 ngx_connection_t *fc; 4383 ngx_connection_t *fc;
4618 ngx_http_v2_node_t *node; 4384 ngx_http_v2_node_t *node;
4619 ngx_http_v2_connection_t *h2c; 4385 ngx_http_v2_connection_t *h2c;
4620 4386
4621 h2c = stream->connection; 4387 h2c = stream->connection;
4622 node = stream->node; 4388 node = stream->node;
4623 4389
4624 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, 4390 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
4625 "http2 close stream %ui, queued %ui, " 4391 "http2 close stream %ui, queued %ui, processing %ui",
4626 "processing %ui, pushing %ui", 4392 node->id, stream->queued, h2c->processing);
4627 node->id, stream->queued, h2c->processing, h2c->pushing);
4628 4393
4629 fc = stream->request->connection; 4394 fc = stream->request->connection;
4630 4395
4631 if (stream->queued) { 4396 if (stream->queued) {
4632 fc->error = 1; 4397 fc->error = 1;
4657 4422
4658 if (h2c->state.stream == stream) { 4423 if (h2c->state.stream == stream) {
4659 h2c->state.stream = NULL; 4424 h2c->state.stream = NULL;
4660 } 4425 }
4661 4426
4662 push = stream->node->id % 2 == 0;
4663
4664 node->stream = NULL; 4427 node->stream = NULL;
4665 4428
4666 ngx_queue_insert_tail(&h2c->closed, &node->reuse); 4429 ngx_queue_insert_tail(&h2c->closed, &node->reuse);
4667 h2c->closed_nodes++; 4430 h2c->closed_nodes++;
4668 4431
4708 } 4471 }
4709 4472
4710 fc->data = h2c->free_fake_connections; 4473 fc->data = h2c->free_fake_connections;
4711 h2c->free_fake_connections = fc; 4474 h2c->free_fake_connections = fc;
4712 4475
4713 if (push) { 4476 h2c->processing--;
4714 h2c->pushing--; 4477
4715 4478 if (h2c->processing || h2c->blocked) {
4716 } else {
4717 h2c->processing--;
4718 }
4719
4720 if (h2c->processing || h2c->pushing || h2c->blocked) {
4721 return; 4479 return;
4722 } 4480 }
4723 4481
4724 ev = h2c->connection->read; 4482 ev = h2c->connection->read;
4725 4483
4891 if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { 4649 if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
4892 (void) ngx_http_v2_send_output_queue(h2c); 4650 (void) ngx_http_v2_send_output_queue(h2c);
4893 } 4651 }
4894 } 4652 }
4895 4653
4896 if (!h2c->processing && !h2c->pushing) { 4654 if (!h2c->processing) {
4897 goto done; 4655 goto done;
4898 } 4656 }
4899 4657
4900 c->read->handler = ngx_http_empty_handler; 4658 c->read->handler = ngx_http_empty_handler;
4901 c->write->handler = ngx_http_empty_handler; 4659 c->write->handler = ngx_http_empty_handler;
4939 } 4697 }
4940 } 4698 }
4941 4699
4942 h2c->blocked = 0; 4700 h2c->blocked = 0;
4943 4701
4944 if (h2c->processing || h2c->pushing) { 4702 if (h2c->processing) {
4945 c->error = 1; 4703 c->error = 1;
4946 return; 4704 return;
4947 } 4705 }
4948 4706
4949 done: 4707 done: