summaryrefslogtreecommitdiff
path: root/lib/ssh/test
diff options
context:
space:
mode:
authorHans Nilsson <hans@erlang.org>2022-01-13 17:04:35 +0100
committerHans Nilsson <hans@erlang.org>2022-01-13 17:04:35 +0100
commitd569f4a52383e6488f4d1b4950338bfbf541373f (patch)
treefcbd9718e18cdc1d2a2f6195b9550ef5e48f4ade /lib/ssh/test
parenta6f9f4d0691b16d0f9d5b7560351616f31757d6d (diff)
parent779cdc929a44e0be201bfce8f90fdee9768486d0 (diff)
downloaderlang-d569f4a52383e6488f4d1b4950338bfbf541373f.tar.gz
Merge branch 'maint'
* maint: ssh: Extend ssh_dbg with 'handshake' ssh: Extend ssh_protocol_SUITE with incomplete connection start ssh: Fix parallel_login option and an intermediate controlling proc
Diffstat (limited to 'lib/ssh/test')
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl122
1 files changed, 119 insertions, 3 deletions
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 07fa24a5a0..7e94bf60c7 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -75,7 +75,8 @@
packet_length_too_short/1,
preferred_algorithms/1,
service_name_length_too_large/1,
- service_name_length_too_short/1
+ service_name_length_too_short/1,
+ client_close_after_hello/1
]).
-define(NEWLINE, <<"\r\n">>).
@@ -112,7 +113,8 @@ all() ->
{group,packet_size_error},
{group,field_size_error},
{group,ext_info},
- {group,preferred_algorithms}
+ {group,preferred_algorithms},
+ {group,client_close_early}
].
groups() ->
@@ -154,7 +156,9 @@ groups() ->
modify_prepend,
modify_rm,
modify_combo
- ]}
+ ]},
+ {client_close_early, [], [client_close_after_hello
+ ]}
].
@@ -896,6 +900,82 @@ modify_combo(Config) ->
]}
]).
+
+%%%----------------------------------------------------------------
+%%%
+client_close_after_hello() -> [{timetrap,{seconds,80}}].
+
+client_close_after_hello(Config0) ->
+ MaxSessions = 20,
+ SleepSec = 15,
+ Config = start_std_daemon(Config0, [{parallel_login,true},
+ {max_sessions,MaxSessions},
+ {negotiation_timeout,SleepSec*1000}
+ ]),
+
+ {Parents0, Conns0, []} = find_handshake_parent(server_port(Config)),
+
+ Cs =
+ [ssh_trpt_test_lib:exec(
+ [{connect,
+ server_host(Config),server_port(Config),
+ [{preferred_algorithms,[{kex,[?DEFAULT_KEX]},
+ {cipher,?DEFAULT_CIPHERS}
+ ]},
+ {silently_accept_hosts, true},
+ {recv_ext_info, false},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false}
+ | proplists:get_value(extra_options,Config,[])
+ ]},
+ {send, hello}
+ ]) || _ <- lists:seq(1,MaxSessions+100)],
+
+ ct:pal("=== Tried to start ~p sessions.", [length(Cs)]),
+
+ ssh_info:print(fun ct:pal/2),
+ {Parents, Conns, Handshakers} = find_handshake_parent(server_port(Config)),
+ ct:pal("Found (Port=~p):~n"
+ " Connections (length ~p): ~p~n"
+ " Handshakers (length ~p): ~p~n"
+ " with parents (length ~p): ~p",
+ [server_port(Config),
+ length(Conns), Conns,
+ length(Handshakers), Handshakers,
+ length(Parents), Parents]),
+ if
+ length(Handshakers)>0 ->
+ lists:foreach(fun(P) -> exit(P,some_reason) end, Parents),
+ ct:pal("After sending exits; now going to sleep", []),
+ timer:sleep((SleepSec+15)*1000),
+ ct:pal("After sleeping", []),
+ ssh_info:print(fun ct:pal/2),
+ {Parents2, Conns2, Handshakers2} = find_handshake_parent(server_port(Config)),
+ ct:pal("Found (Port=~p):~n"
+ " Connections (length ~p): ~p~n"
+ " Handshakers (length ~p): ~p~n"
+ " with parents (length ~p): ~p",
+ [server_port(Config),
+ length(Conns2), Conns2,
+ length(Handshakers2), Handshakers2,
+ length(Parents2), Parents2]),
+ if
+ Handshakers2==[] andalso Conns2==Conns0 ->
+ ok;
+ Handshakers2=/=[] ->
+ ct:pal("Handshakers still alive: ~p", [Handshakers2]),
+ {fail, handshakers_alive};
+ true ->
+ ct:pal("Connections before: ~p~n"
+ "Connections after: ~p", [Conns0,Conns2]),
+ {fail, connections_bad}
+ end;
+
+ true ->
+ {fail, no_handshakers}
+ end.
+
+
%%%================================================================
%%%==== Internal functions ========================================
%%%================================================================
@@ -1073,3 +1153,39 @@ disconnect(Code) ->
tcp_closed,
{tcp_error,econnaborted}
]}.
+
+%%%----------------------------------------------------------------
+find_handshake_parent(Port) ->
+ Acc = {_Parents=[], _Connections=[], _Handshakers=[]},
+ find_handshake_parent(supervisor:which_children(sshd_sup), Port, Acc).
+
+
+find_handshake_parent([{{ssh_system_sup,{address,_,Port,_}},
+ Pid,supervisor, [ssh_system_sup]}|_],
+ Port, Acc) ->
+ find_handshake_parent(supervisor:which_children(Pid), Port, Acc);
+
+find_handshake_parent([{{ssh_acceptor_sup,{address,_,Port,_}},
+ PidS,supervisor,[ssh_acceptor_sup]}|T],
+ Port, {AccP,AccC,AccH}) ->
+ ParentHandshakers =
+ [{PidW,PidH} ||
+ {{ssh_acceptor_sup,{address,_,Port1,_}}, PidW, worker, [ssh_acceptor]} <-
+ supervisor:which_children(PidS),
+ Port1 == Port,
+ PidH <- element(2, process_info(PidW,links)),
+ is_pid(PidH),
+ process_info(PidH,current_function) == {current_function,{ssh_connection_handler,handshake,3}}],
+ {Parents,Handshakers} = lists:unzip(ParentHandshakers),
+ find_handshake_parent(T, Port, {AccP++Parents, AccC, AccH++Handshakers});
+
+find_handshake_parent([{_Ref,PidS,supervisor,[ssh_subsystem_sup]}|T], Port, {AccP,AccC,AccH}) ->
+ Connections =
+ [Pid || {connection,Pid,worker,[ssh_connection_handler]} <- supervisor:which_children(PidS)],
+ find_handshake_parent(T, Port, {AccP, AccC++Connections, AccH});
+
+find_handshake_parent([_|T], Port, Acc) ->
+ find_handshake_parent(T, Port, Acc);
+
+find_handshake_parent(_, _, {AccP,AccC,AccH}) ->
+ {lists:usort(AccP), lists:usort(AccC), lists:usort(AccH)}.