aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2017-03-21 19:50:49 +0100
committerHans Nilsson <[email protected]>2017-04-07 10:23:34 +0200
commit6158cb432092c47e178b4dc1177b46cb8c310ab4 (patch)
tree8d6d5ff1f0f2b70eb7bc1cbe4e5fa5e440e3764e /lib/ssh
parent57d994270d63e7a9ce80eece3c1c3aeca79d3ea4 (diff)
downloadotp-6158cb432092c47e178b4dc1177b46cb8c310ab4.tar.gz
otp-6158cb432092c47e178b4dc1177b46cb8c310ab4.tar.bz2
otp-6158cb432092c47e178b4dc1177b46cb8c310ab4.zip
ssh: Fix supervisors, start daemon and connect code
Remove many internal options and made them as explicit arguments.
Diffstat (limited to 'lib/ssh')
-rw-r--r--lib/ssh/src/ssh.erl240
-rw-r--r--lib/ssh/src/ssh_acceptor.erl3
-rw-r--r--lib/ssh/src/ssh_acceptor_sup.erl22
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl7
-rw-r--r--lib/ssh/src/ssh_file.erl2
-rw-r--r--lib/ssh/src/ssh_subsystem_sup.erl34
-rw-r--r--lib/ssh/src/ssh_sup.erl53
-rw-r--r--lib/ssh/src/ssh_system_sup.erl43
-rw-r--r--lib/ssh/src/sshc_sup.erl14
-rw-r--r--lib/ssh/src/sshd_sup.erl55
10 files changed, 237 insertions, 236 deletions
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],