diff options
author | Tony Han <[email protected]> | 2019-04-28 10:51:50 +0800 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2019-07-26 13:56:39 +0200 |
commit | 00b0b29eacf3eb8a51273dc43064c6367573c4c4 (patch) | |
tree | 9e70f93b3f15ef4f9f2a20132c7072ce6454341a | |
parent | e4df3bb7c726571640c2799bc7a6fbb687b3bdae (diff) | |
download | gun-00b0b29eacf3eb8a51273dc43064c6367573c4c4.tar.gz gun-00b0b29eacf3eb8a51273dc43064c6367573c4c4.tar.bz2 gun-00b0b29eacf3eb8a51273dc43064c6367573c4c4.zip |
Data received after RST_STREAM counts toward window
-rw-r--r-- | src/gun_http2.erl | 9 | ||||
-rw-r--r-- | test/rfc7540_SUITE.erl | 45 |
2 files changed, 54 insertions, 0 deletions
diff --git a/src/gun_http2.erl b/src/gun_http2.erl index 78b137b..20e21ec 100644 --- a/src/gun_http2.erl +++ b/src/gun_http2.erl @@ -142,6 +142,9 @@ frame(State=#http2_state{http2_machine=HTTP2Machine0}, Frame, EvHandler, EvHandl {ok, {data, StreamID, IsFin, Data}, HTTP2Machine} -> data_frame(State#http2_state{http2_machine=HTTP2Machine}, StreamID, IsFin, Data, EvHandler, EvHandlerState); + {ok, {lingering_data, _StreamID, DataLen}, HTTP2Machine} -> + {lingering_data_frame(State#http2_state{http2_machine=HTTP2Machine}, DataLen), + EvHandlerState}; {ok, {headers, StreamID, IsFin, Headers, PseudoHeaders, BodyLen}, HTTP2Machine} -> headers_frame(State#http2_state{http2_machine=HTTP2Machine}, StreamID, IsFin, Headers, PseudoHeaders, BodyLen, @@ -180,6 +183,12 @@ maybe_ack(State=#http2_state{socket=Socket, transport=Transport}, Frame) -> end, State. +lingering_data_frame(State=#http2_state{socket=Socket, transport=Transport, + http2_machine=HTTP2Machine0}, DataLen) -> + Transport:send(Socket, cow_http2:window_update(DataLen)), + HTTP2Machine1 = cow_http2_machine:update_window(DataLen, HTTP2Machine0), + State#http2_state{http2_machine=HTTP2Machine1}. + data_frame(State=#http2_state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0}, StreamID, IsFin, Data, EvHandler, EvHandlerState0) -> diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl index 543a6f0..f494c9f 100644 --- a/test/rfc7540_SUITE.erl +++ b/test/rfc7540_SUITE.erl @@ -70,6 +70,51 @@ do_authority_port(Transport0, DefaultPort, AuthorityHeaderPort) -> AuthorityHeaderPort = Rest, gun:close(ConnPid). +lingering_data_counts_toward_connection_window(_) -> + doc("DATA frames received after sending RST_STREAM must be counted " + "toward the connection flow-control window. (RFC7540 5.1)"), + {ok, _, Port} = init_origin(tcp, http2, fun(_, Socket, Transport) -> + %% Step 2. + %% Receive a HEADERS frame. + {ok, <<SkipLen:24, 1:8, _:8, 1:32>>} = Transport:recv(Socket, 9, 1000), + %% Skip the header. + {ok, _} = gen_tcp:recv(Socket, SkipLen, 1000), + %% Skip the data. + {ok, <<_:24, 0:8, _:8, 1:32>>} = Transport:recv(Socket, 9, 1000), + %% Send a HEADERS frame. + {HeadersBlock, _} = cow_hpack:encode([ + {<<":status">>, <<"200">>} + ]), + %% Step 3. + ok = Transport:send(Socket, [ + cow_http2:headers(1, nofin, HeadersBlock) + ]), + %% Step 5. + %% Make sure Gun sends the RST_STREAM. + timer:sleep(100), + %% Step 7. + ok = Transport:send(Socket, [ + cow_http2:data(1, nofin, <<0:0/unit:8>>), + cow_http2:data(1, nofin, <<0:1000/unit:8>>) + ]), + %% 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) + end), + {ok, ConnPid} = gun:open("localhost", Port, #{protocols => [http2]}), + {ok, http2} = gun:await_up(ConnPid), + timer:sleep(100), %% Give enough time for the handshake to fully complete. + %% Step 1. + StreamRef = gun:get(ConnPid, "/"), + %% Step 4. + {response, nofin, 200, _} = gun:await(ConnPid, StreamRef), + %% Step 6. + gun:cancel(ConnPid, StreamRef), + %% Make sure Gun sends the WINDOW_UPDATE and the server test passes. + timer:sleep(300), + gun:close(ConnPid). + headers_priority_flag(_) -> doc("HEADERS frames may include a PRIORITY flag indicating " "that stream dependency information is attached. (RFC7540 6.2)"), |