File 3822-ssh-Refactor-for-changes-later.patch of Package erlang

From 401f20b46ffa8c6b19d3d7233d058de616e63ff1 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 26 Jan 2021 13:58:05 +0100
Subject: [PATCH 2/2] ssh: Refactor for changes later

---
 lib/ssh/src/ssh.erl                    | 159 +++++++++++--------------
 lib/ssh/src/ssh_acceptor.erl           |  10 +-
 lib/ssh/src/ssh_connection_handler.erl |  52 ++++----
 lib/ssh/src/ssh_connection_sup.erl     |   2 +-
 lib/ssh/src/sshd_sup.erl               |   5 +-
 lib/ssh/test/ssh_sup_SUITE.erl         |   6 +-
 6 files changed, 107 insertions(+), 127 deletions(-)

diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 9abb0fdebb..22fc8f40be 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -144,7 +144,7 @@ connect(Socket, UserOptions, NegotiationTimeout) when is_list(UserOptions) ->
 	Options = #{} ->
             case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of
                 ok ->
-                    ssh_connection_handler:start_connection(client, Socket, Options, NegotiationTimeout);
+                    ssh_connection_handler:start_link(client, Socket, Options, NegotiationTimeout);
                 {error,SockError} ->
                     {error,SockError}
             end
@@ -165,19 +165,8 @@ connect(Host0, Port, UserOptions, NegotiationTimeout) when is_integer(Port),
             {error, Reason};
         
         Options ->
-            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
+            Host = mangle_connect_address(Host0, Options),
+            ssh_connection_handler:start_link(client, Host, Port, Options, NegotiationTimeout)
     end.
 
 %%--------------------------------------------------------------------
@@ -260,42 +249,47 @@ daemon(Port, UserOptions) when 0 =< Port,Port =< 65535 ->
     daemon(any, Port, UserOptions);
 
 daemon(Socket, UserOptions) ->
-    try
-        #{} = Options = ssh_options:handle_options(server, UserOptions),
-
-        case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of
-            ok ->
-                {ok, {IP,Port}} = inet:sockname(Socket),
-                finalize_start(IP, Port, ?GET_OPT(profile, Options),
-                               ?PUT_INTERNAL_OPT({connected_socket, Socket}, Options),
-                               fun(Opts, DefaultResult) ->
-                                       try ssh_acceptor:handle_established_connection(
-                                             IP, Port, Opts, Socket)
-                                       of
-                                           {error,Error} ->
-                                               {error,Error};
-                                           _ ->
-                                               DefaultResult
-                                       catch
-                                           C:R ->
-                                               {error,{could_not_start_connection,{C,R}}}
-                                       end
-                               end);
-            {error,SockError} ->
-                {error,SockError}
-            end
-    catch
-        throw:bad_fd ->
-            {error,bad_fd};
-        throw:bad_socket ->
-            {error,bad_socket};
-        error:{badmatch,{error,Error}} ->
-            {error,Error};
-        error:Error ->
-            {error,Error};
-        _C:_E ->
-            {error,{cannot_start_daemon,_C,_E}}
-    end.
+    case ssh_options:handle_options(server, UserOptions) of
+        #{} = Options0 ->
+            case valid_socket_to_use(Socket, ?GET_OPT(transport,Options0)) of
+                ok ->
+                    try
+                        Options = ?PUT_INTERNAL_OPT({connected_socket, Socket}, Options0),
+                        %% throws error:Error if no usable hostkey is found
+                        ssh_connection_handler:available_hkey_algorithms(server, Options),
+                        {ok, {IP,Port}} = inet:sockname(Socket),
+                        case sshd_sup:start_child(IP, Port, Options) of
+                            Result = {ok,_} ->
+                                case ssh_connection_handler:start_link(server, Socket, Options,
+                                                                       ?GET_OPT(negotiation_timeout,Options))
+                                of
+                                    {error,Error} ->
+                                        {error,Error};
+                                    _ ->
+                                        Result
+                                end;
+                            {error, {already_started, _}} ->
+                                {error, eaddrinuse};
+                            {error, Error} ->
+                                {error, Error}
+                        end
+                    catch
+                        error:{shutdown,Err} ->
+                            {error,Err};
+                        exit:{noproc, _} ->
+                            {error, ssh_not_started};
+                        C:R ->
+                            {error,{could_not_start_connection,{C,R}}}
+                    end;
+
+                {error,SockError} ->
+                    {error,SockError}
+            end;
+
+        {error,OptionError} ->
+            {error,OptionError}
+        end.
+
 
 
 -spec daemon(any | inet:ip_address(), inet:port_number(), daemon_options()) -> {ok,daemon_ref()} | {error,term()}
