Permalink
Browse files

fix websockets reply status codes for client close messages

A number of autobahn WebSockets tests were failing due to replies
containing incorrect status codes. Check client status codes and reply with
correct codes.
  • Loading branch information...
1 parent fd690a6 commit b80121d9cfb3eacfb0cfe2f9cf8dbe0134f341f9 @vinoski vinoski committed Jun 2, 2012
Showing with 39 additions and 4 deletions.
  1. +39 −4 src/yaws_websockets.erl
View
@@ -133,7 +133,8 @@ handle_info({tcp, Socket, FirstPacket}, #state{wsstate=#ws_state{sock=Socket}}=S
CallbackMod:handle_message(M)
end,
BasicMessages),
- {catch lists:foldl(handle_result_fun(WSState), ok, CallbackResults),
+ FoldFun = handle_result_fun(WSState),
+ {catch lists:foldl(FoldFun, ok, lists:zip(FrameInfos, CallbackResults)),
NewCallbackState0};
{advanced,_} ->
catch lists:foldl(do_callback_fun(WSState, CallbackMod),
@@ -226,15 +227,18 @@ handshake(8, Arg, _CliSock, _WebSocketLocation, _Origin, _Protocol) ->
"\r\n"].
handle_result_fun(WSState) ->
- fun(Result, Acc) ->
+ fun({FrameInfo, Result}, Acc) ->
case Result of
{reply, {Type, Data}} ->
do_send(WSState, {Type, Data}),
Acc;
noreply ->
Acc;
{close, Reason} ->
- throw({close, Reason})
+ %% check if client sent a close, and if so, verify that the
+ %% close code is legal
+ NReason = check_close_code(FrameInfo, Reason),
+ throw({close, NReason})
end
end.
@@ -247,10 +251,41 @@ do_callback_fun(WSState, CallbackMod) ->
{noreply, NewCallbackState} ->
{Results, NewCallbackState};
{close, Reason} ->
- throw({{close, Reason}, CallbackState})
+ %% check if client sent a close, and if so, verify that the
+ %% close code is legal
+ NReason = check_close_code(FrameInfo, Reason),
+ throw({{close, NReason}, CallbackState})
end
end.
+%% The checks for close status codes here are based on RFC 6455 and on
+%% the autobahn testsuite (http://autobahn.ws/testsuite).
+check_close_code(#ws_frame_info{opcode=close, length=Len, data=Data}, Reason) ->
+ if
+ Len == 0 ->
+ Reason;
+ Len < 2 ->
+ 1002;
+ true ->
+ <<Code:16/big, _/binary>> = Data,
+ if
+ Code >= 3000 andalso Code =< 4999 ->
+ Reason;
+ Code < 1000 ->
+ 1002;
+ Code >= 1004 andalso Code =< 1006 ->
+ 1002;
+ Code >= 1012 andalso Code =< 1016 ->
+ 1002;
+ Code > 1016 ->
+ 1002;
+ true ->
+ Reason
+ end
+ end;
+check_close_code(_, Reason) ->
+ Reason.
+
do_close(WSState, Reason) ->
Status = case Reason of
_ when is_integer(Reason) -> Reason;

0 comments on commit b80121d

Please sign in to comment.