22% % @doc Erlang websocket client
33-module (websocket_client ).
44
5- -export ([
6- start_link /3 ,
5+ -export ([start_link /3 ,
76 start_link /4 ,
87 cast /2 ,
98 send /2
@@ -182,7 +181,7 @@ handle_websocket_message(WSReq, HandlerState, Buffer, Message) ->
182181 ok = send (Frame , WSReq ),
183182 websocket_loop (WSReq , HandlerState , Buffer );
184183 {_Closed , Socket } ->
185- websocket_close (WSReq , HandlerState , { remote , closed } );
184+ websocket_close (WSReq , HandlerState , remote );
186185 {_TransportType , Socket , Data } ->
187186 case Remaining of
188187 undefined ->
@@ -194,18 +193,11 @@ handle_websocket_message(WSReq, HandlerState, Buffer, Message) ->
194193 end ;
195194 Msg ->
196195 try Handler :websocket_info (Msg , WSReq , HandlerState ) of
197- HandlerResponse ->
198- handle_response (WSReq , HandlerResponse , Buffer )
199- catch Class :Reason ->
200- error_logger :error_msg (
201- " ** Websocket client ~p terminating in ~p /~p~n "
202- " for the reason ~p :~p~n "
203- " ** Last message was ~p~n "
204- " ** Handler state was ~p~n "
205- " ** Stacktrace: ~p~n~n " ,
206- [Handler , websocket_info , 3 , Class , Reason , Msg , HandlerState ,
207- erlang :get_stacktrace ()]),
208- websocket_close (WSReq , HandlerState , Reason )
196+ HandlerResponse ->
197+ handle_response (WSReq , HandlerResponse , Buffer )
198+ catch
199+ _ :Reason ->
200+ websocket_close (WSReq , HandlerState , {handler , Reason })
209201 end
210202 end .
211203
@@ -224,16 +216,26 @@ cancel_keepalive_timer(WSReq) ->
224216 Reason :: tuple ()) -> ok .
225217websocket_close (WSReq , HandlerState , Reason ) ->
226218 Handler = websocket_req :handler (WSReq ),
227- try Handler :websocket_terminate (Reason , WSReq , HandlerState )
228- catch Class :Reason2 ->
229- error_logger :error_msg (
230- " ** Websocket handler ~p terminating in ~p /~p~n "
231- " for the reason ~p :~p~n "
219+ try Handler :websocket_terminate (Reason , WSReq , HandlerState ) of
220+ _ ->
221+ case Reason of
222+ normal -> ok ;
223+ _ -> error_info (Handler , Reason , HandlerState )
224+ end ,
225+ exit (Reason )
226+ catch
227+ _ :Reason2 ->
228+ error_info (Handler , Reason2 , HandlerState ),
229+ exit (Reason2 )
230+ end .
231+
232+ error_info (Handler , Reason , State ) ->
233+ error_logger :error_msg (
234+ " ** Websocket handler ~p terminating~n "
235+ " ** for the reason ~p~n "
232236 " ** Handler state was ~p~n "
233237 " ** Stacktrace: ~p~n~n " ,
234- [Handler , websocket_terminate , 3 , Class , Reason2 , HandlerState ,
235- erlang :get_stacktrace ()])
236- end .
238+ [Handler , Reason , State , erlang :get_stacktrace ()]).
237239
238240% % @doc Key sent in initial handshake
239241-spec generate_ws_key () ->
@@ -339,18 +341,24 @@ retrieve_frame(WSReq, HandlerState, Opcode, Len, Data, Buffer) ->
339341 end ,
340342 case OpcodeName of
341343 close when byte_size (FullPayload ) >= 2 ->
342- << CodeBin :2 /binary , ClosePayload /binary >> = FullPayload ,
344+ << CodeBin :2 /binary , _ClosePayload /binary >> = FullPayload ,
343345 Code = binary :decode_unsigned (CodeBin ),
344346 Reason = case Code of
345- 1000 -> {normal , ClosePayload };
346- 1002 -> {error , badframe , ClosePayload };
347- 1007 -> {error , badencoding , ClosePayload };
348- 1011 -> {error , handler , ClosePayload };
349- _ -> {remote , Code , ClosePayload }
347+ % 1000 indicates a normal closure, meaning that the purpose for
348+ % which the connection was established has been fulfilled.
349+ 1000 -> normal ;
350+
351+ % 1001 indicates that an endpoint is "going away", such as a server
352+ % going down or a browser having navigated away from a page.
353+ 1001 -> normal ;
354+
355+ % See https://tools.ietf.org/html/rfc6455#section-7.4.1
356+ % for error code descriptions.
357+ _ -> {remote , Code }
350358 end ,
351359 websocket_close (WSReq , HandlerState , Reason );
352360 close ->
353- websocket_close (WSReq , HandlerState , { remote , <<>>} );
361+ websocket_close (WSReq , HandlerState , remote );
354362 % % Non-control continuation frame
355363 _ when Opcode < 8 , Continuation =/= undefined , Fin == 0 ->
356364 % % Append to previously existing continuation payloads and continue
@@ -366,36 +374,21 @@ retrieve_frame(WSReq, HandlerState, Opcode, Len, Data, Buffer) ->
366374 try Handler :websocket_handle (
367375 {ContinuationOpcodeName , DefragPayload },
368376 WSReq2 , HandlerState ) of
369- HandlerResponse ->
370- handle_response (websocket_req :remaining (undefined , WSReq1 ),
371- HandlerResponse , Rest )
372- catch Class :Reason ->
373- error_logger :error_msg (
374- " ** Websocket client ~p terminating in ~p /~p~n "
375- " for the reason ~p :~p~n "
376- " ** Websocket message was ~p~n "
377- " ** Handler state was ~p~n "
378- " ** Stacktrace: ~p~n~n " ,
379- [Handler , websocket_handle , 3 , Class , Reason , {ContinuationOpcodeName , DefragPayload }, HandlerState ,
380- erlang :get_stacktrace ()]),
381- websocket_close (WSReq , HandlerState , Reason )
377+ HandlerResponse ->
378+ handle_response (websocket_req :remaining (undefined , WSReq1 ),
379+ HandlerResponse , Rest )
380+ catch _ :Reason ->
381+ websocket_close (WSReq , HandlerState , {handler , Reason })
382382 end ;
383383 _ ->
384384 try Handler :websocket_handle (
385385 {OpcodeName , FullPayload },
386386 WSReq , HandlerState ) of
387- HandlerResponse ->
388- handle_response (websocket_req :remaining (undefined , WSReq ),
389- HandlerResponse , Rest )
390- catch Class :Reason ->
391- error_logger :error_msg (
392- " ** Websocket client ~p terminating in ~p /~p~n "
393- " for the reason ~p :~p~n "
394- " ** Handler state was ~p~n "
395- " ** Stacktrace: ~p~n~n " ,
396- [Handler , websocket_handle , 3 , Class , Reason , HandlerState ,
397- erlang :get_stacktrace ()]),
398- websocket_close (WSReq , HandlerState , Reason )
387+ HandlerResponse ->
388+ handle_response (websocket_req :remaining (undefined , WSReq ),
389+ HandlerResponse , Rest )
390+ catch _ :Reason ->
391+ websocket_close (WSReq , HandlerState , {handler , Reason })
399392 end
400393 end .
401394
@@ -407,11 +400,14 @@ handle_response(WSReq, {reply, Frame, HandlerState}, Buffer) ->
407400 % % we can still have more messages in buffer
408401 case websocket_req :remaining (WSReq ) of
409402 % % buffer should not contain uncomplete messages
410- undefined -> retrieve_frame (WSReq , HandlerState , Buffer );
403+ undefined ->
404+ retrieve_frame (WSReq , HandlerState , Buffer );
411405 % % buffer contain uncomplete message that shouldnt be parsed
412- _ -> websocket_loop (WSReq , HandlerState , Buffer )
406+ _ ->
407+ websocket_loop (WSReq , HandlerState , Buffer )
413408 end ;
414- Reason -> websocket_close (WSReq , HandlerState , Reason )
409+ {error , Reason } ->
410+ websocket_close (WSReq , HandlerState , {local , Reason })
415411 end ;
416412handle_response (WSReq , {ok , HandlerState }, Buffer ) ->
417413 % % we can still have more messages in buffer
@@ -424,7 +420,7 @@ handle_response(WSReq, {ok, HandlerState}, Buffer) ->
424420
425421handle_response (WSReq , {close , Payload , HandlerState }, _ ) ->
426422 send ({close , Payload }, WSReq ),
427- websocket_close (WSReq , HandlerState , { normal , Payload } ).
423+ websocket_close (WSReq , HandlerState , normal ).
428424
429425% % @doc Encodes the data with a header (including a masking key) and
430426% % masks the data
0 commit comments