@@ -307,31 +301,39 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535,
     try
         {Host1, UserOptions} = handle_daemon_args(Host0, UserOptions0),
         #{} = Options0 = ssh_options:handle_options(server, UserOptions),
-        {open_listen_socket(Host1, Port0, Options0), Options0}
+        open_listen_socket(Host1, Port0, Options0)
     of
-        {{{Host,Port}, ListenSocket}, Options1} ->
+        {Host, Port, ListenSocket, Options1} ->
             try
                 %% Now Host,Port is what to use for the supervisor to register its name,
                 %% and ListenSocket is for listening on connections. But it is still owned
                 %% by self()...
-                finalize_start(Host, Port, ?GET_OPT(profile, Options1),
-                               ?PUT_INTERNAL_OPT({lsocket,{ListenSocket,self()}}, Options1),
-                               fun(Opts, Result) ->
-                                       {_, Callback, _} = ?GET_OPT(transport, Opts),
-                                       receive
-                                           {request_control, ListenSocket, ReqPid} ->
-                                               ok = Callback:controlling_process(ListenSocket, ReqPid),
-                                               ReqPid ! {its_yours,ListenSocket},
-                                               Result
-                                       end
-                               end)
+
+                %% throws error:Error if no usable hostkey is found
+                ssh_connection_handler:available_hkey_algorithms(server, Options1),
+                sshd_sup:start_child(Host, Port, Options1)
             of
-                {error,Err} ->
+                Result = {ok,_} ->
+                    receive
+                        {request_control, ListenSocket, ReqPid} ->
+                            {_, Callback, _} = ?GET_OPT(transport, Options1),
+                            ok = Callback:controlling_process(ListenSocket, ReqPid),
+                            ReqPid ! {its_yours,ListenSocket}
+                    end,
+                    Result;
+                {error, {already_started, _}} ->
                     close_listen_socket(ListenSocket, Options1),
-                    {error,Err};
-                OK ->
-                    OK
+                    {error, eaddrinuse};
+                {error, Error} ->
+                    close_listen_socket(ListenSocket, Options1),
+                    {error, Error}
             catch
+                error:{shutdown,Err} ->
+                    close_listen_socket(ListenSocket, Options1),
+                    {error,Err};
+                exit:{noproc, _} ->
+                    close_listen_socket(ListenSocket, Options1),
+                    {error, ssh_not_started};
                 error:Error ->
                     close_listen_socket(ListenSocket, Options1),
                     error(Error);
@@ -760,7 +762,7 @@ open_listen_socket(_Host0, Port0, Options0) ->
                 ssh_acceptor:listen(0, Options0)
         end,
     {ok,{LHost,LPort}} = inet:sockname(LSock),
-    {{LHost,LPort}, LSock}.
+    {LHost, LPort, LSock, ?PUT_INTERNAL_OPT({lsocket,{LSock,self()}}, Options0)}.
 
 %%%----------------------------------------------------------------
 close_listen_socket(ListenSocket, Options) ->
@@ -771,27 +773,6 @@ close_listen_socket(ListenSocket, Options) ->
         _C:_E -> ok
     end.
 
-%%%----------------------------------------------------------------
-finalize_start(Host, Port, Profile, Options0, F) ->
-    try
-        %% throws error:Error if no usable hostkey is found
-        ssh_connection_handler:available_hkey_algorithms(server, Options0),
-
-        sshd_sup:start_child(Host, Port, Profile, Options0)
-    of
-        {error, {already_started, _}} ->
-            {error, eaddrinuse};
-        {error, Error} ->
-            {error, Error};
-        Result = {ok,_} ->
-            F(Options0, Result)
-    catch
-        error:{shutdown,Err} ->
-            {error,Err};
-        exit:{noproc, _} ->
-            {error, ssh_not_started}
-    end.
-
 %%%----------------------------------------------------------------
 map_ip(Fun, {address,IP}) when is_tuple(IP) ->
     Fun(IP);
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index 773d8025cb..7e591fb9d9 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -27,8 +27,7 @@
 %% Internal application API
 -export([start_link/4,
 	 number_of_connections/1,
-	 listen/2,
-	 handle_established_connection/4]).
+	 listen/2]).
 
 %% spawn export  
 -export([acceptor_init/5, acceptor_loop/6]).
