Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3821-ssh-New-connection-start-procedure.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3821-ssh-New-connection-start-procedure.patch of Package erlang
From f32fc320cbffa31554b5468d7b491e63bfc05d68 Mon Sep 17 00:00:00 2001 From: Hans Nilsson <hans@erlang.org> Date: Thu, 3 Dec 2020 09:55:53 +0100 Subject: [PATCH 1/2] ssh: New connection start procedure --- lib/ssh/src/ssh.erl | 72 ++---- lib/ssh/src/ssh_acceptor.erl | 62 ++--- lib/ssh/src/ssh_connection_handler.erl | 330 +++++++++++-------------- lib/ssh/src/sshc_sup.erl | 9 +- lib/ssh/src/sshd_sup.erl | 22 +- lib/ssh/test/ssh_sup_SUITE.erl | 13 +- 6 files changed, 222 insertions(+), 286 deletions(-) diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 023f6d884d..9abb0fdebb 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -140,16 +140,15 @@ connect(Socket, UserOptions, NegotiationTimeout) when is_list(UserOptions) -> case ssh_options:handle_options(client, UserOptions) of {error, Error} -> {error, Error}; - Options -> - case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of - ok -> - connect_socket(Socket, - ?PUT_INTERNAL_OPT({connected_socket,Socket}, Options), - NegotiationTimeout); - {error,SockError} -> - {error,SockError} - end - end. + + Options = #{} -> + case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of + ok -> + ssh_connection_handler:start_connection(client, Socket, Options, NegotiationTimeout); + {error,SockError} -> + {error,SockError} + end + end. -spec connect(Host, Port, Options, NegotiationTimeout) -> {ok,connection_ref()} | {error,term()} when @@ -162,44 +161,25 @@ connect(Host0, Port, UserOptions, NegotiationTimeout) when is_integer(Port), Port>0, is_list(UserOptions) -> case ssh_options:handle_options(client, UserOptions) of - {error, _Reason} = Error -> - Error; + {error, Reason} -> + {error, Reason}; + Options -> - {_, Transport, _} = TransportOpts = ?GET_OPT(transport, Options), - ConnectionTimeout = ?GET_OPT(connect_timeout, Options), - SocketOpts = [{active,false} | ?GET_OPT(socket_options,Options)], - Host = mangle_connect_address(Host0, SocketOpts), - try Transport:connect(Host, Port, SocketOpts, ConnectionTimeout) of - {ok, Socket} -> - connect_socket(Socket, - ?PUT_INTERNAL_OPT({host,Host}, Options), - NegotiationTimeout); - {error, Reason} -> - {error, Reason} - catch - exit:{function_clause, _F} -> - {error, {options, {transport, TransportOpts}}}; - exit:badarg -> - {error, {options, {socket_options, SocketOpts}}} - end + SockOpts = ?GET_OPT(socket_options, Options), + Host = mangle_connect_address(Host0, SockOpts), + {_, Callback, _} = ?GET_OPT(transport, Options), + SocketOpts = [{active,false} | SockOpts], + ConnectionTimeout = ?GET_OPT(connect_timeout, Options), + try Callback:connect(Host, Port, SocketOpts, ConnectionTimeout) of + {ok, Socket} -> + ssh_connection_handler:start_connection(client, Socket, Options, NegotiationTimeout); + {error, Reason} -> + {error, Reason} + catch + _:Error -> {error, Error} + end end. - -connect_socket(Socket, Options0, NegotiationTimeout) -> - {ok, {Host,Port}} = inet:sockname(Socket), - Profile = ?GET_OPT(profile, Options0), - - {ok, {SystemSup, SubSysSup}} = sshc_sup:start_system_subsystem(Host, Port, Profile, Options0), - - ConnectionSup = ssh_system_sup:connection_supervisor(SystemSup), - Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, - {supervisors, [{system_sup, SystemSup}, - {subsystem_sup, SubSysSup}, - {connection_sup, ConnectionSup}]} - ], Options0), - ssh_connection_handler:start_connection(client, Socket, Opts, NegotiationTimeout). - - %%-------------------------------------------------------------------- -spec close(ConnectionRef) -> ok | {error,term()} when ConnectionRef :: connection_ref() . @@ -841,6 +821,8 @@ is_host1(T) when is_tuple(T), size(T)==16 -> lists:all(fun(I) -> 0=<I andalso I= is_host1(loopback) -> true. %%%---------------------------------------------------------------- +mangle_connect_address(A, #{socket_options := SockOpts}) -> + mangle_connect_address(A, SockOpts); mangle_connect_address(A, SockOpts) -> mangle_connect_address1(A, proplists:get_value(inet6,SockOpts,false)). diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl index 7874f93fa2..773d8025cb 100644 --- a/lib/ssh/src/ssh_acceptor.erl +++ b/lib/ssh/src/ssh_acceptor.erl @@ -167,20 +167,20 @@ request_ownership(LSock, SockOwner) -> %%%---------------------------------------------------------------- acceptor_loop(Callback, Port, Address, Opts, ListenSocket, AcceptTimeout) -> - case (catch Callback:accept(ListenSocket, AcceptTimeout)) of - {ok, Socket} -> - handle_connection(Callback, Address, Port, Opts, Socket), - ?MODULE:acceptor_loop(Callback, Port, Address, Opts, - ListenSocket, AcceptTimeout); - {error, Reason} -> - handle_error(Reason), - ?MODULE:acceptor_loop(Callback, Port, Address, Opts, - ListenSocket, AcceptTimeout); - {'EXIT', Reason} -> - handle_error(Reason), - ?MODULE:acceptor_loop(Callback, Port, Address, Opts, - ListenSocket, AcceptTimeout) - end. + case Callback:accept(ListenSocket, AcceptTimeout) of + {ok,Socket} -> + case handle_connection(Callback, Address, Port, Opts, Socket) of + {error,Error} -> + catch Callback:close(Socket), + handle_error(Error); + _ -> + ok + end; + {error,Error} -> + handle_error(Error) + end, + ?MODULE:acceptor_loop(Callback, Port, Address, Opts, + ListenSocket, AcceptTimeout). %%%---------------------------------------------------------------- handle_connection(Callback, Address, Port, Options, Socket) -> @@ -190,16 +190,8 @@ handle_connection(Callback, Address, Port, Options, Socket) -> MaxSessions = ?GET_OPT(max_sessions, Options), case number_of_connections(SystemSup) < MaxSessions of true -> - {ok, SubSysSup} = - ssh_system_sup:start_subsystem(SystemSup, server, Address, Port, Profile, Options), - ConnectionSup = ssh_subsystem_sup:connection_supervisor(SubSysSup), NegTimeout = ?GET_OPT(negotiation_timeout, Options), - ssh_connection_handler:start_connection(server, Socket, - ?PUT_INTERNAL_OPT( - {supervisors, [{system_sup, SystemSup}, - {subsystem_sup, SubSysSup}, - {connection_sup, ConnectionSup}]}, - Options), NegTimeout); + ssh_connection_handler:start_connection(server, {Address,Port}, Socket, Options, NegTimeout); false -> Callback:close(Socket), IPstr = if is_tuple(Address) -> inet:ntoa(Address); @@ -218,29 +210,23 @@ handle_connection(Callback, Address, Port, Options, Socket) -> %%%---------------------------------------------------------------- handle_error(timeout) -> ok; - handle_error(enfile) -> %% Out of sockets... timer:sleep(?SLEEP_TIME); - handle_error(emfile) -> %% Too many open files -> Out of sockets... timer:sleep(?SLEEP_TIME); - handle_error(closed) -> error_logger:info_report("The ssh accept socket was closed by " - "a third party. " - "This will not have an impact on ssh " - "that will open a new accept socket and " - "go on as nothing happened. It does however " - "indicate that some other software is behaving " - "badly."), - exit(normal); - -handle_error(Reason) -> - String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])), - error_logger:error_report(String), - exit({accept_failed, String}). + "a third party. " + "This will not have an impact on ssh " + "that will open a new accept socket and " + "go on as nothing happened. It does however " + "indicate that some other software is behaving " + "badly."); +handle_error(Error) -> + String = lists:flatten(io_lib:format("Accept error: ~p", [Error])), + error_logger:error_report(String). %%%################################################################ %%%# diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index a198a95937..070039b309 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -41,12 +41,13 @@ %%% Start and stop -export([start_link/3, + start_connection/4, start_connection/5, + socket_control/3, stop/1 ]). %%% Internal application API --export([start_connection/4, - available_hkey_algorithms/2, +-export([available_hkey_algorithms/2, open_channel/6, start_channel/5, handle_direct_tcpip/6, @@ -75,8 +76,7 @@ format_status/2, code_change/4]). %%% Exports not intended to be used :). They are used for spawning and tests --export([init_connection_handler/3, % proc_lib:spawn needs this - init_ssh_record/3, % Export of this internal function +-export([init_ssh_record/3, % Export of this internal function % intended for low-level protocol test suites renegotiate/1, alg/1 % Export intended for test cases ]). @@ -97,18 +97,54 @@ %%==================================================================== %% Start / stop %%==================================================================== + +%%-------------------------------------------------------------------- +start_connection(Role, Socket, Options, NegotiationTimeout) -> + {ok, {Host,Port}} = inet:sockname(Socket), + start_connection(Role, {Host,Port}, Socket, Options, NegotiationTimeout). + +start_connection(Role, {Host,Port}, Socket, Options0, NegotiationTimeout) -> + try + Options1 = ?PUT_INTERNAL_OPT([{user_pid, self()} + ], Options0), + Profile = ?GET_OPT(profile, Options1), + {ok, {SystemSup, SubSysSup}} = + case Role of + client -> sshc_sup:start_system_subsystem(Host, Port, Profile, Options1); + server -> sshd_sup:start_system_subsystem(Host, Port, Profile, Options1) + end, + ConnectionSup = ssh_system_sup:connection_supervisor(SystemSup), + Options = ?PUT_INTERNAL_OPT([{supervisors, [{system_sup, SystemSup}, + {subsystem_sup, SubSysSup}, + {connection_sup, ConnectionSup}]} + ], Options1), + case ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Options]) of + {ok, Pid} -> + case socket_control(Socket, Pid, Options) of + ok -> + handshake(Pid, erlang:monitor(process,Pid), NegotiationTimeout); + {error, Reason} -> + {error, Reason} + end; + {error, Reason} -> + {error, Reason} + end + catch + exit:{noproc,{gen_server,call,_}} -> {error, ssh_not_started}; + error:Error -> {error, Error}; + Class:Error -> {error, {Class,Error}} + end. + %%-------------------------------------------------------------------- -spec start_link(role(), gen_tcp:socket(), internal_options() - ) -> {ok, pid()}. -%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -start_link(Role, Socket, Options) -> - {ok, proc_lib:spawn_opt(?MODULE, - init_connection_handler, - [Role, Socket, Options], - [link, {message_queue_data,off_heap}] - )}. + ) -> {ok, pid()} | ignore | {error, term()} . + +start_link(Role, Socket, Options) when Role==client ; Role==server -> + gen_statem:start_link(?MODULE, [Role, Socket, Options], + [{spawn_opt, [{message_queue_data,off_heap}]} + ]). %%-------------------------------------------------------------------- @@ -127,46 +163,6 @@ stop(ConnectionHandler)-> %% Internal application API %%==================================================================== -%%-------------------------------------------------------------------- --spec start_connection(role(), - gen_tcp:socket(), - internal_options(), - timeout() - ) -> {ok, connection_ref()} | {error, term()}. -%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -start_connection(Role, Socket, Options, Timeout) -> - try - case Role of - client -> - ChildPid = start_the_connection_child(self(), Role, Socket, Options), - handshake(ChildPid, erlang:monitor(process,ChildPid), Timeout); - server -> - case ?GET_OPT(parallel_login, Options) of - true -> - HandshakerPid = - spawn_link(fun() -> - process_flag(trap_exit, true), - receive - {do_handshake, Pid} -> - handshake(Pid, erlang:monitor(process,Pid), Timeout) - after Timeout -> - {error, timeout2} - end - end), - ChildPid = start_the_connection_child(HandshakerPid, Role, Socket, Options), - HandshakerPid ! {do_handshake, ChildPid}; - false -> - ChildPid = start_the_connection_child(self(), Role, Socket, Options), - handshake(ChildPid, erlang:monitor(process,ChildPid), Timeout) - end - end - catch - exit:{noproc, _} -> - {error, ssh_not_started}; - _:Error -> - {error, Error} - end. - %%-------------------------------------------------------------------- %%% Some other module has decided to disconnect. @@ -446,92 +445,54 @@ alg(ConnectionHandler) -> %%==================================================================== %% Intitialisation %%==================================================================== -%%-------------------------------------------------------------------- --spec init_connection_handler(role(), - gen_tcp:socket(), - internal_options() - ) -> no_return(). -%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -init_connection_handler(Role, Socket, Opts) -> - case init([Role, Socket, Opts]) of - {ok, StartState, D} when Role == server -> - process_flag(trap_exit, true), - gen_statem:enter_loop(?MODULE, - [], %%[{debug,[trace,log,statistics,debug]} ], %% [] - StartState, - D); - - {ok, StartState, D0=#data{connection_state=C}} when Role == client -> - process_flag(trap_exit, true), - Sups = ?GET_INTERNAL_OPT(supervisors, Opts), - D = D0#data{connection_state = - C#connection{system_supervisor = proplists:get_value(system_sup, Sups), - sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), - connection_supervisor = proplists:get_value(connection_sup, Sups) - }}, - gen_statem:enter_loop(?MODULE, - [], %%[{debug,[trace,log,statistics,debug]} ], %% [] - StartState, - D); - - {stop, Error} -> - D = try - %% Only servers have supervisorts defined in Opts - Sups = ?GET_INTERNAL_OPT(supervisors, Opts), - #connection{system_supervisor = proplists:get_value(system_sup, Sups), - sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), - connection_supervisor = proplists:get_value(connection_sup, Sups) - } - of - C -> - #data{connection_state=C} - catch - _:_ -> - #data{connection_state=#connection{}} - end, - gen_statem:enter_loop(?MODULE, - [], - {init_error,Error}, - D#data{socket=Socket}) - end. - - -init([Role,Socket,Opts]) -> +init([Role, Socket, Opts]) when Role==client ; Role==server -> case inet:peername(Socket) of {ok, PeerAddr} -> - {Protocol, Callback, CloseTag} = ?GET_OPT(transport, Opts), - C = #connection{channel_cache = ssh_client_channel:cache_create(), - channel_id_seed = 0, - requests = [], - options = Opts}, - D0 = #data{starter = ?GET_INTERNAL_OPT(user_pid, Opts), - connection_state = C, - socket = Socket, - transport_protocol = Protocol, - transport_cb = Callback, - transport_close_tag = CloseTag, - ssh_params = init_ssh_record(Role, Socket, PeerAddr, Opts) - }, - D = case Role of - client -> - D0; - server -> - Sups = ?GET_INTERNAL_OPT(supervisors, Opts), - D0#data{connection_state = - C#connection{cli_spec = ?GET_OPT(ssh_cli, Opts, {ssh_cli,[?GET_OPT(shell, Opts)]}), - exec = ?GET_OPT(exec, Opts), - system_supervisor = proplists:get_value(system_sup, Sups), - sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), - connection_supervisor = proplists:get_value(connection_sup, Sups) - }} - end, - {ok, {hello,Role}, D}; - + try + {Protocol, Callback, CloseTag} = ?GET_OPT(transport, Opts), + D = #data{starter = ?GET_INTERNAL_OPT(user_pid, Opts), + socket = Socket, + transport_protocol = Protocol, + transport_cb = Callback, + transport_close_tag = CloseTag, + ssh_params = init_ssh_record(Role, Socket, PeerAddr, Opts), + connection_state = init_connection_record(Role, Opts) + }, + process_flag(trap_exit, true), + {ok, {hello,Role}, D} + catch + _:Error -> + {stop, Error} + end; + {error,Error} -> {stop, Error} end. +%%%---------------------------------------------------------------- +%%% Connection start and initalization helpers + +init_connection_record(Role, Opts) -> + Sups = ?GET_INTERNAL_OPT(supervisors, Opts), + C = #connection{channel_cache = ssh_client_channel:cache_create(), + channel_id_seed = 0, + requests = [], + options = Opts, + system_supervisor = proplists:get_value(system_sup, Sups), + sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), + connection_supervisor = proplists:get_value(connection_sup, Sups) + }, + case Role of + server -> + C#connection{cli_spec = + ?GET_OPT(ssh_cli, Opts, {ssh_cli,[?GET_OPT(shell, Opts)]}), + exec = + ?GET_OPT(exec, Opts)}; + client -> + C + end. + init_ssh_record(Role, Socket, Opts) -> @@ -592,6 +553,42 @@ init_ssh_record(Role, Socket, PeerAddr, Opts) -> end. +socket_control(Socket, Pid, Options) -> + {_, Callback, _} = ?GET_OPT(transport, Options), + case Callback:controlling_process(Socket, Pid) of + ok -> + gen_statem:cast(Pid, socket_control); + {error, Reason} -> + {error, Reason} + end. + + +handshake(Pid, Ref, Timeout) -> + receive + ssh_connected -> + erlang:demonitor(Ref), + {ok, Pid}; + {Pid, not_connected, Reason} -> + {error, Reason}; + {Pid, user_password} -> + Pass = io:get_password(), + Pid ! Pass, + handshake(Pid, Ref, Timeout); + {Pid, question} -> + Answer = io:get_line(""), + Pid ! Answer, + handshake(Pid, Ref, Timeout); + {'DOWN', _, process, Pid, {shutdown, Reason}} -> + {error, Reason}; + {'DOWN', _, process, Pid, Reason} -> + {error, Reason}; + {'EXIT',_,Reason} -> + stop(Pid), + {error, {exit,Reason}} + after Timeout -> + ssh_connection_handler:stop(Pid), + {error, timeout} + end. %%==================================================================== %% gen_statem callbacks @@ -1805,9 +1799,15 @@ terminate(Reason, StateName, D0) -> %% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -format_status(normal, [_, _StateName, D]) -> +format_status(A, B) -> + try format_status0(A, B) + catch + _:_ -> "????" + end. + +format_status0(normal, [_PDict, _StateName, D]) -> [{data, [{"State", D}]}]; -format_status(terminate, [_, _StateName, D]) -> +format_status0(terminate, [_, _StateName, D]) -> [{data, [{"State", clean(D)}]}]. @@ -1882,15 +1882,6 @@ code_change(_OldVsn, StateName, State, _Extra) -> %%-------------------------------------------------------------------- %% Starting -start_the_connection_child(UserPid, Role, Socket, Options0) -> - Sups = ?GET_INTERNAL_OPT(supervisors, Options0), - ConnectionSup = proplists:get_value(connection_sup, Sups), - Options = ?PUT_INTERNAL_OPT({user_pid,UserPid}, Options0), - InitArgs = [Role, Socket, Options], - {ok, Pid} = ssh_connection_sup:start_child(ConnectionSup, InitArgs), - ok = socket_control(Socket, Pid, Options), % transfer the Socket ownership in a controlled way. - Pid. - %%-------------------------------------------------------------------- %% Stopping @@ -1898,20 +1889,15 @@ stop_subsystem(#data{ssh_params = #ssh{role = Role}, connection_state = #connection{system_supervisor = SysSup, - sub_system_supervisor = SubSysSup, - options = Opts} + sub_system_supervisor = SubSysSup} }) when is_pid(SysSup) andalso is_pid(SubSysSup) -> C = self(), spawn(fun() -> wait_until_dead(C, 10000), - case {Role, ?GET_INTERNAL_OPT(connected_socket,Opts,non_socket_started)} of - {server, non_socket_started} -> + case Role of + server -> ssh_system_sup:stop_subsystem(SysSup, SubSysSup); - {client, non_socket_started} -> - ssh_system_sup:stop_system(Role, SysSup); - {server, _Socket} -> - ssh_system_sup:stop_system(Role, SysSup); - {client, _Socket} -> + client -> ssh_system_sup:stop_subsystem(SysSup, SubSysSup), wait_until_dead(SubSysSup, 1000), sshc_sup:stop_system(SysSup) @@ -2496,44 +2482,6 @@ start_channel_request_timer(Channel, From, Time) -> erlang:send_after(Time, self(), {timeout, {Channel, From}}). %%%---------------------------------------------------------------- -%%% Connection start and initialization helpers - -socket_control(Socket, Pid, Options) -> - {_, Callback, _} = ?GET_OPT(transport, Options), - case Callback:controlling_process(Socket, Pid) of - ok -> - gen_statem:cast(Pid, socket_control); - {error, Reason} -> - {error, Reason} - end. - -handshake(Pid, Ref, Timeout) -> - receive - ssh_connected -> - erlang:demonitor(Ref), - {ok, Pid}; - {Pid, not_connected, Reason} -> - {error, Reason}; - {Pid, user_password} -> - Pass = io:get_password(), - Pid ! Pass, - handshake(Pid, Ref, Timeout); - {Pid, question} -> - Answer = io:get_line(""), - Pid ! Answer, - handshake(Pid, Ref, Timeout); - {'DOWN', _, process, Pid, {shutdown, Reason}} -> - {error, Reason}; - {'DOWN', _, process, Pid, Reason} -> - {error, Reason}; - {'EXIT',_,Reason} -> - stop(Pid), - {error, {exit,Reason}} - after Timeout -> - stop(Pid), - {error, timeout} - end. - update_inet_buffers(Socket) -> try {ok, BufSzs0} = inet:getopts(Socket, [sndbuf,recbuf]), @@ -2557,7 +2508,7 @@ ssh_dbg_flags(connection_events) -> [c]; ssh_dbg_flags(terminate) -> [c]; ssh_dbg_flags(disconnect) -> [c]. -ssh_dbg_on(connections) -> dbg:tp(?MODULE, init_connection_handler, 3, x), +ssh_dbg_on(connections) -> dbg:tp(?MODULE, init, 1, x), ssh_dbg_on(terminate); ssh_dbg_on(connection_events) -> dbg:tp(?MODULE, handle_event, 4, x); ssh_dbg_on(connection_handshake) -> dbg:tpl(?MODULE, handshake, 3, x); @@ -2577,11 +2528,11 @@ ssh_dbg_off(renegotiation) -> dbg:ctpl(?MODULE, init_renegotiate_timers, 3), dbg:ctpg(?MODULE, renegotiate, 1); ssh_dbg_off(connection_events) -> dbg:ctpg(?MODULE, handle_event, 4); ssh_dbg_off(connection_handshake) -> dbg:ctpl(?MODULE, handshake, 3); -ssh_dbg_off(connections) -> dbg:ctpg(?MODULE, init_connection_handler, 3), +ssh_dbg_off(connections) -> dbg:ctpg(?MODULE, init, 1), ssh_dbg_off(terminate). -ssh_dbg_format(connections, {call, {?MODULE,init_connection_handler, [Role, Sock, Opts]}}) -> +ssh_dbg_format(connections, {call, {?MODULE,init, [[Role, Sock, Opts]]}}) -> DefaultOpts = ssh_options:handle_options(Role,[]), ExcludedKeys = [internal_options, user_options], NonDefaultOpts = diff --git a/lib/ssh/src/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl index e582733de8..bbf3d16440 100644 --- a/lib/ssh/src/sshc_sup.erl +++ b/lib/ssh/src/sshc_sup.erl @@ -20,13 +20,15 @@ %% %%---------------------------------------------------------------------- -%% Purpose: The ssh client subsystem supervisor +%% Purpose: The ssh client top supervisor %%---------------------------------------------------------------------- -module(sshc_sup). -behaviour(supervisor). +-include("ssh.hrl"). + -export([start_link/0, start_child/4, start_system_subsystem/4, @@ -43,7 +45,7 @@ %%% API %%%========================================================================= start_link() -> - supervisor:start_link({local,?MODULE}, ?MODULE, []). + supervisor:start_link({local,?SSHC_SUP}, ?MODULE, []). start_child(Address, Port, Profile, Options) -> case ssh_system_sup:system_supervisor(Address, Port, Profile) of @@ -82,7 +84,8 @@ init(_) -> start => {ssh_controller, start_link, [client, client_controller]}, restart => permanent, type => worker - }], + } + ], {ok, {SupFlags,ChildSpecs}}. %%%========================================================================= diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl index b716b66ec7..bda156223e 100644 --- a/lib/ssh/src/sshd_sup.erl +++ b/lib/ssh/src/sshd_sup.erl @@ -17,10 +17,10 @@ %% %% %CopyrightEnd% %% + %% %%---------------------------------------------------------------------- -%% Purpose: The top supervisor for ssh servers hangs under -%% ssh_sup. +%% Purpose: The ssh daemon top supervisor %%---------------------------------------------------------------------- -module(sshd_sup). @@ -30,10 +30,11 @@ -include("ssh.hrl"). -export([start_link/0, - start_child/4, + start_child/4, + start_system_subsystem/4, stop_child/1, stop_child/3 -]). + ]). %% Supervisor callback -export([init/1]). @@ -44,8 +45,6 @@ %%% API %%%========================================================================= start_link() -> - %% No children are start now. We wait until the user calls ssh:daemon - %% and uses start_child/4 to create the children supervisor:start_link({local,?SSHD_SUP}, ?MODULE, []). start_child(Address, Port, Profile, Options) -> @@ -62,6 +61,11 @@ start_child(Address, Port, Profile, Options) -> {ok,Pid} end. +start_system_subsystem(Host, Port, Profile, Options) -> + ssh_controller:start_system_subsystem(daemon_controller, ?MODULE, Host, Port, Profile, Options, + child_spec(Host, Port, Profile, Options) + ). + stop_child(ChildId) when is_tuple(ChildId) -> supervisor:terminate_child(?SSHD_SUP, ChildId); stop_child(ChildPid) when is_pid(ChildPid)-> @@ -80,7 +84,11 @@ init(_) -> intensity => 10, period => 3600 }, - ChildSpecs = [ + ChildSpecs = [#{id => daemon_controller, + start => {ssh_controller, start_link, [server, daemon_controller]}, + restart => permanent, + type => worker + } ], {ok, {SupFlags,ChildSpecs}}. diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index 8ad405b1d7..fa9dbe1c7d 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -115,7 +115,7 @@ default_tree(Config) when is_list(Config) -> {value, {sshd_sup, _,supervisor,[sshd_sup]}} = lists:keysearch(sshd_sup, 1, TopSupChildren), ?wait_match([{client_controller,_,worker,_}], supervisor:which_children(sshc_sup)), - ?wait_match([], supervisor:which_children(sshd_sup)). + ?wait_match([{daemon_controller,_,worker,_}], supervisor:which_children(sshd_sup)). %%------------------------------------------------------------------------- sshc_subtree(Config) when is_list(Config) -> @@ -164,14 +164,16 @@ sshd_subtree(Config) when is_list(Config) -> ct:log("Expect HostIP=~p, Port=~p, Daemon=~p",[HostIP,Port,Daemon]), ?wait_match([{{server,ssh_system_sup, ListenIP, Port, ?DEFAULT_PROFILE}, Daemon, supervisor, - [ssh_system_sup]}], + [ssh_system_sup]}, + {daemon_controller,_,worker,_} + ], supervisor:which_children(sshd_sup), [ListenIP,Daemon]), true = ssh_test_lib:match_ip(HostIP, ListenIP), check_sshd_system_tree(Daemon, HostIP, Port, Config), ssh:stop_daemon(HostIP, Port), ct:sleep(?WAIT_FOR_SHUTDOWN), - ?wait_match([], supervisor:which_children(sshd_sup)). + ?wait_match([{daemon_controller,_,worker,_}], supervisor:which_children(sshd_sup)). %%------------------------------------------------------------------------- sshd_subtree_profile(Config) when is_list(Config) -> @@ -186,14 +188,15 @@ sshd_subtree_profile(Config) when is_list(Config) -> ct:log("Expect HostIP=~p, Port=~p, Profile=~p, Daemon=~p",[HostIP,Port,Profile,Daemon]), ?wait_match([{{server,ssh_system_sup, ListenIP,Port,Profile}, Daemon, supervisor, - [ssh_system_sup]}], + [ssh_system_sup]}, + {daemon_controller,_,worker,_}], supervisor:which_children(sshd_sup), [ListenIP,Daemon]), true = ssh_test_lib:match_ip(HostIP, ListenIP), check_sshd_system_tree(Daemon, HostIP, Port, Config), ssh:stop_daemon(HostIP, Port, Profile), ct:sleep(?WAIT_FOR_SHUTDOWN), - ?wait_match([], supervisor:which_children(sshd_sup)). + ?wait_match([{daemon_controller,_,worker,_}], supervisor:which_children(sshd_sup)). %%------------------------------------------------------------------------- killed_acceptor_restarts(Config) -> -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor