-
Callback timeouts
The timeout values that can be returned by the callback functions
have the same semantics as in a gen_server.
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index bcd13213b3..a2cefe7c15 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -59,7 +59,7 @@ MODULES= \
ssh_shell \
ssh_system_sup \
ssh_subsystem_sup \
- ssh_channel_sup \
+ ssh_daemon_channel_sup \
ssh_acceptor_sup \
ssh_acceptor \
ssh_app \
@@ -169,7 +169,7 @@ $(EBIN)/ssh_connection_handler.$(EMULATOR): ssh_connection_handler.erl ssh.hrl \
$(EBIN)/ssh_shell.$(EMULATOR): ssh_shell.erl ssh_connect.hrl
$(EBIN)/ssh_system_sup.$(EMULATOR): ssh_system_sup.erl ssh.hrl
$(EBIN)/ssh_subsystem_sup.$(EMULATOR): ssh_subsystem_sup.erl
-$(EBIN)/ssh_channel_sup.$(EMULATOR): ssh_channel_sup.erl
+$(EBIN)/ssh_daemon_channel_sup.$(EMULATOR): ssh_daemon_channel_sup.erl
$(EBIN)/ssh_acceptor_sup.$(EMULATOR): ssh_acceptor_sup.erl ssh.hrl
$(EBIN)/ssh_acceptor.$(EMULATOR): ssh_acceptor.erl ssh.hrl
$(EBIN)/ssh_app.$(EMULATOR): ssh_app.erl
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 4a22322333..b935ea94d5 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -14,7 +14,7 @@
ssh_cli,
ssh_client_key_api,
ssh_channel,
- ssh_channel_sup,
+ ssh_daemon_channel_sup,
ssh_connection,
ssh_connection_handler,
ssh_connection_sup,
diff --git a/lib/ssh/src/ssh_channel_sup.erl b/lib/ssh/src/ssh_channel_sup.erl
deleted file mode 100644
index 7a12f34049..0000000000
--- a/lib/ssh/src/ssh_channel_sup.erl
+++ /dev/null
@@ -1,62 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-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%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Ssh channel supervisor.
-%%----------------------------------------------------------------------
--module(ssh_channel_sup).
-
--behaviour(supervisor).
-
--export([start_link/1, start_child/5]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% Internal API
-%%%=========================================================================
-start_link(Args) ->
- supervisor:start_link(?MODULE, [Args]).
-
-start_child(Sup, Callback, Id, Args, Exec) ->
- ChildSpec =
- #{id => make_ref(),
- start => {ssh_channel, start_link, [self(), Id, Callback, Args, Exec]},
- restart => temporary,
- type => worker,
- modules => [ssh_channel]
- },
- supervisor:start_child(Sup, ChildSpec).
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
-init(_Args) ->
- RestartStrategy = one_for_one,
- MaxR = 10,
- MaxT = 3600,
- Children = [],
- {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
-
-%%%=========================================================================
-%%% Internal functions
-%%%=========================================================================
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index 382de90ae1..31f6194bf9 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -30,7 +30,7 @@
-include("ssh.hrl").
-include("ssh_connect.hrl").
-%% ssh_channel callbacks
+%% ssh_daemon_channel callbacks
-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]).
-export([dbg_trace/3]).
@@ -47,7 +47,7 @@
}).
%%====================================================================
-%% ssh_channel callbacks
+%% ssh_daemon_channel callbacks
%%====================================================================
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 2261d37d6a..0a07ea778d 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -822,14 +822,14 @@ start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) ->
ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup),
case max_num_channels_not_exceeded(ChannelSup, Opts) of
true ->
- ssh_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec);
+ ssh_daemon_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec);
false ->
throw(max_num_channels_exceeded)
end.
max_num_channels_not_exceeded(ChannelSup, Opts) ->
MaxNumChannels = ?GET_OPT(max_channels, Opts),
- NumChannels = length([x || {_,_,worker,[ssh_channel]} <-
+ NumChannels = length([x || {_,_,worker,[ssh_daemon_channel]} <-
supervisor:which_children(ChannelSup)]),
%% Note that NumChannels is BEFORE starting a new one
NumChannels < MaxNumChannels.
diff --git a/lib/ssh/src/ssh_daemon_channel.erl b/lib/ssh/src/ssh_daemon_channel.erl
index 72853f2d6a..e1d6906bbc 100644
--- a/lib/ssh/src/ssh_daemon_channel.erl
+++ b/lib/ssh/src/ssh_daemon_channel.erl
@@ -25,7 +25,7 @@
-module(ssh_daemon_channel).
-%% API to special server side channel that can be pluged into the erlang ssh daemeon
+%% API to server side channel that can be pluged into the erlang ssh daemeon
-callback init(Args :: term()) ->
{ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
{stop, Reason :: term()} | ignore.
@@ -42,29 +42,14 @@
{stop, ChannelId::ssh:channel_id(),
State::term()}.
-%%% API
--export([start/4, start/5, start_link/4, start_link/5, enter_loop/1]).
-
-%% gen_server callbacks
--export([init/1, terminate/2]).
-
--spec start(ssh:connection_ref(), ssh:channel_id(), atom(), term()) -> term().
-start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
-
-start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
-
-start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+%%% Internal API
+-export([start_link/5,
+ get_print_info/1
+ ]).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
-enter_loop(State) ->
- ssh_channel:enter_loop(State).
-init(Args) ->
- ssh_channel:init(Args).
-terminate(Reason, State) ->
- ssh_channel:terminate(Reason, State).
+get_print_info(Pid) ->
+ ssh_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_daemon_channel_sup.erl b/lib/ssh/src/ssh_daemon_channel_sup.erl
new file mode 100644
index 0000000000..cd86347501
--- /dev/null
+++ b/lib/ssh/src/ssh_daemon_channel_sup.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Ssh channel supervisor.
+%%----------------------------------------------------------------------
+-module(ssh_daemon_channel_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/5]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% Internal API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+start_child(Sup, Callback, Id, Args, Exec) ->
+ ChildSpec =
+ #{id => make_ref(),
+ start => {ssh_daemon_channel, start_link, [self(), Id, Callback, Args, Exec]},
+ restart => temporary,
+ type => worker,
+ modules => [ssh_daemon_channel]
+ },
+ supervisor:start_child(Sup, ChildSpec).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_Args) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index d464def6fa..e1613f0599 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -140,15 +140,15 @@ print_system_sup({{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, superv
-print_channels({{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) ->
+print_channels({{server,ssh_daemon_channel_sup,_,_},Pid,supervisor,[ssh_daemon_channel_sup]}) when is_pid(Pid) ->
Children = supervisor:which_children(Pid),
- ChannelPids = [P || {R,P,worker,[ssh_channel]} <- Children,
+ ChannelPids = [P || {R,P,worker,[ssh_daemon_channel]} <- Children,
is_pid(P),
is_reference(R)],
case ChannelPids of
[] -> io_lib:format(?INDENT?INDENT"No channels~n",[]);
[Ch1Pid|_] ->
- {{ConnManager,_}, _Str} = ssh_channel:get_print_info(Ch1Pid),
+ {{ConnManager,_}, _Str} = ssh_daemon_channel:get_print_info(Ch1Pid),
{{_,Remote},_} = ssh_connection_handler:get_print_info(ConnManager),
[io_lib:format(?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]),
lists:map(fun print_ch/1, ChannelPids)
@@ -159,7 +159,7 @@ print_channels({{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_s
print_ch(Pid) ->
try
- {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid),
+ {{ConnManager,ChannelID}, Str} = ssh_daemon_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
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
index c7c63c5c43..6470f4c492 100644
--- a/lib/ssh/src/ssh_shell.erl
+++ b/lib/ssh/src/ssh_shell.erl
@@ -29,7 +29,7 @@
%%% channel inspite of it being a client.
-behaviour(ssh_daemon_channel).
-%% ssh_channel callbacks
+%% ssh_daemon_channel callbacks
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
%% Spawn export
@@ -46,7 +46,7 @@
).
%%====================================================================
-%% ssh_channel callbacks
+%% ssh_daemon_channel callbacks
%%====================================================================
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
index 77da240a66..f1e74a24ac 100644
--- a/lib/ssh/src/ssh_subsystem_sup.erl
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -48,7 +48,7 @@ connection_supervisor(SupPid) ->
channel_supervisor(SupPid) ->
Children = supervisor:which_children(SupPid),
- ssh_channel_sup(Children).
+ ssh_daemon_channel_sup(Children).
%%%=========================================================================
%%% Supervisor callback
@@ -78,8 +78,8 @@ ssh_connection_child_spec(Role, Address, Port, _Profile, Options) ->
}.
ssh_channel_child_spec(Role, Address, Port, _Profile, Options) ->
- #{id => id(Role, ssh_channel_sup, Address, Port),
- start => {ssh_channel_sup, start_link, [Options]},
+ #{id => id(Role, ssh_daemon_channel_sup, Address, Port),
+ start => {ssh_daemon_channel_sup, start_link, [Options]},
restart => temporary,
type => supervisor
}.
@@ -92,10 +92,10 @@ ssh_connection_sup([{_, Child, _, [ssh_connection_sup]} | _]) ->
ssh_connection_sup([_ | Rest]) ->
ssh_connection_sup(Rest).
-ssh_channel_sup([{_, Child, _, [ssh_channel_sup]} | _]) ->
+ssh_daemon_channel_sup([{_, Child, _, [ssh_daemon_channel_sup]} | _]) ->
Child;
-ssh_channel_sup([_ | Rest]) ->
- ssh_channel_sup(Rest).
+ssh_daemon_channel_sup([_ | Rest]) ->
+ ssh_daemon_channel_sup(Rest).
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index 4e7169d927..ed1840640b 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -290,7 +290,7 @@ shell_channel_tree(Config) ->
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
ok = ssh_connection:shell(ConnectionRef,ChannelId0),
- ?wait_match([{_, GroupPid,worker,[ssh_channel]}],
+ ?wait_match([{_, GroupPid,worker,[ssh_daemon_channel]}],
supervisor:which_children(ChannelSup),
[GroupPid]),
{links,GroupLinks} = erlang:process_info(GroupPid, links),
@@ -339,9 +339,9 @@ chk_empty_con_daemon(Daemon) ->
?wait_match([{{server,ssh_connection_sup, _,_},
ConnectionSup, supervisor,
[ssh_connection_sup]},
- {{server,ssh_channel_sup,_ ,_},
+ {{server,ssh_daemon_channel_sup,_ ,_},
ChannelSup,supervisor,
- [ssh_channel_sup]}],
+ [ssh_daemon_channel_sup]}],
supervisor:which_children(SubSysSup),
[ConnectionSup,ChannelSup]),
?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}],
@@ -372,9 +372,9 @@ check_sshd_system_tree(Daemon, Config) ->
?wait_match([{{server,ssh_connection_sup, _,_},
ConnectionSup, supervisor,
[ssh_connection_sup]},
- {{server,ssh_channel_sup,_ ,_},
+ {{server,ssh_daemon_channel_sup,_ ,_},
ChannelSup,supervisor,
- [ssh_channel_sup]}],
+ [ssh_daemon_channel_sup]}],
supervisor:which_children(SubSysSup),
[ConnectionSup,ChannelSup]),
@@ -388,7 +388,7 @@ check_sshd_system_tree(Daemon, Config) ->
ssh_sftp:start_channel(Client),
- ?wait_match([{_, _,worker,[ssh_channel]}],
+ ?wait_match([{_, _,worker,[ssh_daemon_channel]}],
supervisor:which_children(ChannelSup)),
ssh:close(Client).
--
cgit v1.2.3
From d2f4de0a8e36e6a25cfd7446ea6fc3623b7f1495 Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Thu, 26 Apr 2018 11:50:11 +0200
Subject: ssh: ssh_daemon_channel replaced by ssh_server_channel
---
lib/ssh/doc/src/Makefile | 15 ++-
lib/ssh/doc/src/ref_man.xml | 3 +-
lib/ssh/doc/src/specs.xml | 7 +-
lib/ssh/doc/src/ssh.xml | 6 +-
lib/ssh/doc/src/ssh_channel.xml | 5 +-
lib/ssh/doc/src/ssh_daemon_channel.xml | 127 +------------------
lib/ssh/doc/src/ssh_protocol.xml | 2 +-
lib/ssh/doc/src/ssh_server_channel.xml | 176 ++++++++++++++++++++++++++
lib/ssh/doc/src/ssh_sftpd.xml | 2 +-
lib/ssh/doc/src/using_ssh.xml | 2 +-
lib/ssh/src/Makefile | 42 +++---
lib/ssh/src/ssh.app.src | 3 +-
lib/ssh/src/ssh_cli.erl | 6 +-
lib/ssh/src/ssh_connection.erl | 4 +-
lib/ssh/src/ssh_daemon_channel.erl | 4 +-
lib/ssh/src/ssh_daemon_channel_sup.erl | 62 ---------
lib/ssh/src/ssh_info.erl | 8 +-
lib/ssh/src/ssh_server_channel.erl | 55 ++++++++
lib/ssh/src/ssh_server_channel_sup.erl | 62 +++++++++
lib/ssh/src/ssh_sftpd.erl | 2 +-
lib/ssh/src/ssh_shell.erl | 6 +-
lib/ssh/src/ssh_subsystem_sup.erl | 12 +-
lib/ssh/test/property_test/ssh_eqc_subsys.erl | 2 +-
lib/ssh/test/ssh_bench_dev_null.erl | 2 +-
lib/ssh/test/ssh_echo_server.erl | 2 +-
lib/ssh/test/ssh_peername_sockname_server.erl | 2 +-
lib/ssh/test/ssh_sup_SUITE.erl | 12 +-
27 files changed, 377 insertions(+), 254 deletions(-)
create mode 100644 lib/ssh/doc/src/ssh_server_channel.xml
delete mode 100644 lib/ssh/src/ssh_daemon_channel_sup.erl
create mode 100644 lib/ssh/src/ssh_server_channel.erl
create mode 100644 lib/ssh/src/ssh_server_channel_sup.erl
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index f47a1bfb40..9b5bee34fa 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -38,20 +38,23 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = ssh.xml \
+XML_REF3_FILES = \
+ ssh.xml \
ssh_channel.xml \
- ssh_daemon_channel.xml \
- ssh_connection.xml \
ssh_client_key_api.xml \
+ ssh_connection.xml \
+ ssh_daemon_channel.xml \
+ ssh_server_channel.xml \
ssh_server_key_api.xml \
ssh_sftp.xml \
ssh_sftpd.xml \
XML_REF6_FILES = ssh_app.xml
-XML_PART_FILES = \
- usersguide.xml
-XML_CHAPTER_FILES = notes.xml \
+XML_PART_FILES = usersguide.xml
+
+XML_CHAPTER_FILES = \
+ notes.xml \
introduction.xml \
using_ssh.xml \
configure_algos.xml
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
index 1e1cff9119..3351699c66 100644
--- a/lib/ssh/doc/src/ref_man.xml
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -36,7 +36,8 @@
-
+
+
diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml
index f7837f9c5c..15e76cb5fa 100644
--- a/lib/ssh/doc/src/specs.xml
+++ b/lib/ssh/doc/src/specs.xml
@@ -1,13 +1,14 @@
+
-
+
+
-
-
+
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index c403989ba9..da122b6081 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -68,8 +68,8 @@
ssh_sftp:start_channel/1,2,3.
To write your own client channel handler, use the behaviour
- ssh_channel. and server channel handlers use
- ssh_daemon_channel behaviour.
+ ssh_channel. For server channel handlers use
+ ssh_server_channel behaviour (replaces ssh_daemon_channel).
Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both.
The three sets are called
@@ -379,7 +379,7 @@
ssh_connection:subsystem/4.
The channel_callback is the module that implements the
- ssh_daemon_channel
+ ssh_server_channel (replaces ssh_daemon_channel)
behaviour in the daemon. See the section
Creating a Subsystem
in the User's Guide for more information and an example.
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml
index b4bcd148f3..63a480d747 100644
--- a/lib/ssh/doc/src/ssh_channel.xml
+++ b/lib/ssh/doc/src/ssh_channel.xml
@@ -47,7 +47,8 @@
When implementing a ssh subsystem for daemons, use
- -behaviour(ssh_daemon_channel) instead.
+ -behaviour(ssh_server_channel) (Replaces ssh_daemon_channel)
+ instead.
@@ -223,7 +224,7 @@
Callback Functions
The following functions are to be exported from a
- ssh_daemon_channel callback module.
+ ssh_channel callback module.
diff --git a/lib/ssh/doc/src/ssh_daemon_channel.xml b/lib/ssh/doc/src/ssh_daemon_channel.xml
index 8b0ff93f5f..254f75a4de 100644
--- a/lib/ssh/doc/src/ssh_daemon_channel.xml
+++ b/lib/ssh/doc/src/ssh_daemon_channel.xml
@@ -33,137 +33,20 @@
-behaviour(ssh_daemon_channel).
- SSH services (clients and servers) are implemented as channels
- that are multiplexed over an SSH connection and communicates over
- the SSH
- Connection Protocol. This module provides a callback API
- that takes care of generic channel aspects for daemons, such as flow control
- and close messages. It lets the callback functions take care of
- the service (application) specific parts. This behavior also ensures
- that the channel process honors the principal of an OTP-process so
- that it can be part of a supervisor tree. This is a requirement of
- channel processes implementing a subsystem that will be added to
- the ssh applications supervisor tree.
+
This behaviour should NOT be used for new programs but is kept for compatibility.
-
- When implementing a client subsystem handler, use
- -behaviour(ssh_channel) instead.
-
-
-
+ It is replaced by ssh_server_channel.
-
- Callback Functions
-
- The following functions are to be exported from a
- ssh_daemon_channel callback module.
-
-
-
- Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
- {stop, Reason}
- Makes necessary initializations and returns the
- initial channel state if the initializations succeed.
-
- Args = term()
- Last argument to start_link/4.
- State = term()
- Reason = term()
-
-
- Makes necessary initializations and returns the initial channel
- state if the initializations succeed.
-
- The time-out values that can be returned
- have the same semantics as in a gen_server.
- If the time-out occurs, handle_msg/2
- is called as handle_msg(timeout, State).
-
-
-
-
-
- Module:handle_msg(Msg, State) -> {ok, State} |
- {stop, ChannelId, State}
-
- Handles other messages than SSH connection protocol,
- call, or cast messages sent to the channel.
-
- Msg = timeout | term()
- ChannelId = ssh:channel_id()
- State = term()
-
-
- Handles other messages than SSH Connection Protocol, call, or
- cast messages sent to the channel.
-
-
- Possible Erlang 'EXIT' messages is to be handled by this
- function and all channels are to handle the following message.
-
-
- {ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}
- This is the first message that the channel receives.
- This is especially useful if the
- server wants to send a message to the client without first
- receiving a message from it. If the message is not
- useful for your particular scenario, ignore it by
- immediately returning {ok, State}.
-
-
-
-
-
-
- Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
- ChannelId, State}
- Handles ssh connection protocol messages.
-
- Msg = ssh_connection:event()
- ChannelId = ssh:channel_id()
- State = term()
-
-
- Handles SSH Connection Protocol messages that may need
- service-specific attention. For details,
- see ssh_connection:event().
-
-
- The following message is taken care of by the
- ssh_daemon_channel behavior.
-
-
- {closed, ssh:channel_id()}
- The channel behavior sends a close message to the
- other side, if such a message has not already been sent.
- Then it terminates the channel with reason normal.
-
-
-
-
-
- Module:terminate(Reason, State) -> _
- Does cleaning up before channel process termination.
-
-
- Reason = term()
- State = term()
-
+ Module:CALLBACK(..)
+ ssh_daemon_channel is replaced by ssh_server_channel
- This function is called by a channel process when it is
- about to terminate. Before this function is called, ssh_connection:close/2
- is called, if it has not been called earlier.
- This function does any necessary cleaning
- up. When it returns, the channel process terminates with
- reason Reason. The return value is ignored.
+
See ssh_server_channel which replaces this module.
-
diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml
index 21c755b48e..4548d7bbb6 100644
--- a/lib/ssh/doc/src/ssh_protocol.xml
+++ b/lib/ssh/doc/src/ssh_protocol.xml
@@ -89,7 +89,7 @@
data/"control information" and when it is done close the
channel. The
ssh_channel /
- ssh_daemon_channel
+ ssh_server_channel (Replaces ssh_daemon_channel)
behaviours makes it easy to
write your own SSH client/server processes that use flow
control. It handles generic parts of SSH channel management and
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
new file mode 100644
index 0000000000..19fc20fcda
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+ 2009
+ 2016
+ Ericsson AB, 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.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+
+ ssh_server_channel
+
+
+
+
+
+ ssh_server_channel
+ -behaviour(ssh_server_channel). (Replaces ssh_daemon_channel)
+
+
+
+ This module replaces ssh_daemon_channel.
+ The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+
+
+
+ SSH services (clients and servers) are implemented as channels
+ that are multiplexed over an SSH connection and communicates over
+ the SSH
+ Connection Protocol. This module provides a callback API
+ that takes care of generic channel aspects for daemons, such as flow control
+ and close messages. It lets the callback functions take care of
+ the service (application) specific parts. This behavior also ensures
+ that the channel process honors the principal of an OTP-process so
+ that it can be part of a supervisor tree. This is a requirement of
+ channel processes implementing a subsystem that will be added to
+ the ssh applications supervisor tree.
+
+
+ When implementing a client subsystem handler, use
+ -behaviour(ssh_channel) instead.
+
+
+
+
+
+
+ Callback Functions
+
+ The following functions are to be exported from a
+ ssh_server_channel callback module.
+
+
+
+
+
+ Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ {stop, Reason}
+ Makes necessary initializations and returns the
+ initial channel state if the initializations succeed.
+
+ Args = term()
+ Last argument to start_link/4.
+ State = term()
+ Reason = term()
+
+
+ Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+
+ The time-out values that can be returned
+ have the same semantics as in a gen_server.
+ If the time-out occurs, handle_msg/2
+ is called as handle_msg(timeout, State).
+
+
+
+
+
+ Module:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}
+
+ Handles other messages than SSH connection protocol,
+ call, or cast messages sent to the channel.
+
+ Msg = timeout | term()
+ ChannelId = ssh:channel_id()
+ State = term()
+
+
+ Handles other messages than SSH Connection Protocol, call, or
+ cast messages sent to the channel.
+
+
+ Possible Erlang 'EXIT' messages is to be handled by this
+ function and all channels are to handle the following message.
+
+
+ {ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}
+ This is the first message that the channel receives.
+ This is especially useful if the
+ server wants to send a message to the client without first
+ receiving a message from it. If the message is not
+ useful for your particular scenario, ignore it by
+ immediately returning {ok, State}.
+
+
+
+
+
+
+ Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ChannelId, State}
+ Handles ssh connection protocol messages.
+
+ Msg = ssh_connection:event()
+ ChannelId = ssh:channel_id()
+ State = term()
+
+
+ Handles SSH Connection Protocol messages that may need
+ service-specific attention. For details,
+ see ssh_connection:event().
+
+
+ The following message is taken care of by the
+ ssh_server_channel behavior.
+
+
+ {closed, ssh:channel_id()}
+ The channel behavior sends a close message to the
+ other side, if such a message has not already been sent.
+ Then it terminates the channel with reason normal.
+
+
+
+
+
+ Module:terminate(Reason, State) -> _
+ Does cleaning up before channel process termination.
+
+
+ Reason = term()
+ State = term()
+
+
+ This function is called by a channel process when it is
+ about to terminate. Before this function is called, ssh_connection:close/2
+ is called, if it has not been called earlier.
+ This function does any necessary cleaning
+ up. When it returns, the channel process terminates with
+ reason Reason. The return value is ignored.
+
+
+
+
+
+
+
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index 4c599a7fb9..a25ce123b3 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -44,7 +44,7 @@
"sftp"
channel_callback() =
atom() - Name of the Erlang module implementing the subsystem using the
- ssh_daemon_channel behaviour.
+ ssh_server_channel (replaces ssh_daemon_channel) behaviour.
channel_init_args() =
list() - The one given as argument to function subsystem_spec/1.
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index bde2aaaf99..fef0784eb6 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -306,7 +306,7 @@ ok = erl_tar:close(HandleRead),
-module(ssh_echo_server).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel). % replaces ssh_daemon_channel
-record(state, {
n,
id,
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index a2cefe7c15..1665e8b554 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -40,42 +40,43 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Behaviour (api) modules are first so they are compiled when
# the compiler reaches a callback module using them.
BEHAVIOUR_MODULES= \
- ssh_sftpd_file_api \
- ssh_channel \
- ssh_daemon_channel \
ssh_client_key_api \
- ssh_server_key_api
+ ssh_daemon_channel \
+ ssh_server_channel \
+ ssh_server_key_api \
+ ssh_sftpd_file_api \
+ ssh_channel
MODULES= \
ssh \
- ssh_sup \
- sshc_sup \
- sshd_sup \
- ssh_options \
- ssh_connection_sup \
- ssh_connection \
- ssh_connection_handler \
- ssh_dbg \
- ssh_shell \
- ssh_system_sup \
- ssh_subsystem_sup \
- ssh_daemon_channel_sup \
- ssh_acceptor_sup \
ssh_acceptor \
+ ssh_acceptor_sup \
ssh_app \
ssh_auth\
ssh_bits \
ssh_cli \
+ ssh_connection \
+ ssh_connection_handler \
+ ssh_connection_sup \
+ ssh_dbg \
ssh_file \
- ssh_io \
ssh_info \
+ ssh_io \
ssh_message \
ssh_no_io \
+ ssh_options \
+ ssh_server_channel_sup \
ssh_sftp \
ssh_sftpd \
ssh_sftpd_file\
+ ssh_shell \
+ ssh_subsystem_sup \
+ ssh_sup \
+ ssh_system_sup \
ssh_transport \
- ssh_xfer
+ ssh_xfer \
+ sshc_sup \
+ sshd_sup
HRL_FILES =
@@ -169,7 +170,7 @@ $(EBIN)/ssh_connection_handler.$(EMULATOR): ssh_connection_handler.erl ssh.hrl \
$(EBIN)/ssh_shell.$(EMULATOR): ssh_shell.erl ssh_connect.hrl
$(EBIN)/ssh_system_sup.$(EMULATOR): ssh_system_sup.erl ssh.hrl
$(EBIN)/ssh_subsystem_sup.$(EMULATOR): ssh_subsystem_sup.erl
-$(EBIN)/ssh_daemon_channel_sup.$(EMULATOR): ssh_daemon_channel_sup.erl
+$(EBIN)/ssh_server_channel_sup.$(EMULATOR): ssh_server_channel_sup.erl
$(EBIN)/ssh_acceptor_sup.$(EMULATOR): ssh_acceptor_sup.erl ssh.hrl
$(EBIN)/ssh_acceptor.$(EMULATOR): ssh_acceptor.erl ssh.hrl
$(EBIN)/ssh_app.$(EMULATOR): ssh_app.erl
@@ -210,6 +211,7 @@ $(EBIN)/ssh_xfer.$(EMULATOR): ssh_xfer.erl ssh.hrl ssh_xfer.hrl
$(EBIN)/ssh_sftpd_file_api.$(EMULATOR): ssh_sftpd_file_api.erl
$(EBIN)/ssh_channel.$(EMULATOR): ssh_channel.erl ssh_connect.hrl
$(EBIN)/ssh_daemon_channel.$(EMULATOR): ssh_daemon_channel.erl
+$(EBIN)/ssh_server_channel.$(EMULATOR): ssh_server_channel.erl
$(EBIN)/ssh_client_key_api.$(EMULATOR): ssh_client_key_api.erl \
../../public_key/include/public_key.hrl \
../../public_key/include/OTP-PUB-KEY.hrl \
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index b935ea94d5..897235e054 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -14,7 +14,6 @@
ssh_cli,
ssh_client_key_api,
ssh_channel,
- ssh_daemon_channel_sup,
ssh_connection,
ssh_connection_handler,
ssh_connection_sup,
@@ -27,6 +26,8 @@
ssh_io,
ssh_info,
ssh_no_io,
+ ssh_server_channel,
+ ssh_server_channel_sup,
ssh_server_key_api,
ssh_sftp,
ssh_sftpd,
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index 31f6194bf9..fcc1d3d59f 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -25,12 +25,12 @@
-module(ssh_cli).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-include("ssh.hrl").
-include("ssh_connect.hrl").
-%% ssh_daemon_channel callbacks
+%% ssh_server_channel callbacks
-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]).
-export([dbg_trace/3]).
@@ -47,7 +47,7 @@
}).
%%====================================================================
-%% ssh_daemon_channel callbacks
+%% ssh_server_channel callbacks
%%====================================================================
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 0a07ea778d..cff9ec3a61 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -822,14 +822,14 @@ start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) ->
ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup),
case max_num_channels_not_exceeded(ChannelSup, Opts) of
true ->
- ssh_daemon_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec);
+ ssh_server_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec);
false ->
throw(max_num_channels_exceeded)
end.
max_num_channels_not_exceeded(ChannelSup, Opts) ->
MaxNumChannels = ?GET_OPT(max_channels, Opts),
- NumChannels = length([x || {_,_,worker,[ssh_daemon_channel]} <-
+ NumChannels = length([x || {_,_,worker,[ssh_server_channel]} <-
supervisor:which_children(ChannelSup)]),
%% Note that NumChannels is BEFORE starting a new one
NumChannels < MaxNumChannels.
diff --git a/lib/ssh/src/ssh_daemon_channel.erl b/lib/ssh/src/ssh_daemon_channel.erl
index e1d6906bbc..fdb6c10971 100644
--- a/lib/ssh/src/ssh_daemon_channel.erl
+++ b/lib/ssh/src/ssh_daemon_channel.erl
@@ -48,8 +48,8 @@
]).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
+ ssh_server_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
get_print_info(Pid) ->
- ssh_channel:get_print_info(Pid).
+ ssh_server_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_daemon_channel_sup.erl b/lib/ssh/src/ssh_daemon_channel_sup.erl
deleted file mode 100644
index cd86347501..0000000000
--- a/lib/ssh/src/ssh_daemon_channel_sup.erl
+++ /dev/null
@@ -1,62 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-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%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Ssh channel supervisor.
-%%----------------------------------------------------------------------
--module(ssh_daemon_channel_sup).
-
--behaviour(supervisor).
-
--export([start_link/1, start_child/5]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% Internal API
-%%%=========================================================================
-start_link(Args) ->
- supervisor:start_link(?MODULE, [Args]).
-
-start_child(Sup, Callback, Id, Args, Exec) ->
- ChildSpec =
- #{id => make_ref(),
- start => {ssh_daemon_channel, start_link, [self(), Id, Callback, Args, Exec]},
- restart => temporary,
- type => worker,
- modules => [ssh_daemon_channel]
- },
- supervisor:start_child(Sup, ChildSpec).
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
-init(_Args) ->
- RestartStrategy = one_for_one,
- MaxR = 10,
- MaxT = 3600,
- Children = [],
- {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
-
-%%%=========================================================================
-%%% Internal functions
-%%%=========================================================================
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index e1613f0599..ee244f1432 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -140,15 +140,15 @@ print_system_sup({{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, superv
-print_channels({{server,ssh_daemon_channel_sup,_,_},Pid,supervisor,[ssh_daemon_channel_sup]}) when is_pid(Pid) ->
+print_channels({{server,ssh_server_channel_sup,_,_},Pid,supervisor,[ssh_server_channel_sup]}) when is_pid(Pid) ->
Children = supervisor:which_children(Pid),
- ChannelPids = [P || {R,P,worker,[ssh_daemon_channel]} <- Children,
+ ChannelPids = [P || {R,P,worker,[ssh_server_channel]} <- Children,
is_pid(P),
is_reference(R)],
case ChannelPids of
[] -> io_lib:format(?INDENT?INDENT"No channels~n",[]);
[Ch1Pid|_] ->
- {{ConnManager,_}, _Str} = ssh_daemon_channel:get_print_info(Ch1Pid),
+ {{ConnManager,_}, _Str} = ssh_server_channel:get_print_info(Ch1Pid),
{{_,Remote},_} = ssh_connection_handler:get_print_info(ConnManager),
[io_lib:format(?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]),
lists:map(fun print_ch/1, ChannelPids)
@@ -159,7 +159,7 @@ print_channels({{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_s
print_ch(Pid) ->
try
- {{ConnManager,ChannelID}, Str} = ssh_daemon_channel:get_print_info(Pid),
+ {{ConnManager,ChannelID}, Str} = ssh_server_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
diff --git a/lib/ssh/src/ssh_server_channel.erl b/lib/ssh/src/ssh_server_channel.erl
new file mode 100644
index 0000000000..117b7855e2
--- /dev/null
+++ b/lib/ssh/src/ssh_server_channel.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-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%
+%%
+
+%%
+%% Description: a gen_server implementing a simple
+%% terminal (using the group module) for a CLI
+%% over SSH
+
+-module(ssh_server_channel).
+
+%% API to server side channel that can be pluged into the erlang ssh daemeon
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+
+-callback handle_msg(Msg ::term(), State :: term()) ->
+ {ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
+-callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::ssh:channel_id(),
+ State::term()}.
+
+%%% Internal API
+-export([start_link/5,
+ get_print_info/1
+ ]).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
+
+
+get_print_info(Pid) ->
+ ssh_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_server_channel_sup.erl b/lib/ssh/src/ssh_server_channel_sup.erl
new file mode 100644
index 0000000000..70799db714
--- /dev/null
+++ b/lib/ssh/src/ssh_server_channel_sup.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Ssh channel supervisor.
+%%----------------------------------------------------------------------
+-module(ssh_server_channel_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/5]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% Internal API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+start_child(Sup, Callback, Id, Args, Exec) ->
+ ChildSpec =
+ #{id => make_ref(),
+ start => {ssh_server_channel, start_link, [self(), Id, Callback, Args, Exec]},
+ restart => temporary,
+ type => worker,
+ modules => [ssh_server_channel]
+ },
+ supervisor:start_child(Sup, ChildSpec).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_Args) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index fda9a38a43..cb2eab1fec 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -24,7 +24,7 @@
-module(ssh_sftpd).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-include_lib("kernel/include/file.hrl").
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
index 6470f4c492..084daa6821 100644
--- a/lib/ssh/src/ssh_shell.erl
+++ b/lib/ssh/src/ssh_shell.erl
@@ -27,9 +27,9 @@
%%% As this is an user interactive client it behaves like a daemon
%%% channel inspite of it being a client.
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-%% ssh_daemon_channel callbacks
+%% ssh_server_channel callbacks
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
%% Spawn export
@@ -46,7 +46,7 @@
).
%%====================================================================
-%% ssh_daemon_channel callbacks
+%% ssh_server_channel callbacks
%%====================================================================
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
index f1e74a24ac..f80be7f20b 100644
--- a/lib/ssh/src/ssh_subsystem_sup.erl
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -48,7 +48,7 @@ connection_supervisor(SupPid) ->
channel_supervisor(SupPid) ->
Children = supervisor:which_children(SupPid),
- ssh_daemon_channel_sup(Children).
+ ssh_server_channel_sup(Children).
%%%=========================================================================
%%% Supervisor callback
@@ -78,8 +78,8 @@ ssh_connection_child_spec(Role, Address, Port, _Profile, Options) ->
}.
ssh_channel_child_spec(Role, Address, Port, _Profile, Options) ->
- #{id => id(Role, ssh_daemon_channel_sup, Address, Port),
- start => {ssh_daemon_channel_sup, start_link, [Options]},
+ #{id => id(Role, ssh_server_channel_sup, Address, Port),
+ start => {ssh_server_channel_sup, start_link, [Options]},
restart => temporary,
type => supervisor
}.
@@ -92,10 +92,10 @@ ssh_connection_sup([{_, Child, _, [ssh_connection_sup]} | _]) ->
ssh_connection_sup([_ | Rest]) ->
ssh_connection_sup(Rest).
-ssh_daemon_channel_sup([{_, Child, _, [ssh_daemon_channel_sup]} | _]) ->
+ssh_server_channel_sup([{_, Child, _, [ssh_server_channel_sup]} | _]) ->
Child;
-ssh_daemon_channel_sup([_ | Rest]) ->
- ssh_daemon_channel_sup(Rest).
+ssh_server_channel_sup([_ | Rest]) ->
+ ssh_server_channel_sup(Rest).
diff --git a/lib/ssh/test/property_test/ssh_eqc_subsys.erl b/lib/ssh/test/property_test/ssh_eqc_subsys.erl
index 30b254b9c0..e7de3ea068 100644
--- a/lib/ssh/test/property_test/ssh_eqc_subsys.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_subsys.erl
@@ -21,7 +21,7 @@
-module(ssh_eqc_subsys).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
diff --git a/lib/ssh/test/ssh_bench_dev_null.erl b/lib/ssh/test/ssh_bench_dev_null.erl
index 5166247714..f9da80b6d7 100644
--- a/lib/ssh/test/ssh_bench_dev_null.erl
+++ b/lib/ssh/test/ssh_bench_dev_null.erl
@@ -22,7 +22,7 @@
%%% Description: Example ssh server
-module(ssh_bench_dev_null).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {
cm,
diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl
index 5387d21efd..d03fe9543e 100644
--- a/lib/ssh/test/ssh_echo_server.erl
+++ b/lib/ssh/test/ssh_echo_server.erl
@@ -22,7 +22,7 @@
%%% Description: Example ssh server
-module(ssh_echo_server).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {
n,
id,
diff --git a/lib/ssh/test/ssh_peername_sockname_server.erl b/lib/ssh/test/ssh_peername_sockname_server.erl
index 8731d80f62..5e35fd6612 100644
--- a/lib/ssh/test/ssh_peername_sockname_server.erl
+++ b/lib/ssh/test/ssh_peername_sockname_server.erl
@@ -26,7 +26,7 @@
%% ssh connection.
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {}).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index ed1840640b..b81f66948d 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -290,7 +290,7 @@ shell_channel_tree(Config) ->
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
ok = ssh_connection:shell(ConnectionRef,ChannelId0),
- ?wait_match([{_, GroupPid,worker,[ssh_daemon_channel]}],
+ ?wait_match([{_, GroupPid,worker,[ssh_server_channel]}],
supervisor:which_children(ChannelSup),
[GroupPid]),
{links,GroupLinks} = erlang:process_info(GroupPid, links),
@@ -339,9 +339,9 @@ chk_empty_con_daemon(Daemon) ->
?wait_match([{{server,ssh_connection_sup, _,_},
ConnectionSup, supervisor,
[ssh_connection_sup]},
- {{server,ssh_daemon_channel_sup,_ ,_},
+ {{server,ssh_server_channel_sup,_ ,_},
ChannelSup,supervisor,
- [ssh_daemon_channel_sup]}],
+ [ssh_server_channel_sup]}],
supervisor:which_children(SubSysSup),
[ConnectionSup,ChannelSup]),
?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}],
@@ -372,9 +372,9 @@ check_sshd_system_tree(Daemon, Config) ->
?wait_match([{{server,ssh_connection_sup, _,_},
ConnectionSup, supervisor,
[ssh_connection_sup]},
- {{server,ssh_daemon_channel_sup,_ ,_},
+ {{server,ssh_server_channel_sup,_ ,_},
ChannelSup,supervisor,
- [ssh_daemon_channel_sup]}],
+ [ssh_server_channel_sup]}],
supervisor:which_children(SubSysSup),
[ConnectionSup,ChannelSup]),
@@ -388,7 +388,7 @@ check_sshd_system_tree(Daemon, Config) ->
ssh_sftp:start_channel(Client),
- ?wait_match([{_, _,worker,[ssh_daemon_channel]}],
+ ?wait_match([{_, _,worker,[ssh_server_channel]}],
supervisor:which_children(ChannelSup)),
ssh:close(Client).
--
cgit v1.2.3
From c2ca477c85e0e88732f634ddfb01ac675a97dddb Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Thu, 26 Apr 2018 13:43:45 +0200
Subject: ssh: ssh_channel replaced by ssh_client_channel
---
lib/ssh/doc/src/Makefile | 3 +-
lib/ssh/doc/src/introduction.xml | 2 +-
lib/ssh/doc/src/ref_man.xml | 3 +-
lib/ssh/doc/src/specs.xml | 3 +-
lib/ssh/doc/src/ssh.xml | 2 +-
lib/ssh/doc/src/ssh_channel.xml | 434 -------------------------------
lib/ssh/doc/src/ssh_client_channel.xml | 440 +++++++++++++++++++++++++++++++
lib/ssh/doc/src/ssh_connection.xml | 16 +-
lib/ssh/doc/src/ssh_daemon_channel.xml | 52 ----
lib/ssh/doc/src/ssh_protocol.xml | 2 +-
lib/ssh/doc/src/ssh_server_channel.xml | 2 +-
lib/ssh/doc/src/using_ssh.xml | 2 +-
lib/ssh/src/Makefile | 4 +-
lib/ssh/src/ssh.app.src | 1 +
lib/ssh/src/ssh.erl | 4 +-
lib/ssh/src/ssh_channel.erl | 382 +--------------------------
lib/ssh/src/ssh_client_channel.erl | 456 +++++++++++++++++++++++++++++++++
lib/ssh/src/ssh_connection.erl | 46 ++--
lib/ssh/src/ssh_connection_handler.erl | 44 ++--
lib/ssh/src/ssh_server_channel.erl | 4 +-
lib/ssh/src/ssh_sftp.erl | 18 +-
21 files changed, 983 insertions(+), 937 deletions(-)
delete mode 100644 lib/ssh/doc/src/ssh_channel.xml
create mode 100644 lib/ssh/doc/src/ssh_client_channel.xml
delete mode 100644 lib/ssh/doc/src/ssh_daemon_channel.xml
create mode 100644 lib/ssh/src/ssh_client_channel.erl
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index 9b5bee34fa..7c4dbd7af8 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -40,10 +40,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = \
ssh.xml \
- ssh_channel.xml \
+ ssh_client_channel.xml \
ssh_client_key_api.xml \
ssh_connection.xml \
- ssh_daemon_channel.xml \
ssh_server_channel.xml \
ssh_server_key_api.xml \
ssh_sftp.xml \
diff --git a/lib/ssh/doc/src/introduction.xml b/lib/ssh/doc/src/introduction.xml
index b7a73e2597..6fd8425adf 100644
--- a/lib/ssh/doc/src/introduction.xml
+++ b/lib/ssh/doc/src/introduction.xml
@@ -145,7 +145,7 @@
data that can be sent to the channel peer without adjusting the
window. Typically, an SSH client opens a channel, sends data (commands),
receives data (control information), and then closes the channel.
- The ssh_channel behaviour
+ The ssh_client_channel behaviour
handles generic parts of SSH channel management. This makes it easy
to write your own SSH client/server processes that use flow-control
and thus opens for more focus on the application logic.
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
index 3351699c66..76e6520f94 100644
--- a/lib/ssh/doc/src/ref_man.xml
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -35,9 +35,8 @@
-
+
-
diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml
index 15e76cb5fa..acdbe2ddfd 100644
--- a/lib/ssh/doc/src/specs.xml
+++ b/lib/ssh/doc/src/specs.xml
@@ -1,10 +1,9 @@
-
+
-
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index da122b6081..0223831cb1 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -68,7 +68,7 @@
ssh_sftp:start_channel/1,2,3.
To write your own client channel handler, use the behaviour
- ssh_channel. For server channel handlers use
+ ssh_client_channel. For server channel handlers use
ssh_server_channel behaviour (replaces ssh_daemon_channel).
Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both.
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml
deleted file mode 100644
index 63a480d747..0000000000
--- a/lib/ssh/doc/src/ssh_channel.xml
+++ /dev/null
@@ -1,434 +0,0 @@
-
-
-
-
-
-
- 2009
- 2016
- Ericsson AB, 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
-
- ssh_channel
-
-
-
-
-
- ssh_channel
- -behaviour(ssh_channel).
-
-
- SSH services (clients and servers) are implemented as channels
- that are multiplexed over an SSH connection and communicates over
- the SSH
- Connection Protocol. This module provides a callback API
- that takes care of generic channel aspects for clients, such as flow control
- and close messages. It lets the callback functions take care of
- the service (application) specific parts. This behavior also ensures
- that the channel process honors the principal of an OTP-process so
- that it can be part of a supervisor tree. This is a requirement of
- channel processes implementing a subsystem that will be added to
- the ssh applications supervisor tree.
-
-
- When implementing a ssh subsystem for daemons, use
- -behaviour(ssh_server_channel) (Replaces ssh_daemon_channel)
- instead.
-
-
-
-
- Functions in this module are not supposed to be called outside a module implementing this
- behaviour!
-
-
-
-
-
-
-
- call(ChannelRef, Msg) ->
- call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}
- Makes a synchronous call to a channel.
-
- ChannelRef = pid()
- As returned by start_link/4
- Msg = term()
- Timeout = timeout()
- Reply = term()
- Reason = closed | timeout
-
-
-
- Makes a synchronous call to the channel process by sending
- a message and waiting until a reply arrives, or a time-out
- occurs. The channel calls Module:handle_call/3
- to handle the message. If the channel process does not exist,
- {error, closed} is returned.
-
-
-
-
-
- cast(ChannelRef, Msg) -> ok
- Sends an asynchronous message to the channel
- ChannelRef and returns ok.
-
- ChannelRef = pid()
- As returned by start_link/4
- Msg = term()
-
-
- Sends an asynchronous message to the channel process and
- returns ok immediately, ignoring if the destination node or
- channel process does not exist. The channel calls
- Module:handle_cast/2
- to handle the message.
-
-
-
-
-
- enter_loop(State) -> _
- Makes an existing process an ssh_channel process.
-
- State = term()
- as returned by init/1
-
-
- Makes an existing process an ssh_channel
- process. Does not return, instead the calling process
- enters the ssh_channel process receive loop and become an
- ssh_channel process. The process must have been started using
- one of the start functions in proc_lib, see the proc_lib(3) manual page in STDLIB.
- The user is responsible for any initialization of the process
- and must call init/1.
-
-
-
-
-
- init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason}
- Initiates an ssh_channel process.
-
- Options = [{Option, Value}]
- State = term()
- Timeout = timeout()
- Reason = term()
-
-
-
- The following options must be present:
-
-
- {channel_cb, atom()}
- The module that implements the channel behaviour.
-
- {init_args(), list()}
- The list of arguments to the init function of the callback module.
-
- {cm, ssh:connection_ref()}
- Reference to the ssh connection as returned by
- ssh:connect/3.
-
-
- {channel_id, ssh:channel_id()}
- Id of the ssh channel as returned by
- ssh_connection:session_channel/2,4.
-
-
-
-
- This function is normally not called by the
- user. The user only needs to call if the
- channel process needs to be started with help of
- proc_lib instead of calling
- start/4 or
- start_link/4.
-
-
-
-
-
- reply(Client, Reply) -> _
- Sends a reply to a client.
-
- Client = opaque()
- Reply = term()
-
-
- This function can be used by a channel to send a
- reply to a client that called call/[2,3] when the reply
- cannot be defined in the return value of
- Module:handle_call/3.
- Client must be the From argument provided to
- the callback function handle_call/3.
- Reply is an arbitrary term,
- which is given back to the client as the return value of
- call/[2,3].
-
-
-
-
- start(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
- start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
- {ok, ChannelRef} | {error, Reason}
- Starts a process that handles an SSH channel.
-
- SshConnection = ssh:connection_ref()
- As returned by ssh:connect/3
-
- ChannelId = ssh:channel_id()
- As returned by
-
- ssh_connection:session_channel/[2,4].
-
- ChannelCb = atom()
- Name of the module implementing the service-specific parts
- of the channel.
-
- CbInitArgs = [term()]
- Argument list for the init function in the callback module.
-
- ChannelRef = pid()
-
-
- Starts a process that handles an SSH channel. It is
- called internally, by the ssh daemon, or explicitly by the ssh
- client implementations. The behavior sets the
- trap_exit flag to true.
-
-
-
-
-
-
-
- Callback Functions
-
- The following functions are to be exported from a
- ssh_channel callback module.
-
-
-
- Callback timeouts
- The timeout values that can be returned by the callback functions
- have the same semantics as in a gen_server.
- If the time-out occurs, handle_msg/2
- is called as handle_msg(timeout, State).
-
-
-
-
-
- Module:code_change(OldVsn, State, Extra) -> {ok,
- NewState}
- Converts process state when code is changed.
-
- OldVsn = term()
- In the case of an upgrade, OldVsn is Vsn, and
- in the case of a downgrade, OldVsn is
- {down,Vsn}. Vsn is defined by the vsn
- attribute(s) of the old version of the callback module
- Module. If no such attribute is defined, the version is
- the checksum of the BEAM file.
- State = term()
- Internal state of the channel.
- Extra = term()
- Passed "as-is" from the {advanced,Extra}
- part of the update instruction.
-
-
- Converts process state when code is changed.
-
- This function is called by a client-side channel when it
- is to update its internal state during a release
- upgrade or downgrade, that is, when the instruction
- {update,Module,Change,...}, where
- Change={advanced,Extra}, is given in the appup
- file. For more information, refer to Section 9.11.6
- Release Handling Instructions in the
- System Documentation.
-
-
- Soft upgrade according to the OTP release concept
- is not straight forward for the server side, as subsystem
- channel processes are spawned by the ssh application and
- hence added to its supervisor tree. The subsystem channels can
- be upgraded when upgrading the user application, if the callback
- functions can handle two versions of the state, but this function
- cannot be used in the normal way.
-
-
-
-
-
-
- Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
- {stop, Reason}
- Makes necessary initializations and returns the
- initial channel state if the initializations succeed.
-
- Args = term()
- Last argument to start_link/4.
- State = term()
- Reason = term()
-
-
- Makes necessary initializations and returns the initial channel
- state if the initializations succeed.
-
- For more detailed information on time-outs, see Section
- Callback timeouts.
-
-
-
-
- Module:handle_call(Msg, From, State) -> Result
- Handles messages sent by calling
- call/[2,3].
-
- Msg = term()
- From = opaque()
- Is to be used as argument to
- reply/2
- State = term()
- Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()}
- | {noreply, NewState} | {noreply , NewState, timeout()}
- | {stop, Reason, Reply, NewState} | {stop, Reason, NewState}
- Reply = term()
- Will be the return value of call/[2,3]
- NewState = term()
- Reason = term()
-
-
- Handles messages sent by calling
- call/[2,3]
-
- For more detailed information on time-outs,, see Section
- Callback timeouts.
-
-
-
-
- Module:handle_cast(Msg, State) -> Result
- Handles messages sent by calling
- cast/2.
-
- Msg = term()
- State = term()
- Result = {noreply, NewState} | {noreply, NewState, timeout()}
- | {stop, Reason, NewState}
- NewState = term()
- Reason = term()
-
-
- Handles messages sent by calling
- cast/2.
-
- For more detailed information on time-outs, see Section
- Callback timeouts.
-
-
-
-
- Module:handle_msg(Msg, State) -> {ok, State} |
- {stop, ChannelId, State}
-
- Handles other messages than SSH connection protocol,
- call, or cast messages sent to the channel.
-
- Msg = timeout | term()
- ChannelId = ssh:channel_id()
- State = term()
-
-
- Handles other messages than SSH Connection Protocol, call, or
- cast messages sent to the channel.
-
-
- Possible Erlang 'EXIT' messages is to be handled by this
- function and all channels are to handle the following message.
-
-
- {ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}
- This is the first message that the channel receives.
- It is sent just before the init/1 function
- returns successfully. This is especially useful if the
- server wants to send a message to the client without first
- receiving a message from it. If the message is not
- useful for your particular scenario, ignore it by
- immediately returning {ok, State}.
-
-
-
-
-
-
- Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
- ChannelId, State}
- Handles ssh connection protocol messages.
-
- Msg = ssh_connection:event()
- ChannelId = ssh:channel_id()
- State = term()
-
-
- Handles SSH Connection Protocol messages that may need
- service-specific attention. For details,
- see ssh_connection:event().
-
-
- The following message is taken care of by the
- ssh_channel behavior.
-
-
- {closed, ssh:channel_id()}
- The channel behavior sends a close message to the
- other side, if such a message has not already been sent.
- Then it terminates the channel with reason normal.
-
-
-
-
-
- Module:terminate(Reason, State) -> _
- Does cleaning up before channel process termination.
-
-
- Reason = term()
- State = term()
-
-
- This function is called by a channel process when it is
- about to terminate. Before this function is called, ssh_connection:close/2
- is called, if it has not been called earlier.
- This function does any necessary cleaning
- up. When it returns, the channel process terminates with
- reason Reason. The return value is ignored.
-
-
-
-
-
-
-
diff --git a/lib/ssh/doc/src/ssh_client_channel.xml b/lib/ssh/doc/src/ssh_client_channel.xml
new file mode 100644
index 0000000000..eed49beffa
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_client_channel.xml
@@ -0,0 +1,440 @@
+
+
+
+
+
+
+ 2009
+ 2016
+ Ericsson AB, 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.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+
+ ssh_client_channel
+
+
+
+
+
+ ssh_client_channel
+ -behaviour(ssh_client_channel). (Replaces ssh_channel)
+
+
+
+ This module replaces ssh_channel.
+ The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+
+
+ SSH services (clients and servers) are implemented as channels
+ that are multiplexed over an SSH connection and communicates over
+ the SSH
+ Connection Protocol. This module provides a callback API
+ that takes care of generic channel aspects for clients, such as flow control
+ and close messages. It lets the callback functions take care of
+ the service (application) specific parts. This behavior also ensures
+ that the channel process honors the principal of an OTP-process so
+ that it can be part of a supervisor tree. This is a requirement of
+ channel processes implementing a subsystem that will be added to
+ the ssh applications supervisor tree.
+
+
+ When implementing a ssh subsystem for daemons, use
+ -behaviour(ssh_server_channel) (Replaces ssh_daemon_channel)
+ instead.
+
+
+
+
+ Functions in this module are not supposed to be called outside a module implementing this
+ behaviour!
+
+
+
+
+
+
+
+ call(ChannelRef, Msg) ->
+ call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}
+ Makes a synchronous call to a channel.
+
+ ChannelRef = pid()
+ As returned by start_link/4
+ Msg = term()
+ Timeout = timeout()
+ Reply = term()
+ Reason = closed | timeout
+
+
+
+ Makes a synchronous call to the channel process by sending
+ a message and waiting until a reply arrives, or a time-out
+ occurs. The channel calls Module:handle_call/3
+ to handle the message. If the channel process does not exist,
+ {error, closed} is returned.
+
+
+
+
+
+ cast(ChannelRef, Msg) -> ok
+ Sends an asynchronous message to the channel
+ ChannelRef and returns ok.
+
+ ChannelRef = pid()
+ As returned by start_link/4
+ Msg = term()
+
+
+ Sends an asynchronous message to the channel process and
+ returns ok immediately, ignoring if the destination node or
+ channel process does not exist. The channel calls
+ Module:handle_cast/2
+ to handle the message.
+
+
+
+
+
+ enter_loop(State) -> _
+ Makes an existing process an ssh_client_channel (replaces ssh_channel) process.
+
+ State = term()
+ as returned by init/1
+
+
+ Makes an existing process an ssh_client_channel (replaces ssh_channel)
+ process. Does not return, instead the calling process
+ enters the ssh_client_channel (replaces ssh_channel) process receive loop and become an
+ ssh_client_channel process. The process must have been started using
+ one of the start functions in proc_lib, see the proc_lib(3) manual page in STDLIB.
+ The user is responsible for any initialization of the process
+ and must call init/1.
+
+
+
+
+
+ init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason}
+ Initiates an ssh_client_channel process.
+
+ Options = [{Option, Value}]
+ State = term()
+ Timeout = timeout()
+ Reason = term()
+
+
+
+ The following options must be present:
+
+
+ {channel_cb, atom()}
+ The module that implements the channel behaviour.
+
+ {init_args(), list()}
+ The list of arguments to the init function of the callback module.
+
+ {cm, ssh:connection_ref()}
+ Reference to the ssh connection as returned by
+ ssh:connect/3.
+
+
+ {channel_id, ssh:channel_id()}
+ Id of the ssh channel as returned by
+ ssh_connection:session_channel/2,4.
+
+
+
+
+ This function is normally not called by the
+ user. The user only needs to call if the
+ channel process needs to be started with help of
+ proc_lib instead of calling
+ start/4 or
+ start_link/4.
+
+
+
+
+
+ reply(Client, Reply) -> _
+ Sends a reply to a client.
+
+ Client = opaque()
+ Reply = term()
+
+
+ This function can be used by a channel to send a
+ reply to a client that called call/[2,3] when the reply
+ cannot be defined in the return value of
+ Module:handle_call/3.
+ Client must be the From argument provided to
+ the callback function handle_call/3.
+ Reply is an arbitrary term,
+ which is given back to the client as the return value of
+ call/[2,3].
+
+
+
+
+ start(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ {ok, ChannelRef} | {error, Reason}
+ Starts a process that handles an SSH channel.
+
+ SshConnection = ssh:connection_ref()
+ As returned by ssh:connect/3
+
+ ChannelId = ssh:channel_id()
+ As returned by
+
+ ssh_connection:session_channel/[2,4].
+
+ ChannelCb = atom()
+ Name of the module implementing the service-specific parts
+ of the channel.
+
+ CbInitArgs = [term()]
+ Argument list for the init function in the callback module.
+
+ ChannelRef = pid()
+
+
+ Starts a process that handles an SSH channel. It is
+ called internally, by the ssh daemon, or explicitly by the ssh
+ client implementations. The behavior sets the
+ trap_exit flag to true.
+
+
+
+
+
+
+
+ Callback Functions
+
+ The following functions are to be exported from a
+ ssh_client_channel callback module.
+
+
+
+ Callback timeouts
+ The timeout values that can be returned by the callback functions
+ have the same semantics as in a gen_server.
+ If the time-out occurs, handle_msg/2
+ is called as handle_msg(timeout, State).
+
+
+
+
+
+ Module:code_change(OldVsn, State, Extra) -> {ok,
+ NewState}
+ Converts process state when code is changed.
+
+ OldVsn = term()
+ In the case of an upgrade, OldVsn is Vsn, and
+ in the case of a downgrade, OldVsn is
+ {down,Vsn}. Vsn is defined by the vsn
+ attribute(s) of the old version of the callback module
+ Module. If no such attribute is defined, the version is
+ the checksum of the BEAM file.
+ State = term()
+ Internal state of the channel.
+ Extra = term()
+ Passed "as-is" from the {advanced,Extra}
+ part of the update instruction.
+
+
+ Converts process state when code is changed.
+
+ This function is called by a client-side channel when it
+ is to update its internal state during a release
+ upgrade or downgrade, that is, when the instruction
+ {update,Module,Change,...}, where
+ Change={advanced,Extra}, is given in the appup
+ file. For more information, refer to Section 9.11.6
+ Release Handling Instructions in the
+ System Documentation.
+
+
+ Soft upgrade according to the OTP release concept
+ is not straight forward for the server side, as subsystem
+ channel processes are spawned by the ssh application and
+ hence added to its supervisor tree. The subsystem channels can
+ be upgraded when upgrading the user application, if the callback
+ functions can handle two versions of the state, but this function
+ cannot be used in the normal way.
+
+
+
+
+
+
+ Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ {stop, Reason}
+ Makes necessary initializations and returns the
+ initial channel state if the initializations succeed.
+
+ Args = term()
+ Last argument to start_link/4.
+ State = term()
+ Reason = term()
+
+
+ Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+
+ For more detailed information on time-outs, see Section
+ Callback timeouts.
+
+
+
+
+ Module:handle_call(Msg, From, State) -> Result
+ Handles messages sent by calling
+ call/[2,3].
+
+ Msg = term()
+ From = opaque()
+ Is to be used as argument to
+ reply/2
+ State = term()
+ Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()}
+ | {noreply, NewState} | {noreply , NewState, timeout()}
+ | {stop, Reason, Reply, NewState} | {stop, Reason, NewState}
+ Reply = term()
+ Will be the return value of call/[2,3]
+ NewState = term()
+ Reason = term()
+
+
+ Handles messages sent by calling
+ call/[2,3]
+
+ For more detailed information on time-outs,, see Section
+ Callback timeouts.
+
+
+
+
+ Module:handle_cast(Msg, State) -> Result
+ Handles messages sent by calling
+ cast/2.
+
+ Msg = term()
+ State = term()
+ Result = {noreply, NewState} | {noreply, NewState, timeout()}
+ | {stop, Reason, NewState}
+ NewState = term()
+ Reason = term()
+
+
+ Handles messages sent by calling
+ cast/2.
+
+ For more detailed information on time-outs, see Section
+ Callback timeouts.
+
+
+
+
+ Module:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}
+
+ Handles other messages than SSH connection protocol,
+ call, or cast messages sent to the channel.
+
+ Msg = timeout | term()
+ ChannelId = ssh:channel_id()
+ State = term()
+
+
+ Handles other messages than SSH Connection Protocol, call, or
+ cast messages sent to the channel.
+
+
+ Possible Erlang 'EXIT' messages is to be handled by this
+ function and all channels are to handle the following message.
+
+
+ {ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}
+ This is the first message that the channel receives.
+ It is sent just before the init/1 function
+ returns successfully. This is especially useful if the
+ server wants to send a message to the client without first
+ receiving a message from it. If the message is not
+ useful for your particular scenario, ignore it by
+ immediately returning {ok, State}.
+
+
+
+
+
+
+ Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ChannelId, State}
+ Handles ssh connection protocol messages.
+
+ Msg = ssh_connection:event()
+ ChannelId = ssh:channel_id()
+ State = term()
+
+
+ Handles SSH Connection Protocol messages that may need
+ service-specific attention. For details,
+ see ssh_connection:event().
+
+
+ The following message is taken care of by the
+ ssh_client_channel behavior.
+
+
+ {closed, ssh:channel_id()}
+ The channel behavior sends a close message to the
+ other side, if such a message has not already been sent.
+ Then it terminates the channel with reason normal.
+
+
+
+
+
+ Module:terminate(Reason, State) -> _
+ Does cleaning up before channel process termination.
+
+
+ Reason = term()
+ State = term()
+
+
+ This function is called by a channel process when it is
+ about to terminate. Before this function is called, ssh_connection:close/2
+ is called, if it has not been called earlier.
+ This function does any necessary cleaning
+ up. When it returns, the channel process terminates with
+ reason Reason. The return value is ignored.
+
+
+
+
+
+
+
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index cfe5385eb4..821dfef93d 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -44,9 +44,9 @@
If the receiving channel is an Erlang process, the
messages have the format
.
- If the ssh_channel behavior is used to
+ If the ssh_client_channel behavior is used to
implement the channel process, these messages are handled by
- handle_ssh_msg/2.
+ handle_ssh_msg/2.
@@ -131,7 +131,7 @@
This event is sent as a result of calling
ssh_connection:close/2.
Both the handling of this event and sending it are taken care of by the
- ssh_channel behavior.
+ ssh_client_channel behavior.
@@ -212,10 +212,10 @@
Adjusts the SSH flow control window. This is to be done by both the
client- and server-side channel processes.
- Channels implemented with the ssh_channel
+ Channels implemented with the ssh_client_channel
behavior do not normally need to call this function as flow control
is handled by the behavior. The behavior adjusts the window every time
- the callback
+ the callback
handle_ssh_msg/2 returns after processing channel data.
@@ -232,9 +232,9 @@
sending a close event.
- This function is called by the ssh_channel
+ This function is called by the ssh_client_channel
behavior when the channel is terminated, see ssh_channel(3). Thus, channels implemented
+ marker="ssh_client_channel"> ssh_client_channel(3). Thus, channels implemented
with the behavior are not to call this function explicitly.
@@ -277,7 +277,7 @@
1 x {ssh_cm, connection_ref(),
{closed, channel_id()}}
- Indicates that the ssh_channel started for the
+ Indicates that the ssh_client_channel started for the
execution of the command has now been shut down.
diff --git a/lib/ssh/doc/src/ssh_daemon_channel.xml b/lib/ssh/doc/src/ssh_daemon_channel.xml
deleted file mode 100644
index 254f75a4de..0000000000
--- a/lib/ssh/doc/src/ssh_daemon_channel.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
- 2009
- 2016
- Ericsson AB, 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.
-
- The Initial Developer of the Original Code is Ericsson AB.
-
- ssh_daemon_channel
-
-
-
-
-
- ssh_daemon_channel
- -behaviour(ssh_daemon_channel).
-
-
- This behaviour should NOT be used for new programs but is kept for compatibility.
-
- It is replaced by ssh_server_channel.
-
-
-
-
- Module:CALLBACK(..)
- ssh_daemon_channel is replaced by ssh_server_channel
-
- See ssh_server_channel which replaces this module.
-
-
-
-
-
-
diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml
index 4548d7bbb6..53f0524b97 100644
--- a/lib/ssh/doc/src/ssh_protocol.xml
+++ b/lib/ssh/doc/src/ssh_protocol.xml
@@ -88,7 +88,7 @@
SSH client will open a channel, send data/commands, receive
data/"control information" and when it is done close the
channel. The
- ssh_channel /
+ ssh_client_channel /
ssh_server_channel (Replaces ssh_daemon_channel)
behaviours makes it easy to
write your own SSH client/server processes that use flow
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
index 19fc20fcda..af51ec470b 100644
--- a/lib/ssh/doc/src/ssh_server_channel.xml
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -54,7 +54,7 @@
When implementing a client subsystem handler, use
- -behaviour(ssh_channel) instead.
+ -behaviour(ssh_client_channel) instead.
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index fef0784eb6..efd2a997f5 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -384,7 +384,7 @@ terminate(_Reason, _State) ->
{ssh_msg, <0.57.0>, {closed, 0}}
7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).
-See also ssh_channel(3).
+See also ssh_client_channel(3) (replaces ssh_channel(3)).
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 1665e8b554..5e4efb6b99 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -45,7 +45,8 @@ BEHAVIOUR_MODULES= \
ssh_server_channel \
ssh_server_key_api \
ssh_sftpd_file_api \
- ssh_channel
+ ssh_channel \
+ ssh_client_channel
MODULES= \
ssh \
@@ -209,6 +210,7 @@ $(EBIN)/ssh_transport.$(EMULATOR): ssh_transport.erl \
ssh_transport.hrl ssh.hrl
$(EBIN)/ssh_xfer.$(EMULATOR): ssh_xfer.erl ssh.hrl ssh_xfer.hrl
$(EBIN)/ssh_sftpd_file_api.$(EMULATOR): ssh_sftpd_file_api.erl
+$(EBIN)/ssh_client_channel.$(EMULATOR): ssh_client_channel.erl ssh_connect.hrl
$(EBIN)/ssh_channel.$(EMULATOR): ssh_channel.erl ssh_connect.hrl
$(EBIN)/ssh_daemon_channel.$(EMULATOR): ssh_daemon_channel.erl
$(EBIN)/ssh_server_channel.$(EMULATOR): ssh_server_channel.erl
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 897235e054..410061cded 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -12,6 +12,7 @@
ssh_message,
ssh_bits,
ssh_cli,
+ ssh_client_channel,
ssh_client_key_api,
ssh_channel,
ssh_connection,
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 209f53d249..7ddb1ca5be 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -426,9 +426,9 @@ start_shell({ok, ConnectionRef}) ->
Args = [{channel_cb, ssh_shell},
{init_args,[ConnectionRef, ChannelId]},
{cm, ConnectionRef}, {channel_id, ChannelId}],
- {ok, State} = ssh_channel:init([Args]),
+ {ok, State} = ssh_client_channel:init([Args]),
try
- ssh_channel:enter_loop(State)
+ ssh_client_channel:enter_loop(State)
catch
exit:normal ->
ok
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index 359e29fdbe..81c495a815 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -56,401 +56,37 @@
State::term()) -> {ok, State::term()} |
{stop, ChannelId::ssh:channel_id(),
State::term()}.
--behaviour(gen_server).
-
%%% API
-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
cast/2, reply/2, enter_loop/1]).
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
-%% Internal application API
--export([cache_create/0, cache_lookup/2, cache_update/2,
- cache_delete/1, cache_delete/2, cache_foldl/3,
- cache_info/2, cache_find/2,
- get_print_info/1]).
-
--export([dbg_trace/3]).
-
--record(state, {
- cm,
- channel_cb,
- channel_state,
- channel_id,
- close_sent = false
- }).
-
%%====================================================================
%% API
%%====================================================================
call(ChannelPid, Msg) ->
- call(ChannelPid, Msg, infinity).
+ ssh_client_channel:call(ChannelPid, Msg).
call(ChannelPid, Msg, TimeOute) ->
- try gen_server:call(ChannelPid, Msg, TimeOute) of
- Result ->
- Result
- catch
- exit:{noproc, _} ->
- {error, closed};
- exit:{normal, _} ->
- {error, closed};
- exit:{shutdown, _} ->
- {error, closed};
- exit:{{shutdown, _}, _} ->
- {error, closed};
- exit:{timeout, _} ->
- {error, timeout}
- end.
+ ssh_client_channel:call(ChannelPid, Msg, TimeOute).
cast(ChannelPid, Msg) ->
- gen_server:cast(ChannelPid, Msg).
-
+ ssh_client_channel:cast(ChannelPid, Msg).
reply(From, Msg) ->
- gen_server:reply(From, Msg).
+ ssh_client_channel:reply(From, Msg).
-%%====================================================================
-%% Internal application API
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the server
-%%--------------------------------------------------------------------
start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+ ssh_client_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs).
start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- Options = [{channel_cb, CallBack},
- {channel_id, ChannelId},
- {init_args, CbInitArgs},
- {cm, ConnectionManager},
- {exec, Exec}],
- gen_server:start(?MODULE, [Options], []).
+ ssh_client_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- Options = [{channel_cb, CallBack},
- {channel_id, ChannelId},
- {init_args, CbInitArgs},
- {cm, ConnectionManager},
- {exec, Exec}],
- gen_server:start_link(?MODULE, [Options], []).
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
enter_loop(State) ->
- gen_server:enter_loop(?MODULE, [], State).
-
-%%====================================================================
-%% gen_server callbacks
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%--------------------------------------------------------------------
-init([Options]) ->
- Cb = proplists:get_value(channel_cb, Options),
- ConnectionManager = proplists:get_value(cm, Options),
- ChannelId = proplists:get_value(channel_id, Options),
- process_flag(trap_exit, true),
- try Cb:init(channel_cb_init_args(Options)) of
- {ok, ChannelState} ->
- State = #state{cm = ConnectionManager,
- channel_cb = Cb,
- channel_id = ChannelId,
- channel_state = ChannelState},
- self() ! {ssh_channel_up, ChannelId, ConnectionManager},
- {ok, State};
- {ok, ChannelState, Timeout} ->
- State = #state{cm = ConnectionManager,
- channel_cb = Cb,
- channel_id = ChannelId,
- channel_state = ChannelState},
- self() ! {ssh_channel_up, ChannelId, ConnectionManager},
- {ok, State, Timeout};
- {stop, Why} ->
- {stop, Why}
- catch
- _:Reason ->
- {stop, Reason}
- end.
-
-channel_cb_init_args(Options) ->
- case proplists:get_value(exec, Options) of
- undefined ->
- proplists:get_value(init_args, Options);
- Exec ->
- proplists:get_value(init_args, Options) ++ [Exec]
- end.
-
-%%--------------------------------------------------------------------
-%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% {stop, Reason, State}
-%% Description: Handling call messages
-%%--------------------------------------------------------------------
-handle_call(get_print_info, _From, State) ->
- Reply =
- {{State#state.cm,
- State#state.channel_id},
- io_lib:format('CB=~p',[State#state.channel_cb])
- },
- {reply, Reply, State};
-
-handle_call(Request, From, #state{channel_cb = Module,
- channel_state = ChannelState} = State) ->
- try Module:handle_call(Request, From, ChannelState) of
- Result ->
- handle_cb_result(Result, State)
- catch
- error:{undef, _} ->
- {noreply, State}
- end.
-
-
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
-handle_cast(Msg, #state{channel_cb = Module,
- channel_state = ChannelState} = State) ->
-
- try Module:handle_cast(Msg, ChannelState) of
- Result ->
- handle_cb_result(Result, State)
- catch
- error:{undef, _} ->
- {noreply, State}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
-handle_info({ssh_cm, ConnectionManager, {closed, _ChannelId}},
- #state{cm = ConnectionManager,
- close_sent = true} = State) ->
- {stop, normal, State};
-handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
- #state{cm = ConnectionManager,
- close_sent = false} = State) ->
- %% To be on the safe side, i.e. the manager has already been terminated.
- (catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, normal, State#state{close_sent = true}};
-
-handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
- channel_cb = Module,
- channel_state = ChannelState0} = State) ->
- case Module:handle_ssh_msg(Msg, ChannelState0) of
- {ok, ChannelState} ->
- adjust_window(Msg),
- {noreply, State#state{channel_state = ChannelState}};
- {ok, ChannelState, Timeout} ->
- adjust_window(Msg),
- {noreply, State#state{channel_state = ChannelState}, Timeout};
- {stop, ChannelId, ChannelState} ->
- catch ssh_connection:close(ConnectionManager, ChannelId),
- {stop, normal, State#state{close_sent = true,
- channel_state = ChannelState}}
- end;
-
-handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
- channel_state = ChannelState0} = State) ->
- case Module:handle_msg(Msg, ChannelState0) of
- {ok, ChannelState} ->
- {noreply, State#state{channel_state = ChannelState}};
- {ok, ChannelState, Timeout} ->
- {noreply, State#state{channel_state = ChannelState}, Timeout};
- {stop, Reason, ChannelState} when is_atom(Reason)->
- {stop, Reason, State#state{close_sent = true,
- channel_state = ChannelState}};
- {stop, ChannelId, ChannelState} ->
- Reason =
- case Msg of
- {'EXIT', _Pid, shutdown} ->
- shutdown;
- _ ->
- normal
- end,
- (catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, Reason, State#state{close_sent = true,
- channel_state = ChannelState}}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> void()
-%% Description: This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any necessary
-%% cleaning up. When it returns, the gen_server terminates with Reason.
-%% The return value is ignored.
-%%--------------------------------------------------------------------
-terminate(Reason, #state{cm = ConnectionManager,
- channel_id = ChannelId,
- close_sent = false} = State) ->
- catch ssh_connection:close(ConnectionManager, ChannelId),
- terminate(Reason, State#state{close_sent = true});
-terminate(_, #state{channel_cb = Cb, channel_state = ChannelState}) ->
- catch Cb:terminate(Cb, ChannelState),
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
-code_change(OldVsn, #state{channel_cb = Module,
- channel_state = ChannelState0} = State, Extra) ->
- {ok, ChannelState} = Module:code_change(OldVsn, ChannelState0, Extra),
- {ok, State#state{channel_state = ChannelState}}.
-
-%%====================================================================
-%% Internal application API
-%%====================================================================
-cache_create() ->
- ets:new(cm_tab, [set,{keypos, #channel.local_id}]).
-
-cache_lookup(Cache, Key) ->
- case ets:lookup(Cache, Key) of
- [Channel] ->
- Channel;
- [] ->
- undefined
- end.
-
-cache_update(Cache, #channel{local_id = Id} = Entry) when Id =/= undefined ->
- ets:insert(Cache, Entry).
-
-cache_delete(Cache, Key) ->
- ets:delete(Cache, Key).
-
-cache_delete(Cache) ->
- ets:delete(Cache).
-
-cache_foldl(Fun, Acc, Cache) ->
- ets:foldl(Fun, Acc, Cache).
-
-cache_info(num_entries, Cache) ->
- proplists:get_value(size, ets:info(Cache)).
-
-cache_find(ChannelPid, Cache) ->
- case ets:match_object(Cache, #channel{user = ChannelPid}) of
- [] ->
- undefined;
- [Channel] ->
- Channel
- end.
-
-get_print_info(Pid) ->
- call(Pid, get_print_info, 1000).
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-handle_cb_result({reply, Reply, ChannelState}, State) ->
- {reply, Reply, State#state{channel_state = ChannelState}};
-handle_cb_result({reply, Reply, ChannelState, Timeout}, State) ->
- {reply, Reply,State#state{channel_state = ChannelState}, Timeout};
-handle_cb_result({noreply, ChannelState}, State) ->
- {noreply, State#state{channel_state = ChannelState}};
-handle_cb_result({noreply, ChannelState, Timeout}, State) ->
- {noreply, State#state{channel_state = ChannelState}, Timeout};
-handle_cb_result({stop, Reason, Reply, ChannelState}, State) ->
- {stop, Reason, Reply, State#state{channel_state = ChannelState}};
-handle_cb_result({stop, Reason, ChannelState}, State) ->
- {stop, Reason, State#state{channel_state = ChannelState}}.
-
-adjust_window({ssh_cm, ConnectionManager,
- {data, ChannelId, _, Data}}) ->
- ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
-adjust_window(_) ->
- ok.
-
-
-%%%################################################################
-%%%#
-%%%# Tracing
-%%%#
-
-dbg_trace(points, _, _) -> [terminate, channels, channel_events];
-
-
-dbg_trace(flags, channels, A) -> [c] ++ dbg_trace(flags, terminate, A);
-dbg_trace(on, channels, A) -> dbg:tp(?MODULE, init, 1, x),
- dbg_trace(on, terminate, A);
-dbg_trace(off, channels, A) -> dbg:ctpg(?MODULE, init, 1),
- dbg_trace(off, terminate, A);
-dbg_trace(format, channels, {call, {?MODULE,init, [[KVs]]}}) ->
- ["Server Channel Starting:\n",
- io_lib:format("Connection: ~p, ChannelId: ~p, CallBack: ~p\nCallBack init args = ~p",
- [proplists:get_value(K,KVs) || K <- [cm, channel_id, channel_cb]]
- ++ [channel_cb_init_args(KVs)])
- ];
-dbg_trace(format, channels, {return_from, {?MODULE,init,1}, {stop,Reason}}) ->
- ["Server Channel Start FAILED!\n",
- io_lib:format("Reason = ~p", [Reason])
- ];
-dbg_trace(format, channels, F) ->
- dbg_trace(format, terminate, F);
-
-
-dbg_trace(flags, terminate, _) -> [c];
-dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
-dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
-dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
- ["Server Channel Terminating:\n",
- io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
- ];
-
-dbg_trace(flags, channel_events, _) -> [c];
-dbg_trace(on, channel_events, _) -> dbg:tp(?MODULE, handle_call, 3, x),
- dbg:tp(?MODULE, handle_cast, 2, x),
- dbg:tp(?MODULE, handle_info, 2, x);
-dbg_trace(off, channel_events, _) -> dbg:ctpg(?MODULE, handle_call, 3),
- dbg:ctpg(?MODULE, handle_cast, 2),
- dbg:ctpg(?MODULE, handle_info, 2);
-dbg_trace(format, channel_events, {call, {?MODULE,handle_call, [Call,From,State]}}) ->
- [hdr("is called", State),
- io_lib:format("From: ~p~nCall: ~p~n", [From, Call])
- ];
-dbg_trace(format, channel_events, {return_from, {?MODULE,handle_call,3}, Ret}) ->
- ["Server Channel call returned:\n",
- io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
- ];
-dbg_trace(format, channel_events, {call, {?MODULE,handle_cast, [Cast,State]}}) ->
- [hdr("got cast", State),
- io_lib:format("Cast: ~p~n", [Cast])
- ];
-dbg_trace(format, channel_events, {return_from, {?MODULE,handle_cast,2}, Ret}) ->
- ["Server Channel cast returned:\n",
- io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
- ];
-dbg_trace(format, channel_events, {call, {?MODULE,handle_info, [Info,State]}}) ->
- [hdr("got info", State),
- io_lib:format("Info: ~p~n", [Info])
- ];
-dbg_trace(format, channel_events, {return_from, {?MODULE,handle_info,2}, Ret}) ->
- ["Server Channel info returned:\n",
- io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
- ].
-
-hdr(Title, S) ->
- io_lib:format("Server Channel (Id=~p, CB=~p) ~s:\n", [S#state.channel_id, S#state.channel_cb, Title]).
-
-?wr_record(state).
-
-
+ ssh_client_channel:enter_loop(State).
diff --git a/lib/ssh/src/ssh_client_channel.erl b/lib/ssh/src/ssh_client_channel.erl
new file mode 100644
index 0000000000..f20007baaf
--- /dev/null
+++ b/lib/ssh/src/ssh_client_channel.erl
@@ -0,0 +1,456 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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_client_channel).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
+ Extra :: term()) ->
+ {ok, NewState :: term()} | {error, Reason :: term()}.
+
+-callback handle_msg(Msg ::term(), State :: term()) ->
+ {ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
+
+-callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::ssh:channel_id(),
+ State::term()}.
+-behaviour(gen_server).
+
+%%% API
+-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
+ cast/2, reply/2, enter_loop/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%% Internal application API
+-export([cache_create/0, cache_lookup/2, cache_update/2,
+ cache_delete/1, cache_delete/2, cache_foldl/3,
+ cache_info/2, cache_find/2,
+ get_print_info/1]).
+
+-export([dbg_trace/3]).
+
+-record(state, {
+ cm,
+ channel_cb,
+ channel_state,
+ channel_id,
+ close_sent = false
+ }).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+call(ChannelPid, Msg) ->
+ call(ChannelPid, Msg, infinity).
+
+call(ChannelPid, Msg, TimeOute) ->
+ try gen_server:call(ChannelPid, Msg, TimeOute) of
+ Result ->
+ Result
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{shutdown, _} ->
+ {error, closed};
+ exit:{{shutdown, _}, _} ->
+ {error, closed};
+ exit:{timeout, _} ->
+ {error, timeout}
+ end.
+
+cast(ChannelPid, Msg) ->
+ gen_server:cast(ChannelPid, Msg).
+
+
+reply(From, Msg) ->
+ gen_server:reply(From, Msg).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start(?MODULE, [Options], []).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start_link(?MODULE, [Options], []).
+
+enter_loop(State) ->
+ gen_server:enter_loop(?MODULE, [], State).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([Options]) ->
+ Cb = proplists:get_value(channel_cb, Options),
+ ConnectionManager = proplists:get_value(cm, Options),
+ ChannelId = proplists:get_value(channel_id, Options),
+ process_flag(trap_exit, true),
+ try Cb:init(channel_cb_init_args(Options)) of
+ {ok, ChannelState} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State};
+ {ok, ChannelState, Timeout} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State, Timeout};
+ {stop, Why} ->
+ {stop, Why}
+ catch
+ _:Reason ->
+ {stop, Reason}
+ end.
+
+channel_cb_init_args(Options) ->
+ case proplists:get_value(exec, Options) of
+ undefined ->
+ proplists:get_value(init_args, Options);
+ Exec ->
+ proplists:get_value(init_args, Options) ++ [Exec]
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call(get_print_info, _From, State) ->
+ Reply =
+ {{State#state.cm,
+ State#state.channel_id},
+ io_lib:format('CB=~p',[State#state.channel_cb])
+ },
+ {reply, Reply, State};
+
+handle_call(Request, From, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+ try Module:handle_call(Request, From, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast(Msg, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+
+ try Module:handle_cast(Msg, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info({ssh_cm, ConnectionManager, {closed, _ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = true} = State) ->
+ {stop, normal, State};
+handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = false} = State) ->
+ %% To be on the safe side, i.e. the manager has already been terminated.
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, normal, State#state{close_sent = true}};
+
+handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
+ channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_ssh_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, ChannelId, ChannelState} ->
+ catch ssh_connection:close(ConnectionManager, ChannelId),
+ {stop, normal, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end;
+
+handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, Reason, ChannelState} when is_atom(Reason)->
+ {stop, Reason, State#state{close_sent = true,
+ channel_state = ChannelState}};
+ {stop, ChannelId, ChannelState} ->
+ Reason =
+ case Msg of
+ {'EXIT', _Pid, shutdown} ->
+ shutdown;
+ _ ->
+ normal
+ end,
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, Reason, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(Reason, #state{cm = ConnectionManager,
+ channel_id = ChannelId,
+ close_sent = false} = State) ->
+ catch ssh_connection:close(ConnectionManager, ChannelId),
+ terminate(Reason, State#state{close_sent = true});
+terminate(_, #state{channel_cb = Cb, channel_state = ChannelState}) ->
+ catch Cb:terminate(Cb, ChannelState),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(OldVsn, #state{channel_cb = Module,
+ channel_state = ChannelState0} = State, Extra) ->
+ {ok, ChannelState} = Module:code_change(OldVsn, ChannelState0, Extra),
+ {ok, State#state{channel_state = ChannelState}}.
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+cache_create() ->
+ ets:new(cm_tab, [set,{keypos, #channel.local_id}]).
+
+cache_lookup(Cache, Key) ->
+ case ets:lookup(Cache, Key) of
+ [Channel] ->
+ Channel;
+ [] ->
+ undefined
+ end.
+
+cache_update(Cache, #channel{local_id = Id} = Entry) when Id =/= undefined ->
+ ets:insert(Cache, Entry).
+
+cache_delete(Cache, Key) ->
+ ets:delete(Cache, Key).
+
+cache_delete(Cache) ->
+ ets:delete(Cache).
+
+cache_foldl(Fun, Acc, Cache) ->
+ ets:foldl(Fun, Acc, Cache).
+
+cache_info(num_entries, Cache) ->
+ proplists:get_value(size, ets:info(Cache)).
+
+cache_find(ChannelPid, Cache) ->
+ case ets:match_object(Cache, #channel{user = ChannelPid}) of
+ [] ->
+ undefined;
+ [Channel] ->
+ Channel
+ end.
+
+get_print_info(Pid) ->
+ call(Pid, get_print_info, 1000).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+handle_cb_result({reply, Reply, ChannelState}, State) ->
+ {reply, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({reply, Reply, ChannelState, Timeout}, State) ->
+ {reply, Reply,State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({noreply, ChannelState}, State) ->
+ {noreply, State#state{channel_state = ChannelState}};
+handle_cb_result({noreply, ChannelState, Timeout}, State) ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({stop, Reason, Reply, ChannelState}, State) ->
+ {stop, Reason, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({stop, Reason, ChannelState}, State) ->
+ {stop, Reason, State#state{channel_state = ChannelState}}.
+
+adjust_window({ssh_cm, ConnectionManager,
+ {data, ChannelId, _, Data}}) ->
+ ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
+adjust_window(_) ->
+ ok.
+
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate, channels, channel_events];
+
+
+dbg_trace(flags, channels, A) -> [c] ++ dbg_trace(flags, terminate, A);
+dbg_trace(on, channels, A) -> dbg:tp(?MODULE, init, 1, x),
+ dbg_trace(on, terminate, A);
+dbg_trace(off, channels, A) -> dbg:ctpg(?MODULE, init, 1),
+ dbg_trace(off, terminate, A);
+dbg_trace(format, channels, {call, {?MODULE,init, [[KVs]]}}) ->
+ ["Server Channel Starting:\n",
+ io_lib:format("Connection: ~p, ChannelId: ~p, CallBack: ~p\nCallBack init args = ~p",
+ [proplists:get_value(K,KVs) || K <- [cm, channel_id, channel_cb]]
+ ++ [channel_cb_init_args(KVs)])
+ ];
+dbg_trace(format, channels, {return_from, {?MODULE,init,1}, {stop,Reason}}) ->
+ ["Server Channel Start FAILED!\n",
+ io_lib:format("Reason = ~p", [Reason])
+ ];
+dbg_trace(format, channels, F) ->
+ dbg_trace(format, terminate, F);
+
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["Server Channel Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ];
+
+dbg_trace(flags, channel_events, _) -> [c];
+dbg_trace(on, channel_events, _) -> dbg:tp(?MODULE, handle_call, 3, x),
+ dbg:tp(?MODULE, handle_cast, 2, x),
+ dbg:tp(?MODULE, handle_info, 2, x);
+dbg_trace(off, channel_events, _) -> dbg:ctpg(?MODULE, handle_call, 3),
+ dbg:ctpg(?MODULE, handle_cast, 2),
+ dbg:ctpg(?MODULE, handle_info, 2);
+dbg_trace(format, channel_events, {call, {?MODULE,handle_call, [Call,From,State]}}) ->
+ [hdr("is called", State),
+ io_lib:format("From: ~p~nCall: ~p~n", [From, Call])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_call,3}, Ret}) ->
+ ["Server Channel call returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ];
+dbg_trace(format, channel_events, {call, {?MODULE,handle_cast, [Cast,State]}}) ->
+ [hdr("got cast", State),
+ io_lib:format("Cast: ~p~n", [Cast])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_cast,2}, Ret}) ->
+ ["Server Channel cast returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ];
+dbg_trace(format, channel_events, {call, {?MODULE,handle_info, [Info,State]}}) ->
+ [hdr("got info", State),
+ io_lib:format("Info: ~p~n", [Info])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_info,2}, Ret}) ->
+ ["Server Channel info returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ].
+
+hdr(Title, S) ->
+ io_lib:format("Server Channel (Id=~p, CB=~p) ~s:\n", [S#state.channel_id, S#state.channel_cb, Title]).
+
+?wr_record(state).
+
+
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index cff9ec3a61..ed03b4e2ed 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -271,7 +271,7 @@ channel_data(ChannelId, DataType, Data, Connection, From) when is_list(Data)->
channel_data(ChannelId, DataType, Data,
#connection{channel_cache = Cache} = Connection,
From) ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{remote_id = Id, sent_close = false} = Channel0 ->
{SendList, Channel} =
update_send_window(Channel0#channel{flow_control = From}, DataType,
@@ -303,9 +303,9 @@ handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId,
#connection{channel_cache = Cache} = Connection0, _) ->
#channel{remote_id = undefined} = Channel =
- ssh_channel:cache_lookup(Cache, ChannelId),
+ ssh_client_channel:cache_lookup(Cache, ChannelId),
- ssh_channel:cache_update(Cache, Channel#channel{
+ ssh_client_channel:cache_update(Cache, Channel#channel{
remote_id = RemoteId,
recv_packet_size = max(32768, % rfc4254/5.2
min(PacketSz, Channel#channel.recv_packet_size)
@@ -319,8 +319,8 @@ handle_msg(#ssh_msg_channel_open_failure{recipient_channel = ChannelId,
description = Descr,
lang = Lang},
#connection{channel_cache = Cache} = Connection0, _) ->
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- ssh_channel:cache_delete(Cache, ChannelId),
+ Channel = ssh_client_channel:cache_lookup(Cache, ChannelId),
+ ssh_client_channel:cache_delete(Cache, ChannelId),
reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang});
handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId}, Connection, _) ->
@@ -335,10 +335,10 @@ handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId}, Connection, _) -
handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId},
#connection{channel_cache = Cache} = Connection0, _) ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{sent_close = Closed, remote_id = RemoteId,
flow_control = FlowControl} = Channel ->
- ssh_channel:cache_delete(Cache, ChannelId),
+ ssh_client_channel:cache_delete(Cache, ChannelId),
{CloseMsg, Connection} =
reply_msg(Channel, Connection0, {closed, ChannelId}),
ConnReplyMsgs =
@@ -379,7 +379,7 @@ handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
bytes_to_add = Add},
#connection{channel_cache = Cache} = Connection, _) ->
#channel{send_window_size = Size, remote_id = RemoteId} =
- Channel0 = ssh_channel:cache_lookup(Cache, ChannelId),
+ Channel0 = ssh_client_channel:cache_lookup(Cache, ChannelId),
{SendList, Channel} = %% TODO: Datatype 0 ?
update_send_window(Channel0#channel{send_window_size = Size + Add},
@@ -455,7 +455,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
?BOOLEAN(_Core),
?DEC_BIN(Err, _ErrLen),
?DEC_BIN(Lang, _LangLen)>> = Data,
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ Channel = ssh_client_channel:cache_lookup(Cache, ChannelId),
RemoteId = Channel#channel.remote_id,
{Reply, Connection} = reply_msg(Channel, Connection0,
{exit_signal, ChannelId,
@@ -500,7 +500,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
<> = Data,
#channel{remote_id = RemoteId} = Channel0 =
- ssh_channel:cache_lookup(Cache, ChannelId),
+ ssh_client_channel:cache_lookup(Cache, ChannelId),
ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)},
@@ -508,7 +508,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
{ok, Pid} = start_subsystem(SsName, Connection, Channel0, ReplyMsg),
erlang:monitor(process, Pid),
Channel = Channel0#channel{user = Pid},
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
Reply = {connection_reply,
channel_success_msg(RemoteId)},
{[Reply], Connection}
@@ -588,7 +588,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
want_reply = WantReply},
#connection{channel_cache = Cache} = Connection, _) ->
if WantReply == true ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{remote_id = RemoteId} ->
FailMsg = channel_failure_msg(RemoteId),
{[{connection_reply, FailMsg}], Connection};
@@ -631,14 +631,14 @@ handle_msg(#ssh_msg_disconnect{code = Code,
%%%
handle_stop(#connection{channel_cache = Cache} = Connection0) ->
{Connection, Replies} =
- ssh_channel:cache_foldl(
+ ssh_client_channel:cache_foldl(
fun(Channel, {Connection1, Acc}) ->
{Reply, Connection2} =
reply_msg(Channel, Connection1,
{closed, Channel#channel.local_id}),
{Connection2, Reply ++ Acc}
end, {Connection0, []}, Cache),
- ssh_channel:cache_delete(Cache),
+ ssh_client_channel:cache_delete(Cache),
{Replies, Connection}.
%%%----------------------------------------------------------------
@@ -779,7 +779,7 @@ setup_session(#connection{channel_cache = Cache,
send_buf = queue:new(),
remote_id = RemoteId
},
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
OpenConfMsg = channel_open_confirmation_msg(RemoteId, NewChannelID,
?DEFAULT_WINDOW_SIZE,
?DEFAULT_PACKET_SIZE),
@@ -868,7 +868,7 @@ update_send_window(#channel{send_buf = SendBuffer} = Channel, DataType, Data,
do_update_send_window(Channel0, Cache) ->
{SendMsgs, Channel} = get_window(Channel0, []),
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
{SendMsgs, Channel}.
get_window(#channel{send_window_size = 0
@@ -919,13 +919,13 @@ flow_control(Channel, Cache) ->
flow_control([window_adjusted], Channel, Cache).
flow_control([], Channel, Cache) ->
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
[];
flow_control([_|_], #channel{flow_control = From,
send_buf = Buffer} = Channel, Cache) when From =/= undefined ->
case queue:is_empty(Buffer) of
true ->
- ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
+ ssh_client_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
[{flow_control, Cache, Channel, From, ok}];
false ->
[]
@@ -1169,14 +1169,14 @@ backwards_compatible([Value| Rest], Acc) ->
handle_cli_msg(C0, ChId, Reply0) ->
Cache = C0#connection.channel_cache,
- Ch0 = ssh_channel:cache_lookup(Cache, ChId),
+ Ch0 = ssh_client_channel:cache_lookup(Cache, ChId),
case Ch0#channel.user of
undefined ->
case (catch start_cli(C0, ChId)) of
{ok, Pid} ->
erlang:monitor(process, Pid),
Ch = Ch0#channel{user = Pid},
- ssh_channel:cache_update(Cache, Ch),
+ ssh_client_channel:cache_update(Cache, Ch),
reply_msg(Ch, C0, Reply0);
_Other ->
Reply = {connection_reply, channel_failure_msg(Ch0#channel.remote_id)},
@@ -1194,10 +1194,10 @@ handle_cli_msg(C0, ChId, Reply0) ->
%%%
channel_data_reply_msg(ChannelId, Connection, DataType, Data) ->
- case ssh_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of
#channel{recv_window_size = Size} = Channel ->
WantedSize = Size - size(Data),
- ssh_channel:cache_update(Connection#connection.channel_cache,
+ ssh_client_channel:cache_update(Connection#connection.channel_cache,
Channel#channel{recv_window_size = WantedSize}),
reply_msg(Channel, Connection, {data, ChannelId, DataType, Data});
undefined ->
@@ -1206,7 +1206,7 @@ channel_data_reply_msg(ChannelId, Connection, DataType, Data) ->
reply_msg(ChId, C, Reply) when is_integer(ChId) ->
- reply_msg(ssh_channel:cache_lookup(C#connection.channel_cache, ChId), C, Reply);
+ reply_msg(ssh_client_channel:cache_lookup(C#connection.channel_cache, ChId), C, Reply);
reply_msg(Channel, Connection, {open, _} = Reply) ->
request_reply_or_data(Channel, Connection, Reply);
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index ab7fc1cf46..57641cf74c 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -414,7 +414,7 @@ init([Role,Socket,Opts]) ->
case inet:peername(Socket) of
{ok, PeerAddr} ->
{Protocol, Callback, CloseTag} = ?GET_OPT(transport, Opts),
- C = #connection{channel_cache = ssh_channel:cache_create(),
+ C = #connection{channel_cache = ssh_client_channel:cache_create(),
channel_id_seed = 0,
port_bindings = [],
requests = [],
@@ -1109,13 +1109,13 @@ handle_event(cast, _, StateName, _) when not ?CONNECTED(StateName) ->
{keep_state_and_data, [postpone]};
handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{recv_window_size = WinSize,
recv_window_pending = Pending,
recv_packet_size = PktSize} = Channel
when (WinSize-Bytes) >= 2*PktSize ->
%% The peer can send at least two more *full* packet, no hurry.
- ssh_channel:cache_update(cache(D),
+ ssh_client_channel:cache_update(cache(D),
Channel#channel{recv_window_pending = Pending + Bytes}),
keep_state_and_data;
@@ -1123,7 +1123,7 @@ handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTE
recv_window_pending = Pending,
remote_id = Id} = Channel ->
%% Now we have to update the window - we can't receive so many more pkts
- ssh_channel:cache_update(cache(D),
+ ssh_client_channel:cache_update(cache(D),
Channel#channel{recv_window_size =
WinSize + Bytes + Pending,
recv_window_pending = 0}),
@@ -1135,7 +1135,7 @@ handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTE
end;
handle_event(cast, {reply_request,success,ChannelId}, StateName, D) when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{remote_id = RemoteId} ->
Msg = ssh_connection:channel_success_msg(RemoteId),
update_inet_buffers(D#data.socket),
@@ -1178,7 +1178,7 @@ handle_event({call,From}, {connection_info, Options}, _, D) ->
{keep_state_and_data, [{reply,From,Info}]};
handle_event({call,From}, {channel_info,ChannelId,Options}, _, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{} = Channel ->
Info = fold_keys(Options, fun chann_info/2, Channel),
{keep_state_and_data, [{reply,From,Info}]};
@@ -1188,14 +1188,14 @@ handle_event({call,From}, {channel_info,ChannelId,Options}, _, D) ->
handle_event({call,From}, {info, all}, _, D) ->
- Result = ssh_channel:cache_foldl(fun(Channel, Acc) ->
+ Result = ssh_client_channel:cache_foldl(fun(Channel, Acc) ->
[Channel | Acc]
end,
[], cache(D)),
{keep_state_and_data, [{reply, From, {ok,Result}}]};
handle_event({call,From}, {info, ChannelPid}, _, D) ->
- Result = ssh_channel:cache_foldl(
+ Result = ssh_client_channel:cache_foldl(
fun(Channel, Acc) when Channel#channel.user == ChannelPid ->
[Channel | Acc];
(_, Acc) ->
@@ -1241,7 +1241,7 @@ handle_event({call,From}, {data, ChannelId, Type, Data, Timeout}, StateName, D0)
handle_event({call,From}, {eof, ChannelId}, StateName, D0)
when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D0), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D0), ChannelId) of
#channel{remote_id = Id, sent_close = false} ->
D = send_msg(ssh_connection:channel_eof_msg(Id), D0),
{keep_state, D, [{reply,From,ok}]};
@@ -1259,7 +1259,7 @@ handle_event({call,From},
InitialWindowSize,
MaxPacketSize, Data),
D1),
- ssh_channel:cache_update(cache(D2),
+ ssh_client_channel:cache_update(cache(D2),
#channel{type = Type,
sys = "none",
user = ChannelPid,
@@ -1274,7 +1274,7 @@ handle_event({call,From},
handle_event({call,From}, {send_window, ChannelId}, StateName, D)
when ?CONNECTED(StateName) ->
- Reply = case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ Reply = case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{send_window_size = WinSize,
send_packet_size = Packsize} ->
{ok, {WinSize, Packsize}};
@@ -1285,7 +1285,7 @@ handle_event({call,From}, {send_window, ChannelId}, StateName, D)
handle_event({call,From}, {recv_window, ChannelId}, StateName, D)
when ?CONNECTED(StateName) ->
- Reply = case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ Reply = case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{recv_window_size = WinSize,
recv_packet_size = Packsize} ->
{ok, {WinSize, Packsize}};
@@ -1296,10 +1296,10 @@ handle_event({call,From}, {recv_window, ChannelId}, StateName, D)
handle_event({call,From}, {close, ChannelId}, StateName, D0)
when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D0), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D0), ChannelId) of
#channel{remote_id = Id} = Channel ->
D1 = send_msg(ssh_connection:channel_close_msg(Id), D0),
- ssh_channel:cache_update(cache(D1), Channel#channel{sent_close = true}),
+ ssh_client_channel:cache_update(cache(D1), Channel#channel{sent_close = true}),
{keep_state, cache_request_idle_timer_check(D1), [{reply,From,ok}]};
undefined ->
{keep_state_and_data, [{reply,From,ok}]}
@@ -1859,7 +1859,7 @@ is_usable_user_pubkey(A, Ssh) ->
%%%----------------------------------------------------------------
handle_request(ChannelPid, ChannelId, Type, Data, WantReply, From, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{remote_id = Id,
sent_close = false} = Channel ->
update_sys(cache(D), Channel, Type, ChannelPid),
@@ -1874,7 +1874,7 @@ handle_request(ChannelPid, ChannelId, Type, Data, WantReply, From, D) ->
end.
handle_request(ChannelId, Type, Data, WantReply, From, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{remote_id = Id,
sent_close = false} ->
send_msg(ssh_connection:channel_request_msg(Id, Type, WantReply, Data),
@@ -1890,10 +1890,10 @@ handle_request(ChannelId, Type, Data, WantReply, From, D) ->
%%%----------------------------------------------------------------
handle_channel_down(ChannelPid, D) ->
Cache = cache(D),
- ssh_channel:cache_foldl(
+ ssh_client_channel:cache_foldl(
fun(#channel{user=U,
local_id=Id}, Acc) when U == ChannelPid ->
- ssh_channel:cache_delete(Cache, Id),
+ ssh_client_channel:cache_delete(Cache, Id),
Acc;
(_,Acc) ->
Acc
@@ -1902,7 +1902,7 @@ handle_channel_down(ChannelPid, D) ->
update_sys(Cache, Channel, Type, ChannelPid) ->
- ssh_channel:cache_update(Cache,
+ ssh_client_channel:cache_update(Cache,
Channel#channel{sys = Type, user = ChannelPid}).
add_request(false, _ChannelId, _From, State) ->
@@ -1979,7 +1979,7 @@ conn_info(sockname, #data{ssh_params=S}) -> S#ssh.local;
%% dbg options ( = not documented):
conn_info(socket, D) -> D#data.socket;
conn_info(chan_ids, D) ->
- ssh_channel:cache_foldl(fun(#channel{local_id=Id}, Acc) ->
+ ssh_client_channel:cache_foldl(fun(#channel{local_id=Id}, Acc) ->
[Id | Acc]
end, [], cache(D)).
@@ -2070,7 +2070,7 @@ get_repl({channel_data,Pid,Data}, Acc) ->
get_repl({channel_request_reply,From,Data}, {CallRepls,S}) ->
{[{reply,From,Data}|CallRepls], S};
get_repl({flow_control,Cache,Channel,From,Msg}, {CallRepls,S}) ->
- ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
+ ssh_client_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
{[{reply,From,Msg}|CallRepls], S};
get_repl({flow_control,From,Msg}, {CallRepls,S}) ->
{[{reply,From,Msg}|CallRepls], S};
@@ -2146,7 +2146,7 @@ cache_init_idle_timer(D) ->
cache_check_set_idle_timer(D = #data{idle_timer_ref = undefined,
idle_timer_value = IdleTime}) ->
%% No timer set - shall we set one?
- case ssh_channel:cache_info(num_entries, cache(D)) of
+ case ssh_client_channel:cache_info(num_entries, cache(D)) of
0 when IdleTime == infinity ->
%% No. Meaningless to set a timer that fires in an infinite time...
D;
diff --git a/lib/ssh/src/ssh_server_channel.erl b/lib/ssh/src/ssh_server_channel.erl
index 117b7855e2..f1c9a85639 100644
--- a/lib/ssh/src/ssh_server_channel.erl
+++ b/lib/ssh/src/ssh_server_channel.erl
@@ -48,8 +48,8 @@
]).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
get_print_info(Pid) ->
- ssh_channel:get_print_info(Pid).
+ ssh_client_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index f00c0aed1f..5984713ec9 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -24,7 +24,7 @@
-module(ssh_sftp).
--behaviour(ssh_channel).
+-behaviour(ssh_client_channel).
-include_lib("kernel/include/file.hrl").
-include("ssh.hrl").
@@ -47,7 +47,7 @@
recv_window/1, list_dir/2, read_file/2, write_file/3,
recv_window/2, list_dir/3, read_file/3, write_file/4]).
-%% ssh_channel callbacks
+%% ssh_client_channel callbacks
-export([init/1, handle_call/3, handle_cast/2, code_change/3, handle_msg/2, handle_ssh_msg/2, terminate/2]).
%% TODO: Should be placed elsewhere ssh_sftpd should not call functions in ssh_sftp!
-export([info_to_attr/1, attr_to_info/1]).
@@ -123,7 +123,7 @@ start_channel(Cm, UserOptions) when is_pid(Cm) ->
{_SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
case ssh_xfer:attach(Cm, [], ChanOpts) of
{ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId,
+ case ssh_client_channel:start(Cm, ChannelId,
?MODULE, [Cm, ChannelId, SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
@@ -151,7 +151,7 @@ start_channel(Host, Port, UserOptions) ->
proplists:get_value(timeout, SftpOpts, infinity)),
case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of
{ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,ChannelId,SftpOpts]) of
+ case ssh_client_channel:start(Cm, ChannelId, ?MODULE, [Cm,ChannelId,SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
ok ->
@@ -825,7 +825,7 @@ handle_msg({ssh_channel_up, _, _}, #state{opts = Options, xf = Xf} = State) ->
%% Version negotiation timed out
handle_msg({timeout, undefined, From},
#state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
- ssh_channel:reply(From, {error, timeout}),
+ ssh_client_channel:reply(From, {error, timeout}),
{stop, ChannelId, State};
handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
@@ -834,7 +834,7 @@ handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
{ok, State};
_ ->
ReqList = lists:keydelete(Id, 1, ReqList0),
- ssh_channel:reply(From, {error, timeout}),
+ ssh_client_channel:reply(From, {error, timeout}),
{ok, State#state{req_list = ReqList}}
end;
@@ -882,7 +882,7 @@ handle_options([Opt|Rest], Sftp, Chan, Ssh) ->
handle_options(Rest, Sftp, Chan, [Opt|Ssh]).
call(Pid, Msg, TimeOut) ->
- ssh_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
+ ssh_client_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
handle_reply(State, <>) ->
do_handle_reply(State, Reply, Rest);
@@ -901,7 +901,7 @@ do_handle_reply(#state{xf = Xf} = State,
true ->
ok
end,
- ssh_channel:reply(From, ok)
+ ssh_client_channel:reply(From, ok)
end,
State#state{xf = Xf#ssh_xfer{vsn = Version, ext = Ext}, rep_buf = Rest};
@@ -949,7 +949,7 @@ async_reply(ReqID, Reply, _From={To,_}, State) ->
State.
sync_reply(Reply, From, State) ->
- catch (ssh_channel:reply(From, Reply)),
+ catch (ssh_client_channel:reply(From, Reply)),
State.
open2(OrigReqID,FileName,Handle,Mode,Async,From,State) ->
--
cgit v1.2.3