@@ -112,11 +111,6 @@ listen(Port, Options) ->
 	    Other
     end.
 
-%%%----------------------------------------------------------------
-handle_established_connection(Address, Port, Options, Socket) ->
-    {_, Callback, _} = ?GET_OPT(transport, Options),
-    handle_connection(Callback, Address, Port, Options, Socket).
-
 %%--------------------------------------------------------------------
 %%% Internal functions
 %%--------------------------------------------------------------------
@@ -191,7 +185,7 @@ handle_connection(Callback, Address, Port, Options, Socket) ->
     case number_of_connections(SystemSup) < MaxSessions of
 	true ->
 	    NegTimeout = ?GET_OPT(negotiation_timeout, Options),
-            ssh_connection_handler:start_connection(server, {Address,Port}, Socket, Options, NegTimeout);
+            ssh_connection_handler:start_link(server, Address, Port, Socket, Options, NegTimeout);
 	false ->
 	    Callback:close(Socket),
 	    IPstr = if is_tuple(Address) -> inet:ntoa(Address);
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 070039b309..870ce97333 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -40,8 +40,7 @@
 %%====================================================================
 
 %%% Start and stop
--export([start_link/3,
-         start_connection/4, start_connection/5,
+-export([start_link/4, start_link/5, start_link/6,
          socket_control/3,
 	 stop/1
 	]).
@@ -98,12 +97,26 @@
 %% Start / stop
 %%====================================================================
 
-%%--------------------------------------------------------------------
-start_connection(Role, Socket, Options, NegotiationTimeout) ->
+start_link(client, Host, Port, Options, NegotiationTimeout) ->
+    {_, Callback, _} = ?GET_OPT(transport, Options),
+    SocketOpts = [{active,false} | ?GET_OPT(socket_options,Options)],
+    try Callback:connect(Host, Port, SocketOpts, ?GET_OPT(connect_timeout,Options)) of
+        {ok, Socket} ->
+            start_link(client, Socket, Options, NegotiationTimeout);
+        {error, Reason} ->
+            {error, Reason}
+    catch
+        _:badarg -> {error, {options,?GET_OPT(socket_options,Options)}};
+        _:{error,Reason} -> {error,Reason};
+        error:Error -> {error,Error};
+        Class:Error -> {error, {Class,Error}}
+    end.
+
+start_link(Role, Socket, Options, NegotiationTimeout) ->
     {ok, {Host,Port}} = inet:sockname(Socket),
-    start_connection(Role, {Host,Port}, Socket, Options, NegotiationTimeout).
+    start_link(Role, Host, Port, Socket, Options, NegotiationTimeout).
 
-start_connection(Role, {Host,Port}, Socket, Options0, NegotiationTimeout) ->
+start_link(Role, Host, Port, Socket, Options0, NegotiationTimeout) ->
     try
         Options1 = ?PUT_INTERNAL_OPT([{user_pid, self()}
                                      ], Options0),
@@ -118,7 +131,9 @@ start_connection(Role, {Host,Port}, Socket, Options0, NegotiationTimeout) ->
                                                     {subsystem_sup, SubSysSup},
                                                     {connection_sup, ConnectionSup}]}
                                     ], Options1),
-        case ssh_connection_sup:start_child(ConnectionSup, [Role, Socket, Options]) of
+        case ssh_connection_sup:start_child(ConnectionSup,
+                                            [?MODULE, [Role, Socket, Options], [{spawn_opt, [{message_queue_data,off_heap}]}]]
+                                           ) of
             {ok, Pid} ->
                 case socket_control(Socket, Pid, Options) of
                     ok ->
@@ -131,22 +146,11 @@ start_connection(Role, {Host,Port}, Socket, Options0, NegotiationTimeout) ->
         end
     catch
         exit:{noproc,{gen_server,call,_}} -> {error, ssh_not_started};
