aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-05-13 13:18:01 +0200
committerLoïc Hoguin <[email protected]>2019-05-13 13:18:01 +0200
commit3aa7168404e62f9ea9e290380b93569eff4372a8 (patch)
treeab8cb6f89c2e5e3abb5cb27d34b9b902b427625f
parentcfd702a716f834c431abd46532e8cfa4debd1468 (diff)
downloadgun-3aa7168404e62f9ea9e290380b93569eff4372a8.tar.gz
gun-3aa7168404e62f9ea9e290380b93569eff4372a8.tar.bz2
gun-3aa7168404e62f9ea9e290380b93569eff4372a8.zip
Add the disconnect event callback
-rw-r--r--src/gun.erl13
-rw-r--r--src/gun_default_event_h.erl4
-rw-r--r--src/gun_event.erl9
-rw-r--r--test/event_SUITE.erl20
4 files changed, 42 insertions, 4 deletions
diff --git a/src/gun.erl b/src/gun.erl
index e958d2e..44dbdeb 100644
--- a/src/gun.erl
+++ b/src/gun.erl
@@ -1006,7 +1006,8 @@ commands([{switch_protocol, Protocol, _ProtoState0}|Tail],
disconnect(State=#state{owner=Owner, opts=Opts,
socket=Socket, transport=Transport,
- protocol=Protocol, protocol_state=ProtoState}, Reason) ->
+ protocol=Protocol, protocol_state=ProtoState,
+ event_handler=EventHandler, event_handler_state=EventHandlerState0}, Reason) ->
Protocol:close(Reason, ProtoState),
%% @todo Need a special state for orderly shutdown of a connection.
Transport:close(Socket),
@@ -1015,14 +1016,20 @@ disconnect(State=#state{owner=Owner, opts=Opts,
%% @todo Stop keepalive timeout, flush message.
{KilledStreams, UnprocessedStreams} = Protocol:down(ProtoState),
Owner ! {gun_down, self(), Protocol:name(), Reason, KilledStreams, UnprocessedStreams},
+ %% Trigger the disconnect event.
+ DisconnectEvent = #{
+ reason => Reason
+ },
+ EventHandlerState = EventHandler:disconnect(DisconnectEvent, EventHandlerState0),
Retry = maps:get(retry, Opts, 5),
case Retry of
0 ->
- {stop, {shutdown, Reason}};
+ {stop, {shutdown, Reason}, State#state{event_handler_state=EventHandlerState}};
_ ->
{next_state, not_connected,
keepalive_cancel(State#state{socket=undefined,
- protocol=undefined, protocol_state=undefined}),
+ protocol=undefined, protocol_state=undefined,
+ event_handler_state=EventHandlerState}),
{next_event, internal, {retries, Retry - 1}}}
end.
diff --git a/src/gun_default_event_h.erl b/src/gun_default_event_h.erl
index e242e84..f234dda 100644
--- a/src/gun_default_event_h.erl
+++ b/src/gun_default_event_h.erl
@@ -18,6 +18,7 @@
-export([init/2]).
-export([connect_start/2]).
-export([connect_end/2]).
+-export([disconnect/2]).
init(_EventData, State) ->
State.
@@ -27,3 +28,6 @@ connect_start(_EventData, State) ->
connect_end(_EventData, State) ->
State.
+
+disconnect(_EventData, State) ->
+ State.
diff --git a/src/gun_event.erl b/src/gun_event.erl
index fffcafe..bb541ed 100644
--- a/src/gun_event.erl
+++ b/src/gun_event.erl
@@ -43,6 +43,14 @@
-callback connect_start(connect_event(), State) -> State.
-callback connect_end(connect_event(), State) -> State.
+%% disconnect.
+
+-type disconnect_event() :: #{
+ reason := normal | closed | {error, any()}
+}.
+
+-callback disconnect(disconnect_event(), State) -> State.
+
%% @todo domain_lookup_start
%% @todo domain_lookup_end
%% @todo tls_handshake_start
@@ -50,7 +58,6 @@
%% @todo origin_changed
%% @todo transport_changed
%% @todo protocol_changed
-%% @todo disconnected
%% @todo terminate
%% @todo stream_start
%% @todo stream_end
diff --git a/test/event_SUITE.erl b/test/event_SUITE.erl
index 383ac46..50a1ce2 100644
--- a/test/event_SUITE.erl
+++ b/test/event_SUITE.erl
@@ -20,6 +20,7 @@
-import(ct_helper, [config/2]).
-import(ct_helper, [doc/1]).
+-import(gun_test, [init_origin/1]).
all() ->
ct_helper:all(?MODULE).
@@ -99,6 +100,21 @@ connect_end_ok(Config) ->
} = do_receive_event(connect_end),
gun:close(Pid).
+disconnect(_) ->
+ doc("Confirm that the disconnect event callback is called on disconnect."),
+ Self = self(),
+ Opts = #{event_handler => {?MODULE, Self}},
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
+ {ok, Pid} = gun:open("localhost", OriginPort, Opts),
+ {ok, http} = gun:await_up(Pid),
+ %% We make the origin exit to trigger a disconnect.
+ unlink(OriginPid),
+ exit(OriginPid, shutdown),
+ #{
+ reason := closed
+ } = do_receive_event(disconnect),
+ gun:close(Pid).
+
%% Internal.
do_receive_event(Event) ->
@@ -122,3 +138,7 @@ connect_start(EventData, Pid) ->
connect_end(EventData, Pid) ->
Pid ! {?FUNCTION_NAME, EventData},
Pid.
+
+disconnect(EventData, Pid) ->
+ Pid ! {?FUNCTION_NAME, EventData},
+ Pid.