Skip to content

Commit

Permalink
Merge pull request #9231 from IngelaAndin/ingela/ssl/use-which_child-…
Browse files Browse the repository at this point in the history
…to-improve-start-up/OTP-19406

ssl: Use supervisor:which_child/2 to improve start up
  • Loading branch information
IngelaAndin authored Jan 9, 2025
2 parents 1878f14 + 23f2d56 commit ab37756
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 126 deletions.
2 changes: 1 addition & 1 deletion lib/ssl/src/dtls_connection_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ init(_) ->
period => 3600
},
ChildSpecs = [#{id => undefined,
start => {ssl_gen_statem, start_link, []},
start => {ssl_gen_statem, dtls_start_link, []},
restart => temporary,
shutdown => 4000,
modules => [ssl_gen_statem, dtls_connection],
Expand Down
2 changes: 1 addition & 1 deletion lib/ssl/src/ssl.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@
{applications, [crypto, public_key, kernel, stdlib]},
{env, []},
{mod, {ssl_app, []}},
{runtime_dependencies, ["stdlib-6.0","public_key-1.16.4","kernel-9.0",
{runtime_dependencies, ["stdlib-@OTP-19345@","public_key-1.16.4","kernel-9.0",
"erts-15.0","crypto-5.0", "inets-5.10.7",
"runtime_tools-1.15.1"]}]}.
14 changes: 3 additions & 11 deletions lib/ssl/src/ssl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2174,7 +2174,7 @@ connect(TCPSocket, TLSOptions, Timeout)
try
tls_gen_connection = connection_cb(TLSOptions),
{ok, Config} = ssl_config:handle_options(TCPSocket, TLSOptions, client, undefined),
tls_socket:upgrade(TCPSocket, Config, Timeout)
tls_socket:upgrade(client, TCPSocket, Config, Timeout)
catch
error:{badmatch, _} ->
{error, {dtls_upgrade, notsup}};
Expand Down Expand Up @@ -2448,17 +2448,9 @@ handshake(Socket, SslOptions, Timeout)
when is_list(SslOptions), ?IS_TIMEOUT(Timeout) ->
try
tls_gen_connection = connection_cb(SslOptions),
{ok, #config{transport_info = CbInfo, ssl = SslOpts, emulated = EmOpts}} =
{ok, Config} =
ssl_config:handle_options(Socket, SslOptions, server, undefined),
Transport = element(1, CbInfo),
ok = tls_socket:setopts(Transport, Socket, tls_socket:internal_inet_values()),
{ok, Port} = tls_socket:port(Transport, Socket),
{ok, SessionIdHandle} = tls_socket:session_id_tracker(ssl_unknown_listener, SslOpts),
tls_gen_connection:start_fsm(server, "localhost", Port, Socket,
{SslOpts,
tls_socket:emulated_socket_options(EmOpts, #socket_options{}),
[{session_id_tracker, SessionIdHandle}]},
self(), CbInfo, Timeout)
tls_socket:upgrade(server, Socket, Config, Timeout)
catch
error:{badmatch, _} ->
{error, {dtls_upgrade, notsup}};
Expand Down
18 changes: 10 additions & 8 deletions lib/ssl/src/ssl_gen_statem.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
-include("tls_connection.hrl").

%% Initial Erlang process setup
-export([start_link/7,
start_link/8,
-export([tls_start_link/7,
dtls_start_link/7,
init/1]).

%% TLS connection setup
Expand Down Expand Up @@ -108,26 +108,26 @@
%%% Initial Erlang process setup
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
-spec start_link(client| server, pid(), ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
-spec tls_start_link(client | server, ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, ssl:reason()}.
%%
%% Description: Creates a process which calls Module:init/1 to
%% choose appropriat gen_statem and initialize.
%%--------------------------------------------------------------------
start_link(Role, Sender, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo) ->
tls_start_link(Role, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo) ->
ReceiverOpts = maps:get(receiver_spawn_opts, SslOpts, []),
Opts = [link | proplists:delete(link, ReceiverOpts)],
Pid = proc_lib:spawn_opt(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]], Opts),
Pid = proc_lib:spawn_opt(?MODULE, init, [[Role, self(), Host, Port, Socket, Options, User, CbInfo]], Opts),
{ok, Pid}.

%%--------------------------------------------------------------------
-spec start_link(atom(), ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
-spec dtls_start_link(client | server, ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, ssl:reason()}.
%%
%% Description: Creates a gen_statem process which calls Module:init/1 to
%% initialize.
%%--------------------------------------------------------------------
start_link(Role, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo) ->
dtls_start_link(Role, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo) ->
ReceiverOpts = maps:get(receiver_spawn_opts, SslOpts, []),
Opts = [link | proplists:delete(link, ReceiverOpts)],
Pid = proc_lib:spawn_opt(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]], Opts),
Expand All @@ -138,9 +138,11 @@ start_link(Role, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo) ->
-spec init(list()) -> no_return().
%% Description: Initialization
%%--------------------------------------------------------------------
init([Role, Sender |[Host, Port, _Socket, {TLSOpts, _, _}, _User, _CbInfo] = InitArgs]) ->
init([Role, Sup | [Host, Port, _Socket, {TLSOpts, _, _}, _User, _CbInfo] = InitArgs]) ->
process_flag(trap_exit, true),

{ok, {_, Sender,_,_}} = supervisor:which_child(Sup, sender),

case maps:get(erl_dist, TLSOpts, false) of
true ->
process_flag(priority, max);
Expand Down
2 changes: 1 addition & 1 deletion lib/ssl/src/ssl_trace.erl
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ trace_profiles() ->
{dtls_server_connection,
[{initial_hello, 3}]},
{tls_gen_connection,
[{start_connection_tree, 5}, {socket_control, 2}]}
[{start_connection_tree, 3}]}
]},
{csp, %% OCSP
fun(M, F, A) -> dbg:tpl(M, F, A, x) end,
Expand Down
18 changes: 6 additions & 12 deletions lib/ssl/src/tls_dyn_connection_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,27 @@
-behaviour(supervisor).

%% API
-export([start_link/0]).
-export([start_child/3]).
-export([start_link/2]).

%% Supervisor callback
-export([init/1]).

%%%=========================================================================
%%% API
%%%=========================================================================
start_link() ->
supervisor:start_link(?MODULE, []).
start_link(SenderArgs, ReciverArgs) ->
supervisor:start_link(?MODULE, [SenderArgs, ReciverArgs]).

start_child(Sup, sender, Args) ->
supervisor:start_child(Sup, sender(Args));
start_child(Sup, receiver, Args) ->
supervisor:start_child(Sup, receiver(Args)).

%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
init(_) ->
init([SenderArgs, ReciverArgs]) ->
SupFlags = #{strategy => one_for_all,
auto_shutdown => any_significant,
intensity => 0,
period => 3600
},
ChildSpecs = [],
ChildSpecs = [sender(SenderArgs), receiver(ReciverArgs)],
{ok, {SupFlags, ChildSpecs}}.

