From d86d55c1f90b37d991e20ad0f1ac37b1e38b36e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Thu, 26 Sep 2019 10:43:12 +0200 Subject: Add a function to change the connection owner While at it the gun:info/1 function has been fixed to work even when we are in the not_connected state, and the owner is now also returned. --- src/gun.erl | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gun.erl b/src/gun.erl index 12f4319..3154b9b 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -23,6 +23,7 @@ -export([open/2]). -export([open/3]). -export([open_unix/2]). +-export([set_owner/2]). -export([info/1]). -export([close/1]). -export([shutdown/1]). @@ -396,9 +397,14 @@ consider_tracing(ServerPid, #{trace := true}) -> consider_tracing(_, _) -> ok. +-spec set_owner(pid(), pid()) -> ok. +set_owner(ServerPid, NewOwnerPid) -> + gen_statem:cast(ServerPid, {set_owner, self(), NewOwnerPid}). + -spec info(pid()) -> map(). info(ServerPid) -> {_, #state{ + owner=Owner, socket=Socket, transport=Transport, protocol=Protocol, @@ -407,22 +413,33 @@ info(ServerPid) -> origin_port=OriginPort, intermediaries=Intermediaries }} = sys:get_state(ServerPid), - {ok, {SockIP, SockPort}} = Transport:sockname(Socket), - #{ + Info0 = #{ + owner => Owner, socket => Socket, transport => case OriginScheme of <<"http">> -> tcp; <<"https">> -> tls end, - protocol => Protocol:name(), - sock_ip => SockIP, - sock_port => SockPort, origin_scheme => OriginScheme, origin_host => OriginHost, origin_port => OriginPort, %% Intermediaries are listed in the order data goes through them. intermediaries => lists:reverse(Intermediaries) - }. + }, + Info = case Socket of + undefined -> + Info0; + _ -> + {ok, {SockIP, SockPort}} = Transport:sockname(Socket), + Info0#{ + sock_ip => SockIP, + sock_port => SockPort + } + end, + case Protocol of + undefined -> Info; + _ -> Info#{protocol => Protocol:name()} + end. -spec close(pid()) -> ok. close(ServerPid) -> @@ -1253,6 +1270,16 @@ handle_common_connected_no_input(Type, Event, StateName, State) -> handle_common(Type, Event, StateName, State). %% Common events. +handle_common(cast, {set_owner, CurrentOwner, NewOwner}, _, + State=#state{owner=CurrentOwner, status={up, CurrentOwnerRef}}) -> + demonitor(CurrentOwnerRef, [flush]), + NewOwnerRef = monitor(process, NewOwner), + {keep_state, State#state{owner=NewOwner, status={up, NewOwnerRef}}}; +%% We cannot change the owner when we are shutting down. +handle_common(cast, {set_owner, CurrentOwner, _}, _, #state{owner=CurrentOwner}) -> + CurrentOwner ! {gun_error, self(), {badstate, + "The owner of the connection cannot be changed when the connection is shutting down."}}, + keep_state_and_state; handle_common(cast, {shutdown, Owner}, StateName, State=#state{ owner=Owner, status=Status, socket=Socket, transport=Transport, protocol=Protocol}) -> case {Socket, Protocol} of -- cgit v1.2.3