0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Fix cal_and_update_window

This commit is contained in:
Tony Han 2019-07-30 20:50:24 +08:00
parent 3fea604ed8
commit 987afaccde
2 changed files with 16 additions and 18 deletions

View file

@ -310,8 +310,7 @@ data_frame(State=#state{opts=Opts, streams=Streams}, StreamID, IsFin, Data) ->
lingering_data_frame(State=#state{socket=Socket, transport=Transport, lingering_data_frame(State=#state{socket=Socket, transport=Transport,
http2_machine=HTTP2Machine0}, DataLen) -> http2_machine=HTTP2Machine0}, DataLen) ->
Transport:send(Socket, cow_http2:window_update(DataLen)), HTTP2Machine1 = cal_and_update_window(Transport, Socket, HTTP2Machine0),
HTTP2Machine1 = cal_and_update_window(DataLen, HTTP2Machine0),
State#state{http2_machine=HTTP2Machine1}. State#state{http2_machine=HTTP2Machine1}.
headers_frame(State, StreamID, IsFin, Headers, headers_frame(State, StreamID, IsFin, Headers,
@ -581,13 +580,9 @@ commands(State0=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Ma
end, end,
commands(State, StreamID, Tail); commands(State, StreamID, Tail);
commands(State=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0}, commands(State=#state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0},
StreamID, [{flow, Size}|Tail]) -> StreamID, [{flow, _Size}|Tail]) ->
Transport:send(Socket, [ HTTP2Machine1 = cal_and_update_window(Transport, Socket, HTTP2Machine0),
cow_http2:window_update(Size), HTTP2Machine = cal_and_update_window(Transport, Socket, StreamID, HTTP2Machine1),
cow_http2:window_update(StreamID, Size)
]),
HTTP2Machine1 = cal_and_update_window(Size, HTTP2Machine0),
HTTP2Machine = cal_and_update_window(StreamID, Size, HTTP2Machine1),
commands(State#state{http2_machine=HTTP2Machine}, StreamID, Tail); commands(State#state{http2_machine=HTTP2Machine}, StreamID, Tail);
%% Supervise a child process. %% Supervise a child process.
commands(State=#state{children=Children}, StreamID, [{spawn, Pid, Shutdown}|Tail]) -> 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) send_data(State#state{http2_machine=HTTP2Machine}, SendData)
end. end.
cal_and_update_window(DataLen, HTTP2Machine) -> cal_and_update_window(Transport, Socket, HTTP2Machine) ->
case cow_http2_machine:cal_increasing_window(DataLen, HTTP2Machine) of case cow_http2_machine:cal_increasing_window(HTTP2Machine) of
0 -> 0 ->
HTTP2Machine; HTTP2Machine;
NewSize -> NewSize ->
Transport:send(Socket, cow_http2:window_update(NewSize)),
cow_http2_machine:update_window(NewSize, HTTP2Machine) cow_http2_machine:update_window(NewSize, HTTP2Machine)
end. 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 case cow_http2_machine:cal_increasing_window(StreamID, HTTP2Machine) of
0 -> 0 ->
HTTP2Machine; HTTP2Machine;
NewSize -> NewSize ->
Transport:send(Socket, cow_http2:window_update(StreamID, NewSize)),
cow_http2_machine:update_window(StreamID, NewSize, HTTP2Machine) cow_http2_machine:update_window(StreamID, NewSize, HTTP2Machine)
end. end.

View file

@ -3121,8 +3121,7 @@ lingering_data_counts_toward_connection_window(Config0) ->
doc("DATA frames received after sending RST_STREAM must be counted " doc("DATA frames received after sending RST_STREAM must be counted "
"toward the connection flow-control window. (RFC7540 5.1)"), "toward the connection flow-control window. (RFC7540 5.1)"),
Config = cowboy_test:init_http(?FUNCTION_NAME, #{ Config = cowboy_test:init_http(?FUNCTION_NAME, #{
env => #{dispatch => cowboy_router:compile(init_routes(Config0))}, env => #{dispatch => cowboy_router:compile(init_routes(Config0))}
initial_connection_window_size => 100000
}, Config0), }, Config0),
try try
%% We need to do the handshake manually because a WINDOW_UPDATE %% 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), {ok, << 4:8, 0:40, _:Len1/binary >>} = gen_tcp:recv(Socket, 6 + Len1, 1000),
%% Send the SETTINGS ack. %% Send the SETTINGS ack.
ok = gen_tcp:send(Socket, cow_http2: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. %% Receive the SETTINGS ack.
{ok, << 0:24, 4:8, 1:8, 0:32 >>} = gen_tcp:recv(Socket, 9, 1000), {ok, << 0:24, 4:8, 1:8, 0:32 >>} = gen_tcp:recv(Socket, 9, 1000),
Headers = [ Headers = [
@ -3153,7 +3150,11 @@ lingering_data_counts_toward_connection_window(Config0) ->
% Make sure server send RST_STREAM. % Make sure server send RST_STREAM.
timer:sleep(100), timer:sleep(100),
ok = gen_tcp:send(Socket, [ 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), {ok, << SkipLen:24, 1:8, _:8, 1:32 >>} = gen_tcp:recv(Socket, 9, 1000),
% Skip the header. % Skip the header.
@ -3161,7 +3162,7 @@ lingering_data_counts_toward_connection_window(Config0) ->
% Skip RST_STREAM. % Skip RST_STREAM.
{ok, << 4:24, 3:8, 1:40, _:32 >>} = gen_tcp:recv(Socket, 13, 1000), {ok, << 4:24, 3:8, 1:40, _:32 >>} = gen_tcp:recv(Socket, 13, 1000),
% Received a WINDOW_UPDATE frame after we got RST_STREAM. % 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 after
cowboy:stop_listener(?FUNCTION_NAME) cowboy:stop_listener(?FUNCTION_NAME)
end. end.