comparison src/http/v2/ngx_http_v2.c @ 7024:79de0d2aa432

HTTP/2: make SETTINGS ACK frame reusable. Signed-off-by: Piotr Sikora <piotrsikora@google.com>
author Piotr Sikora <piotrsikora@google.com>
date Fri, 02 Jun 2017 15:05:28 +0300
parents 859d80f57aab
children 7206c3630310
comparison
equal deleted inserted replaced
7023:859d80f57aab 7024:79de0d2aa432
26 #define NGX_HTTP_V2_ENHANCE_YOUR_CALM 0xb 26 #define NGX_HTTP_V2_ENHANCE_YOUR_CALM 0xb
27 #define NGX_HTTP_V2_INADEQUATE_SECURITY 0xc 27 #define NGX_HTTP_V2_INADEQUATE_SECURITY 0xc
28 #define NGX_HTTP_V2_HTTP_1_1_REQUIRED 0xd 28 #define NGX_HTTP_V2_HTTP_1_1_REQUIRED 0xd
29 29
30 /* frame sizes */ 30 /* frame sizes */
31 #define NGX_HTTP_V2_SETTINGS_ACK_SIZE 0
31 #define NGX_HTTP_V2_RST_STREAM_SIZE 4 32 #define NGX_HTTP_V2_RST_STREAM_SIZE 4
32 #define NGX_HTTP_V2_PRIORITY_SIZE 5 33 #define NGX_HTTP_V2_PRIORITY_SIZE 5
33 #define NGX_HTTP_V2_PING_SIZE 8 34 #define NGX_HTTP_V2_PING_SIZE 8
34 #define NGX_HTTP_V2_GOAWAY_SIZE 8 35 #define NGX_HTTP_V2_GOAWAY_SIZE 8
35 #define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4 36 #define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4
126 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( 127 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node(
127 ngx_http_v2_connection_t *h2c); 128 ngx_http_v2_connection_t *h2c);
128 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) 129 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1)
129 #define ngx_http_v2_index(h2scf, sid) ((sid >> 1) & h2scf->streams_index_mask) 130 #define ngx_http_v2_index(h2scf, sid) ((sid >> 1) & h2scf->streams_index_mask)
130 131
131 static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, 132 static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c);
132 ngx_uint_t ack);
133 static ngx_int_t ngx_http_v2_settings_frame_handler( 133 static ngx_int_t ngx_http_v2_settings_frame_handler(
134 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); 134 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
135 static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, 135 static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c,
136 ngx_uint_t sid, size_t window); 136 ngx_uint_t sid, size_t window);
137 static ngx_int_t ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, 137 static ngx_int_t ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c,
267 if (h2c->streams_index == NULL) { 267 if (h2c->streams_index == NULL) {
268 ngx_http_close_connection(c); 268 ngx_http_close_connection(c);
269 return; 269 return;
270 } 270 }
271 271
272 if (ngx_http_v2_send_settings(h2c, 0) == NGX_ERROR) { 272 if (ngx_http_v2_send_settings(h2c) == NGX_ERROR) {
273 ngx_http_close_connection(c); 273 ngx_http_close_connection(c);
274 return; 274 return;
275 } 275 }
276 276
277 if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW 277 if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW
1965 1965
1966 static u_char * 1966 static u_char *
1967 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, 1967 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
1968 u_char *end) 1968 u_char *end)
1969 { 1969 {
1970 ssize_t window_delta; 1970 ssize_t window_delta;
1971 ngx_uint_t id, value; 1971 ngx_uint_t id, value;
1972 ngx_http_v2_out_frame_t *frame;
1972 1973
1973 window_delta = 0; 1974 window_delta = 0;
1974 1975
1975 while (h2c->state.length) { 1976 while (h2c->state.length) {
1976 if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) { 1977 if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
2022 } 2023 }
2023 2024
2024 pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE; 2025 pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
2025 } 2026 }
2026 2027
2027 ngx_http_v2_send_settings(h2c, 1); 2028 frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_SETTINGS_ACK_SIZE,
2029 NGX_HTTP_V2_SETTINGS_FRAME,
2030 NGX_HTTP_V2_ACK_FLAG, 0);
2031 if (frame == NULL) {
2032 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
2033 }
2034
2035 ngx_http_v2_queue_blocked_frame(h2c, frame);
2028 2036
2029 if (window_delta) { 2037 if (window_delta) {
2030 if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) { 2038 if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
2031 return ngx_http_v2_connection_error(h2c, 2039 return ngx_http_v2_connection_error(h2c,
2032 NGX_HTTP_V2_INTERNAL_ERROR); 2040 NGX_HTTP_V2_INTERNAL_ERROR);
2474 return NGX_AGAIN; 2482 return NGX_AGAIN;
2475 } 2483 }
2476 2484
2477 2485
2478 static ngx_int_t 2486 static ngx_int_t
2479 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) 2487 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c)
2480 { 2488 {
2481 size_t len; 2489 size_t len;
2482 ngx_buf_t *buf; 2490 ngx_buf_t *buf;
2483 ngx_chain_t *cl; 2491 ngx_chain_t *cl;
2484 ngx_http_v2_srv_conf_t *h2scf; 2492 ngx_http_v2_srv_conf_t *h2scf;
2485 ngx_http_v2_out_frame_t *frame; 2493 ngx_http_v2_out_frame_t *frame;
2486 2494
2487 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, 2495 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2488 "http2 send SETTINGS frame ack:%ui", ack); 2496 "http2 send SETTINGS frame");
2489 2497
2490 frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t)); 2498 frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t));
2491 if (frame == NULL) { 2499 if (frame == NULL) {
2492 return NGX_ERROR; 2500 return NGX_ERROR;
2493 } 2501 }
2495 cl = ngx_alloc_chain_link(h2c->pool); 2503 cl = ngx_alloc_chain_link(h2c->pool);
2496 if (cl == NULL) { 2504 if (cl == NULL) {
2497 return NGX_ERROR; 2505 return NGX_ERROR;
2498 } 2506 }
2499 2507
2500 len = ack ? 0 : (sizeof(uint16_t) + sizeof(uint32_t)) * 3; 2508 len = NGX_HTTP_V2_SETTINGS_PARAM_SIZE * 3;
2501 2509
2502 buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len); 2510 buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len);
2503 if (buf == NULL) { 2511 if (buf == NULL) {
2504 return NGX_ERROR; 2512 return NGX_ERROR;
2505 } 2513 }
2519 frame->blocked = 0; 2527 frame->blocked = 0;
2520 2528
2521 buf->last = ngx_http_v2_write_len_and_type(buf->last, len, 2529 buf->last = ngx_http_v2_write_len_and_type(buf->last, len,
2522 NGX_HTTP_V2_SETTINGS_FRAME); 2530 NGX_HTTP_V2_SETTINGS_FRAME);
2523 2531
2524 *buf->last++ = ack ? NGX_HTTP_V2_ACK_FLAG : NGX_HTTP_V2_NO_FLAG; 2532 *buf->last++ = NGX_HTTP_V2_NO_FLAG;
2525 2533
2526 buf->last = ngx_http_v2_write_sid(buf->last, 0); 2534 buf->last = ngx_http_v2_write_sid(buf->last, 0);
2527 2535
2528 if (!ack) { 2536 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2529 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, 2537 ngx_http_v2_module);
2530 ngx_http_v2_module); 2538
2531 2539 buf->last = ngx_http_v2_write_uint16(buf->last,
2532 buf->last = ngx_http_v2_write_uint16(buf->last, 2540 NGX_HTTP_V2_MAX_STREAMS_SETTING);
2533 NGX_HTTP_V2_MAX_STREAMS_SETTING); 2541 buf->last = ngx_http_v2_write_uint32(buf->last,
2534 buf->last = ngx_http_v2_write_uint32(buf->last, 2542 h2scf->concurrent_streams);
2535 h2scf->concurrent_streams); 2543
2536 2544 buf->last = ngx_http_v2_write_uint16(buf->last,
2537 buf->last = ngx_http_v2_write_uint16(buf->last,
2538 NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); 2545 NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING);
2539 buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); 2546 buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size);
2540 2547
2541 buf->last = ngx_http_v2_write_uint16(buf->last, 2548 buf->last = ngx_http_v2_write_uint16(buf->last,
2542 NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); 2549 NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING);
2543 buf->last = ngx_http_v2_write_uint32(buf->last, 2550 buf->last = ngx_http_v2_write_uint32(buf->last,
2544 NGX_HTTP_V2_MAX_FRAME_SIZE); 2551 NGX_HTTP_V2_MAX_FRAME_SIZE);
2545 }
2546 2552
2547 ngx_http_v2_queue_blocked_frame(h2c, frame); 2553 ngx_http_v2_queue_blocked_frame(h2c, frame);
2548 2554
2549 return NGX_OK; 2555 return NGX_OK;
2550 } 2556 }