2
2
% % @doc Erlang websocket client
3
3
-module (websocket_client ).
4
4
5
- -export ([
6
- start_link /3 ,
5
+ -export ([start_link /3 ,
7
6
start_link /4 ,
8
7
cast /2 ,
9
8
send /2
@@ -182,7 +181,7 @@ handle_websocket_message(WSReq, HandlerState, Buffer, Message) ->
182
181
ok = send (Frame , WSReq ),
183
182
websocket_loop (WSReq , HandlerState , Buffer );
184
183
{_Closed , Socket } ->
185
- websocket_close (WSReq , HandlerState , { remote , closed } );
184
+ websocket_close (WSReq , HandlerState , remote );
186
185
{_TransportType , Socket , Data } ->
187
186
case Remaining of
188
187
undefined ->
@@ -194,18 +193,11 @@ handle_websocket_message(WSReq, HandlerState, Buffer, Message) ->
194
193
end ;
195
194
Msg ->
196
195
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 })
209
201
end
210
202
end .
211
203
@@ -224,16 +216,26 @@ cancel_keepalive_timer(WSReq) ->
224
216
Reason :: tuple ()) -> ok .
225
217
websocket_close (WSReq , HandlerState , Reason ) ->
226
218
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 "
232
236
" ** Handler state was ~p~n "
233
237
" ** 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 ()]).
237
239
238
240
% % @doc Key sent in initial handshake
239
241
-spec generate_ws_key () ->
@@ -339,18 +341,24 @@ retrieve_frame(WSReq, HandlerState, Opcode, Len, Data, Buffer) ->
339
341
end ,
340
342
case OpcodeName of
341
343
close when byte_size (FullPayload ) >= 2 ->
342
- << CodeBin :2 /binary , ClosePayload /binary >> = FullPayload ,
344
+ << CodeBin :2 /binary , _ClosePayload /binary >> = FullPayload ,
343
345
Code = binary :decode_unsigned (CodeBin ),
344
346
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 }
350
358
end ,
351
359
websocket_close (WSReq , HandlerState , Reason );
352
360
close ->
353
- websocket_close (WSReq , HandlerState , { remote , <<>>} );
361
+ websocket_close (WSReq , HandlerState , remote );
354
362
% % Non-control continuation frame
355
363
_ when Opcode < 8 , Continuation =/= undefined , Fin == 0 ->
356
364
% % Append to previously existing continuation payloads and continue
@@ -366,36 +374,21 @@ retrieve_frame(WSReq, HandlerState, Opcode, Len, Data, Buffer) ->
366
374
try Handler :websocket_handle (
367
375
{ContinuationOpcodeName , DefragPayload },
368
376
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 })
382
382
end ;
383
383
_ ->
384
384
try Handler :websocket_handle (
385
385
{OpcodeName , FullPayload },
386
386
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 })
399
392
end
400
393
end .
401
394
@@ -407,11 +400,14 @@ handle_response(WSReq, {reply, Frame, HandlerState}, Buffer) ->
407
400
% % we can still have more messages in buffer
408
401
case websocket_req :remaining (WSReq ) of
409
402
% % buffer should not contain uncomplete messages
410
- undefined -> retrieve_frame (WSReq , HandlerState , Buffer );
403
+ undefined ->
404
+ retrieve_frame (WSReq , HandlerState , Buffer );
411
405
% % buffer contain uncomplete message that shouldnt be parsed
412
- _ -> websocket_loop (WSReq , HandlerState , Buffer )
406
+ _ ->
407
+ websocket_loop (WSReq , HandlerState , Buffer )
413
408
end ;
414
- Reason -> websocket_close (WSReq , HandlerState , Reason )
409
+ {error , Reason } ->
410
+ websocket_close (WSReq , HandlerState , {local , Reason })
415
411
end ;
416
412
handle_response (WSReq , {ok , HandlerState }, Buffer ) ->
417
413
% % we can still have more messages in buffer
@@ -424,7 +420,7 @@ handle_response(WSReq, {ok, HandlerState}, Buffer) ->
424
420
425
421
handle_response (WSReq , {close , Payload , HandlerState }, _ ) ->
426
422
send ({close , Payload }, WSReq ),
427
- websocket_close (WSReq , HandlerState , { normal , Payload } ).
423
+ websocket_close (WSReq , HandlerState , normal ).
428
424
429
425
% % @doc Encodes the data with a header (including a masking key) and
430
426
% % masks the data
0 commit comments