diff --git a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs index 3e6ab67d..9959362b 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs @@ -16,6 +16,8 @@ namespace Renci.SshClient.Channels private uint _maximumPacketSize = 0x4000; + private int _chanelOpenFailedAttempts = 0; + public abstract ChannelTypes ChannelType { get; } public uint ClientChannelNumber { get; set; } @@ -155,9 +157,18 @@ namespace Renci.SshClient.Channels private void HandleMessage(ChannelOpenFailureMessage message) { - this.IsOpen = false; - this._channelOpenWaitHandle.Set(); - this.OnChannelFailed(message.ReasonCode, message.Description); + if (_chanelOpenFailedAttempts > this.Session.ConnectionInfo.RetryAttempts) + { + this.IsOpen = false; + + this._channelOpenWaitHandle.Set(); + this.OnChannelFailed(message.ReasonCode, message.Description); + } + else + { + // Try to open channel again + this.Open(); + } } private void HandleMessage(ChannelWindowAdjustMessage message) diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs index 8bb6082a..f1c4d1fe 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs @@ -99,6 +99,7 @@ namespace Renci.SshClient.Channels protected override void OnChannelFailed(uint reasonCode, string description) { base.OnChannelFailed(reasonCode, description); + this._exception = new InvalidOperationException(string.Format("Channel failed to open. Code: {0}, Reason {1}", reasonCode, description)); this.ExecutionCompleted(); } diff --git a/Renci.SshClient/Renci.SshClient/ConnectionInfo.cs b/Renci.SshClient/Renci.SshClient/ConnectionInfo.cs index a27f31fa..8f5fd828 100644 --- a/Renci.SshClient/Renci.SshClient/ConnectionInfo.cs +++ b/Renci.SshClient/Renci.SshClient/ConnectionInfo.cs @@ -14,11 +14,14 @@ public int Timeout { get; set; } + public int RetryAttempts { get; set; } + public ConnectionInfo() { // Set default connection values this.Port = 22; this.Timeout = 1000 * 10; // Set default timeout to 10 sec + this.RetryAttempts = 3; } } } diff --git a/Renci.SshClient/Renci.SshClient/Session.cs b/Renci.SshClient/Renci.SshClient/Session.cs index 9f5e6697..c7951ce0 100644 --- a/Renci.SshClient/Renci.SshClient/Session.cs +++ b/Renci.SshClient/Renci.SshClient/Session.cs @@ -29,10 +29,10 @@ namespace Renci.SshClient /// New version specific session. public static Session CreateSession(ConnectionInfo connectionInfo) { + // TODO: See if possible to move socket connection logic to Connect method + var ep = new IPEndPoint(Dns.GetHostAddresses(connectionInfo.Host)[0], connectionInfo.Port); var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - socket.NoDelay = true; - socket.ExclusiveAddressUse = true; // Connect socket with 5 seconds timeout var connectResult = socket.BeginConnect(ep, null, null); @@ -41,11 +41,14 @@ namespace Renci.SshClient socket.EndConnect(connectResult); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1); + // Get server version from the server, // ignore text lines which are sent before if any var serverVersion = string.Empty; - using (StreamReader sr = new StreamReader(new NetworkStream(socket))) + using (var ns = new NetworkStream(socket)) + using (var sr = new StreamReader(ns)) { while (true) { @@ -59,6 +62,7 @@ namespace Renci.SshClient break; } } + ns.Close(); } // TODO: Create session based on server version @@ -199,13 +203,9 @@ namespace Renci.SshClient { this.ConnectionInfo = connectionInfo; this._socket = socket; - this._socket.NoDelay = true; - this._socket.Blocking = true; this.ServerVersion = serverVersion; this.ClientVersion = string.Format("SSH-2.0-Renci.SshClient.{0}", this.GetType().Assembly.GetName().Version); - - this._socketStream = new NetworkStream(socket); } private static IDictionary> _channels = new Dictionary>() @@ -236,6 +236,8 @@ namespace Renci.SshClient { lock (this._socket) { + this._socketStream = new NetworkStream(this._socket); + // If connected dont connect again if (this.IsConnected) return; @@ -615,6 +617,10 @@ namespace Renci.SshClient { // Stop running listener thread + + if (this._socketStream != null) + this._socketStream.Close(); + // Close all open channels if any foreach (var channelId in this._openChannels.Values) { @@ -625,11 +631,12 @@ namespace Renci.SshClient } // Close socket connection if still open - if (this.IsConnected) + if (this._socket != null) { - this._socket.Disconnect(false); - this.IsConnected = false; + this._socket.Close(); } + + this.IsConnected = false; } ///