mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-16 05:00:24 +00:00
Simplify the SPDY code by adding child management functions
This commit is contained in:
parent
9b52ccad03
commit
d83205243a
1 changed files with 38 additions and 35 deletions
|
@ -131,7 +131,7 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport,
|
||||||
{recv, FromSocket = {Pid, StreamID}, FromPid, Length, _Timeout}
|
{recv, FromSocket = {Pid, StreamID}, FromPid, Length, _Timeout}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
Child = #child{in_buffer=InBuffer, is_recv=false}
|
Child = #child{in_buffer=InBuffer, is_recv=false}
|
||||||
= lists:keyfind(StreamID, #child.streamid, Children),
|
= get_child(StreamID, State),
|
||||||
if
|
if
|
||||||
Length =:= 0, InBuffer =/= <<>> ->
|
Length =:= 0, InBuffer =/= <<>> ->
|
||||||
FromPid ! {recv, FromSocket, {ok, InBuffer}},
|
FromPid ! {recv, FromSocket, {ok, InBuffer}},
|
||||||
|
@ -152,55 +152,40 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport,
|
||||||
end;
|
end;
|
||||||
{reply, {Pid, StreamID}, Status, Headers}
|
{reply, {Pid, StreamID}, Status, Headers}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
Child = #child{output=nofin} = lists:keyfind(StreamID,
|
Child = #child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
syn_reply(State, StreamID, true, Status, Headers),
|
syn_reply(State, StreamID, true, Status, Headers),
|
||||||
Children2 = lists:keyreplace(StreamID,
|
loop(out_fin_child(Child, State));
|
||||||
#child.streamid, Children, Child#child{output=fin}),
|
|
||||||
loop(State#state{children=Children2});
|
|
||||||
{reply, {Pid, StreamID}, Status, Headers, Body}
|
{reply, {Pid, StreamID}, Status, Headers, Body}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
Child = #child{output=nofin} = lists:keyfind(StreamID,
|
Child = #child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
syn_reply(State, StreamID, false, Status, Headers),
|
syn_reply(State, StreamID, false, Status, Headers),
|
||||||
data(State, StreamID, true, Body),
|
data(State, StreamID, true, Body),
|
||||||
Children2 = lists:keyreplace(StreamID,
|
loop(out_fin_child(Child, State));
|
||||||
#child.streamid, Children, Child#child{output=fin}),
|
|
||||||
loop(State#state{children=Children2});
|
|
||||||
{stream_reply, {Pid, StreamID}, Status, Headers}
|
{stream_reply, {Pid, StreamID}, Status, Headers}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
#child{output=nofin} = lists:keyfind(StreamID,
|
#child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
syn_reply(State, StreamID, false, Status, Headers),
|
syn_reply(State, StreamID, false, Status, Headers),
|
||||||
loop(State);
|
loop(State);
|
||||||
{stream_data, {Pid, StreamID}, Data}
|
{stream_data, {Pid, StreamID}, Data}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
#child{output=nofin} = lists:keyfind(StreamID,
|
#child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
data(State, StreamID, false, Data),
|
data(State, StreamID, false, Data),
|
||||||
loop(State);
|
loop(State);
|
||||||
{stream_close, {Pid, StreamID}}
|
{stream_close, {Pid, StreamID}}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
Child = #child{output=nofin} = lists:keyfind(StreamID,
|
Child = #child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
data(State, StreamID, true, <<>>),
|
data(State, StreamID, true, <<>>),
|
||||||
Children2 = lists:keyreplace(StreamID,
|
loop(out_fin_child(Child, State));
|
||||||
#child.streamid, Children, Child#child{output=fin}),
|
|
||||||
loop(State#state{children=Children2});
|
|
||||||
{sendfile, {Pid, StreamID}, Filepath}
|
{sendfile, {Pid, StreamID}, Filepath}
|
||||||
when Pid =:= self() ->
|
when Pid =:= self() ->
|
||||||
Child = #child{output=nofin} = lists:keyfind(StreamID,
|
Child = #child{output=nofin} = get_child(StreamID, State),
|
||||||
#child.streamid, Children),
|
|
||||||
data_from_file(State, StreamID, Filepath),
|
data_from_file(State, StreamID, Filepath),
|
||||||
Children2 = lists:keyreplace(StreamID,
|
loop(out_fin_child(Child, State));
|
||||||
#child.streamid, Children, Child#child{output=fin}),
|
|
||||||
loop(State#state{children=Children2});
|
|
||||||
{'EXIT', Parent, Reason} ->
|
{'EXIT', Parent, Reason} ->
|
||||||
exit(Reason);
|
exit(Reason);
|
||||||
{'EXIT', Pid, _} ->
|
{'EXIT', Pid, _} ->
|
||||||
%% @todo Report the error if any.
|
%% @todo Report the error if any.
|
||||||
Children2 = lists:keydelete(Pid, #child.pid, Children),
|
loop(delete_child(Pid, State));
|
||||||
loop(State#state{children=Children2});
|
|
||||||
{system, From, Request} ->
|
{system, From, Request} ->
|
||||||
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State);
|
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State);
|
||||||
%% Calls from the supervisor module.
|
%% Calls from the supervisor module.
|
||||||
|
@ -248,17 +233,14 @@ handle_frame(State, {syn_stream, StreamID, AssocToStreamID,
|
||||||
%% Erlang does not allow us to control the priority of processes
|
%% Erlang does not allow us to control the priority of processes
|
||||||
%% so we ignore that value entirely.
|
%% so we ignore that value entirely.
|
||||||
handle_frame(State=#state{middlewares=Middlewares, env=Env,
|
handle_frame(State=#state{middlewares=Middlewares, env=Env,
|
||||||
onrequest=OnRequest, onresponse=OnResponse, peer=Peer,
|
onrequest=OnRequest, onresponse=OnResponse, peer=Peer},
|
||||||
children=Children}, {syn_stream, StreamID, _, IsFin,
|
{syn_stream, StreamID, _, IsFin, _, _,
|
||||||
_, _, Method, _, Host, Path, Version, Headers}) ->
|
Method, _, Host, Path, Version, Headers}) ->
|
||||||
Pid = spawn_link(?MODULE, request_init, [
|
Pid = spawn_link(?MODULE, request_init, [
|
||||||
{self(), StreamID}, Peer, OnRequest, OnResponse,
|
{self(), StreamID}, Peer, OnRequest, OnResponse,
|
||||||
Env, Middlewares, Method, Host, Path, Version, Headers
|
Env, Middlewares, Method, Host, Path, Version, Headers
|
||||||
]),
|
]),
|
||||||
IsFin2 = if IsFin -> fin; true -> nofin end,
|
loop(new_child(State, StreamID, Pid, IsFin));
|
||||||
loop(State#state{last_streamid=StreamID,
|
|
||||||
children=[#child{streamid=StreamID, pid=Pid,
|
|
||||||
input=IsFin2, output=nofin}|Children]});
|
|
||||||
%% RST_STREAM.
|
%% RST_STREAM.
|
||||||
handle_frame(State, {rst_stream, StreamID, Status}) ->
|
handle_frame(State, {rst_stream, StreamID, Status}) ->
|
||||||
error_logger:error_msg("Received RST_STREAM frame ~p ~p",
|
error_logger:error_msg("Received RST_STREAM frame ~p ~p",
|
||||||
|
@ -278,7 +260,7 @@ handle_frame(State=#state{socket=Socket, transport=Transport},
|
||||||
handle_frame(State=#state{children=Children},
|
handle_frame(State=#state{children=Children},
|
||||||
{data, StreamID, IsFin, Data}) ->
|
{data, StreamID, IsFin, Data}) ->
|
||||||
Child = #child{input=nofin, in_buffer=Buffer, is_recv=IsRecv}
|
Child = #child{input=nofin, in_buffer=Buffer, is_recv=IsRecv}
|
||||||
= lists:keyfind(StreamID, #child.streamid, Children),
|
= get_child(StreamID, State),
|
||||||
Data2 = << Buffer/binary, Data/binary >>,
|
Data2 = << Buffer/binary, Data/binary >>,
|
||||||
IsFin2 = if IsFin -> fin; true -> nofin end,
|
IsFin2 = if IsFin -> fin; true -> nofin end,
|
||||||
Child2 = case IsRecv of
|
Child2 = case IsRecv of
|
||||||
|
@ -342,6 +324,27 @@ data_from_file(Socket, Transport, StreamID, IoDevice) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% Children.
|
||||||
|
|
||||||
|
new_child(State=#state{children=Children}, StreamID, Pid, IsFin) ->
|
||||||
|
IsFin2 = if IsFin -> fin; true -> nofin end,
|
||||||
|
State#state{last_streamid=StreamID,
|
||||||
|
children=[#child{streamid=StreamID,
|
||||||
|
pid=Pid, input=IsFin2}|Children]}.
|
||||||
|
|
||||||
|
delete_child(Pid, State=#state{children=Children}) ->
|
||||||
|
Children2 = lists:keydelete(Pid, #child.pid, Children),
|
||||||
|
State#state{children=Children2}.
|
||||||
|
|
||||||
|
get_child(StreamID, #state{children=Children}) ->
|
||||||
|
lists:keyfind(StreamID, #child.streamid, Children).
|
||||||
|
|
||||||
|
out_fin_child(Child=#child{streamid=StreamID},
|
||||||
|
State=#state{children=Children}) ->
|
||||||
|
Children2 = lists:keyreplace(StreamID,
|
||||||
|
#child.streamid, Children, Child#child{output=fin}),
|
||||||
|
State#state{children=Children2}.
|
||||||
|
|
||||||
%% Request process.
|
%% Request process.
|
||||||
|
|
||||||
request_init(FakeSocket, Peer, OnRequest, OnResponse,
|
request_init(FakeSocket, Peer, OnRequest, OnResponse,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue