Skip to content

Commit

Permalink
Detect ping frames
Browse files Browse the repository at this point in the history
A new option ws_ping_timeout enables to set the time to wait for the ws pings coming from the server.
  • Loading branch information
ziopio committed May 24, 2024
1 parent e60b25b commit e2dbbb1
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ Such client is disabled by default (`{ntp, false}`), and is not required to auth
Accepts an integer that represents time in milliseconds, default value is `5_000`.
Allows to tweak the timeout of each API request going through the websocket.

### ws_ping_timeout
Accepts an integer that represents time in milliseconds, default value is `60_000`.
Allows to tweak the timeout between expected ping frames from the server.
If the timeout is exceeded, the socket is closed and a new connection is attempted.

### logs_interval

Accepts an integer that represents time in milliseconds, default value is `2_000`.
Expand Down
1 change: 1 addition & 0 deletions src/grisp_connect.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
{connect, true}, % keeps a constant connection with grisp.io
{ntp, false}, % if set to true, starts the NTP client
{ws_requests_timeout, 5_000},
{ws_ping_timeout, 60_000},
{logs_interval, 2_000},
{logs_batch_size, 100},
{logger, [
Expand Down
30 changes: 25 additions & 5 deletions src/grisp_connect_ws.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
gun_pid,
gun_ref,
ws_stream,
ws_up = false
ws_up = false,
ping_timer
}).

-define(disconnected_state,
Expand Down Expand Up @@ -72,19 +73,29 @@ handle_cast({send, Payload}, #state{gun_pid = Pid, ws_stream = Stream} = S) ->
handle_info({gun_up, GunPid, _}, #state{gun_pid = GunPid} = S) ->
?LOG_INFO(#{event => connection_enstablished}),
GunRef = monitor(process, GunPid),
WsStream = gun:ws_upgrade(GunPid, "/grisp-connect/ws"),
WsStream = gun:ws_upgrade(GunPid, "/grisp-connect/ws",[],
#{silence_pings => false}),
NewState = S#state{gun_pid = GunPid, gun_ref = GunRef, ws_stream = WsStream},
{noreply, NewState};
handle_info({gun_up, _OldPid, http}, #state{gun_pid = _GunPid} = S) ->
% Ignoring outdated gun_up messages
{noreply, S};
handle_info({gun_upgrade, Pid, Stream, [<<"websocket">>], _},
#state{gun_pid = Pid, ws_stream = Stream} = S) ->
?LOG_INFO(#{event => ws_upgrade}),
{noreply, S#state{ws_up = true}};
PingTimer = start_ping_timer(),
{noreply, S#state{ws_up = true, ping_timer = PingTimer}};
handle_info({gun_response, Pid, Stream, _, Status, _Headers},
#state{gun_pid = Pid, ws_stream = Stream} = S) ->
?LOG_ERROR(#{event => ws_upgrade_failure, status => Status}),
{noreply, shutdown_gun(S)};
handle_info({gun_ws, Conn, Stream, {text, Text}},
#state{gun_pid = Conn, ws_stream = Stream} = S) ->
handle_info({gun_ws, Pid, Stream, ping},
#state{gun_pid = Pid, ws_stream = Stream,
ping_timer = PingTimer} = S) ->
timer:cancel(PingTimer),
{noreply, S#state{ping_timer = undefined}};
handle_info({gun_ws, Pid, Stream, {text, Text}},
#state{gun_pid = Pid, ws_stream = Stream} = S) ->
grisp_connect_client:handle_message(Text),
{noreply, S};
handle_info({gun_down, Pid, ws, closed, [Stream]}, #state{gun_pid = Pid, ws_stream = Stream} = S) ->
Expand All @@ -95,6 +106,10 @@ handle_info({'DOWN', _, process, Pid, Reason}, #state{gun_pid = Pid} = S) ->
?LOG_WARNING(#{event => gun_crash, reason => Reason}),
grisp_connect_client:disconnected(),
{noreply, S?disconnected_state};
handle_info(ping_timeout, S) ->
?LOG_WARNING(#{event => ping_timeout}),
grisp_connect_client:disconnected(),
{noreply, S?disconnected_state};
handle_info(M, S) ->
?LOG_WARNING(#{event => unhandled_info, info => M, state => S}),
{noreply, S}.
Expand All @@ -105,3 +120,8 @@ shutdown_gun(#state{gun_pid = Pid, gun_ref = GunRef} = State) ->
demonitor(GunRef),
gun:shutdown(Pid),
State?disconnected_state.

start_ping_timer() ->
{ok, Timeout} = application:get_env(grisp_connect, ws_ping_timeout),
{ok, Tref} = timer:send_after(Timeout, ping_timeout),
Tref.

0 comments on commit e2dbbb1

Please sign in to comment.