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

Check for errors when calling Transport:send in the websocket protocol

In some situations, the underlying socket might become "half-open" in
which case the websocket will stay in a waiting state indefinitely. The
detection of this state requires checking for errors when calling send.
This commit is contained in:
Ali Sabil 2012-04-08 11:57:30 +02:00 committed by Ali Sabil
parent 8386e10dcc
commit 9b0049fdd7

View file

@ -452,22 +452,38 @@ handler_call(State=#state{handler=Handler, opts=Opts}, Req, HandlerState,
Req2, HandlerState2, RemainingData); Req2, HandlerState2, RemainingData);
{reply, Payload, Req2, HandlerState2} {reply, Payload, Req2, HandlerState2}
when is_tuple(Payload) -> when is_tuple(Payload) ->
ok = websocket_send(Payload, State), case websocket_send(Payload, State) of
NextState(State, Req2, HandlerState2, RemainingData); ok ->
NextState(State, Req2, HandlerState2, RemainingData);
{error, _} = Error ->
handler_terminate(State, Req2, HandlerState2, Error)
end;
{reply, Payload, Req2, HandlerState2, hibernate} {reply, Payload, Req2, HandlerState2, hibernate}
when is_tuple(Payload) -> when is_tuple(Payload) ->
ok = websocket_send(Payload, State), case websocket_send(Payload, State) of
NextState(State#state{hibernate=true}, ok ->
Req2, HandlerState2, RemainingData); NextState(State#state{hibernate=true},
Req2, HandlerState2, RemainingData);
{error, _} = Error ->
handler_terminate(State, Req2, HandlerState2, Error)
end;
{reply, Payload, Req2, HandlerState2} {reply, Payload, Req2, HandlerState2}
when is_list(Payload) -> when is_list(Payload) ->
ok = websocket_send_many(Payload, State), case websocket_send_many(Payload, State) of
NextState(State, Req2, HandlerState2, RemainingData); ok ->
NextState(State, Req2, HandlerState2, RemainingData);
{error, _} = Error ->
handler_terminate(State, Req2, HandlerState2, Error)
end;
{reply, Payload, Req2, HandlerState2, hibernate} {reply, Payload, Req2, HandlerState2, hibernate}
when is_list(Payload) -> when is_list(Payload) ->
ok = websocket_send_many(Payload, State), case websocket_send_many(Payload, State) of
NextState(State#state{hibernate=true}, ok ->
Req2, HandlerState2, RemainingData); NextState(State#state{hibernate=true},
Req2, HandlerState2, RemainingData);
{error, _} = Error ->
handler_terminate(State, Req2, HandlerState2, Error)
end;
{shutdown, Req2, HandlerState2} -> {shutdown, Req2, HandlerState2} ->
websocket_close(State, Req2, HandlerState2, {normal, shutdown}) websocket_close(State, Req2, HandlerState2, {normal, shutdown})
catch Class:Reason -> catch Class:Reason ->
@ -507,8 +523,10 @@ websocket_send({Type, Payload}, #state{socket=Socket, transport=Transport}) ->
websocket_send_many([], _) -> websocket_send_many([], _) ->
ok; ok;
websocket_send_many([Frame|Tail], State) -> websocket_send_many([Frame|Tail], State) ->
ok = websocket_send(Frame, State), case websocket_send(Frame, State) of
websocket_send_many(Tail, State). ok -> websocket_send_many(Tail, State);
Error -> Error
end.
-spec websocket_close(#state{}, cowboy_req:req(), any(), {atom(), atom()}) -spec websocket_close(#state{}, cowboy_req:req(), any(), {atom(), atom()})
-> closed. -> closed.