# HG changeset patch # User Ruslan Ermilov # Date 1517231193 -10800 # Node ID 61d276dcd4932c6bbbe181379f391bbbe47908a3 # Parent e11a0679d349df20a8f40c0764d71586dde7f972 HTTP/2: more style, comments, and debugging. diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -185,16 +185,16 @@ static void ngx_http_v2_pool_cleanup(voi static ngx_http_v2_handler_pt ngx_http_v2_frame_states[] = { - ngx_http_v2_state_data, - ngx_http_v2_state_headers, - ngx_http_v2_state_priority, - ngx_http_v2_state_rst_stream, - ngx_http_v2_state_settings, - ngx_http_v2_state_push_promise, - ngx_http_v2_state_ping, - ngx_http_v2_state_goaway, - ngx_http_v2_state_window_update, - ngx_http_v2_state_continuation + ngx_http_v2_state_data, /* NGX_HTTP_V2_DATA_FRAME */ + ngx_http_v2_state_headers, /* NGX_HTTP_V2_HEADERS_FRAME */ + ngx_http_v2_state_priority, /* NGX_HTTP_V2_PRIORITY_FRAME */ + ngx_http_v2_state_rst_stream, /* NGX_HTTP_V2_RST_STREAM_FRAME */ + ngx_http_v2_state_settings, /* NGX_HTTP_V2_SETTINGS_FRAME */ + ngx_http_v2_state_push_promise, /* NGX_HTTP_V2_PUSH_PROMISE_FRAME */ + ngx_http_v2_state_ping, /* NGX_HTTP_V2_PING_FRAME */ + ngx_http_v2_state_goaway, /* NGX_HTTP_V2_GOAWAY_FRAME */ + ngx_http_v2_state_window_update, /* NGX_HTTP_V2_WINDOW_UPDATE_FRAME */ + ngx_http_v2_state_continuation /* NGX_HTTP_V2_CONTINUATION_FRAME */ }; #define NGX_HTTP_V2_FRAME_STATES \ @@ -1046,7 +1046,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co depend = 0; excl = 0; - weight = 16; + weight = NGX_HTTP_V2_DEFAULT_WEIGHT; if (priority) { dependency = ngx_http_v2_parse_uint32(pos); @@ -1059,7 +1059,8 @@ ngx_http_v2_state_headers(ngx_http_v2_co } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 HEADERS frame sid:%ui on %ui excl:%ui weight:%ui", + "http2 HEADERS frame sid:%ui " + "depends on %ui excl:%ui weight:%ui", h2c->state.sid, depend, excl, weight); if (h2c->state.sid % 2 == 0 || h2c->state.sid <= h2c->last_sid) { @@ -1788,7 +1789,8 @@ ngx_http_v2_state_priority(ngx_http_v2_c pos += NGX_HTTP_V2_PRIORITY_SIZE; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 PRIORITY frame sid:%ui on %ui excl:%ui weight:%ui", + "http2 PRIORITY frame sid:%ui " + "depends on %ui excl:%ui weight:%ui", h2c->state.sid, depend, excl, weight); if (h2c->state.sid == 0) { @@ -1986,6 +1988,9 @@ ngx_http_v2_state_settings_params(ngx_ht id = ngx_http_v2_parse_uint16(pos); value = ngx_http_v2_parse_uint32(&pos[2]); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 setting %ui:%ui", id, value); + switch (id) { case NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING: @@ -3343,7 +3348,7 @@ ngx_http_v2_construct_request_line(ngx_h } else if (r->schema_start == NULL) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent no :schema header"); + "client sent no :scheme header"); } else { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -49,6 +49,8 @@ #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 +#define NGX_HTTP_V2_DEFAULT_WEIGHT 16 + typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; @@ -272,7 +274,6 @@ ngx_http_v2_queue_ordered_frame(ngx_http void ngx_http_v2_init(ngx_event_t *rev); -void ngx_http_v2_request_headers_init(void); ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -138,6 +138,7 @@ ngx_http_v2_header_filter(ngx_http_reque ngx_table_elt_t *header; ngx_connection_t *fc; ngx_http_cleanup_t *cln; + ngx_http_v2_stream_t *stream; ngx_http_v2_out_frame_t *frame; ngx_http_v2_connection_t *h2c; ngx_http_core_loc_conf_t *clcf; @@ -157,7 +158,9 @@ ngx_http_v2_header_filter(ngx_http_reque ngx_http_v2_literal_size(NGINX_VER_BUILD); static u_char nginx_ver_build[ngx_http_v2_literal_size(NGINX_VER_BUILD)]; - if (!r->stream) { + stream = r->stream; + + if (!stream) { return ngx_http_next_header_filter(r); } @@ -236,7 +239,7 @@ ngx_http_v2_header_filter(ngx_http_reque } } - h2c = r->stream->connection; + h2c = stream->connection; len = h2c->table_update ? 1 : 0; @@ -633,9 +636,9 @@ ngx_http_v2_header_filter(ngx_http_reque return NGX_ERROR; } - ngx_http_v2_queue_blocked_frame(r->stream->connection, frame); + ngx_http_v2_queue_blocked_frame(h2c, frame); - r->stream->queued = 1; + stream->queued = 1; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { @@ -643,124 +646,12 @@ ngx_http_v2_header_filter(ngx_http_reque } cln->handler = ngx_http_v2_filter_cleanup; - cln->data = r->stream; + cln->data = stream; fc->send_chain = ngx_http_v2_send_chain; fc->need_last_buf = 1; - return ngx_http_v2_filter_send(fc, r->stream); -} - - -static ngx_http_v2_out_frame_t * -ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) -{ - u_char *pos, *start, *tmp; - size_t len, tmp_len; - ngx_uint_t i; - ngx_list_part_t *part; - ngx_table_elt_t *header; - - len = 0; - tmp_len = 0; - - part = &r->headers_out.trailers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - if (header[i].hash == 0) { - continue; - } - - if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, - "too long response trailer name: \"%V\"", - &header[i].key); - return NULL; - } - - if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, - "too long response trailer value: \"%V: %V\"", - &header[i].key, &header[i].value); - return NULL; - } - - len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len - + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; - - if (header[i].key.len > tmp_len) { - tmp_len = header[i].key.len; - } - - if (header[i].value.len > tmp_len) { - tmp_len = header[i].value.len; - } - } - - if (len == 0) { - return NGX_HTTP_V2_NO_TRAILERS; - } - - tmp = ngx_palloc(r->pool, tmp_len); - pos = ngx_pnalloc(r->pool, len); - - if (pos == NULL || tmp == NULL) { - return NULL; - } - - start = pos; - - part = &r->headers_out.trailers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - if (header[i].hash == 0) { - continue; - } - -#if (NGX_DEBUG) - if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) { - ngx_strlow(tmp, header[i].key.data, header[i].key.len); - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 output trailer: \"%*s: %V\"", - header[i].key.len, tmp, &header[i].value); - } -#endif - - *pos++ = 0; - - pos = ngx_http_v2_write_name(pos, header[i].key.data, - header[i].key.len, tmp); - - pos = ngx_http_v2_write_value(pos, header[i].value.data, - header[i].value.len, tmp); - } - - return ngx_http_v2_create_headers_frame(r, start, pos, 1); + return ngx_http_v2_filter_send(fc, stream); } @@ -917,6 +808,120 @@ ngx_http_v2_create_headers_frame(ngx_htt } +static ngx_http_v2_out_frame_t * +ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) +{ + u_char *pos, *start, *tmp; + size_t len, tmp_len; + ngx_uint_t i; + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_connection_t *fc; + + fc = r->connection; + len = 0; + tmp_len = 0; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, + "too long response trailer name: \"%V\"", + &header[i].key); + return NULL; + } + + if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, + "too long response trailer value: \"%V: %V\"", + &header[i].key, &header[i].value); + return NULL; + } + + len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; + + if (header[i].key.len > tmp_len) { + tmp_len = header[i].key.len; + } + + if (header[i].value.len > tmp_len) { + tmp_len = header[i].value.len; + } + } + + if (len == 0) { + return NGX_HTTP_V2_NO_TRAILERS; + } + + tmp = ngx_palloc(r->pool, tmp_len); + pos = ngx_pnalloc(r->pool, len); + + if (pos == NULL || tmp == NULL) { + return NULL; + } + + start = pos; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + +#if (NGX_DEBUG) + if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) { + ngx_strlow(tmp, header[i].key.data, header[i].key.len); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output trailer: \"%*s: %V\"", + header[i].key.len, tmp, &header[i].value); + } +#endif + + *pos++ = 0; + + pos = ngx_http_v2_write_name(pos, header[i].key.data, + header[i].key.len, tmp); + + pos = ngx_http_v2_write_value(pos, header[i].value.data, + header[i].value.len, tmp); + } + + return ngx_http_v2_create_headers_frame(r, start, pos, 1); +} + + static ngx_chain_t * ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) { @@ -1240,31 +1245,6 @@ ngx_http_v2_filter_get_data_frame(ngx_ht static ngx_inline ngx_int_t -ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream) -{ - stream->blocked = 1; - - if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) { - fc->error = 1; - return NGX_ERROR; - } - - stream->blocked = 0; - - if (stream->queued) { - fc->buffered |= NGX_HTTP_V2_BUFFERED; - fc->write->active = 1; - fc->write->ready = 0; - return NGX_AGAIN; - } - - fc->buffered &= ~NGX_HTTP_V2_BUFFERED; - - return NGX_OK; -} - - -static ngx_inline ngx_int_t ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { @@ -1317,6 +1297,30 @@ ngx_http_v2_waiting_queue(ngx_http_v2_co } +static ngx_inline ngx_int_t +ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream) +{ + stream->blocked = 1; + + if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) { + fc->error = 1; + return NGX_ERROR; + } + + stream->blocked = 0; + + if (stream->queued) { + fc->buffered |= NGX_HTTP_V2_BUFFERED; + fc->write->active = 1; + fc->write->ready = 0; + return NGX_AGAIN; + } + + fc->buffered &= ~NGX_HTTP_V2_BUFFERED; + + return NGX_OK; +} + static ngx_int_t ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c,