From 6158cb432092c47e178b4dc1177b46cb8c310ab4 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 21 Mar 2017 19:50:49 +0100 Subject: ssh: Fix supervisors, start daemon and connect code Remove many internal options and made them as explicit arguments. --- lib/ssh/src/ssh.erl | 240 +++++++++++++++++++++------------ lib/ssh/src/ssh_acceptor.erl | 3 +- lib/ssh/src/ssh_acceptor_sup.erl | 22 ++- lib/ssh/src/ssh_connection_handler.erl | 7 +- lib/ssh/src/ssh_file.erl | 2 + lib/ssh/src/ssh_subsystem_sup.erl | 34 ++--- lib/ssh/src/ssh_sup.erl | 53 +------- lib/ssh/src/ssh_system_sup.erl | 43 +++--- lib/ssh/src/sshc_sup.erl | 14 +- lib/ssh/src/sshd_sup.erl | 55 +++----- 10 files changed, 237 insertions(+), 236 deletions(-) (limited to 'lib') diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 9047b7e0f0..680047dffd 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -108,7 +108,7 @@ connect(Socket, UserOptions, Timeout) when is_port(Socket), case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of ok -> {ok, {Host,_Port}} = inet:sockname(Socket), - Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,fmt_host(Host)}], Options), + Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,Host}], Options), ssh_connection_handler:start_connection(client, Socket, Opts, Timeout); {error,SockError} -> {error,SockError} @@ -132,7 +132,7 @@ connect(Host, Port, UserOptions, Timeout) when is_integer(Port), SocketOpts = [{active,false} | ?GET_OPT(socket_options,Options)], try Transport:connect(Host, Port, SocketOpts, ConnectionTimeout) of {ok, Socket} -> - Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,fmt_host(Host)}], Options), + Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,Host}], Options), ssh_connection_handler:start_connection(client, Socket, Opts, Timeout); {error, Reason} -> {error, Reason} @@ -188,14 +188,11 @@ daemon(Socket, UserOptions) when is_port(Socket) -> case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of ok -> {ok, {IP,Port}} = inet:sockname(Socket), - finalize_start(fmt_host(IP), Port, ?GET_OPT(profile, Options), + finalize_start(IP, Port, ?GET_OPT(profile, Options), ?PUT_INTERNAL_OPT({connected_socket, Socket}, Options), fun(Opts, DefaultResult) -> try ssh_acceptor:handle_established_connection( - ?GET_INTERNAL_OPT(address, Opts), - ?GET_INTERNAL_OPT(port, Opts), - Opts, - Socket) + IP, Port, Opts, Socket) of {error,Error} -> {error,Error}; @@ -238,7 +235,7 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535 -> %% and ListenSocket is for listening on connections. But it is still owned %% by self()... - finalize_start(fmt_host(Host), Port, ?GET_OPT(profile, Options0), + finalize_start(Host, Port, ?GET_OPT(profile, Options0), ?PUT_INTERNAL_OPT({lsocket,{ListenSocket,self()}}, Options0), fun(Opts, Result) -> {_, Callback, _} = ?GET_OPT(transport, Opts), @@ -269,17 +266,27 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535 -> daemon_info(Pid) -> case catch ssh_system_sup:acceptor_supervisor(Pid) of AsupPid when is_pid(AsupPid) -> - [{ListenAddr,Port,Profile}] = - [{LA,Prt,Prf} || {{ssh_acceptor_sup,LA,Prt,Prf}, - _WorkerPid,worker,[ssh_acceptor]} <- supervisor:which_children(AsupPid)], + [{Name,Port,Profile}] = + [{Nam,Prt,Prf} + || {{ssh_acceptor_sup,Hst,Prt,Prf},_Pid,worker,[ssh_acceptor]} + <- supervisor:which_children(AsupPid), + Nam <- [case inet:parse_strict_address(Hst) of + {ok,IP} -> IP; + _ when Hst=="any" -> any; + _ when Hst=="loopback" -> loopback; + _ -> Hst + end] + ], {ok, [{port,Port}, - {listen_address,ListenAddr}, + {name,Name}, {profile,Profile} ]}; _ -> {error,bad_daemon_ref} end. + + %%-------------------------------------------------------------------- -spec stop_listener(daemon_ref()) -> ok. -spec stop_listener(inet:ip_address(), inet:port_number()) -> ok. @@ -361,49 +368,128 @@ default_algorithms() -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -handle_daemon_args(HostAddr, Opts) -> + +%% - if Address is 'any' and no ip-option is present, the name is +%% 'any' and the socket will listen to all addresses +%% +%% - if Address is 'any' and an ip-option is present, the name is +%% set to the value of the ip-option and the socket will listen +%% to that address +%% +%% - if Address is 'loopback' and no ip-option is present, the name +%% is 'loopback' and an loopback address will be choosen by the +%% underlying layers +%% +%% - if Address is 'loopback' and an ip-option is present, the name +%% is set to the value of the ip-option kept and the socket will +%% listen to that address +%% +%% - if Address is an ip-address, that ip-address is the name and +%% the listening address. An ip-option will be discarded. +%% +%% - if Address is a HostName, and that resolves to an ip-address, +%% that ip-address is the name and the listening address. An +%% ip-option will be discarded. +%% +%% - if Address is a string or an atom other than thoose defined +%% above, that Address will be the name and the listening address +%% will be choosen by the lower layers taking an ip-option in +%% consideration +%% + +handle_daemon_args(any, Opts) -> + case proplists:get_value(ip, Opts) of + undefined -> {any, Opts}; + IP -> {IP, Opts} + end; + +handle_daemon_args(loopback, Opts) -> + case proplists:get_value(ip, Opts) of + undefined -> {loopback, [{ip,loopback}|Opts]}; + IP -> {IP, Opts} + end; + +handle_daemon_args(IPaddr, Opts) when is_tuple(IPaddr) -> + case proplists:get_value(ip, Opts) of + undefined -> {IPaddr, [{ip,IPaddr}|Opts]}; + IPaddr -> {IPaddr, Opts}; + IP -> {IPaddr, [{ip,IPaddr}|Opts--[{ip,IP}]]} %% Backward compatibility + end; + +handle_daemon_args(Address, Opts) when is_list(Address) ; is_atom(Address) -> IP = proplists:get_value(ip, Opts), - IPh = case inet:parse_strict_address(HostAddr) of - {ok, IPtuple} -> IPtuple; - {error, einval} when is_tuple(HostAddr), - size(HostAddr)==4 ; size(HostAddr)==6 -> HostAddr; - _ -> undefined - end, - handle_daemon_args(HostAddr, IPh, IP, Opts). - - -%% HostAddr is 'any' -handle_daemon_args(any, undefined, undefined, Opts) -> {any, Opts}; -handle_daemon_args(any, undefined, IP, Opts) -> {IP, Opts}; - -%% HostAddr is 'loopback' or "localhost" -handle_daemon_args(loopback, undefined, {127,_,_,_}=IP, Opts) -> {IP, Opts}; -handle_daemon_args(loopback, undefined, {0,0,0,0,0,0,0,1}=IP, Opts) -> {IP, Opts}; -handle_daemon_args(loopback, undefined, undefined, Opts) -> - IP = case proplists:get_value(inet,Opts) of - true -> {127,0,0,1}; - inet -> {127,0,0,1}; - inet6 -> {0,0,0,0,0,0,0,1}; - _ -> case proplists:get_value(inet6,Opts) of - true -> {0,0,0,0,0,0,0,1}; - _ -> {127,0,0,1} % default if no 'inet' nor 'inet6' - end - end, - {IP, [{ip,IP}|Opts]}; -handle_daemon_args("localhost", IPh, IP, Opts) -> - handle_daemon_args(loopback, IPh, IP, Opts); - -%% HostAddr is ip and no ip-option -handle_daemon_args(_, IP, undefined, Opts) when is_tuple(IP) -> {IP, [{ip,IP}|Opts]}; - -%% HostAddr and ip-option are equal -handle_daemon_args(_, IP, IP, Opts) when is_tuple(IP) -> {IP, Opts}; - -%% HostAddr is ip, but ip-option is different! -handle_daemon_args(_, IPh, IPo, _) when is_tuple(IPh), is_tuple(IPo) -> error({eoption,{ip,IPo}}); - -%% Something else. Whatever it is, it is wrong. -handle_daemon_args(_, _, _, _) -> error(badarg). + case inet:parse_strict_address(Address) of + {ok, IP} -> {IP, Opts}; + {ok, OtherIP} -> {OtherIP, [{ip,OtherIP}|Opts--[{ip,IP}]]}; + _ -> + case inet:getaddr(Address, family(Opts)) of + {ok, IP} -> {Address, Opts}; + {ok, OtherIP} -> {Address, [{ip,OtherIP}|Opts--[{ip,IP}]]}; + _ -> {Address, Opts} + end + end. + + +-ifdef(hulahopp). +%% Check the Address parameter and set an ip-option in some cases. The +%% Address parameter is left unchanged because ssh:stop_listener and +%% ssh:stop_daemon needs to find the system supervisor by name + +handle_daemon_args(any, Opts) -> + %% Listen to 0.0.0.0. The caller may have set an ip-option. Trust + %% that one in such a case. + {any, Opts}; + +handle_daemon_args(loopback, Opts) -> + %% Listen to a loopback address. Let the underlying layers decide + %% in case the caller hasn't set the ip-option. + {loopback, ensure_ip_option(loopback,Opts)}; + +handle_daemon_args(IP, Opts) when is_tuple(IP) -> + %% An IP address in Erlang tuple format: + {IP, ensure_ip_option(IP,Opts)}; + +handle_daemon_args(Address, Opts) when is_list(Address) ; is_atom(Address) -> + %% This might be a host name, an FQDN, an IP address in string format ("127.1.1.1") + %% etc. It might be a string or an atom since inet:hostname() is defined in that way + case inet:parse_strict_address(Address) of + {ok, IP} -> + {Address, ensure_ip_option(IP,Opts)}; + _ -> + %% Try to lookup as a hostname: + case inet:getaddr(Address, family(Opts)) of + {ok, IP} -> + {Address, ensure_ip_option(IP,Opts)}; + _ -> + %% Give up and let the underlying system handle this + {Address, Opts} + end + end. + + +%% Add an ip-option if not already present. +ensure_ip_option(Address, Opts) -> + case proplists:get_value(ip, Opts) of + undefined -> [{ip,Address}|Opts]; + _ -> Opts + end. +-endif. + + +%% Has the caller indicated the address family? +family(Opts) -> + family(Opts, inet). + +family(Opts, Default) -> + case proplists:get_value(inet,Opts) of + true -> inet; + inet -> inet; + inet6 -> inet6; + _ -> case proplists:get_value(inet6,Opts) of + true -> inet6; + _ -> Default + end + end. %%%---------------------------------------------------------------- valid_socket_to_use(Socket, {tcp,_,_}) -> @@ -434,8 +520,9 @@ open_listen_socket(Host0, Port0, Options0) -> case ?GET_SOCKET_OPT(fd, Options0) of undefined -> {ok,LSock} = ssh_acceptor:listen(Port0, Options0), - {ok,{_,LPort}} = inet:sockname(LSock), - {{Host0,LPort}, LSock}; + {ok,{_LHost,LPort}} = inet:sockname(LSock), + {{_LHost,LPort}, LSock}; +%% {{Host0,LPort}, LSock}; Fd when is_integer(Fd) -> %% Do gen_tcp:listen with the option {fd,Fd}: @@ -446,35 +533,18 @@ open_listen_socket(Host0, Port0, Options0) -> %%%---------------------------------------------------------------- finalize_start(Host, Port, Profile, Options0, F) -> - Options = ?PUT_INTERNAL_OPT([{address, Host}, - {port, Port}, - {role, server}], Options0), - case ssh_system_sup:system_supervisor(Host, Port, Profile) of - undefined -> - try sshd_sup:start_child(Options) of - {error, {already_started, _}} -> - {error, eaddrinuse}; - {error, Error} -> - {error, Error}; - Result = {ok,_} -> - F(Options, Result) - catch - exit:{noproc, _} -> - {error, ssh_not_started} - end; - Sup -> - AccPid = ssh_system_sup:acceptor_supervisor(Sup), - case ssh_acceptor_sup:start_child(AccPid, Options) of - {error, {already_started, _}} -> - {error, eaddrinuse}; - {error, Error} -> - {error, Error}; - {ok, _} -> - F(Options, {ok,Sup}) - end + try + sshd_sup:start_child(Host, Port, Profile, Options0) + of + {error, {already_started, _}} -> + {error, eaddrinuse}; + {error, Error} -> + {error, Error}; + Result = {ok,_} -> + F(Options0, Result) + catch + exit:{noproc, _} -> + {error, ssh_not_started} end. %%%---------------------------------------------------------------- -fmt_host(any) -> "any"; -fmt_host(IP) when is_tuple(IP) -> inet:ntoa(IP); -fmt_host(Str) when is_list(Str) -> Str. diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl index f9e2280212..f7fbd7ccad 100644 --- a/lib/ssh/src/ssh_acceptor.erl +++ b/lib/ssh/src/ssh_acceptor.erl @@ -129,7 +129,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, Options), + {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, diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl index 613d8fbc75..4606107f56 100644 --- a/lib/ssh/src/ssh_acceptor_sup.erl +++ b/lib/ssh/src/ssh_acceptor_sup.erl @@ -29,7 +29,7 @@ -include("ssh.hrl"). --export([start_link/1, start_child/2, stop_child/4]). +-export([start_link/4, start_child/5, stop_child/4]). %% Supervisor callback -export([init/1]). @@ -41,16 +41,13 @@ %%%========================================================================= %%% API %%%========================================================================= -start_link(Servers) -> - supervisor:start_link(?MODULE, [Servers]). +start_link(Address, Port, Profile, Options) -> + supervisor:start_link(?MODULE, [Address, Port, Profile, Options]). -start_child(AccSup, Options) -> - Spec = child_spec(Options), +start_child(AccSup, Address, Port, Profile, Options) -> + Spec = child_spec(Address, Port, Profile, Options), case supervisor:start_child(AccSup, Spec) of {error, already_present} -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Profile = ?GET_OPT(profile, Options), stop_child(AccSup, Address, Port, Profile), supervisor:start_child(AccSup, Spec); Reply -> @@ -69,21 +66,18 @@ stop_child(AccSup, Address, Port, Profile) -> %%%========================================================================= %%% Supervisor callback %%%========================================================================= -init([Options]) -> +init([Address, Port, Profile, Options]) -> RestartStrategy = one_for_one, MaxR = 10, MaxT = 3600, - Children = [child_spec(Options)], + Children = [child_spec(Address, Port, Profile, Options)], {ok, {{RestartStrategy, MaxR, MaxT}, Children}}. %%%========================================================================= %%% Internal functions %%%========================================================================= -child_spec(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), +child_spec(Address, Port, Profile, Options) -> Timeout = ?GET_INTERNAL_OPT(timeout, Options, ?DEFAULT_TIMEOUT), - Profile = ?GET_OPT(profile, Options), Name = id(Address, Port, Profile), StartFunc = {ssh_acceptor, start_link, [Port, Address, Options, Timeout]}, Restart = transient, diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 50a29bbb53..ff94e5dfb6 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -440,7 +440,12 @@ init_ssh_record(Role, Socket, Opts) -> {Vsn, Version} = ssh_transport:versions(Role, Opts), case Role of client -> - PeerName = ?GET_INTERNAL_OPT(host, Opts), + PeerName = case ?GET_INTERNAL_OPT(host, Opts) of + PeerIP when is_tuple(PeerIP) -> + inet_parse:ntoa(PeerIP); + PeerName0 -> + PeerName0 + end, S0#ssh{c_vsn = Vsn, c_version = Version, io_cb = case ?GET_OPT(user_interaction, Opts) of diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index 898b4cc5c4..88f4d10792 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -221,6 +221,8 @@ file_name(Type, Name, Opts) -> %% in: "host" out: "host,1.2.3.4. +add_ip(IP) when is_tuple(IP) -> + ssh_connection:encode_ip(IP); add_ip(Host) -> case inet:getaddr(Host, inet) of {ok, Addr} -> diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl index cf82db458f..c5ab422265 100644 --- a/lib/ssh/src/ssh_subsystem_sup.erl +++ b/lib/ssh/src/ssh_subsystem_sup.erl @@ -28,7 +28,7 @@ -include("ssh.hrl"). --export([start_link/1, +-export([start_link/5, connection_supervisor/1, channel_supervisor/1 ]). @@ -39,8 +39,8 @@ %%%========================================================================= %%% API %%%========================================================================= -start_link(Options) -> - supervisor:start_link(?MODULE, [Options]). +start_link(Role, Address, Port, Profile, Options) -> + supervisor:start_link(?MODULE, [Role, Address, Port, Profile, Options]). connection_supervisor(SupPid) -> Children = supervisor:which_children(SupPid), @@ -53,30 +53,23 @@ channel_supervisor(SupPid) -> %%%========================================================================= %%% Supervisor callback %%%========================================================================= --spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore . - -init([Options]) -> +init([Role, Address, Port, Profile, Options]) -> RestartStrategy = one_for_all, MaxR = 0, MaxT = 3600, - Children = child_specs(Options), + Children = child_specs(Role, Address, Port, Profile, Options), {ok, {{RestartStrategy, MaxR, MaxT}, Children}}. %%%========================================================================= %%% Internal functions %%%========================================================================= -child_specs(Options) -> - case ?GET_INTERNAL_OPT(role, Options) of - client -> - []; - server -> - [ssh_channel_child_spec(Options), ssh_connectinon_child_spec(Options)] - end. +child_specs(client, _Address, _Port, _Profile, _Options) -> + []; +child_specs(server, Address, Port, Profile, Options) -> + [ssh_channel_child_spec(server, Address, Port, Profile, Options), + ssh_connection_child_spec(server, Address, Port, Profile, Options)]. -ssh_connectinon_child_spec(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Role = ?GET_INTERNAL_OPT(role, Options), +ssh_connection_child_spec(Role, Address, Port, _Profile, Options) -> Name = id(Role, ssh_connection_sup, Address, Port), StartFunc = {ssh_connection_sup, start_link, [Options]}, Restart = temporary, @@ -85,10 +78,7 @@ ssh_connectinon_child_spec(Options) -> Type = supervisor, {Name, StartFunc, Restart, Shutdown, Type, Modules}. -ssh_channel_child_spec(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Role = ?GET_INTERNAL_OPT(role, Options), +ssh_channel_child_spec(Role, Address, Port, _Profile, Options) -> Name = id(Role, ssh_channel_sup, Address, Port), StartFunc = {ssh_channel_sup, start_link, [Options]}, Restart = temporary, diff --git a/lib/ssh/src/ssh_sup.erl b/lib/ssh/src/ssh_sup.erl index 8b57387589..5463401dcd 100644 --- a/lib/ssh/src/ssh_sup.erl +++ b/lib/ssh/src/ssh_sup.erl @@ -31,63 +31,20 @@ %%%========================================================================= %%% Supervisor callback %%%========================================================================= --spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore . - -init([]) -> +init(_) -> SupFlags = {one_for_one, 10, 3600}, - Children = children(), + Children = [child_spec(sshd_sup), child_spec(sshc_sup)], %%children(), {ok, {SupFlags, Children}}. %%%========================================================================= %%% Internal functions %%%========================================================================= -get_services() -> - case (catch application:get_env(ssh, services)) of - {ok, Services} -> - Services; - _ -> - [] - end. - -children() -> - Services = get_services(), - Clients = [Service || Service <- Services, is_client(Service)], - Servers = [Service || Service <- Services, is_server(Service)], - - [server_child_spec(Servers), client_child_spec(Clients)]. - -server_child_spec(Servers) -> - Name = sshd_sup, - StartFunc = {sshd_sup, start_link, [Servers]}, +child_spec(Name) -> + StartFunc = {Name, start_link, []}, Restart = permanent, Shutdown = infinity, - Modules = [sshd_sup], + Modules = [Name], Type = supervisor, {Name, StartFunc, Restart, Shutdown, Type, Modules}. -client_child_spec(Clients) -> - Name = sshc_sup, - StartFunc = {sshc_sup, start_link, [Clients]}, - Restart = permanent, - Shutdown = infinity, - Modules = [sshc_sup], - Type = supervisor, - {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -is_server({sftpd, _}) -> - true; -is_server({shelld, _}) -> - true; -is_server(_) -> - false. - -is_client({sftpc, _}) -> - true; -is_client({shellc, _}) -> - true; -is_client(_) -> - false. - - - diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl index 4083f666c3..a923b5ef71 100644 --- a/lib/ssh/src/ssh_system_sup.erl +++ b/lib/ssh/src/ssh_system_sup.erl @@ -31,12 +31,12 @@ -include("ssh.hrl"). --export([start_link/1, stop_listener/1, +-export([start_link/4, stop_listener/1, stop_listener/3, stop_system/1, stop_system/3, system_supervisor/3, subsystem_supervisor/1, channel_supervisor/1, connection_supervisor/1, - acceptor_supervisor/1, start_subsystem/2, restart_subsystem/3, + acceptor_supervisor/1, start_subsystem/6, restart_subsystem/3, restart_acceptor/3, stop_subsystem/2]). %% Supervisor callback @@ -45,12 +45,9 @@ %%%========================================================================= %%% Internal API %%%========================================================================= -start_link(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Profile = ?GET_OPT(profile, Options), +start_link(Address, Port, Profile, Options) -> Name = make_name(Address, Port, Profile), - supervisor:start_link({local, Name}, ?MODULE, [Options]). + supervisor:start_link({local, Name}, ?MODULE, [Address, Port, Profile, Options]). stop_listener(SysSup) -> stop_acceptor(SysSup). @@ -86,8 +83,8 @@ connection_supervisor(SystemSup) -> acceptor_supervisor(SystemSup) -> ssh_acceptor_sup(supervisor:which_children(SystemSup)). -start_subsystem(SystemSup, Options) -> - Spec = ssh_subsystem_child_spec(Options), +start_subsystem(SystemSup, Role, Address, Port, Profile, Options) -> + Spec = ssh_subsystem_child_spec(Role, Address, Port, Profile, Options), supervisor:start_child(SystemSup, Spec). stop_subsystem(SystemSup, SubSys) -> @@ -125,14 +122,12 @@ restart_acceptor(Address, Port, Profile) -> %%%========================================================================= %%% Supervisor callback %%%========================================================================= --spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore . - -init([Options]) -> +init([Address, Port, Profile, Options]) -> RestartStrategy = one_for_one, MaxR = 0, MaxT = 3600, Children = case ?GET_INTERNAL_OPT(connected_socket,Options,undefined) of - undefined -> child_specs(Options); + undefined -> child_specs(Address, Port, Profile, Options); _ -> [] end, {ok, {{RestartStrategy, MaxR, MaxT}, Children}}. @@ -140,24 +135,21 @@ init([Options]) -> %%%========================================================================= %%% Internal functions %%%========================================================================= -child_specs(Options) -> - [ssh_acceptor_child_spec(Options)]. +child_specs(Address, Port, Profile, Options) -> + [ssh_acceptor_child_spec(Address, Port, Profile, Options)]. -ssh_acceptor_child_spec(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Profile = ?GET_OPT(profile, Options), +ssh_acceptor_child_spec(Address, Port, Profile, Options) -> Name = id(ssh_acceptor_sup, Address, Port, Profile), - StartFunc = {ssh_acceptor_sup, start_link, [Options]}, + StartFunc = {ssh_acceptor_sup, start_link, [Address, Port, Profile, Options]}, Restart = transient, Shutdown = infinity, Modules = [ssh_acceptor_sup], Type = supervisor, {Name, StartFunc, Restart, Shutdown, Type, Modules}. -ssh_subsystem_child_spec(Options) -> +ssh_subsystem_child_spec(Role, Address, Port, Profile, Options) -> Name = make_ref(), - StartFunc = {ssh_subsystem_sup, start_link, [Options]}, + StartFunc = {ssh_subsystem_sup, start_link, [Role, Address, Port, Profile, Options]}, Restart = temporary, Shutdown = infinity, Modules = [ssh_subsystem_sup], @@ -169,7 +161,12 @@ id(Sup, Address, Port, Profile) -> {Sup, Address, Port, Profile}. make_name(Address, Port, Profile) -> - list_to_atom(lists:flatten(io_lib:format("ssh_system_~s_~p_~p_sup", [Address, Port, Profile]))). + list_to_atom(lists:flatten(io_lib:format("ssh_system_~s_~p_~p_sup", [fmt_host(Address), Port, Profile]))). + +fmt_host(IP) when is_tuple(IP) -> inet:ntoa(IP); +fmt_host(A) when is_atom(A) -> A; +fmt_host(S) when is_list(S) -> S. + ssh_subsystem_sup([{_, Child, _, [ssh_subsystem_sup]} | _]) -> Child; diff --git a/lib/ssh/src/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl index 15858f36e1..9aab9d57e9 100644 --- a/lib/ssh/src/sshc_sup.erl +++ b/lib/ssh/src/sshc_sup.erl @@ -27,7 +27,7 @@ -behaviour(supervisor). --export([start_link/1, start_child/1, stop_child/1]). +-export([start_link/0, start_child/1, stop_child/1]). %% Supervisor callback -export([init/1]). @@ -35,8 +35,8 @@ %%%========================================================================= %%% API %%%========================================================================= -start_link(Args) -> - supervisor:start_link({local, ?MODULE}, ?MODULE, [Args]). +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). start_child(Args) -> supervisor:start_child(?MODULE, Args). @@ -51,18 +51,16 @@ stop_child(Client) -> %%%========================================================================= %%% Supervisor callback %%%========================================================================= --spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore . - -init(Args) -> +init(_) -> RestartStrategy = simple_one_for_one, MaxR = 0, MaxT = 3600, - {ok, {{RestartStrategy, MaxR, MaxT}, [child_spec(Args)]}}. + {ok, {{RestartStrategy, MaxR, MaxT}, [child_spec()]}}. %%%========================================================================= %%% Internal functions %%%========================================================================= -child_spec(_) -> +child_spec() -> Name = undefined, % As simple_one_for_one is used. StartFunc = {ssh_connection_handler, start_link, []}, Restart = temporary, diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl index 791456839d..d4805e9465 100644 --- a/lib/ssh/src/sshd_sup.erl +++ b/lib/ssh/src/sshd_sup.erl @@ -29,8 +29,11 @@ -include("ssh.hrl"). --export([start_link/1, start_child/1, stop_child/1, - stop_child/3, system_name/1]). +-export([start_link/0, + start_child/4, + stop_child/1, + stop_child/3, + system_name/1]). %% Supervisor callback -export([init/1]). @@ -38,27 +41,23 @@ %%%========================================================================= %%% API %%%========================================================================= -start_link(Servers) -> - supervisor:start_link({local, ?MODULE}, ?MODULE, [Servers]). +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). -start_child(Options) -> - Address = ?GET_INTERNAL_OPT(address, Options), - Port = ?GET_INTERNAL_OPT(port, Options), - Profile = ?GET_OPT(profile, Options), +start_child(Address, Port, Profile, Options) -> +io:format("~p:~p ~p:~p~n",[?MODULE,?LINE,Address, Port]), case ssh_system_sup:system_supervisor(Address, Port, Profile) of undefined -> - Spec = child_spec(Address, Port, Options), - case supervisor:start_child(?MODULE, Spec) of - {error, already_present} -> - Name = id(Address, Port, Profile), - supervisor:delete_child(?MODULE, Name), - supervisor:start_child(?MODULE, Spec); - Reply -> - Reply - end; +io:format("~p:~p undefined~n",[?MODULE,?LINE]), + Spec = child_spec(Address, Port, Profile, Options), + Reply = supervisor:start_child(?MODULE, Spec), +io:format("~p:~p Reply=~p~n",[?MODULE,?LINE,Reply]), + Reply; Pid -> +io:format("~p:~p Pid=~p~n",[?MODULE,?LINE,Pid]), AccPid = ssh_system_sup:acceptor_supervisor(Pid), - ssh_acceptor_sup:start_child(AccPid, Options) + ssh_acceptor_sup:start_child(AccPid, Address, Port, Profile, Options), + {ok,Pid} end. stop_child(Name) -> @@ -75,27 +74,15 @@ system_name(SysSup) -> %%%========================================================================= %%% Supervisor callback %%%========================================================================= --spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore . - -init([Servers]) -> - RestartStrategy = one_for_one, - MaxR = 10, - MaxT = 3600, - Fun = fun(ServerOpts) -> - Address = ?GET_INTERNAL_OPT(address, ServerOpts), - Port = ?GET_INTERNAL_OPT(port, ServerOpts), - child_spec(Address, Port, ServerOpts) - end, - Children = lists:map(Fun, Servers), - {ok, {{RestartStrategy, MaxR, MaxT}, Children}}. +init(_) -> + {ok, {{one_for_one, 10, 3600}, []}}. %%%========================================================================= %%% Internal functions %%%========================================================================= -child_spec(Address, Port, Options) -> - Profile = ?GET_OPT(profile, Options), +child_spec(Address, Port, Profile, Options) -> Name = id(Address, Port,Profile), - StartFunc = {ssh_system_sup, start_link, [Options]}, + StartFunc = {ssh_system_sup, start_link, [Address, Port, Profile, Options]}, Restart = temporary, Shutdown = infinity, Modules = [ssh_system_sup], -- cgit v1.2.3