diff --git a/src/cowboy_http2.erl b/src/cowboy_http2.erl index deb57ce6..6b64030f 100644 --- a/src/cowboy_http2.erl +++ b/src/cowboy_http2.erl @@ -310,8 +310,7 @@ data_frame(State=#state{opts=Opts, streams=Streams}, StreamID, IsFin, Data) -> lingering_data_frame(State=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0}, DataLen) -> - Transport:send(Socket, cow_http2:window_update(DataLen)), - HTTP2Machine1 = cal_and_update_window(DataLen, HTTP2Machine0), + HTTP2Machine1 = cal_and_update_window(Transport, Socket, HTTP2Machine0), State#state{http2_machine=HTTP2Machine1}. headers_frame(State, StreamID, IsFin, Headers, @@ -581,13 +580,9 @@ commands(State0=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Ma end, commands(State, StreamID, Tail); commands(State=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0}, - StreamID, [{flow, Size}|Tail]) -> - Transport:send(Socket, [ - cow_http2:window_update(Size), - cow_http2:window_update(StreamID, Size) - ]), - HTTP2Machine1 = cal_and_update_window(Size, HTTP2Machine0), - HTTP2Machine = cal_and_update_window(StreamID, Size, HTTP2Machine1), + StreamID, [{flow, _Size}|Tail]) -> + HTTP2Machine1 = cal_and_update_window(Transport, Socket, HTTP2Machine0), + HTTP2Machine = cal_and_update_window(Transport, Socket, StreamID, HTTP2Machine1), commands(State#state{http2_machine=HTTP2Machine}, StreamID, Tail); %% Supervise a child process. commands(State=#state{children=Children}, StreamID, [{spawn, Pid, Shutdown}|Tail]) -> @@ -666,19 +661,21 @@ maybe_send_data(State=#state{http2_machine=HTTP2Machine0}, StreamID, IsFin, Data send_data(State#state{http2_machine=HTTP2Machine}, SendData) end. -cal_and_update_window(DataLen, HTTP2Machine) -> - case cow_http2_machine:cal_increasing_window(DataLen, HTTP2Machine) of +cal_and_update_window(Transport, Socket, HTTP2Machine) -> + case cow_http2_machine:cal_increasing_window(HTTP2Machine) of 0 -> HTTP2Machine; NewSize -> + Transport:send(Socket, cow_http2:window_update(NewSize)), cow_http2_machine:update_window(NewSize, HTTP2Machine) end. -cal_and_update_window(StreamID, _DataLen, HTTP2Machine) -> +cal_and_update_window(Transport, Socket, StreamID, HTTP2Machine) -> case cow_http2_machine:cal_increasing_window(StreamID, HTTP2Machine) of 0 -> HTTP2Machine; NewSize -> + Transport:send(Socket, cow_http2:window_update(StreamID, NewSize)), cow_http2_machine:update_window(StreamID, NewSize, HTTP2Machine) end. diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl index 9f36b5b8..3ad43de1 100644 --- a/test/rfc7540_SUITE.erl +++ b/test/rfc7540_SUITE.erl @@ -3121,8 +3121,7 @@ lingering_data_counts_toward_connection_window(Config0) -> doc("DATA frames received after sending RST_STREAM must be counted " "toward the connection flow-control window. (RFC7540 5.1)"), Config = cowboy_test:init_http(?FUNCTION_NAME, #{ - env => #{dispatch => cowboy_router:compile(init_routes(Config0))}, - initial_connection_window_size => 100000 + env => #{dispatch => cowboy_router:compile(init_routes(Config0))} }, Config0), try %% We need to do the handshake manually because a WINDOW_UPDATE @@ -3135,8 +3134,6 @@ lingering_data_counts_toward_connection_window(Config0) -> {ok, << 4:8, 0:40, _:Len1/binary >>} = gen_tcp:recv(Socket, 6 + Len1, 1000), %% Send the SETTINGS ack. ok = gen_tcp:send(Socket, cow_http2:settings_ack()), - %% Receive the WINDOW_UPDATE for the connection. - {ok, << 4:24, 8:8, 0:40, _:32 >>} = gen_tcp:recv(Socket, 13, 1000), %% Receive the SETTINGS ack. {ok, << 0:24, 4:8, 1:8, 0:32 >>} = gen_tcp:recv(Socket, 9, 1000), Headers = [ @@ -3153,7 +3150,11 @@ lingering_data_counts_toward_connection_window(Config0) -> % Make sure server send RST_STREAM. timer:sleep(100), ok = gen_tcp:send(Socket, [ - cow_http2:data(1, fin, <<0:1000/unit:8>>) + %% WINDOW_UPDATE is sent only if remote_windows passes half of max + cow_http2:data(1, fin, <<0:10000/unit:8>>), + cow_http2:data(1, fin, <<0:10000/unit:8>>), + cow_http2:data(1, fin, <<0:10000/unit:8>>), + cow_http2:data(1, fin, <<0:10000/unit:8>>) ]), {ok, << SkipLen:24, 1:8, _:8, 1:32 >>} = gen_tcp:recv(Socket, 9, 1000), % Skip the header. @@ -3161,7 +3162,7 @@ lingering_data_counts_toward_connection_window(Config0) -> % Skip RST_STREAM. {ok, << 4:24, 3:8, 1:40, _:32 >>} = gen_tcp:recv(Socket, 13, 1000), % Received a WINDOW_UPDATE frame after we got RST_STREAM. - {ok, << 4:24, 8:8, 0:40, 1000:32 >>} = gen_tcp:recv(Socket, 13, 1000) + {ok, << 4:24, 8:8, 0:40, 41000:32 >>} = gen_tcp:recv(Socket, 13, 1000) after cowboy:stop_listener(?FUNCTION_NAME) end.