Add ChannelAsyncResult and BeginEecute and EndExecute methods

This commit is contained in:
olegkap_cp
2010-08-11 21:27:42 +00:00
parent 775bb96b43
commit 7b6deebeee
6 changed files with 115 additions and 32 deletions
@@ -1,6 +1,5 @@
using System;
using System.Text;
using System.Threading;
using Renci.SshClient.Common;
using Renci.SshClient.Messages;
@@ -22,10 +21,6 @@ namespace Renci.SshClient.Channels
//private uint _maximumPacketSize = 0x4000;
private uint _maximumPacketSize = 1024;
protected StringBuilder ChannelData { get; private set; }
protected StringBuilder ChannelExtendedData { get; private set; }
public abstract ChannelTypes ChannelType { get; }
public uint ClientChannelNumber { get; set; }
@@ -62,8 +57,6 @@ namespace Renci.SshClient.Channels
}
this.Session = session;
this.ChannelData = new StringBuilder((int)this._initialWindowSize);
this.ChannelExtendedData = new StringBuilder((int)this._initialWindowSize);
this.WindowSize = this._initialWindowSize; // Initial window size
this.PacketSize = this._maximumPacketSize; // Maximum packet size
}
@@ -0,0 +1,33 @@
using System;
using System.Threading;
namespace Renci.SshClient.Channels
{
public class ChannelAsyncResult : IAsyncResult
{
/// <summary>
/// Gets or sets the channel that async result was created for.
/// </summary>
/// <value>The channel.</value>
internal ChannelExec Channel { get; private set; }
public int BytesReceived { get; set; }
#region IAsyncResult Members
public object AsyncState { get; internal set; }
public WaitHandle AsyncWaitHandle { get; internal set; }
public bool CompletedSynchronously { get; internal set; }
public bool IsCompleted { get; internal set; }
#endregion
internal ChannelAsyncResult(ChannelExec channel)
{
this.Channel = channel;
}
}
}
@@ -10,14 +10,16 @@ namespace Renci.SshClient.Channels
internal class ChannelExec : Channel
{
private EventWaitHandle _channelExecutionWaitHandle = new AutoResetEvent(false);
private Stream _channelData;
private Stream _channelExtendedData;
private Exception _exception;
private ChannelAsyncResult _asyncResult;
private AsyncCallback _callback;
public override ChannelTypes ChannelType
{
get { return ChannelTypes.Session; }
@@ -28,8 +30,24 @@ namespace Renci.SshClient.Channels
{
}
internal void Execute(string command, Stream output, Stream extendedOutput)
internal ChannelAsyncResult BeginExecute(string command, Stream output, Stream extendedOutput, AsyncCallback callback, object state)
{
// Prevent from executing BeginExecute before calling EndExecute
if (this._asyncResult != null)
{
throw new InvalidOperationException("");
}
// Create new AsyncResult object
this._asyncResult = new ChannelAsyncResult(this)
{
AsyncWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset),
IsCompleted = false,
AsyncState = state,
};
this._callback = callback;
this._channelData = output;
this._channelExtendedData = extendedOutput;
@@ -44,11 +62,25 @@ namespace Renci.SshClient.Channels
Command = command,
});
return _asyncResult;
}
this.Session.WaitHandle(this._channelExecutionWaitHandle);
internal void EndExecute(IAsyncResult result)
{
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._asyncResult.AsyncWaitHandle.WaitOne();
this.Close();
this._asyncResult = null;
if (this._exception != null)
{
var exception = this._exception;
@@ -61,14 +93,14 @@ namespace Renci.SshClient.Channels
{
base.OnChannelEof();
this._channelExecutionWaitHandle.Set();
this.ExecutionCompleted();
}
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._channelExecutionWaitHandle.Set();
this.ExecutionCompleted();
}
protected override void OnChannelData(string data)
@@ -92,10 +124,14 @@ namespace Renci.SshClient.Channels
}
}
private void Init()
private void ExecutionCompleted()
{
this.ChannelData.Length = 0;
this.ChannelExtendedData.Length = 0;
this._asyncResult.IsCompleted = true;
if (this._callback != null)
{
this._callback(this._asyncResult);
}
((EventWaitHandle)_asyncResult.AsyncWaitHandle).Set();
}
}
}
@@ -44,6 +44,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Channels\ChannelAsyncResult.cs" />
<Compile Include="Security\Algorithm.cs" />
<Compile Include="Security\Cipher.cs" />
<Compile Include="Security\CipherAES128.cs" />
+9 -3
View File
@@ -27,7 +27,13 @@ namespace Renci.SshClient
var ep = new IPEndPoint(Dns.GetHostAddresses(connectionInfo.Host)[0], connectionInfo.Port);
var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.ExclusiveAddressUse = true;
socket.Connect(ep);
// Connect socket with 5 seconds timeout
var connectResult = socket.BeginConnect(ep, null, null);
connectResult.AsyncWaitHandle.WaitOne(1000 * 15);
socket.EndConnect(connectResult);
// Get server version from the server,
// ignore text lines which are sent before if any
@@ -208,9 +214,9 @@ namespace Renci.SshClient
internal abstract void SendMessage(Message message);
internal void WaitHandle(EventWaitHandle waitHandle)
internal void WaitHandle(WaitHandle waitHandle)
{
var waitHandles = new EventWaitHandle[]
var waitHandles = new WaitHandle[]
{
this._disconnectWaitHandle,
this._exceptionWaitHandle,
+27 -13
View File
@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Text;
using Renci.SshClient.Channels;
@@ -15,28 +16,41 @@ namespace Renci.SshClient
public string Execute(string command)
{
//var channel = new ChannelSession(this._session);
MemoryStream resultStream = new MemoryStream();
var channel = this._session.CreateChannel<ChannelExec>();
channel.Execute(command, resultStream, null);
return Encoding.ASCII.GetString(resultStream.ToArray());
return this.Execute(command, null);
}
public string Execute(string command, Stream extended)
{
MemoryStream resultStream = new MemoryStream();
var channel = this._session.CreateChannel<ChannelExec>();
channel.Execute(command, resultStream, extended);
this.Execute(command, resultStream, extended);
return Encoding.ASCII.GetString(resultStream.ToArray());
}
public void Execute(string command, Stream output, Stream extended)
{
this.EndExecute(this.BeginExecute(command, output, extended, null, null));
}
public IAsyncResult BeginExecute(string command, Stream output, AsyncCallback callback, object state)
{
return this.BeginExecute(command, output, null, callback, state);
}
public IAsyncResult BeginExecute(string command, Stream output, Stream extendedOutput, AsyncCallback callback, object state)
{
var channel = this._session.CreateChannel<ChannelExec>();
return channel.BeginExecute(command, output, extendedOutput, callback, state);
}
public void EndExecute(IAsyncResult asynchResult)
{
ChannelAsyncResult channelAsyncResult = asynchResult as ChannelAsyncResult;
channelAsyncResult.Channel.EndExecute(asynchResult);
}
}
}