aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gun_http.erl20
-rw-r--r--src/gun_spdy.erl14
-rw-r--r--test/spdy_SUITE.erl17
3 files changed, 34 insertions, 17 deletions
diff --git a/src/gun_http.erl b/src/gun_http.erl
index 67c235f..1090e6b 100644
--- a/src/gun_http.erl
+++ b/src/gun_http.erl
@@ -241,11 +241,11 @@ request(State=#http_state{socket=Socket, transport=Transport, version=Version,
new_stream(State#http_state{connection=Conn}, StreamRef).
%% We are expecting a new stream.
-data(State=#http_state{out=head}, _, _, _) ->
- error_stream_closed(State);
+data(State=#http_state{out=head}, StreamRef, _, _) ->
+ error_stream_closed(State, StreamRef);
%% There are no active streams.
-data(State=#http_state{streams=[]}, _, _, _) ->
- error_stream_not_found(State);
+data(State=#http_state{streams=[]}, StreamRef, _, _) ->
+ error_stream_not_found(State, StreamRef);
%% We can only send data on the last created stream.
data(State=#http_state{socket=Socket, transport=Transport, version=Version,
out=Out, streams=Streams}, StreamRef, IsFin, Data) ->
@@ -280,7 +280,7 @@ data(State=#http_state{socket=Socket, transport=Transport, version=Version,
State
end;
{_, _} ->
- error_stream_not_found(State)
+ error_stream_not_found(State, StreamRef)
end.
%% We can't cancel anything, we can just stop forwarding messages to the owner.
@@ -289,7 +289,7 @@ cancel(State, StreamRef) ->
true ->
cancel_stream(State, StreamRef);
false ->
- error_stream_not_found(State)
+ error_stream_not_found(State, StreamRef)
end.
%% HTTP does not provide any way to figure out what streams are unprocessed.
@@ -300,13 +300,13 @@ down(#http_state{streams=Streams}) ->
end || {Ref, _} <- Streams],
{KilledStreams, []}.
-error_stream_closed(State=#http_state{owner=Owner}) ->
- Owner ! {gun_error, self(), {badstate,
+error_stream_closed(State=#http_state{owner=Owner}, StreamRef) ->
+ Owner ! {gun_error, self(), StreamRef, {badstate,
"The stream has already been closed."}},
State.
-error_stream_not_found(State=#http_state{owner=Owner}) ->
- Owner ! {gun_error, self(), {badstate,
+error_stream_not_found(State=#http_state{owner=Owner}, StreamRef) ->
+ Owner ! {gun_error, self(), StreamRef, {badstate,
"The stream cannot be found."}},
State.
diff --git a/src/gun_spdy.erl b/src/gun_spdy.erl
index 9a7d493..ef5d0cb 100644
--- a/src/gun_spdy.erl
+++ b/src/gun_spdy.erl
@@ -246,7 +246,7 @@ data(State=#spdy_state{socket=Socket, transport=Transport},
StreamRef, IsFin, Data) ->
case get_stream_by_ref(StreamRef, State) of
#stream{out=false} ->
- error_stream_closed(State);
+ error_stream_closed(State, StreamRef);
S = #stream{} ->
IsFin2 = IsFin =:= fin,
Transport:send(Socket, cow_spdy:data(S#stream.id, IsFin2, Data)),
@@ -256,7 +256,7 @@ data(State=#spdy_state{socket=Socket, transport=Transport},
State
end;
false ->
- error_stream_not_found(State)
+ error_stream_not_found(State, StreamRef)
end.
cancel(State=#spdy_state{socket=Socket, transport=Transport},
@@ -266,7 +266,7 @@ cancel(State=#spdy_state{socket=Socket, transport=Transport},
Transport:send(Socket, cow_spdy:rst_stream(StreamID, cancel)),
delete_stream(StreamID, State);
false ->
- error_stream_not_found(State)
+ error_stream_not_found(State, StreamRef)
end.
%% @todo Add unprocessed streams when GOAWAY handling is done.
@@ -274,13 +274,13 @@ down(#spdy_state{streams=Streams}) ->
KilledStreams = [Ref || #stream{ref=Ref} <- Streams],
{KilledStreams, []}.
-error_stream_closed(State=#spdy_state{owner=Owner}) ->
- Owner ! {gun_error, self(), {badstate,
+error_stream_closed(State=#spdy_state{owner=Owner}, StreamRef) ->
+ Owner ! {gun_error, self(), StreamRef, {badstate,
"The stream has already been closed."}},
State.
-error_stream_not_found(State=#spdy_state{owner=Owner}) ->
- Owner ! {gun_error, self(), {badstate,
+error_stream_not_found(State=#spdy_state{owner=Owner}, StreamRef) ->
+ Owner ! {gun_error, self(), StreamRef, {badstate,
"The stream cannot be found."}},
State.
diff --git a/test/spdy_SUITE.erl b/test/spdy_SUITE.erl
index 645d13c..c1ae1ba 100644
--- a/test/spdy_SUITE.erl
+++ b/test/spdy_SUITE.erl
@@ -186,3 +186,20 @@ stream_duplicate_streamid(_) ->
]),
wait(),
[_, {goaway, 1, protocol_error}] = spdy_server:stop(ServerPid).
+
+no_sending_frames_after_flag_fin(_) ->
+ doc("Do not send frames after sending FLAG_FIN. (spdy-protocol-draft3-1 2.3.6)"),
+ {ok, ServerPid, Port} = spdy_server:start_link(),
+ {ok, ConnPid} = gun:open("localhost", Port, #{transport=>ssl}),
+ {ok, spdy} = gun:await_up(ConnPid),
+ %% Send a POST frame with no content header so that Gun sets FLAG_FIN,
+ %% then try sending data. Gun should reject this second call.
+ StreamRef = gun:post(ConnPid, "/", []),
+ gun:data(ConnPid, StreamRef, false, <<"Hello world!">>),
+ receive {gun_error, ConnPid, StreamRef, _} ->
+ ok
+ after 5000 ->
+ exit(timeout)
+ end,
+ wait(),
+ [{syn_stream, _, _, _, _, _, _, _, _, _, _, _}] = spdy_server:stop(ServerPid).