sender(Args) ->
Expand All @@ -74,7 +68,7 @@ receiver(Args) ->
restart => temporary,
type => worker,
significant => true,
start => {ssl_gen_statem, start_link, Args},
start => {ssl_gen_statem, tls_start_link, Args},
modules => [ssl_gen_statem,
tls_client_connection,
tls_server_connection,
Expand Down
85 changes: 32 additions & 53 deletions lib/ssl/src/tls_gen_connection.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
-include("tls_record_1_3.hrl").

%% Setup
-export([start_fsm/8,
-export([start_fsm/6,
start_fsm/7,
pids/1,
initialize_tls_sender/1]).

Expand Down Expand Up @@ -72,20 +73,33 @@
%%====================================================================
%% Setup
%%====================================================================
start_fsm(Role, Host, Port, Socket, {SSLOpts, _, _Trackers} = Opts,
start_fsm(Host, Port, Socket, {SSLOpts, _, _Trackers} = Opts,
User, CbInfo, Timeout) ->
ErlDist = maps:get(erl_dist, SSLOpts, false),
SenderSpawnOpts = maps:get(sender_spawn_opts, SSLOpts, []),
SenderOptions = handle_sender_options(ErlDist, SenderSpawnOpts),
Starter = start_connection_tree(User, ErlDist, SenderOptions,
Role, [Host, Port, Socket, Opts, User, CbInfo]),
receive
{Starter, {ok, SockReceiver}} ->
receive {SockReceiver, user_socket, UserSocket} ->
socket_control(UserSocket, Timeout)
end;
{Starter, Error} ->
Error
{ok, DynSup} = start_connection_tree(ErlDist, SenderOptions,
[client, Host, Port, Socket, Opts, User, CbInfo]),
{ok, {_, Receiver,_,_}} = supervisor:which_child(DynSup, receiver),
receive {Receiver, user_socket, UserSocket} ->
case ssl_gen_statem:socket_control(UserSocket) of
{ok, SslSocket} ->
ssl_gen_statem:handshake(SslSocket, Timeout);
Error ->
Error
end
end.

start_fsm(Port, Socket, {SSLOpts, _, _Trackers} = Opts,
User, CbInfo, _Timeout) ->
ErlDist = maps:get(erl_dist, SSLOpts, false),
SenderSpawnOpts = maps:get(sender_spawn_opts, SSLOpts, []),
SenderOptions = handle_sender_options(ErlDist, SenderSpawnOpts),
{ok, DynSup} = start_connection_tree(ErlDist, SenderOptions,
[server, "localhost", Port, Socket, Opts, User, CbInfo]),
{ok, {_, Receiver,_,_}} = supervisor:which_child(DynSup, receiver),
receive {Receiver, user_socket, UserSocket} ->
ssl_gen_statem:socket_control(UserSocket)
end.

handle_sender_options(ErlDist, SpawnOpts) ->
Expand All @@ -96,48 +110,13 @@ handle_sender_options(ErlDist, SpawnOpts) ->
[[{spawn_opt, SpawnOpts}]]
end.

start_connection_tree(User, IsErlDist, SenderOpts, Role, ReceiverOpts) ->
StartConnectionTree =
fun() ->
try start_dyn_connection_sup(IsErlDist) of
{ok, DynSup} ->
case tls_dyn_connection_sup:start_child(DynSup, sender, SenderOpts) of
{ok, Sender} ->
Args = [Role, Sender | ReceiverOpts],
case tls_dyn_connection_sup:start_child(DynSup, receiver, Args) of
{ok, Receiver} ->
User ! {self(), {ok, Receiver}};
{error, _} = Error ->
User ! {self(), Error},
exit(DynSup, shutdown)
end;
{error, _} = Error ->
User ! {self(), Error},
exit(DynSup, shutdown)
end;
{error, _Error} = Error ->
User ! {self(), Error}
catch exit:{noproc, _} ->
User ! {self(), {error, ssl_not_started}};
_:Reason:ST -> %% Don't hang signal internal error
?SSL_LOG(notice, internal_error, [{error, Reason}, {stacktrace, ST}]),
User ! {self(), {error, internal_error}}
end
end,
spawn(StartConnectionTree).

start_dyn_connection_sup(true) ->
tls_connection_sup:start_child_dist([]);
start_dyn_connection_sup(false) ->
tls_connection_sup:start_child([]).

socket_control(SslSocket, Timeout) ->
case ssl_gen_statem:socket_control(SslSocket) of
{ok, SslSocket} ->
ssl_gen_statem:handshake(SslSocket, Timeout);
Error ->
Error
end.
start_connection_tree(IsErlDist, SenderOpts, ReceiverOpts) ->
case IsErlDist of
false ->
tls_connection_sup:start_child([SenderOpts, ReceiverOpts]);
true ->
tls_connection_sup:start_child_dist([SenderOpts, ReceiverOpts])
end.

pids(#state{protocol_specific = #{sender := Sender}}) ->
[self(), Sender].
Expand Down
78 changes: 39 additions & 39 deletions lib/ssl/src/tls_socket.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
accept/3,
socket/6,
connect/4,
upgrade/3,
upgrade/4,
setopts/3,
getopts/3,
getstat/3,
Expand All @@ -51,7 +51,6 @@
start_link/3,
terminate/2,
inherit_tracker/3,
session_id_tracker/2,
emulated_socket_options/2,
get_emulated_opts/1,
set_emulated_opts/2,
Expand Down Expand Up @@ -112,25 +111,27 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_,_} = CbInfo,
{error, Reason}
end.

upgrade(Socket, #config{transport_info = {Transport,_,_,_,_}= CbInfo,
ssl = SslOptions,
emulated = EmOpts}, Timeout) ->
ok = setopts(Transport, Socket, tls_socket:internal_inet_values()),
upgrade(client, Socket, #config{transport_info = CbInfo,
ssl = SslOptions,
emulated = EmOpts}, Timeout) ->
Transport = element(1, CbInfo),
ok = setopts(Transport, Socket, internal_inet_values()),
case peername(Transport, Socket) of
{ok, {Host, Port}} ->
try tls_gen_connection:start_fsm(client, Host, Port, Socket,
{SslOptions,
emulated_socket_options(EmOpts, #socket_options{}), undefined},
self(), CbInfo, Timeout) of
Result ->
Result
catch
exit:{noproc, _} ->
{error, ssl_not_started}
end;
start_tls_client_connection(Host, Port, Socket, SslOptions, EmOpts, CbInfo, Timeout);
{error, Error} ->
{error, Error}
end.
end;
upgrade(server, Socket, #config{transport_info = CbInfo,
ssl = SslOpts,
emulated = EmOpts}, Timeout) ->
Transport = element(1, CbInfo),
ok = setopts(Transport, Socket, internal_inet_values()),
{ok, Port} = port(Transport, Socket),
{ok, SessionIdHandle} = session_id_tracker(ssl_unknown_listener, SslOpts),
Trackers = [{session_id_tracker, SessionIdHandle}],
{ok, SSocket} = start_tls_server_connection(SslOpts, Port, Socket, EmOpts, Trackers, CbInfo),
ssl_gen_statem:handshake(SSocket, Timeout).

connect(Host, Port,
#config{transport_info = CbInfo, inet_user = UserOpts, ssl = SslOpts,
Expand All @@ -139,16 +140,7 @@ connect(Host, Port,
{Transport, _, _, _, _} = CbInfo,
try Transport:connect(Host, Port, SocketOpts, Timeout) of
{ok, Socket} ->
try tls_gen_connection:start_fsm(client, Host, Port, Socket,
{SslOpts,
emulated_socket_options(EmOpts, #socket_options{}), undefined},
self(), CbInfo, Timeout) of
Result ->
Result
catch
exit:{noproc, _} ->
{error, ssl_not_started}
end;
start_tls_client_connection(Host, Port, Socket, SslOpts, EmOpts, CbInfo, Timeout);
{error, Reason} ->
{error, Reason}
catch
Expand Down Expand Up @@ -420,19 +412,27 @@ call(Pid, Msg) ->
gen_server:call(Pid, Msg, infinity).

start_tls_server_connection(SslOpts, Port, Socket, EmOpts, Trackers, CbInfo) ->
try
{ok, DynSup} = tls_connection_sup:start_child([]),
SenderOpts = maps:get(sender_spawn_opts, SslOpts, []),
{ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, [[{spawn_opt, SenderOpts}]]),
ConnArgs = [server, Sender, "localhost", Port, Socket,
{SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Trackers}, self(), CbInfo],
{ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, ConnArgs),
receive {Pid, user_socket, UserSocket} ->
ssl_gen_statem:socket_control(UserSocket)
end
try tls_gen_connection:start_fsm(Port, Socket,
{SslOpts,
emulated_socket_options(EmOpts, #socket_options{}), Trackers},
self(), CbInfo, infinity) of
Result ->
Result
catch
exit:{noproc, _} ->
{error, ssl_not_started}
end.

start_tls_client_connection(Host, Port, Socket, SslOpts, EmOpts, CbInfo, Timeout) ->
try tls_gen_connection:start_fsm(Host, Port, Socket,
{SslOpts,
emulated_socket_options(EmOpts, #socket_options{}), undefined},
self(), CbInfo, Timeout) of
Result ->
Result
catch
error:{badmatch, {error, _} = Error} ->
Error
exit:{noproc, _} ->
{error, ssl_not_started}
end.

split_options(Opts) ->
Expand Down

0 comments on commit ab37756

Please sign in to comment.