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;
}
///