Minor channel communication improvemtns, disconecting and error handeling improved

This commit is contained in:
olegkap_cp
2010-08-31 15:52:41 +00:00
parent f866e2f187
commit 073767a9fe
4 changed files with 93 additions and 36 deletions
@@ -13,7 +13,7 @@ namespace Renci.SshClient.Channels
private uint _initialWindowSize = 0x100000;
private uint _maximumPacketSize = 0x4000;
private uint _maximumPacketSize = 0x8000;
/// <summary>
/// Counts faile channel open attempts
@@ -196,10 +196,19 @@ namespace Renci.SshClient.Channels
if (message.RequestName == RequestNames.ExitStatus)
{
var exitStatus = message.ExitStatus;
replyMessage = new ChannelSuccessMessage()
{
ChannelNumber = message.ChannelNumber,
};
this.SendChannelCloseMessage();
// TODO: if exitStatus is not 0 then throw an exception or notify user that command failed to execute correctly
}
else
{
throw new NotImplementedException(string.Format("Request name {0} is not implemented.", message.RequestName));
}
if (message.WantReply)
@@ -229,6 +238,8 @@ namespace Renci.SshClient.Channels
this._channelClosedWaitHandle.Set();
}
#endregion
private void AdjustDataWindow(string messageData)
{
this.WindowSize -= (uint)messageData.Length;
@@ -245,8 +256,6 @@ namespace Renci.SshClient.Channels
}
}
#endregion
private void RaiseOpened()
{
if (this.Opened != null)
@@ -26,7 +26,7 @@ namespace Renci.SshClient.Channels
}
public ChannelExec(Session session, uint channelId)
: base(session, channelId, 0x100000, 0x1000)
: base(session, channelId, 0x100000, 0x8000)
{
}
@@ -47,7 +47,6 @@ namespace Renci.SshClient.Channels
};
this._callback = callback;
this._channelData = output;
this._channelExtendedData = extendedOutput;
@@ -67,26 +66,34 @@ namespace Renci.SshClient.Channels
internal void EndExecute(IAsyncResult result)
{
ChannelAsyncResult channelAsyncResult = result as ChannelAsyncResult;
if (channelAsyncResult.Channel != this)
try
{
throw new InvalidOperationException("Invalid IAsyncResult parameter");
ChannelAsyncResult channelAsyncResult = result as ChannelAsyncResult;
if (channelAsyncResult.Channel != this)
{
throw new InvalidOperationException("Invalid IAsyncResult parameter");
}
//Make sure that operation completed if not wait for it to finish
this.Session.WaitHandle(this._asyncResult.AsyncWaitHandle);
this.Close();
this._asyncResult = null;
if (this._exception != null)
{
var exception = this._exception;
this._exception = null; // Clean exception
throw exception;
}
}
catch (Exception exp)
{
throw;
}
//Make sure that operation completed if not wait for it to finish
this.Session.WaitHandle(this._asyncResult.AsyncWaitHandle);
this.Close();
this._asyncResult = null;
if (this._exception != null)
{
var exception = this._exception;
this._exception = null; // Clean exception
throw exception;
}
}
protected override void OnChannelEof()
@@ -96,6 +103,13 @@ namespace Renci.SshClient.Channels
this.ExecutionCompleted();
}
protected override void OnChannelClose()
{
base.OnChannelClose();
this.ExecutionCompleted();
}
protected override void OnChannelFailed(uint reasonCode, string description)
{
base.OnChannelFailed(reasonCode, description);
@@ -126,12 +126,12 @@ namespace Renci.SshClient.Common
public bool IsSynchronized
{
get { throw new System.NotImplementedException(); }
get { return true; }
}
public object SyncRoot
{
get { throw new System.NotImplementedException(); }
get { return this; }
}
#endregion
+46 -12
View File
@@ -72,6 +72,11 @@ namespace Renci.SshClient
/// </summary>
private EventWaitHandle _exceptionWaitHandle = new AutoResetEvent(false);
/// <summary>
/// WaitHandle to signal that listner ended
/// </summary>
private EventWaitHandle _listenerWaitHandle = new AutoResetEvent(false);
/// <summary>
/// Keeps track of all open channels
/// </summary>
@@ -87,6 +92,11 @@ namespace Renci.SshClient
/// </summary>
private bool _isAuthenticated;
/// <summary>
/// Specifies weither Disconnect method was called
/// </summary>
private bool _isDisconnecting;
/// <summary>
/// holds number to be used for session channels
/// </summary>
@@ -233,15 +243,18 @@ namespace Renci.SshClient
if (this.IsConnected)
return;
lock (this)
try
{
// If connected dont connect again
_authenticationConnection.Wait();
if (this.IsConnected)
return;
try
lock (this)
{
_authenticationConnection.Wait();
// If connected dont connect again
if (this.IsConnected)
return;
var ep = new IPEndPoint(Dns.GetHostAddresses(connectionInfo.Host)[0], connectionInfo.Port);
this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -331,11 +344,13 @@ namespace Renci.SshClient
{
throw new AuthenticationException(errorMessage ?? "User cannot be authenticated.");
}
Monitor.Pulse(this);
}
finally
{
_authenticationConnection.Release();
}
}
finally
{
_authenticationConnection.Release();
}
}
@@ -344,7 +359,8 @@ namespace Renci.SshClient
/// </summary>
public void Disconnect()
{
// TODO: Change message to something more appropriate
this._isDisconnecting = true;
this.Disconnect(DisconnectReasonCodes.ByApplication, "Connection terminated by the client.");
this.DisconnectCleanup();
@@ -359,6 +375,7 @@ namespace Renci.SshClient
var waitHandles = new WaitHandle[]
{
this._exceptionWaitHandle,
this._listenerWaitHandle, // When listener exits
waitHandle,
};
@@ -491,7 +508,7 @@ namespace Renci.SshClient
// Test packet minimum and maximum boundaries
if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > Session.MAXIMUM_PACKET_SIZE - 4)
throw new InvalidOperationException(string.Format("Bad packet length {0}", packetLength));
throw new IOException(string.Format("Bad packet length {0}", packetLength));
// Read rest of the packet data
int bytesToRead = (int)(packetLength - (blockSize - 4));
@@ -525,7 +542,7 @@ namespace Renci.SshClient
if (!serverHash.IsEqualTo(clientHash))
{
throw new InvalidOperationException("MAC error");
throw new IOException("MAC error");
}
}
@@ -839,9 +856,19 @@ namespace Renci.SshClient
this.RaiseMessageReceived(this, new MessageReceivedEventArgs(message));
}
}
catch (IOException)
catch (IOException exp)
{
// Ignore this error since socket was disconected
// Ensure socket is disconnected
this._socket.Close();
if (!this._isDisconnecting)
{
this._exceptionToThrow = exp;
this._exceptionWaitHandle.Set();
}
}
catch (Exception exp)
{
@@ -854,6 +881,8 @@ namespace Renci.SshClient
this._exceptionWaitHandle.Set();
}
this._listenerWaitHandle.Set();
}
/// <summary>
@@ -910,6 +939,11 @@ namespace Renci.SshClient
{
this._exceptionWaitHandle.Dispose();
}
if (this._listenerWaitHandle != null)
{
this._listenerWaitHandle.Dispose();
}
}
// Note disposing has been done.