From 2bbb42508ba14c863dacfba0d8cf905d5597d17b Mon Sep 17 00:00:00 2001 From: olegkap_cp Date: Fri, 10 Dec 2010 14:09:44 +0000 Subject: [PATCH] Add method KeepAlive to SshClient to allow to send dummy KeepAlive requests Dont allow por forwarding to start or stop if its already started or stopped --- .../Renci.SshClient/ForwardedPort.cs | 2 + .../Renci.SshClient/ForwardedPortLocal.cs | 15 +++++++ .../Renci.SshClient/ForwardedPortRemote.cs | 12 ++++++ .../Connection/GlobalRequestMessage.cs | 19 ++++++++- .../Messages/Connection/GlobalRequestNames.cs | 6 ++- Renci.SshClient/Renci.SshClient/Session.cs | 12 ++++++ Renci.SshClient/Renci.SshClient/SshClient.cs | 40 ++++++------------- 7 files changed, 76 insertions(+), 30 deletions(-) diff --git a/Renci.SshClient/Renci.SshClient/ForwardedPort.cs b/Renci.SshClient/Renci.SshClient/ForwardedPort.cs index 00f40309..44d4bbbc 100644 --- a/Renci.SshClient/Renci.SshClient/ForwardedPort.cs +++ b/Renci.SshClient/Renci.SshClient/ForwardedPort.cs @@ -12,6 +12,8 @@ namespace Renci.SshClient public uint ConnectedPort { get; internal set; } + public bool IsStarted { get; protected set; } + public event EventHandler Exception; internal ForwardedPort() diff --git a/Renci.SshClient/Renci.SshClient/ForwardedPortLocal.cs b/Renci.SshClient/Renci.SshClient/ForwardedPortLocal.cs index 02a89d28..9e0d1716 100644 --- a/Renci.SshClient/Renci.SshClient/ForwardedPortLocal.cs +++ b/Renci.SshClient/Renci.SshClient/ForwardedPortLocal.cs @@ -16,6 +16,10 @@ namespace Renci.SshClient { base.Start(); + // If port already started dont start it again + if (this.IsStarted) + return; + var ep = new IPEndPoint(Dns.GetHostAddresses("localhost")[0], (int)this.BoundPort); this._listener = new TcpListener(ep); this._listener.Start(); @@ -53,13 +57,24 @@ namespace Renci.SshClient { this.RaiseExceptionEvent(exp); } + + this.Stop(); }); + + this.IsStarted = true; } public override void Stop() { + // If port not started you cant stop it + if (!this.IsStarted) + return; + this._listener.Stop(); this._listenerTask.Wait(); + + this.IsStarted = false; + } } } diff --git a/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs b/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs index 31df54c1..2acf247c 100644 --- a/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs +++ b/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs @@ -16,6 +16,10 @@ namespace Renci.SshClient { base.Start(); + // If port already started dont start it again + if (this.IsStarted) + return; + this.Session.RegisterMessageType(Messages.MessageTypes.RequestFailure); this.Session.RegisterMessageType(Messages.MessageTypes.RequestSuccess); this.Session.RegisterMessageType(Messages.MessageTypes.ChannelOpen); @@ -40,10 +44,16 @@ namespace Renci.SshClient // If request failed dont handle channel opening for this request this.Session.ChannelOpenReceived -= Session_ChannelOpening; } + + this.IsStarted = true; } public override void Stop() { + // If port not started you cant stop it + if (!this.IsStarted) + return; + // Send global request to cancel direct tcpip this.Session.SendMessage(new GlobalRequestMessage { @@ -58,6 +68,8 @@ namespace Renci.SshClient this.Session.RequestSuccessReceived -= Session_RequestSuccess; this.Session.RequestFailureReceived -= Session_RequestFailure; this.Session.ChannelOpenReceived -= Session_ChannelOpening; + + this.IsStarted = false; } private void Session_ChannelOpening(object sender, MessageEventArgs e) diff --git a/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestMessage.cs b/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestMessage.cs index 1ee9669b..895b2b5b 100644 --- a/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestMessage.cs +++ b/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestMessage.cs @@ -47,12 +47,27 @@ namespace Renci.SshClient.Messages.Connection case GlobalRequestNames.CancelTcpIpForward: this.Write("cancel-tcpip-forward"); break; + case GlobalRequestNames.KeepAlive: + this.Write("keep-alive-message-ignore-me"); + break; default: break; } + this.Write(this.WantReply); - this.Write(this.AddressToBind); - this.Write(this.PortToBind); + + switch (this.RequestName) + { + case GlobalRequestNames.TcpIpForward: + case GlobalRequestNames.CancelTcpIpForward: + this.Write(this.AddressToBind); + this.Write(this.PortToBind); + break; + case GlobalRequestNames.KeepAlive: + break; + default: + break; + } } } } diff --git a/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestNames.cs b/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestNames.cs index 8eb0c61f..3078e881 100644 --- a/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestNames.cs +++ b/Renci.SshClient/Renci.SshClient/Messages/Connection/GlobalRequestNames.cs @@ -9,6 +9,10 @@ /// /// cancel-tcpip-forward /// - CancelTcpIpForward + CancelTcpIpForward, + /// + /// keep-alive-message-ignore-me + /// + KeepAlive } } diff --git a/Renci.SshClient/Renci.SshClient/Session.cs b/Renci.SshClient/Renci.SshClient/Session.cs index 0a4f7136..ed09e873 100644 --- a/Renci.SshClient/Renci.SshClient/Session.cs +++ b/Renci.SshClient/Renci.SshClient/Session.cs @@ -568,6 +568,18 @@ namespace Renci.SshClient return channel; } + /// + /// Sends "keep alive" message to keep connection alive. + /// + internal void KeepAlive() + { + this.SendMessage(new GlobalRequestMessage + { + RequestName = GlobalRequestNames.KeepAlive, + WantReply = false + }); + } + /// /// Waits for handle to signal while checking other handles as well including timeout check to prevent waiting for ever /// diff --git a/Renci.SshClient/Renci.SshClient/SshClient.cs b/Renci.SshClient/Renci.SshClient/SshClient.cs index 40059eb8..9b435446 100644 --- a/Renci.SshClient/Renci.SshClient/SshClient.cs +++ b/Renci.SshClient/Renci.SshClient/SshClient.cs @@ -23,23 +23,6 @@ namespace Renci.SshClient } } - //private Sftp _sftp; - ///// - ///// Gets the shell. - ///// - ///// The shell. - //public Sftp Sftp - //{ - // get - // { - // if (this._sftp == null) - // { - // this._sftp = new Sftp(this._session); - // } - // return this._sftp; - // } - //} - public IEnumerable ForwardedPorts { get @@ -128,6 +111,19 @@ namespace Renci.SshClient return port; } + public void RemoveForwardedPort(ForwardedPort port) + { + // Stop port forwarding before removing it + port.Stop(); + + this._forwardedPorts.Remove(port); + } + + public void KeepAlive() + { + this._session.KeepAlive(); + } + public SshCommand CreateCommand(string commandText) { return new SshCommand(this._session, commandText); @@ -145,16 +141,6 @@ namespace Renci.SshClient return new Shell(this._session, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode); } - //public Sftp CreateSftp() - //{ - // return new Sftp(this._session); - //} - - public void RemoveForwardedPort(ForwardedPort port) - { - this._forwardedPorts.Remove(port); - } - #region IDisposable Members private bool disposed = false;