From f1021031962159ffa2fe0e9cb68a9ab5080c3854 Mon Sep 17 00:00:00 2001 From: Yang Gao Date: Sat, 18 Apr 2015 00:10:29 -0700 Subject: [PATCH] Proof of concept fix for flow control error --- src/core/transport/chttp2/frame.h | 1 + src/core/transport/chttp2/frame_settings.c | 4 ++++ src/core/transport/chttp2_transport.c | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/src/core/transport/chttp2/frame.h b/src/core/transport/chttp2/frame.h index fbb941969e9..cd1d47342f5 100644 --- a/src/core/transport/chttp2/frame.h +++ b/src/core/transport/chttp2/frame.h @@ -54,6 +54,7 @@ typedef struct { gpr_uint8 process_ping_reply; gpr_uint8 goaway; + gpr_uint32 initial_window_update; gpr_uint32 window_update; gpr_uint32 goaway_last_stream_index; gpr_uint32 goaway_error; diff --git a/src/core/transport/chttp2/frame_settings.c b/src/core/transport/chttp2/frame_settings.c index 8d3250c34ff..9b9374e0fd8 100644 --- a/src/core/transport/chttp2/frame_settings.c +++ b/src/core/transport/chttp2/frame_settings.c @@ -218,6 +218,10 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse( return GRPC_CHTTP2_CONNECTION_ERROR; } } + if (parser->id == 4 && parser->incoming_settings[parser->id] != parser->value) { + state->initial_window_update = parser->value - parser->incoming_settings[parser->id]; + gpr_log(GPR_DEBUG, "adding %d for initial_window change", state->window_update); + } parser->incoming_settings[parser->id] = parser->value; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "CHTTP2: got setting %d = %d", parser->id, diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 110a4b544f3..fbd9d8a146b 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1485,6 +1485,18 @@ static int parse_frame_slice(transport *t, gpr_slice slice, int is_last) { } } } + if (st.initial_window_update) { + for (i = 0; i < t->stream_map.count; i++) { + stream *s = (stream*)(t->stream_map.values[i]); + /* TODO there are other scenarios */ + if (s->outgoing_window == 0) { + s->outgoing_window += st.initial_window_update; + if (s->outgoing_sopb.nops) { + stream_list_join(t, s, WRITABLE); + } + } + } + } if (st.window_update) { if (t->incoming_stream_id) { /* if there was a stream id, this is for some stream */