HTTP/2: more style, comments, and debugging.

This commit is contained in:
Ruslan Ermilov 2018-01-29 16:06:33 +03:00
parent 34cf5d5e6a
commit 0b8b91f45f
3 changed files with 168 additions and 158 deletions

View File

@ -185,16 +185,16 @@ static void ngx_http_v2_pool_cleanup(void *data);
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_connection_t *h2c, u_char *pos,
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_connection_t *h2c, u_char *pos,
}
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_connection_t *h2c, u_char *pos,
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_http_v2_connection_t *h2c, u_char *pos,
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_http_request_t *r)
} 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,

View File

@ -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_v2_connection_t *h2c,
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);

View File

@ -138,6 +138,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
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_request_t *r)
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_request_t *r)
}
}
h2c = r->stream->connection;
h2c = stream->connection;
len = h2c->table_update ? 1 : 0;
@ -633,9 +636,9 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
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_request_t *r)
}
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_http_request_t *r, u_char *pos,
}
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)
{
@ -1239,31 +1244,6 @@ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream,
}
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_connection_t *h2c,
}
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,