-        error:Error ->  {error, Error};
-        Class:Error ->  {error, {Class,Error}}
+        _:{error,Error} -> {error,Error};
+        error:Error -> {error,Error};
+        Class:Error -> {error, {Class,Error}}
     end.
 
-%%--------------------------------------------------------------------
--spec start_link(role(),
-		 gen_tcp:socket(),
-                 internal_options()
-		) -> {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}]}
-                          ]).
-
-
 %%--------------------------------------------------------------------
 -spec stop(connection_ref()
 	  ) -> ok | {error, term()}.
@@ -462,12 +466,12 @@ init([Role, Socket, Opts]) when Role==client ; Role==server ->
                 process_flag(trap_exit, true),
                 {ok, {hello,Role}, D}
             catch
-                _:Error ->
-                    {stop, Error}
+                _:{error,Error} ->
+                    {stop, {error,Error}}
             end;
 
         {error,Error} ->
-            {stop, Error}
+            {stop, {error,Error}}
     end.
 
 %%%----------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_connection_sup.erl b/lib/ssh/src/ssh_connection_sup.erl
index 79804b8630..192ce6f65d 100644
--- a/lib/ssh/src/ssh_connection_sup.erl
+++ b/lib/ssh/src/ssh_connection_sup.erl
@@ -51,7 +51,7 @@ init(_) ->
                  period    => 3600
                 },
     ChildSpecs = [#{id       => undefined, % As simple_one_for_one is used.
-                    start    => {ssh_connection_handler, start_link, []},
+                    start    => {gen_statem, start_link, []},
                     restart  => temporary % because there is no way to restart a crashed connection
                    }
                  ],
diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl
index bda156223e..6fd36bf97a 100644
--- a/lib/ssh/src/sshd_sup.erl
+++ b/lib/ssh/src/sshd_sup.erl
@@ -30,7 +30,7 @@
 -include("ssh.hrl").
 
 -export([start_link/0,
-         start_child/4, 
+         start_child/3,
          start_system_subsystem/4,
          stop_child/1,
 	 stop_child/3
@@ -47,7 +47,8 @@
 start_link() ->
     supervisor:start_link({local,?SSHD_SUP}, ?MODULE, []).
 
-start_child(Address, Port, Profile, Options) ->
+start_child(Address, Port, Options) ->
+    Profile = ?GET_OPT(profile,Options),
     case ssh_system_sup:system_supervisor(Address, Port, Profile) of
        undefined ->
             %% Here we start listening on a new Host/Port/Profile
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index fa9dbe1c7d..dc98325c9f 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -368,7 +368,7 @@ chk_empty_con_daemon(Daemon) ->
 		[ConnectionSup,ChannelSup]),
     ?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}],
 		supervisor:which_children(AccSup)),
-    ?wait_match([{_, _, worker,[ssh_connection_handler]}],
+    ?wait_match([{_, _, worker,[gen_statem]}],
 		supervisor:which_children(ConnectionSup)),
     ?wait_match([], supervisor:which_children(ChannelSup)),
     [ChannelSup, ConnectionSup, SubSysSup, AccSup].
@@ -404,7 +404,7 @@ check_sshd_system_tree(Daemon, Host, Port, Config) ->
     ?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}],
 		supervisor:which_children(AccSup)),
     
-    ?wait_match([{_, _, worker,[ssh_connection_handler]}],
+    ?wait_match([{_, _, worker,[gen_statem]}],
 		supervisor:which_children(ConnectionSup)),
     
     ?wait_match([], supervisor:which_children(ChannelSup)),
@@ -433,7 +433,7 @@ check_sshc_system_tree(SysSup, Connection, LocalIP, LocalPort, _Config) ->
 		  [ssh_channel_sup]}],
 		supervisor:which_children(SubSysSup),
 		[ConnectionSup,ChannelSup,FwdAccSup]),
-    ?wait_match([{_, Connection, worker,[ssh_connection_handler]}],
+    ?wait_match([{_, Connection, worker,[gen_statem]}],
 		supervisor:which_children(ConnectionSup)),
     ?wait_match([], supervisor:which_children(ChannelSup)),
     ?wait_match([], supervisor:which_children(FwdAccSup)),
-- 
2.26.2

openSUSE Build Service is sponsored by