diff options
author | Hans Nilsson <[email protected]> | 2018-04-27 10:31:01 +0200 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2018-04-27 10:31:01 +0200 |
commit | 82ac72abf72c25fb092486e50ddac700bec17341 (patch) | |
tree | 06b0de823c66c64ade945049d30c5cbda854bd9f /lib | |
parent | 56e88f364a32b471b03e2364c2eb84783642ad88 (diff) | |
parent | c2ca477c85e0e88732f634ddfb01ac675a97dddb (diff) | |
download | otp-82ac72abf72c25fb092486e50ddac700bec17341.tar.gz otp-82ac72abf72c25fb092486e50ddac700bec17341.tar.bz2 otp-82ac72abf72c25fb092486e50ddac700bec17341.zip |
Merge branch 'hans/ssh/channel_maintenance/OTP-15041'
* hans/ssh/channel_maintenance/OTP-15041:
ssh: ssh_channel replaced by ssh_client_channel
ssh: ssh_daemon_channel replaced by ssh_server_channel
ssh: Use ssh_daemon_channel_sup and ssh_damon_channel
ssh: Create doc for the ssh_daemon_channel behaviour
Diffstat (limited to 'lib')
32 files changed, 898 insertions, 561 deletions
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile index 0063484f72..7c4dbd7af8 100644 --- a/lib/ssh/doc/src/Makefile +++ b/lib/ssh/doc/src/Makefile @@ -38,19 +38,22 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # Target Specs # ---------------------------------------------------- XML_APPLICATION_FILES = ref_man.xml -XML_REF3_FILES = ssh.xml \ - ssh_channel.xml \ - ssh_connection.xml \ +XML_REF3_FILES = \ + ssh.xml \ + ssh_client_channel.xml \ ssh_client_key_api.xml \ + ssh_connection.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/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 <seealso marker="ssh_channel">ssh_channel</seealso> behaviour + The <seealso marker="ssh_client_channel">ssh_client_channel</seealso> 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 140ebd8c76..76e6520f94 100644 --- a/lib/ssh/doc/src/ref_man.xml +++ b/lib/ssh/doc/src/ref_man.xml @@ -35,7 +35,8 @@ </description> <xi:include href="ssh_app.xml"/> <xi:include href="ssh.xml"/> - <xi:include href="ssh_channel.xml"/> + <xi:include href="ssh_client_channel.xml"/> + <xi:include href="ssh_server_channel.xml"/> <xi:include href="ssh_connection.xml"/> <xi:include href="ssh_client_key_api.xml"/> <xi:include href="ssh_server_key_api.xml"/> diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml index 3ab4f43aec..acdbe2ddfd 100644 --- a/lib/ssh/doc/src/specs.xml +++ b/lib/ssh/doc/src/specs.xml @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="utf-8" ?> <specs xmlns:xi="http://www.w3.org/2001/XInclude"> - <xi:include href="../specs/specs_ssh_channel.xml"/> + <xi:include href="../specs/specs_ssh.xml"/> + <xi:include href="../specs/specs_ssh_client_channel.xml"/> <xi:include href="../specs/specs_ssh_client_key_api.xml"/> <xi:include href="../specs/specs_ssh_connection.xml"/> + <xi:include href="../specs/specs_ssh_server_channel.xml"/> <xi:include href="../specs/specs_ssh_server_key_api.xml"/> - <xi:include href="../specs/specs_ssh_sftpd.xml"/> <xi:include href="../specs/specs_ssh_sftp.xml"/> - <xi:include href="../specs/specs_ssh.xml"/> + <xi:include href="../specs/specs_ssh_sftpd.xml"/> </specs> diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 03078cfd83..0223831cb1 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -68,8 +68,8 @@ <seealso marker="ssh_sftp#start_channel/1">ssh_sftp:start_channel/1,2,3</seealso>. </p> <p>To write your own client channel handler, use the behaviour - <seealso marker="ssh_channel">ssh_channel</seealso>. For own server channel handlers use the ssh_daemon_channel - behaviour: see the <seealso marker="ssh_channel#ssh_daemon_channel">note in ssh_channel</seealso>. + <seealso marker="ssh_client_channel">ssh_client_channel</seealso>. For server channel handlers use + <seealso marker="ssh_server_channel">ssh_server_channel</seealso> behaviour (replaces ssh_daemon_channel). </p> <p>Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both. The three sets are called @@ -378,7 +378,8 @@ <p>The <c>subsystem_name</c> is the name that a client requests to start with for example <seealso marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seealso>. </p> - <p>The <c>channel_callback</c> is the module that implements the <c>ssh_daemon_channel</c> + <p>The <c>channel_callback</c> is the module that implements the + <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel) behaviour in the daemon. See the section <seealso marker="using_ssh#usersguide_creating_a_subsystem">Creating a Subsystem</seealso> 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_client_channel.xml index 0355f7bf52..eed49beffa 100644 --- a/lib/ssh/doc/src/ssh_channel.xml +++ b/lib/ssh/doc/src/ssh_client_channel.xml @@ -23,21 +23,27 @@ The Initial Developer of the Original Code is Ericsson AB. </legalnotice> - <title>ssh_channel</title> + <title>ssh_client_channel</title> <prepared></prepared> <docno></docno> <date></date> <rev></rev> </header> - <module>ssh_channel</module> - <modulesummary>-behaviour(ssh_channel). + <module>ssh_client_channel</module> + <modulesummary>-behaviour(ssh_client_channel). (Replaces ssh_channel) </modulesummary> <description> + <note> + <p>This module replaces ssh_channel.</p> + <p>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 + </p> + </note> <p>SSH services (clients and servers) are implemented as channels that are multiplexed over an SSH connection and communicates over the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH Connection Protocol</url>. This module provides a callback API - that takes care of generic channel aspects, such as flow control + 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 @@ -46,14 +52,18 @@ the <c>ssh</c> applications supervisor tree. </p> - <marker id="ssh_daemon_channel"/> - <note><p>When implementing an <c>ssh</c> subsystem, use - <c>-behaviour(ssh_daemon_channel)</c> instead of <c>-behaviour(ssh_channel)</c>. - The reason is that the only relevant callback functions for subsystems are - <c>init/1</c>, <c>handle_ssh_msg/2</c>, <c>handle_msg/2</c>, and <c>terminate/2</c>. - So, the <c>ssh_daemon_channel</c> behaviour is a limited version of the - <c>ssh_channel</c> behaviour. - </p></note> + <note><p>When implementing a <c>ssh</c> subsystem for daemons, use + <seealso marker="ssh_server_channel">-behaviour(ssh_server_channel)</seealso> (Replaces ssh_daemon_channel) + instead. + </p> + </note> + + <dont> + <p>Functions in this module are not supposed to be called outside a module implementing this + behaviour! + </p> + </dont> + </description> <funcs> @@ -100,18 +110,18 @@ </desc> </func> - <func> + <func> <name>enter_loop(State) -> _ </name> - <fsummary>Makes an existing process an ssh_channel process.</fsummary> + <fsummary>Makes an existing process an ssh_client_channel (replaces ssh_channel) process.</fsummary> <type> <v>State = term()</v> <d>as returned by <seealso marker = "#init-1">init/1</seealso></d> </type> <desc> - <p>Makes an existing process an <c>ssh_channel</c> + <p>Makes an existing process an <c>ssh_client_channel</c> (replaces ssh_channel) process. Does not return, instead the calling process - enters the <c>ssh_channel</c> process receive loop and become an - <c>ssh_channel process</c>. The process must have been started using + enters the <c>ssh_client_channel</c> (replaces ssh_channel) process receive loop and become an + <c>ssh_client_channel</c> process. The process must have been started using one of the start functions in <c>proc_lib</c>, see the <seealso marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in STDLIB. The user is responsible for any initialization of the process @@ -122,7 +132,7 @@ <func> <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name> - <fsummary>Initiates an <c>ssh_channel</c> process.</fsummary> + <fsummary>Initiates an <c>ssh_client_channel</c> process.</fsummary> <type> <v>Options = [{Option, Value}]</v> <v>State = term()</v> @@ -217,13 +227,19 @@ </funcs> <section> + <title>Callback Functions</title> + <p> + The following functions are to be exported from a + <c>ssh_client_channel</c> callback module. + </p> <marker id="cb_timeouts"></marker> - <title>CALLBACK TIME-OUTS</title> - - <p>The time-out values that can be returned by the callback functions - have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>. - If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso> - is called as <c>handle_msg(timeout, State)</c>.</p> + <section> + <title>Callback timeouts</title> + <p>The timeout values that can be returned by the callback functions + have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>. + If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso> + is called as <c>handle_msg(timeout, State)</c>.</p> + </section> </section> <funcs> @@ -286,7 +302,7 @@ state if the initializations succeed. </p> <p>For more detailed information on time-outs, see Section - <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>. </p> + <seealso marker="#cb_timeouts">Callback timeouts</seealso>. </p> </desc> </func> @@ -313,7 +329,7 @@ <seealso marker="#call-2">call/[2,3]</seealso> </p> <p>For more detailed information on time-outs,, see Section - <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p> + <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p> </desc> </func> @@ -334,7 +350,7 @@ <c>cast/2</c>. </p> <p>For more detailed information on time-outs, see Section - <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p> + <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p> </desc> </func> @@ -388,7 +404,7 @@ </p> <p>The following message is taken care of by the - <c>ssh_channel</c> behavior.</p> + <c>ssh_client_channel</c> behavior.</p> <taglist> <tag><c>{closed, ssh:channel_id()}</c></tag> 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 <c><![CDATA[{ssh_cm, connection_ref(), ssh_event_msg()}]]></c>. - If the <seealso marker="ssh_channel">ssh_channel</seealso> behavior is used to + If the <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior is used to implement the channel process, these messages are handled by - <seealso marker="ssh_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p> + <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p> </description> <section> @@ -131,7 +131,7 @@ <item><p>This event is sent as a result of calling <seealso marker="ssh_connection#close-2">ssh_connection:close/2</seealso>. Both the handling of this event and sending it are taken care of by the - <seealso marker="ssh_channel">ssh_channel</seealso> behavior.</p></item> + <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior.</p></item> </taglist> </item> @@ -212,10 +212,10 @@ <p>Adjusts the SSH flow control window. This is to be done by both the client- and server-side channel processes.</p> - <note><p>Channels implemented with the <seealso marker="ssh_channel"> ssh_channel</seealso> + <note><p>Channels implemented with the <seealso marker="ssh_client_channel"> ssh_client_channel</seealso> 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 <seealso marker="ssh_channel#Module:handle_ssh_msg-2"> + the callback <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2"> handle_ssh_msg/2</seealso> returns after processing channel data.</p></note> </desc> </func> @@ -232,9 +232,9 @@ sending a close event. </p> - <note><p>This function is called by the <c>ssh_channel</c> + <note><p>This function is called by the <c>ssh_client_channel</c> behavior when the channel is terminated, see <seealso - marker="ssh_channel"> ssh_channel(3)</seealso>. Thus, channels implemented + marker="ssh_client_channel"> ssh_client_channel(3)</seealso>. Thus, channels implemented with the behavior are not to call this function explicitly.</p></note> </desc> </func> @@ -277,7 +277,7 @@ <tag><c>1 x {ssh_cm, connection_ref(), {closed, channel_id()}}</c></tag> - <item><p>Indicates that the <c>ssh_channel</c> started for the + <item><p>Indicates that the <c>ssh_client_channel</c> started for the execution of the command has now been shut down.</p></item> </taglist> </desc> diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml index a0032ab449..53f0524b97 100644 --- a/lib/ssh/doc/src/ssh_protocol.xml +++ b/lib/ssh/doc/src/ssh_protocol.xml @@ -87,8 +87,10 @@ connection, and all channels are flow-controlled. Typically an SSH client will open a channel, send data/commands, receive data/"control information" and when it is done close the - channel. The <seealso - marker="ssh_channel">ssh_channel</seealso> behaviour makes it easy to + channel. The + <seealso marker="ssh_client_channel">ssh_client_channel</seealso> / + <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (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 lets you focus on the application logic. 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..af51ec470b --- /dev/null +++ b/lib/ssh/doc/src/ssh_server_channel.xml @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2009</year> + <year>2016</year> + <holder>Ericsson AB, All Rights Reserved</holder> + </copyright> + <legalnotice> + 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. + </legalnotice> + <title>ssh_server_channel</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>ssh_server_channel</module> + <modulesummary>-behaviour(ssh_server_channel). (Replaces ssh_daemon_channel) + </modulesummary> + <description> + <note> + <p>This module replaces ssh_daemon_channel.</p> + <p>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 + </p> + </note> + + <p>SSH services (clients and servers) are implemented as channels + that are multiplexed over an SSH connection and communicates over + the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH + Connection Protocol</url>. 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 <c>ssh</c> applications supervisor tree. + </p> + + <note><p>When implementing a client subsystem handler, use + <seealso marker="ssh_client_channel">-behaviour(ssh_client_channel)</seealso> instead. + </p> + </note> + + </description> + + <section> + <title>Callback Functions</title> + <p> + The following functions are to be exported from a + <c>ssh_server_channel</c> callback module. + </p> + </section> + + <funcs> + <func> + <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} | + {stop, Reason}</name> + <fsummary>Makes necessary initializations and returns the + initial channel state if the initializations succeed.</fsummary> + <type> + <v>Args = term()</v> + <d>Last argument to <c>start_link/4</c>.</d> + <v>State = term()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Makes necessary initializations and returns the initial channel + state if the initializations succeed. + </p> + <p>The time-out values that can be returned + have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>. + If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso> + is called as <c>handle_msg(timeout, State)</c>. + </p> + </desc> + </func> + + <func> + <name>Module:handle_msg(Msg, State) -> {ok, State} | + {stop, ChannelId, State}</name> + + <fsummary>Handles other messages than SSH connection protocol, + call, or cast messages sent to the channel.</fsummary> + <type> + <v>Msg = timeout | term()</v> + <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v> + <v>State = term() </v> + </type> + <desc> + <p>Handles other messages than SSH Connection Protocol, call, or + cast messages sent to the channel. + </p> + + <p>Possible Erlang 'EXIT' messages is to be handled by this + function and all channels are to handle the following message.</p> + + <taglist> + <tag><c>{ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}</c></tag> + <item><p>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 <c>{ok, State}</c>. + </p></item> + </taglist> + </desc> + </func> + + <func> + <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop, + ChannelId, State}</name> + <fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary> + <type> + <v>Msg = ssh_connection:event()</v> + <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v> + <v>State = term()</v> + </type> + <desc> + <p>Handles SSH Connection Protocol messages that may need + service-specific attention. For details, + see <seealso marker="ssh_connection"> ssh_connection:event()</seealso>. + </p> + + <p>The following message is taken care of by the + <c>ssh_server_channel</c> behavior.</p> + + <taglist> + <tag><c>{closed, ssh:channel_id()}</c></tag> + <item><p>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 <c>normal</c>.</p></item> + </taglist> + </desc> + </func> + + <func> + <name>Module:terminate(Reason, State) -> _</name> + <fsummary>Does cleaning up before channel process termination. + </fsummary> + <type> + <v>Reason = term()</v> + <v>State = term()</v> + </type> + <desc> + <p>This function is called by a channel process when it is + about to terminate. Before this function is called, <seealso + marker="ssh_connection#close-2"> ssh_connection:close/2 + </seealso> 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 <c>Reason</c>. The return value is ignored. + </p> + </desc> + </func> + + </funcs> + +</erlref> diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml index 1be29b3b29..a25ce123b3 100644 --- a/lib/ssh/doc/src/ssh_sftpd.xml +++ b/lib/ssh/doc/src/ssh_sftpd.xml @@ -44,8 +44,7 @@ <item><p><c>"sftp"</c></p></item> <tag><c>channel_callback() =</c></tag> <item><p><c>atom()</c> - Name of the Erlang module implementing the subsystem using the - <c>ssh_channel</c> behavior, see the - <seealso marker="ssh_channel">ssh_channel(3)</seealso> manual page.</p></item> + <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel) behaviour.</p></item> <tag><c>channel_init_args() =</c></tag> <item><p><c>list()</c> - The one given as argument to function <c>subsystem_spec/1</c>.</p></item> </taglist> diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml index bde2aaaf99..efd2a997f5 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), <code type="erl" > -module(ssh_echo_server). --behaviour(ssh_daemon_channel). +-behaviour(ssh_server_channel). % replaces ssh_daemon_channel -record(state, { n, id, @@ -384,7 +384,7 @@ terminate(_Reason, _State) -> {ssh_msg, <0.57.0>, {closed, 0}} 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity). </code> -<p>See also <seealso marker="ssh_channel"> ssh_channel(3)</seealso>.</p> +<p>See also <seealso marker="ssh_client_channel">ssh_client_channel(3)</seealso> (replaces ssh_channel(3)).</p> </section> diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile index bcd13213b3..5e4efb6b99 100644 --- a/lib/ssh/src/Makefile +++ b/lib/ssh/src/Makefile @@ -40,42 +40,44 @@ 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 \ + ssh_client_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_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 +171,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_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 @@ -208,8 +210,10 @@ $(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 $(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 4a22322333..410061cded 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -12,9 +12,9 @@ ssh_message, ssh_bits, ssh_cli, + ssh_client_channel, ssh_client_key_api, ssh_channel, - ssh_channel_sup, ssh_connection, ssh_connection_handler, ssh_connection_sup, @@ -27,6 +27,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.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_cli.erl b/lib/ssh/src/ssh_cli.erl index 382de90ae1..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_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_channel callbacks +%% ssh_server_channel callbacks %%==================================================================== %%-------------------------------------------------------------------- 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 2261d37d6a..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, <<?DEC_BIN(SsName,_SsLen)>> = 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), @@ -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_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_channel]} <- + NumChannels = length([x || {_,_,worker,[ssh_server_channel]} <- supervisor:which_children(ChannelSup)]), %% Note that NumChannels is BEFORE starting a new one NumChannels < MaxNumChannels. @@ -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_daemon_channel.erl b/lib/ssh/src/ssh_daemon_channel.erl index 72853f2d6a..fdb6c10971 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). + ssh_server_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_server_channel:get_print_info(Pid). diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl index d464def6fa..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_channel_sup,_,_},Pid,supervisor,[ssh_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_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_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_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..f1c9a85639 --- /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_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec). + + +get_print_info(Pid) -> + ssh_client_channel:get_print_info(Pid). diff --git a/lib/ssh/src/ssh_channel_sup.erl b/lib/ssh/src/ssh_server_channel_sup.erl index 7a12f34049..70799db714 100644 --- a/lib/ssh/src/ssh_channel_sup.erl +++ b/lib/ssh/src/ssh_server_channel_sup.erl @@ -22,7 +22,7 @@ %%---------------------------------------------------------------------- %% Purpose: Ssh channel supervisor. %%---------------------------------------------------------------------- --module(ssh_channel_sup). +-module(ssh_server_channel_sup). -behaviour(supervisor). @@ -40,10 +40,10 @@ start_link(Args) -> start_child(Sup, Callback, Id, Args, Exec) -> ChildSpec = #{id => make_ref(), - start => {ssh_channel, start_link, [self(), Id, Callback, Args, Exec]}, + start => {ssh_server_channel, start_link, [self(), Id, Callback, Args, Exec]}, restart => temporary, type => worker, - modules => [ssh_channel] + modules => [ssh_server_channel] }, supervisor:start_child(Sup, ChildSpec). 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, <<?UINT32(Len),Reply:Len/binary,Rest/binary>>) -> 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) -> 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 c7c63c5c43..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_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_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 77da240a66..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_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_channel_sup, Address, Port), - start => {ssh_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_channel_sup([{_, Child, _, [ssh_channel_sup]} | _]) -> +ssh_server_channel_sup([{_, Child, _, [ssh_server_channel_sup]} | _]) -> Child; -ssh_channel_sup([_ | Rest]) -> - ssh_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 4e7169d927..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_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_channel_sup,_ ,_}, + {{server,ssh_server_channel_sup,_ ,_}, ChannelSup,supervisor, - [ssh_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_channel_sup,_ ,_}, + {{server,ssh_server_channel_sup,_ ,_}, ChannelSup,supervisor, - [ssh_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_channel]}], + ?wait_match([{_, _,worker,[ssh_server_channel]}], supervisor:which_children(ChannelSup)), ssh:close(Client). |