Skip to content

Add .SendData method for SshCommand #803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions src/Renci.SshNet.Tests/Classes/SshCommandTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Renci.SshNet.Tests.Properties;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
#if FEATURE_TPL
Expand Down Expand Up @@ -266,7 +267,7 @@ public void Test_Execute_Command_ExitStatus()
client.Connect();

var cmd = client.RunCommand("exit 128");

Console.WriteLine(cmd.ExitStatus);

client.Disconnect();
Expand Down Expand Up @@ -500,6 +501,55 @@ public void Test_Execute_Invalid_Command()
}
}

[TestMethod]
[TestCategory("integration")]
public void SendDataTestText()
{
SendDataTest(
Encoding.UTF8.GetBytes("Hello "), Encoding.UTF8.GetBytes("world!"),
Encoding.UTF8.GetBytes("A\nB\nC\nD"));
}

[TestMethod]
[TestCategory("integration")]
public void SendDataTestRandomBytes()
{
var random = new Random();
var randomData = new byte[1024];
random.NextBytes(randomData);

SendDataTest(randomData);
}

public void SendDataTest(params byte[][] data)
{
using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
{
#region Example SshCommand CreateCommand BeginExecute SendData EndExecute

client.Connect();

var cmd = client.CreateCommand("cat -");

var asynch = cmd.BeginExecute();

foreach (var dataBlock in data)
{
cmd.SendData(dataBlock);

var fromStdout = new byte[dataBlock.Length];
cmd.OutputStream.Read(fromStdout, 0, 0);

Assert.IsTrue(dataBlock.SequenceEqual(fromStdout));
}

cmd.EndExecute(asynch);

client.Disconnect();

#endregion
}
}

/// <summary>
///A test for BeginExecute
Expand Down Expand Up @@ -637,7 +687,7 @@ public void Test_MultipleThread_Example_MultipleConnections()

try
{
#region Example SshCommand RunCommand Parallel
#region Example SshCommand RunCommand Parallel
System.Threading.Tasks.Parallel.For(0, 10000,
() =>
{
Expand All @@ -657,7 +707,7 @@ public void Test_MultipleThread_Example_MultipleConnections()
client.Dispose();
}
);
#endregion
#endregion

}
catch (Exception exp)
Expand Down
35 changes: 35 additions & 0 deletions src/Renci.SshNet/SshCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,41 @@ private void Channel_DataReceived(object sender, ChannelDataEventArgs e)
}
}

/// <summary>
/// Sends a SSH_MSG_CHANNEL_DATA message with the specified payload.
/// </summary>
/// <param name="data">The payload to send.</param>
public void SendData(byte[] data)
{
_channel.SendData(data);
}

/// <summary>
/// Sends a SSH_MSG_CHANNEL_DATA message with the specified payload.
/// </summary>
/// <param name="data">An array of <see cref="byte"/> containing the payload to send.</param>
/// <param name="offset">The zero-based offset in <paramref name="data"/> at which to begin taking data from.</param>
/// <param name="size">The number of bytes of <paramref name="data"/> to send.</param>
/// <remarks>
/// <para>
/// When the size of the data to send exceeds the maximum packet size or the remote window
/// size does not allow the full data to be sent, then this method will send the data in
/// multiple chunks and will wait for the remote window size to be adjusted when it's zero.
/// </para>
/// <para>
/// This is done to support SSH servers will a small window size that do not agressively
/// increase their window size. We need to take into account that there may be SSH servers
/// that only increase their window size when it has reached zero.
/// </para>
/// </remarks>
public void SendData(byte[] data, int offset, int size)
{
_channel.SendData(data, offset, size);
}

/// <summary>
/// Waits on the wait handle <paramref name="waitHandle"/>.
/// </summary>
/// <exception cref="SshOperationTimeoutException">Command '{0}' has timed out.</exception>
/// <remarks>The actual command will be included in the exception message.</remarks>
private void WaitOnHandle(WaitHandle waitHandle)
Expand Down