aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_asm.erl6
-rw-r--r--lib/compiler/src/compile.erl12
-rw-r--r--lib/compiler/test/compile_SUITE.erl42
-rw-r--r--lib/kernel/src/file.erl3
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl47
-rw-r--r--lib/sasl/test/test_lib.hrl4
-rw-r--r--lib/ssh/src/Makefile1
-rw-r--r--lib/ssh/src/ssh.app.src1
-rw-r--r--lib/ssh/src/ssh_dbg.erl140
-rw-r--r--lib/ssh/src/ssh_info.erl288
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl17
-rw-r--r--lib/ssh/test/ssh_echo_server.erl1
-rw-r--r--lib/ssl/doc/src/ssl.xml22
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl2
14 files changed, 441 insertions, 145 deletions
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 95be471de3..28fd061bdc 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -225,10 +225,14 @@ flatten_imports(Imps) ->
list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
build_attributes(Opts, SourceFile, Attr, MD5) ->
+ Misc0 = case SourceFile of
+ [] -> [];
+ [_|_] -> [{source,SourceFile}]
+ end,
Misc = case member(slim, Opts) of
false ->
{{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
- [{time,{Y,Mo,D,H,Mi,S}},{source,SourceFile}];
+ [{time,{Y,Mo,D,H,Mi,S}}|Misc0];
true -> []
end,
Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 332bc0bdf9..65566df025 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1328,7 +1328,7 @@ save_core_code(St) ->
beam_asm(#compile{ifile=File,code=Code0,
abstract_code=Abst,mod_options=Opts0}=St) ->
- Source = filename:absname(File),
+ Source = paranoid_absname(File),
Opts1 = lists:map(fun({debug_info_key,_}) -> {debug_info_key,'********'};
(Other) -> Other
end, Opts0),
@@ -1337,6 +1337,16 @@ beam_asm(#compile{ifile=File,code=Code0,
{ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}}
end.
+paranoid_absname(""=File) ->
+ File;
+paranoid_absname(File) ->
+ case file:get_cwd() of
+ {ok,Cwd} ->
+ filename:absname(File, Cwd);
+ _ ->
+ File
+ end.
+
test_native(#compile{options=Opts}) ->
%% This test is done late, in case some other option has turned off native.
%% 'native' given on the command line can be overridden by
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index fc04c9a60a..f1e75771bf 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -127,13 +127,39 @@ forms_2(Config) when is_list(Config) ->
Src = "/foo/bar",
AbsSrc = filename:absname(Src),
Anno = erl_anno:new(1),
- {ok,simple,Binary} = compile:forms([{attribute,Anno,module,simple}],
- [binary,{source,Src}]),
- code:load_binary(simple, Src, Binary),
- Info = simple:module_info(compile),
+ SimpleCode = [{attribute,Anno,module,simple}],
+ {ok,simple,Bin1} = compile:forms(SimpleCode, [binary,{source,Src}]),
- %% Test that the proper source is returned.
- AbsSrc = proplists:get_value(source, Info),
+ %% Load and test that the proper source is returned.
+ AbsSrc = forms_load_code(simple, Src, Bin1),
+
+ %% Work in a deleted directory.
+ PrivDir = proplists:get_value(priv_dir, Config),
+ WorkDir = filename:join(PrivDir, ?FUNCTION_NAME),
+ ok = file:make_dir(WorkDir),
+ ok = file:set_cwd(WorkDir),
+ case os:type() of
+ {unix,_} -> os:cmd("rm -rf " ++ WorkDir);
+ _ -> ok
+ end,
+ {ok,simple,Bin2} = compile:forms(SimpleCode),
+ undefined = forms_load_code(simple, "ignore", Bin2),
+
+ {ok,simple,Bin3} = compile:forms(SimpleCode, [{source,Src},report]),
+ case forms_load_code(simple, "ignore", Bin3) of
+ Src -> %Unix.
+ ok;
+ AbsSrc -> %Windows.
+ ok
+ end,
+
+ ok.
+
+
+forms_load_code(Mod, Src, Bin) ->
+ {module,Mod} = code:load_binary(Mod, Src, Bin),
+ Info = Mod:module_info(compile),
+ SourceOption = proplists:get_value(source, Info),
%% Ensure that the options are not polluted with 'source'.
[] = proplists:get_value(options, Info),
@@ -141,7 +167,9 @@ forms_2(Config) when is_list(Config) ->
%% Cleanup.
true = code:delete(simple),
false = code:purge(simple),
- ok.
+
+ SourceOption.
+
module_mismatch(Config) when is_list(Config) ->
DataDir = proplists:get_value(data_dir, Config),
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 1007f04413..1076e02422 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1227,7 +1227,8 @@ change_time(Name, {{AY, AM, AD}, {AH, AMin, ASec}}=Atime,
%% Send data using sendfile
%%
--define(MAX_CHUNK_SIZE, (1 bsl 20)*20). %% 20 MB, has to fit in primary memory
+%% 1 MB, Windows seems to behave badly if it is much larger then this
+-define(MAX_CHUNK_SIZE, (1 bsl 20)).
-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
{'ok', non_neg_integer()} | {'error', inet:posix() |
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index 6a487a1ddb..624a3536c0 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -2530,13 +2530,54 @@ latest(App) ->
rm_missing_app(Apps) ->
lists:keydelete(?MISSING_APP_NAME,#app.name,Apps).
+%% We will compare the script generated by systools with
+%% the script generated by Reltool.
+%%
+%% The systools script may include additional modules in
+%% the first primLoad command (as a pure optimization).
+%% Therefore, we cannot compare the primLoad commands
+%% directly. Instead we will collect all modules from
+%% all primLoad commands in each script. The same
+%% modules must be loaded by both scripts. In addition,
+%% the error_handler module must be included in the
+%% first primLoad in each script.
+
diff_script(Script, Script) ->
equal;
diff_script({script, Rel, Commands1}, {script, Rel, Commands2}) ->
- diff_cmds(Commands1, Commands2);
+ case diff_cmds(Commands1, Commands2) of
+ equal ->
+ Loaded = diff_get_prim_load(Commands1),
+ case diff_get_prim_load(Commands2) of
+ Loaded ->
+ equal;
+ Other ->
+ io:format("Only loaded by systools: ~p",
+ [Loaded--Other]),
+ io:format("Only loaded by reltool: ~p",
+ [Other--Loaded]),
+ ct:fail(different_prim_loads)
+ end;
+ Error ->
+ Error
+ end;
diff_script({script, Rel1, _}, {script, Rel2, _}) ->
{error, {Rel1, Rel2}}.
+diff_cmds([{primLoad, Ms1}=Cmd1 | Commands1],
+ [{primLoad, Ms2}=Cmd2 | Commands2]) ->
+ case lists:member(error_handler, Ms1) xor
+ lists:member(error_handler, Ms2) of
+ false ->
+ %% error_handler either present in both or
+ %% absent in both.
+ diff_cmds(Commands1, Commands2);
+ true ->
+ %% error_handler only present in one primLoad.
+ %% Not OK.
+ {diff, missing_error_handler,
+ {expected, Cmd1}, {actual, Cmd2}}
+ end;
diff_cmds([Cmd | Commands1], [Cmd | Commands2]) ->
diff_cmds(Commands1, Commands2);
diff_cmds([Cmd1 | _Commands1], [Cmd2 | _Commands2]) ->
@@ -2544,6 +2585,10 @@ diff_cmds([Cmd1 | _Commands1], [Cmd2 | _Commands2]) ->
diff_cmds([], []) ->
equal.
+diff_get_prim_load(Cmds) ->
+ L = [Ms || {primLoad, Ms} <- Cmds],
+ lists:sort(lists:flatten(L)).
+
os_cmd(Cmd) when is_list(Cmd) ->
%% Call the plain os:cmd with an echo command appended to print command status
%% io:format("os:cmd(~p).\n", [Cmd]),
diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl
index b16c4ac34c..2d897e9903 100644
--- a/lib/sasl/test/test_lib.hrl
+++ b/lib/sasl/test/test_lib.hrl
@@ -1,3 +1,3 @@
-define(ertsvsn,"4.4").
--define(kernelvsn,"3.0").
--define(stdlibvsn,"2.0").
+-define(kernelvsn,"4.0").
+-define(stdlibvsn,"2.5").
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index b44c8eef35..d8e4bfd50c 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -54,6 +54,7 @@ MODULES= \
ssh_connection_sup \
ssh_connection \
ssh_connection_handler \
+ ssh_dbg \
ssh_shell \
ssh_system_sup \
ssh_subsystem_sup \
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 4a76fd9cd3..c67350bf72 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -18,6 +18,7 @@
ssh_connection_handler,
ssh_connection_sup,
ssh_daemon_channel,
+ ssh_dbg,
ssh_shell,
sshc_sup,
sshd_sup,
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
new file mode 100644
index 0000000000..fbf85cfcfc
--- /dev/null
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -0,0 +1,140 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_dbg).
+
+-export([messages/0,
+ messages/1
+ ]).
+
+-include("ssh.hrl").
+-include("ssh_transport.hrl").
+-include("ssh_connect.hrl").
+-include("ssh_auth.hrl").
+
+-record(data, {
+ writer,
+ acc = []}).
+%%%================================================================
+messages() -> messages(fun(String,_D) -> io:format(String) end).
+%% messages() -> messages(fun(String,Acc) -> [String|Acc] end)
+
+messages(Write) when is_function(Write,2) ->
+ catch dbg:start(),
+
+ Handler = fun msg_formater/2,
+ InitialData = #data{writer = Write},
+ {ok,_} = dbg:tracer(process, {Handler, InitialData}),
+
+ dbg:p(new,c),
+ dbg:tp(ssh_message,encode,1, x),
+ dbg:tp(ssh_message,decode,1, x),
+ dbg:tpl(ssh_transport,select_algorithm,3, x).
+
+%%%================================================================
+msg_formater({trace,Pid,call,{ssh_message,encode,[Msg]}}, D) ->
+ fmt("~nSEND ~p ~s~n", [Pid,wr_record(shrink_bin(Msg))], D);
+
+msg_formater({trace,Pid,return_from,{ssh_message,decode,1},Msg}, D) ->
+ fmt("~nRECV ~p ~s~n", [Pid,wr_record(shrink_bin(Msg))], D);
+
+msg_formater({trace,Pid,return_from,{ssh_transport,select_algorithm,3},{ok,Alg}}, D) ->
+ fmt("~nALGORITHMS ~p~n~s~n", [Pid, wr_record(Alg)], D);
+
+msg_formater(_, D) ->
+ D.
+
+
+fmt(Fmt, Args, D=#data{writer=Write,acc=Acc}) ->
+ D#data{acc = Write(io_lib:format(Fmt, Args), Acc)}.
+
+%%%----------------------------------------------------------------
+shrink_bin(B) when is_binary(B), size(B)>100 -> {'*** SHRINKED BIN',size(B),element(1,split_binary(B,20)),'***'};
+shrink_bin(L) when is_list(L) -> lists:map(fun shrink_bin/1, L);
+shrink_bin(T) when is_tuple(T) -> list_to_tuple(shrink_bin(tuple_to_list(T)));
+shrink_bin(X) -> X.
+
+%%%----------------------------------------------------------------
+-define(wr_record(N,BlackList), wr_record(R=#N{}) -> wr_record(R, record_info(fields,N), BlackList)).
+
+-define(wr_record(N), ?wr_record(N, [])).
+
+
+?wr_record(alg);
+
+?wr_record(ssh_msg_disconnect);
+?wr_record(ssh_msg_ignore);
+?wr_record(ssh_msg_unimplemented);
+?wr_record(ssh_msg_debug);
+?wr_record(ssh_msg_service_request);
+?wr_record(ssh_msg_service_accept);
+?wr_record(ssh_msg_kexinit);
+?wr_record(ssh_msg_kexdh_init);
+?wr_record(ssh_msg_kexdh_reply);
+?wr_record(ssh_msg_newkeys);
+?wr_record(ssh_msg_kex_dh_gex_request);
+?wr_record(ssh_msg_kex_dh_gex_request_old);
+?wr_record(ssh_msg_kex_dh_gex_group);
+?wr_record(ssh_msg_kex_dh_gex_init);
+?wr_record(ssh_msg_kex_dh_gex_reply);
+?wr_record(ssh_msg_kex_ecdh_init);
+?wr_record(ssh_msg_kex_ecdh_reply);
+
+?wr_record(ssh_msg_userauth_request);
+?wr_record(ssh_msg_userauth_failure);
+?wr_record(ssh_msg_userauth_success);
+?wr_record(ssh_msg_userauth_banner);
+?wr_record(ssh_msg_userauth_passwd_changereq);
+?wr_record(ssh_msg_userauth_pk_ok);
+?wr_record(ssh_msg_userauth_info_request);
+?wr_record(ssh_msg_userauth_info_response);
+
+?wr_record(ssh_msg_global_request);
+?wr_record(ssh_msg_request_success);
+?wr_record(ssh_msg_request_failure);
+?wr_record(ssh_msg_channel_open);
+?wr_record(ssh_msg_channel_open_confirmation);
+?wr_record(ssh_msg_channel_open_failure);
+?wr_record(ssh_msg_channel_window_adjust);
+?wr_record(ssh_msg_channel_data);
+?wr_record(ssh_msg_channel_extended_data);
+?wr_record(ssh_msg_channel_eof);
+?wr_record(ssh_msg_channel_close);
+?wr_record(ssh_msg_channel_request);
+?wr_record(ssh_msg_channel_success);
+?wr_record(ssh_msg_channel_failure);
+
+wr_record(R) -> io_lib:format('~p~n',[R]).
+
+
+wr_record(T, Fs, BL) when is_tuple(T) ->
+ wr_record(tuple_to_list(T), Fs, BL);
+wr_record([Name|Values], Fields, BlackL) ->
+ W = case Fields of
+ [] -> 0;
+ _ -> lists:max([length(atom_to_list(F)) || F<-Fields])
+ end,
+ [io_lib:format("~p:~n",[string:to_upper(atom_to_list(Name))])
+ | [io_lib:format(" ~*p: ~p~n",[W,Tag,Value]) || {Tag,Value} <- lists:zip(Fields,Values),
+ not lists:member(Tag,BlackL)
+ ]
+ ].
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index 2dfc55cd92..67130d5eac 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -31,134 +31,168 @@
collect_pids/0
]).
+-include("ssh_connect.hrl").
+
print() ->
- print(user).
+ io:format("~s", [string()]).
+print(File) when is_list(File) ->
+ {ok,D} = file:open(File, write),
+ print(D),
+ file:close(D);
print(D) ->
+ io:format(D, "~s", [string()]).
+
+string() ->
try supervisor:which_children(ssh_sup)
of
_ ->
- io__nl(D),
- print_general(D),
- io__nl(D),
- underline(D, "Client part", $=),
- print_clients(D),
- io__nl(D),
- underline(D, "Server part", $=),
- print_servers(D),
- io__nl(D),
- underline(D, "Supervisors", $=),
- walk_sups(D, ssh_sup),
- io__nl(D)
+ [io_lib:nl(),
+ print_general(),
+ io_lib:nl(),
+ underline("Client part", $=),
+ print_clients(),
+ io_lib:nl(),
+ underline("Server part", $=),
+ print_servers(),
+ io_lib:nl(),
+ underline("Supervisors", $=),
+ walk_sups(ssh_sup),
+ io_lib:nl()]
catch
_:_ ->
- io__format(D,"Ssh not found~n",[])
+ io_lib:format("Ssh not found~n",[])
end.
-string() ->
- Pid = spawn(fun init/0),
- print(Pid),
- Pid ! {get,self()},
- receive
- {result,R} -> R
- end.
-
-%%%================================================================
-print_general(D) ->
- {_Name, Slogan, Ver} = lists:keyfind(ssh,1,application:which_applications()),
- underline(D, io_lib:format("~s ~s", [Slogan, Ver]), $=),
- io__format(D, 'This printout is generated ~s. ~n',[datetime()]).
%%%================================================================
-define(INDENT, " ").
-print_clients(D) ->
- PrintClient = fun(X) -> print_client(D,X) end,
+print_general() ->
+ {_Name, Slogan, Ver} = lists:keyfind(ssh,1,application:which_applications()),
+ [underline(io_lib:format("~s ~s", [Slogan, Ver]), $=),
+ io_lib:format('This printout is generated ~s. ~n',[datetime()])
+ ].
+
+print_clients() ->
try
- lists:foreach(PrintClient, supervisor:which_children(sshc_sup))
+ lists:map(fun print_client/1,
+ supervisor:which_children(sshc_sup))
catch
C:E ->
- io__format(D, '***FAILED: ~p:~p~n',[C,E])
+ io_lib:format('***print_clients FAILED: ~p:~p~n',[C,E])
end.
-print_client(D, {undefined,Pid,supervisor,[ssh_connection_handler]}) ->
+print_client({undefined,Pid,supervisor,[ssh_connection_handler]}) ->
{{Local,Remote},_Str} = ssh_connection_handler:get_print_info(Pid),
- io__format(D, ?INDENT"Local: ~s Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Local),fmt_host_port(Remote),Pid]);
-print_client(D, Other) ->
- io__format(D, " [[Other 1: ~p]]~n",[Other]).
+ [io_lib:format(?INDENT"Local: ~s Remote: ~s ConnectionRef = ~p~n",
+ [fmt_host_port(Local), fmt_host_port(Remote), Pid]),
+ case channels(Pid) of
+ {ok,Channels=[_|_]} ->
+ [print_ch(ChPid) || #channel{user=ChPid} <- Channels];
+ _ ->
+ io_lib:format(?INDENT?INDENT?INDENT"No channels~n",[])
+ end];
+
+print_client(Other) ->
+ io_lib:format(" [[Other 1: ~p]]~n",[Other]).
%%%================================================================
-print_servers(D) ->
- PrintServer = fun(X) -> print_server(D,X) end,
+print_servers() ->
try
- lists:foreach(PrintServer, supervisor:which_children(sshd_sup))
+ lists:map(fun print_server/1,
+ supervisor:which_children(sshd_sup))
catch
C:E ->
- io__format(D, '***FAILED: ~p:~p~n',[C,E])
+ io_lib:format('***print_servers FAILED: ~p:~p~n',[C,E])
end.
-print_server(D, {{server,ssh_system_sup,LocalHost,LocalPort,Profile},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) ->
- io__format(D, ?INDENT"Listen: ~s (~p children) Profile ~p~n",[fmt_host_port({LocalHost,LocalPort}),
- ssh_acceptor:number_of_connections(Pid),
- Profile]),
- PrintSystemSup = fun(X) -> print_system_sup(D,X) end,
- lists:foreach(PrintSystemSup, supervisor:which_children(Pid)).
+print_server({{server,ssh_system_sup,LocalHost,LocalPort,Profile},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) ->
+ Children = supervisor:which_children(Pid),
+ [io_lib:format(?INDENT"Listen: ~s (~p children) Profile ~p",[fmt_host_port({LocalHost,LocalPort}),
+ ssh_acceptor:number_of_connections(Pid),
+ Profile]),
+ case [AccPid
+ || {{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, AccPid, supervisor, [ssh_acceptor_sup]}
+ <- Children] of
+ AcceptorPids = [_|_] ->
+ [io_lib:format(" [Acceptor Pid", []),
+ [io_lib:format(" ~p",[AccPid]) || AccPid <- AcceptorPids],
+ io_lib:format("]~n", [])
+ ];
+ [] ->
+ io_lib:nl()
+ end,
+ lists:map(fun print_system_sup/1,
+ supervisor:which_children(Pid))
+ ].
+
+
+print_system_sup({Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref),
+ is_pid(Pid) ->
+ lists:map(fun print_channels/1,
+ supervisor:which_children(Pid));
+print_system_sup({{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) ->
+ [].
-print_system_sup(D, {Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref),
- is_pid(Pid) ->
- PrintChannels = fun(X) -> print_channels(D,X) end,
- lists:foreach(PrintChannels, supervisor:which_children(Pid));
-print_system_sup(D, {{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) ->
- io__format(D, ?INDENT?INDENT"[Acceptor Pid ~p]~n",[Pid]).
-print_channels(D, {{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) ->
+print_channels({{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) ->
Children = supervisor:which_children(Pid),
ChannelPids = [P || {R,P,worker,[ssh_channel]} <- Children,
is_pid(P),
is_reference(R)],
case ChannelPids of
- [] -> io__format(D, ?INDENT?INDENT"No channels~n",[]);
+ [] -> io_lib:format(?INDENT?INDENT"No channels~n",[]);
[Ch1Pid|_] ->
{{ConnManager,_}, _Str} = ssh_channel:get_print_info(Ch1Pid),
{{_,Remote},_} = ssh_connection_handler:get_print_info(ConnManager),
- io__format(D, ?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]),
- lists:foreach(fun(P) -> print_ch(D,P) end, ChannelPids)
+ [io_lib:format(?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]),
+ lists:map(fun print_ch/1, ChannelPids)
+ ]
end;
-print_channels(_D, {{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_sup]}) when is_pid(Pid) ->
- ok. % The supervisor of the connections socket owning process
-
-print_ch(D, Pid) ->
- {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid),
- {_LocalRemote,StrM} = ssh_connection_handler:get_print_info(ConnManager),
- io__format(D, ?INDENT?INDENT?INDENT"ch ~p: ~s ~s~n",[ChannelID, StrM, Str]).
-
+print_channels({{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_sup]}) when is_pid(Pid) ->
+ []. % The supervisor of the connections socket owning process
+
+print_ch(Pid) ->
+ try
+ {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid),
+ {_LocalRemote,StrM} = ssh_connection_handler:get_print_info(ConnManager),
+ io_lib:format(?INDENT?INDENT?INDENT"ch ~p ~p: ~s ~s~n",[ChannelID, Pid, StrM, Str])
+ catch
+ C:E ->
+ io_lib:format('****print_ch FAILED for ChanPid ~p: ~p:~p~n',[Pid, C, E])
+ end.
+
+
%%%================================================================
-define(inc(N), (N+4)).
-walk_sups(D, StartPid) ->
- io__format(D, "Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]),
- walk_sups(D, children(StartPid), _Indent=?inc(0)).
-
-walk_sups(D, [H={_,Pid,_,_}|T], Indent) ->
- indent(D, Indent), io__format(D, '~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]),
- case H of
- {_,_,supervisor,[ssh_connection_handler]} -> ok;
- {_,Pid,supervisor,_} -> walk_sups(D, children(Pid), ?inc(Indent));
- _ -> ok
- end,
- walk_sups(D, T, Indent);
-walk_sups(_D, [], _) ->
- ok.
+walk_sups(StartPid) ->
+ io_lib:format("Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]),
+ walk_sups(children(StartPid), _Indent=?inc(0)).
+
+walk_sups([H={_,Pid,_,_}|T], Indent) ->
+ [indent(Indent),
+ io_lib:format('~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]),
+ case H of
+ {_,_,supervisor,[ssh_connection_handler]} -> "";
+ {_,Pid,supervisor,_} -> walk_sups(children(Pid), ?inc(Indent));
+ _ -> ""
+ end,
+ walk_sups(T, Indent)
+ ];
+walk_sups([], _) ->
+ "".
dead_or_alive(Name) when is_atom(Name) ->
case whereis(Name) of
- undefined ->
+ undefined ->
"**UNDEFINED**";
- Pid ->
+ Pid ->
dead_or_alive(Pid)
end;
dead_or_alive(Pid) when is_pid(Pid) ->
@@ -167,7 +201,8 @@ dead_or_alive(Pid) when is_pid(Pid) ->
_ -> "alive"
end.
-indent(D, I) -> io__format(D,'~*c',[I,$ ]).
+indent(I) -> io_lib:format('~*c',[I,$ ]).
+
children(Pid) ->
Parent = self(),
@@ -178,20 +213,39 @@ children(Pid) ->
{Helper,L} when is_list(L) ->
L
after
- 2000 ->
+ 2000 ->
catch exit(Helper, kill),
[]
end.
+is_connection_handler(Pid) ->
+ try
+ {ssh_connection_handler,init,_} =
+ proplists:get_value(
+ '$initial_call',
+ proplists:get_value(
+ dictionary,
+ process_info(Pid, [dictionary])))
+ of
+ _ -> true
+
+ catch
+ _:_ ->
+ false
+ end.
+
+channels(Pid) ->
+ case is_connection_handler(Pid) of
+ true ->
+ ssh_connection_handler:info(Pid,all);
+ false ->
+ false
+ end.
+
%%%================================================================
-underline(D, Str, LineChar) ->
- Len = lists:flatlength(Str),
- io__format(D, '~s~n',[Str]),
- line(D,Len,LineChar).
+underline(Str, LineChar) ->
+ io_lib:format('~s~n~*c~n',[Str, lists:flatlength(Str), LineChar]).
-line(D, Len, Char) ->
- io__format(D, '~*c~n', [Len,Char]).
-
datetime() ->
{{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(erlang:timestamp()),
@@ -202,28 +256,9 @@ fmt_host_port({{A,B,C,D},Port}) -> io_lib:format('~p.~p.~p.~p:~p',[A,B,C,D,Port]
fmt_host_port({Host,Port}) -> io_lib:format('~s:~p',[Host,Port]).
%%%################################################################
-
-io__nl(D) when is_atom(D) -> io:nl(D);
-io__nl(P) when is_pid(P) -> P ! {string,io_lib:nl()}.
-
-io__format(D, Fmt, Args) when is_atom(D) -> io:format(D, Fmt, Args);
-io__format(P, Fmt, Args) when is_pid(P) -> P ! {string,io_lib:format(Fmt, Args)}.
-
-
-init() -> loop([]).
-
-loop(Acc) ->
- receive
- {string,Str} ->
- loop([Str|Acc]);
- {get,Who} ->
- Who ! {result,lists:flatten(lists:reverse(Acc))}
- end.
-
-%%%################################################################
collect_pids() -> collect_pids(ssh_sup).
-collect_pids(P) ->
+collect_pids(P) ->
Collector = pcollect_pids(P, spawn(fun init_collector/0)),
Collector ! {get_values,self()},
receive
@@ -231,7 +266,7 @@ collect_pids(P) ->
Values
end.
-%%%----------------
+%%%----------------
pcollect_pids(undefined, Collector) ->
Collector;
@@ -249,17 +284,43 @@ pcollect_pids(Pid, Collector) when is_pid(Pid) ->
end),
Collector;
-pcollect_pids({_,Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+pcollect_pids({Ref,Pid,supervisor,_}, Collector) when is_pid(Pid),
+ is_reference(Ref) ->
pcollect_pids(Pid, Collector);
-pcollect_pids({_,Pid,worker,_}, Collector) when is_pid(Pid) ->
+pcollect_pids({sshc_sup,Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+ pcollect_pids(Pid, Collector);
+
+pcollect_pids({sshd_sup,Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+ pcollect_pids(Pid, Collector);
+
+pcollect_pids({{ssh_acceptor_sup,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+ pcollect_pids(Pid, Collector);
+
+pcollect_pids({{server,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+ pcollect_pids(Pid, Collector);
+
+pcollect_pids({{server,_,_,_,_},Pid,supervisor,_}, Collector) when is_pid(Pid) ->
+ pcollect_pids(Pid, Collector);
+
+pcollect_pids({undefined,Pid,supervisor,[ssh_connection_handler]}, Collector) ->
+ Collector ! {value,Pid,Pid},
+ case channels(Pid) of
+ {ok,L} ->
+ [Collector!{value,P,P} || #channel{user=P} <- L];
+ _ ->
+ ok
+ end,
+ Collector;
+
+pcollect_pids({_,Pid,_,_}, Collector) when is_pid(Pid) ->
Collector ! {value,Pid,Pid},
Collector;
pcollect_pids(_, Collector) ->
Collector.
-%%%----------------
+%%%----------------
init_collector() ->
loop_collector([],[]).
@@ -273,6 +334,3 @@ loop_collector(Expects, Values) ->
%% Values=/=[] ->
From ! {values,Values}
end.
-
-
-
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 256c8c8da3..2dc228a3cf 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -28,7 +28,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 50000).
+-define(TIMEOUT, 10000).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -192,7 +192,7 @@ simple_exec_groups_no_match_too_large(Config) ->
%%--------------------------------------------------------------------
%% Testing all default groups
-simple_exec_groups() -> [{timetrap,{seconds,90}}].
+simple_exec_groups() -> [{timetrap,{seconds,180}}].
simple_exec_groups(Config) ->
Sizes = interpolate( public_key:dh_gex_group_sizes() ),
@@ -221,8 +221,6 @@ interpolate(Is) ->
%%--------------------------------------------------------------------
%% Use the ssh client of the OS to connect
-sshc_simple_exec() -> [{timetrap,{seconds,90}}].
-
sshc_simple_exec(Config) ->
PrivDir = ?config(priv_dir, Config),
KnownHosts = filename:join(PrivDir, "known_hosts"),
@@ -233,12 +231,21 @@ sshc_simple_exec(Config) ->
ct:log("~p",[Cmd]),
SshPort = open_port({spawn, Cmd}, [binary]),
Expect = <<"2\n">>,
+ rcv_expected(SshPort, Expect).
+
+
+rcv_expected(SshPort, Expect) ->
receive
{SshPort, {data,Expect}} ->
ct:log("Got expected ~p from ~p",[Expect,SshPort]),
catch port_close(SshPort),
- ok
+ ok;
+ Other ->
+ ct:log("Got UNEXPECTED ~p",[Other]),
+ rcv_expected(SshPort, Expect)
+
after ?TIMEOUT ->
+ catch port_close(SshPort),
ct:fail("Did not receive answer")
end.
diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl
index 96c9aad135..8b6273c3fe 100644
--- a/lib/ssh/test/ssh_echo_server.erl
+++ b/lib/ssh/test/ssh_echo_server.erl
@@ -31,6 +31,7 @@
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
init([N]) ->
+ ct:pal("Echo server: ~p",[self()]),
{ok, #state{n = N}}.
handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index a76d46ee9b..82bede69d0 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -48,7 +48,7 @@
<item><p><c>true | false</c></p></item>
<tag><c>option() =</c></tag>
- <item><p><c>socketoption() | ssloption() | transportoption()</c></p>
+ <item><p><c>socketoption() | ssl_option() | transport_option()</c></p>
</item>
<tag><c>socketoption() =</c></tag>
@@ -60,7 +60,7 @@
<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> manual pages
in Kernel.</p></item>
- <tag><marker id="type-ssloption"/><c>ssloption() =</c></tag>
+ <tag><marker id="type-ssloption"/><c>ssl_option() =</c></tag>
<item>
<p><c>{verify, verify_type()}</c></p>
<p><c>| {verify_fun, {fun(), term()}}</c></p>
@@ -85,11 +85,11 @@
[binary()]} | {client | server, [binary()], binary()}}</c></p>
<p><c>| {log_alert, boolean()}</c></p>
<p><c>| {server_name_indication, hostname() | disable}</c></p>
- <p><c>| {sni_hosts, [{hostname(), ssloptions()}]}</c></p>
+ <p><c>| {sni_hosts, [{hostname(), [ssl_option()]}]}</c></p>
<p><c>| {sni_fun, SNIfun::fun()}</c></p>
</item>
- <tag><c>transportoption() =</c></tag>
+ <tag><c>transport_option() =</c></tag>
<item><p><c>{cb_info, {CallbackModule::atom(), DataTag::atom(),
ClosedTag::atom(), ErrTag:atom()}}</c></p>
@@ -168,7 +168,7 @@
| srp_4096 | srp_6144 | srp_8192</c></p></item>
<tag><c>SNIfun::fun()</c></tag>
- <item><p><c>= fun(ServerName :: string()) -> ssloptions()</c></p></item>
+ <item><p><c>= fun(ServerName :: string()) -> [ssl_option()]</c></p></item>
</taglist>
</section>
@@ -617,7 +617,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
selection. If set to <c>false</c> (the default), use the client
preference.</p></item>
- <tag><c>{sni_hosts, [{hostname(), ssloptions()}]}</c></tag>
+ <tag><c>{sni_hosts, [{hostname(), [ssl_option()]}]}</c></tag>
<item><p>If the server receives a SNI (Server Name Indication) from the client
matching a host listed in the <c>sni_hosts</c> option, the specific options for
that host will override previously specified options.
@@ -626,11 +626,11 @@ fun(srp, Username :: string(), UserState :: term()) ->
<tag><c>{sni_fun, SNIfun::fun()}</c></tag>
<item><p>If the server receives a SNI (Server Name Indication) from the client,
- the given function will be called to retrieve <c>ssloptions()</c> for the indicated server.
- These options will be merged into predefined <c>ssloptions()</c>.
+ the given function will be called to retrieve <c>[ssl_option()]</c> for the indicated server.
+ These options will be merged into predefined <c>[ssl_option()]</c>.
The function should be defined as:
- <c>fun(ServerName :: string()) -> ssloptions()</c>
+ <c>fun(ServerName :: string()) -> [ssl_option()]</c>
and can be specified as a fun or as named <c>fun module:function/1</c>
The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p></item>
@@ -710,7 +710,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
equivalent, connected socket to an SSL socket.</fsummary>
<type>
<v>Socket = socket()</v>
- <v>SslOptions = [ssloption()]</v>
+ <v>SslOptions = [ssl_option()]</v>
<v>Timeout = integer() | infinity</v>
<v>SslSocket = sslsocket()</v>
<v>Reason = term()</v>
@@ -1023,7 +1023,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<fsummary>Performs server-side SSL/TLS handshake.</fsummary>
<type>
<v>Socket = socket() | sslsocket() </v>
- <v>SslOptions = ssloptions()</v>
+ <v>SslOptions = [ssl_option()]</v>
<v>Timeout = integer()</v>
<v>Reason = term()</v>
</type>
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 847a9f19de..f2cf99e8a8 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -4096,7 +4096,7 @@ connection_information_result(Socket) ->
{ok, Info = [_ | _]} = ssl:connection_information(Socket),
case length(Info) > 3 of
true ->
- %% Atleast one ssloption() is set
+ %% Atleast one ssl_option() is set
ct:log("Info ~p", [Info]),
ok;
false ->