From 82246e3cc929945461cba9c2481fb9778b7e4618 Mon Sep 17 00:00:00 2001 From: Eugen Cowie Date: Sat, 21 Sep 2024 15:24:22 +0100 Subject: [PATCH] Add interface to SshClient (#1499) --- src/Renci.SshNet/IBaseClient.cs | 5 + src/Renci.SshNet/ISshClient.cs | 246 ++++++++++++++++++++++++++++++++ src/Renci.SshNet/SshClient.cs | 220 +++------------------------- 3 files changed, 269 insertions(+), 202 deletions(-) create mode 100644 src/Renci.SshNet/ISshClient.cs diff --git a/src/Renci.SshNet/IBaseClient.cs b/src/Renci.SshNet/IBaseClient.cs index 9feab44cc..c628483b8 100644 --- a/src/Renci.SshNet/IBaseClient.cs +++ b/src/Renci.SshNet/IBaseClient.cs @@ -51,6 +51,11 @@ public interface IBaseClient : IDisposable /// event EventHandler HostKeyReceived; + /// + /// Occurs when server identification received. + /// + event EventHandler? ServerIdentificationReceived; + /// /// Connects client to the server. /// diff --git a/src/Renci.SshNet/ISshClient.cs b/src/Renci.SshNet/ISshClient.cs new file mode 100644 index 000000000..1d6edfebf --- /dev/null +++ b/src/Renci.SshNet/ISshClient.cs @@ -0,0 +1,246 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Renci.SshNet.Common; + +namespace Renci.SshNet +{ + /// + /// Provides client connection to SSH server. + /// + public interface ISshClient : IBaseClient + { + /// + /// Gets the list of forwarded ports. + /// + IEnumerable ForwardedPorts { get; } + + /// + /// Adds the forwarded port. + /// + /// The port. + /// Forwarded port is already added to a different client. + /// is . + /// Client is not connected. + public void AddForwardedPort(ForwardedPort port); + + /// + /// Stops and removes the forwarded port from the list. + /// + /// Forwarded port. + /// is . + public void RemoveForwardedPort(ForwardedPort port); + + /// + /// Creates the command to be executed. + /// + /// The command text. + /// object. + /// Client is not connected. + public SshCommand CreateCommand(string commandText); + + /// + /// Creates the command to be executed with specified encoding. + /// + /// The command text. + /// The encoding to use for results. + /// object which uses specified encoding. + /// This method will change current default encoding. + /// Client is not connected. + /// or is . + public SshCommand CreateCommand(string commandText, Encoding encoding); + + /// + /// Creates and executes the command. + /// + /// The command text. + /// Returns an instance of with execution results. + /// This method internally uses asynchronous calls. + /// CommandText property is empty. + /// Invalid Operation - An existing channel was used to execute this command. + /// Asynchronous operation is already in progress. + /// Client is not connected. + /// is . + public SshCommand RunCommand(string commandText); + + /// + /// Creates the shell. + /// + /// The input. + /// The output. + /// The extended output. + /// Name of the terminal. + /// The columns. + /// The rows. + /// The width. + /// The height. + /// The terminal mode. + /// Size of the internal read buffer. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary? terminalModes, int bufferSize); + + /// + /// Creates the shell. + /// + /// The input. + /// The output. + /// The extended output. + /// Name of the terminal. + /// The columns. + /// The rows. + /// The width. + /// The height. + /// The terminal mode. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary terminalModes); + + /// + /// Creates the shell. + /// + /// The input. + /// The output. + /// The extended output. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Stream input, Stream output, Stream extendedOutput); + + /// + /// Creates the shell. + /// + /// The encoding to use to send the input. + /// The input. + /// The output. + /// The extended output. + /// Name of the terminal. + /// The columns. + /// The rows. + /// The width. + /// The height. + /// The terminal mode. + /// Size of the internal read buffer. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary? terminalModes, int bufferSize); + + /// + /// Creates the shell. + /// + /// The encoding. + /// The input. + /// The output. + /// The extended output. + /// Name of the terminal. + /// The columns. + /// The rows. + /// The width. + /// The height. + /// The terminal modes. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary terminalModes); + + /// + /// Creates the shell. + /// + /// The encoding. + /// The input. + /// The output. + /// The extended output. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput); + + /// + /// Creates the shell without allocating a pseudo terminal, + /// similar to the ssh -T option. + /// + /// The input. + /// The output. + /// The extended output. + /// Size of the internal read buffer. + /// + /// Returns a representation of a object. + /// + /// Client is not connected. + public Shell CreateShellNoTerminal(Stream input, Stream output, Stream extendedOutput, int bufferSize = -1); + + /// + /// Creates the shell stream. + /// + /// The TERM environment variable. + /// The terminal width in columns. + /// The terminal width in rows. + /// The terminal width in pixels. + /// The terminal height in pixels. + /// The size of the buffer. + /// + /// The created instance. + /// + /// Client is not connected. + /// + /// + /// The TERM environment variable contains an identifier for the text window's capabilities. + /// You can get a detailed list of these capabilities by using the ‘infocmp’ command. + /// + /// + /// The column/row dimensions override the pixel dimensions(when nonzero). Pixel dimensions refer + /// to the drawable area of the window. + /// + /// + public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize); + + /// + /// Creates the shell stream. + /// + /// The TERM environment variable. + /// The terminal width in columns. + /// The terminal width in rows. + /// The terminal width in pixels. + /// The terminal height in pixels. + /// The size of the buffer. + /// The terminal mode values. + /// + /// The created instance. + /// + /// Client is not connected. + /// + /// + /// The TERM environment variable contains an identifier for the text window's capabilities. + /// You can get a detailed list of these capabilities by using the ‘infocmp’ command. + /// + /// + /// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer + /// to the drawable area of the window. + /// + /// + public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize, IDictionary? terminalModeValues); + + /// + /// Creates the shell stream without allocating a pseudo terminal, + /// similar to the ssh -T option. + /// + /// The size of the buffer. + /// + /// The created instance. + /// + /// Client is not connected. + public ShellStream CreateShellStreamNoTerminal(int bufferSize = -1); + } +} diff --git a/src/Renci.SshNet/SshClient.cs b/src/Renci.SshNet/SshClient.cs index c9ace80f9..3051074e1 100644 --- a/src/Renci.SshNet/SshClient.cs +++ b/src/Renci.SshNet/SshClient.cs @@ -10,10 +10,8 @@ namespace Renci.SshNet { - /// - /// Provides client connection to SSH server. - /// - public class SshClient : BaseClient + /// + public class SshClient : BaseClient, ISshClient { /// /// Holds the list of forwarded ports. @@ -30,9 +28,7 @@ public class SshClient : BaseClient private MemoryStream? _inputStream; - /// - /// Gets the list of forwarded ports. - /// + /// public IEnumerable ForwardedPorts { get @@ -156,13 +152,7 @@ protected override void OnDisconnecting() } } - /// - /// Adds the forwarded port. - /// - /// The port. - /// Forwarded port is already added to a different client. - /// is . - /// Client is not connected. + /// public void AddForwardedPort(ForwardedPort port) { ThrowHelper.ThrowIfNull(port); @@ -173,11 +163,7 @@ public void AddForwardedPort(ForwardedPort port) _forwardedPorts.Add(port); } - /// - /// Stops and removes the forwarded port from the list. - /// - /// Forwarded port. - /// is . + /// public void RemoveForwardedPort(ForwardedPort port) { ThrowHelper.ThrowIfNull(port); @@ -204,26 +190,13 @@ private static void DetachForwardedPort(ForwardedPort port) port.Session = null; } - /// - /// Creates the command to be executed. - /// - /// The command text. - /// object. - /// Client is not connected. + /// public SshCommand CreateCommand(string commandText) { return CreateCommand(commandText, ConnectionInfo.Encoding); } - /// - /// Creates the command to be executed with specified encoding. - /// - /// The command text. - /// The encoding to use for results. - /// object which uses specified encoding. - /// This method will change current default encoding. - /// Client is not connected. - /// or is . + /// public SshCommand CreateCommand(string commandText, Encoding encoding) { EnsureSessionIsOpen(); @@ -232,17 +205,7 @@ public SshCommand CreateCommand(string commandText, Encoding encoding) return new SshCommand(Session!, commandText, encoding); } - /// - /// Creates and executes the command. - /// - /// The command text. - /// Returns an instance of with execution results. - /// This method internally uses asynchronous calls. - /// CommandText property is empty. - /// Invalid Operation - An existing channel was used to execute this command. - /// Asynchronous operation is already in progress. - /// Client is not connected. - /// is . + /// public SshCommand RunCommand(string commandText) { var cmd = CreateCommand(commandText); @@ -250,23 +213,7 @@ public SshCommand RunCommand(string commandText) return cmd; } - /// - /// Creates the shell. - /// - /// The input. - /// The output. - /// The extended output. - /// Name of the terminal. - /// The columns. - /// The rows. - /// The width. - /// The height. - /// The terminal mode. - /// Size of the internal read buffer. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary? terminalModes, int bufferSize) { EnsureSessionIsOpen(); @@ -274,60 +221,19 @@ public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, str return new Shell(Session, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalModes, bufferSize); } - /// - /// Creates the shell. - /// - /// The input. - /// The output. - /// The extended output. - /// Name of the terminal. - /// The columns. - /// The rows. - /// The width. - /// The height. - /// The terminal mode. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary terminalModes) { return CreateShell(input, output, extendedOutput, terminalName, columns, rows, width, height, terminalModes, 1024); } - /// - /// Creates the shell. - /// - /// The input. - /// The output. - /// The extended output. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Stream input, Stream output, Stream extendedOutput) { return CreateShell(input, output, extendedOutput, string.Empty, 0, 0, 0, 0, terminalModes: null, 1024); } - /// - /// Creates the shell. - /// - /// The encoding to use to send the input. - /// The input. - /// The output. - /// The extended output. - /// Name of the terminal. - /// The columns. - /// The rows. - /// The width. - /// The height. - /// The terminal mode. - /// Size of the internal read buffer. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary? terminalModes, int bufferSize) { /* @@ -347,56 +253,19 @@ public Shell CreateShell(Encoding encoding, string input, Stream output, Stream return CreateShell(_inputStream, output, extendedOutput, terminalName, columns, rows, width, height, terminalModes, bufferSize); } - /// - /// Creates the shell. - /// - /// The encoding. - /// The input. - /// The output. - /// The extended output. - /// Name of the terminal. - /// The columns. - /// The rows. - /// The width. - /// The height. - /// The terminal modes. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary terminalModes) { return CreateShell(encoding, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalModes, 1024); } - /// - /// Creates the shell. - /// - /// The encoding. - /// The input. - /// The output. - /// The extended output. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput) { return CreateShell(encoding, input, output, extendedOutput, string.Empty, 0, 0, 0, 0, terminalModes: null, 1024); } - /// - /// Creates the shell without allocating a pseudo terminal, - /// similar to the ssh -T option. - /// - /// The input. - /// The output. - /// The extended output. - /// Size of the internal read buffer. - /// - /// Returns a representation of a object. - /// - /// Client is not connected. + /// public Shell CreateShellNoTerminal(Stream input, Stream output, Stream extendedOutput, int bufferSize = -1) { EnsureSessionIsOpen(); @@ -404,58 +273,13 @@ public Shell CreateShellNoTerminal(Stream input, Stream output, Stream extendedO return new Shell(Session, input, output, extendedOutput, bufferSize); } - /// - /// Creates the shell stream. - /// - /// The TERM environment variable. - /// The terminal width in columns. - /// The terminal width in rows. - /// The terminal width in pixels. - /// The terminal height in pixels. - /// The size of the buffer. - /// - /// The created instance. - /// - /// Client is not connected. - /// - /// - /// The TERM environment variable contains an identifier for the text window's capabilities. - /// You can get a detailed list of these capabilities by using the ‘infocmp’ command. - /// - /// - /// The column/row dimensions override the pixel dimensions(when nonzero). Pixel dimensions refer - /// to the drawable area of the window. - /// - /// + /// public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize) { return CreateShellStream(terminalName, columns, rows, width, height, bufferSize, terminalModeValues: null); } - /// - /// Creates the shell stream. - /// - /// The TERM environment variable. - /// The terminal width in columns. - /// The terminal width in rows. - /// The terminal width in pixels. - /// The terminal height in pixels. - /// The size of the buffer. - /// The terminal mode values. - /// - /// The created instance. - /// - /// Client is not connected. - /// - /// - /// The TERM environment variable contains an identifier for the text window's capabilities. - /// You can get a detailed list of these capabilities by using the ‘infocmp’ command. - /// - /// - /// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer - /// to the drawable area of the window. - /// - /// + /// public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize, IDictionary? terminalModeValues) { EnsureSessionIsOpen(); @@ -463,15 +287,7 @@ public ShellStream CreateShellStream(string terminalName, uint columns, uint row return ServiceFactory.CreateShellStream(Session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize); } - /// - /// Creates the shell stream without allocating a pseudo terminal, - /// similar to the ssh -T option. - /// - /// The size of the buffer. - /// - /// The created instance. - /// - /// Client is not connected. + /// public ShellStream CreateShellStreamNoTerminal(int bufferSize = -1) { EnsureSessionIsOpen();