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

Send many frames in one TCP send

Includes refactoring of the related code to avoid repetition.
This commit is contained in:
Loïc Hoguin 2016-08-15 20:04:37 +02:00
parent 1d01d0fc06
commit c750dd76b4

View file

@ -320,29 +320,7 @@ handler_call(State=#state{handler=Handler}, HandlerState,
{ok, HandlerState2} -> {ok, HandlerState2} ->
NextState(State, HandlerState2, RemainingData); NextState(State, HandlerState2, RemainingData);
{ok, HandlerState2, hibernate} -> {ok, HandlerState2, hibernate} ->
NextState(State#state{hibernate=true}, NextState(State#state{hibernate=true}, HandlerState2, RemainingData);
HandlerState2, RemainingData);
{reply, Payload, HandlerState2}
when is_list(Payload) ->
case websocket_send_many(Payload, State) of
ok ->
NextState(State, HandlerState2, RemainingData);
stop ->
handler_terminate(State, HandlerState2, stop);
Error = {error, _} ->
handler_terminate(State, HandlerState2, Error)
end;
{reply, Payload, HandlerState2, hibernate}
when is_list(Payload) ->
case websocket_send_many(Payload, State) of
ok ->
NextState(State#state{hibernate=true},
HandlerState2, RemainingData);
stop ->
handler_terminate(State, HandlerState2, stop);
Error = {error, _} ->
handler_terminate(State, HandlerState2, Error)
end;
{reply, Payload, HandlerState2} -> {reply, Payload, HandlerState2} ->
case websocket_send(Payload, State) of case websocket_send(Payload, State) of
ok -> ok ->
@ -370,26 +348,33 @@ handler_call(State=#state{handler=Handler}, HandlerState,
end. end.
-spec websocket_send(cow_ws:frame(), #state{}) -> ok | stop | {error, atom()}. -spec websocket_send(cow_ws:frame(), #state{}) -> ok | stop | {error, atom()}.
websocket_send(Frames, State) when is_list(Frames) ->
websocket_send_many(Frames, State, []);
websocket_send(Frame, #state{socket=Socket, transport=Transport, extensions=Extensions}) -> websocket_send(Frame, #state{socket=Socket, transport=Transport, extensions=Extensions}) ->
Res = Transport:send(Socket, cow_ws:frame(Frame, Extensions)), Res = Transport:send(Socket, cow_ws:frame(Frame, Extensions)),
case Frame of case is_close_frame(Frame) of
close -> stop; true -> stop;
{close, _} -> stop; false -> Res
{close, _, _} -> stop;
_ -> Res
end. end.
-spec websocket_send_many([cow_ws:frame()], #state{}) -> ok | stop | {error, atom()}. websocket_send_many([], #state{socket=Socket, transport=Transport}, Acc) ->
websocket_send_many([], _) -> Transport:send(Socket, lists:reverse(Acc));
ok; websocket_send_many([Frame|Tail], State=#state{socket=Socket, transport=Transport,
websocket_send_many([Frame|Tail], State) -> extensions=Extensions}, Acc0) ->
%% @todo Send the frames all in one larger TCP packet rather than potentially many small. Acc = [cow_ws:frame(Frame, Extensions)|Acc0],
case websocket_send(Frame, State) of case is_close_frame(Frame) of
ok -> websocket_send_many(Tail, State); true ->
stop -> stop; _ = Transport:send(Socket, lists:reverse(Acc)),
Error -> Error stop;
false ->
websocket_send_many(Tail, State, Acc)
end. end.
is_close_frame(close) -> true;
is_close_frame({close, _}) -> true;
is_close_frame({close, _, _}) -> true;
is_close_frame(_) -> false.
-spec websocket_close(#state{}, any(), terminate_reason()) -spec websocket_close(#state{}, any(), terminate_reason())
-> {ok, cowboy_middleware:env()}. -> {ok, cowboy_middleware:env()}.
websocket_close(State=#state{socket=Socket, transport=Transport, extensions=Extensions}, websocket_close(State=#state{socket=Socket, transport=Transport, extensions=Extensions},