Skip to content

Commit c61633a

Browse files
committed
* Introduced ChannelExtendedDataEventArgs which is used to signal receive of extended data.
* Removed DataTypeCode from ChannelDataEventArgs, as this is specific to extended data. * Large set of optimizations in receive and send of SSH messages: - removed several buffer copies - modified most of the SSH messages to allow the size of the message to be calculated in advance to eliminate need to resize buffer. - added Compress(byte[] data, int offset, int length) overload to Compressor to compress part of a given buffer thereby avoiding need for buffer copy. - added Encrypt(byte[] data, int offset, int length) overload to Cipher to encrypt part of a given buffer thereby avoiding need for buffer copy. * SshData: - SshData.GetBytes uses a SshDataStream which has a capacity that (in almost all cases) matches the size of the SSH message. - Added a Load(byte[] value, int offset) overload. - Added a LoadBytes(byte[] bytes, int offset) overload. - Added a Write(byte[] data) overload. - Added a Write(byte[] buffer, int offset, int count) overload. * Added SendData(byte[] data, int offset, int size) overload to Channel to allow sending part of a given buffer. This avoids a buffer copy in ScpClient, SftpClient, Shell, ChannelDirectTcpip, ChannelForwardedTcpip. Fixes issue #1516. All optimization changes above are only active when the TUNING conditional compilation symbol is defined. By default, this symbol is defined.
1 parent be314d2 commit c61633a

File tree

220 files changed

+8986
-769
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

220 files changed

+8986
-769
lines changed

Renci.SshClient/Renci.SshNet.Tests/Classes/CipherInfoTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Renci.SshNet.Common;
23
using Renci.SshNet.Security.Cryptography;
34
using Renci.SshNet.Tests.Common;
45
using System;

Renci.SshClient/Renci.SshNet.Tests/Classes/Common/SshDataTest.cs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,35 @@ public class SshDataTest
99
[TestMethod]
1010
public void Write_Boolean_False()
1111
{
12-
var sshData = new MySshData();
13-
sshData.Load(new byte[0]);
12+
var sshData = new BoolSshData(false);
13+
14+
var bytes = sshData.GetBytes();
1415

15-
sshData.Write(false);
16-
Assert.AreEqual((byte) 0, sshData.ReadByte());
17-
Assert.IsTrue(sshData.IsEndOfData);
16+
Assert.AreEqual((byte) 0, bytes[0]);
1817
}
1918

2019
[TestMethod]
2120
public void Write_Boolean_True()
2221
{
23-
var sshData = new MySshData();
24-
sshData.Load(new byte[0]);
22+
var sshData = new BoolSshData(true);
2523

26-
sshData.Write(true);
27-
Assert.AreEqual((byte) 1, sshData.ReadByte());
28-
Assert.IsTrue(sshData.IsEndOfData);
24+
var bytes = sshData.GetBytes();
25+
26+
Assert.AreEqual((byte) 1, bytes[0]);
2927
}
3028

31-
private class MySshData : SshData
29+
private class BoolSshData : SshData
3230
{
33-
public new void Write(bool data)
31+
private readonly bool _value;
32+
33+
public BoolSshData(bool value)
34+
{
35+
_value = value;
36+
}
37+
38+
public new bool IsEndOfData
3439
{
35-
base.Write(data);
40+
get { return base.IsEndOfData; }
3641
}
3742

3843
public new byte ReadByte()
@@ -46,6 +51,7 @@ protected override void LoadData()
4651

4752
protected override void SaveData()
4853
{
54+
Write(_value);
4955
}
5056
}
5157
}

Renci.SshClient/Renci.SshNet.Tests/Classes/ForwardedPortRemoteTest_Dispose_PortStarted_ChannelBound.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ protected void Arrange()
100100
_sessionMock.Raise(s => s.RequestSuccessReceived += null,
101101
new MessageEventArgs<RequestSuccessMessage>(new RequestSuccessMessage())));
102102
_sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>()));
103-
_sessionMock.Setup(p => p.SendMessage(It.Is<ChannelOpenFailureMessage>(c => c.LocalChannelNumber == _remoteChannelNumberWhileClosing && c.ReasonCode == ChannelOpenFailureMessage.AdministrativelyProhibited && c.Description == string.Empty && c.Language == null)));
103+
_sessionMock.Setup(p => p.SendMessage(It.Is<ChannelOpenFailureMessage>(c => c.LocalChannelNumber == _remoteChannelNumberWhileClosing && c.ReasonCode == ChannelOpenFailureMessage.AdministrativelyProhibited && c.Description == string.Empty && c.Language == "en")));
104104
_sessionMock.Setup(p => p.CreateChannelForwardedTcpip(_remoteChannelNumberStarted, _remoteWindowSizeStarted, _remotePacketSizeStarted)).Returns(_channelMock.Object);
105105
_channelMock.Setup(
106106
p =>

Renci.SshClient/Renci.SshNet.Tests/Classes/ForwardedPortRemoteTest_Started.cs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -179,28 +179,6 @@ public void ForwardedPortShouldIgnoreChannelOpenMessageForOtherHostAndBoundPort(
179179
Assert.AreEqual(0, _exceptionRegister.Count);
180180
}
181181

182-
[TestMethod]
183-
public void ForwardedPortShouldIgnoreChannelOpenMessageWhenChannelOpenInfoIsNull()
184-
{
185-
var channelNumber = (uint)new Random().Next(1001, int.MaxValue);
186-
var initialWindowSize = (uint)new Random().Next(0, int.MaxValue);
187-
var maximumPacketSize = (uint)new Random().Next(0, int.MaxValue);
188-
var channelMock = new Mock<IChannelForwardedTcpip>(MockBehavior.Strict);
189-
190-
_sessionMock.Setup(
191-
p =>
192-
p.CreateChannelForwardedTcpip(channelNumber, initialWindowSize, maximumPacketSize)).Returns(channelMock.Object);
193-
194-
_sessionMock.Raise(p => p.ChannelOpenReceived += null,
195-
new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(channelNumber, initialWindowSize,
196-
maximumPacketSize, null)));
197-
198-
_sessionMock.Verify(p => p.CreateChannelForwardedTcpip(channelNumber, initialWindowSize, maximumPacketSize), Times.Never);
199-
200-
Assert.AreEqual(0, _closingRegister.Count);
201-
Assert.AreEqual(0, _exceptionRegister.Count);
202-
}
203-
204182
[TestMethod]
205183
public void ForwardedPortShouldIgnoreChannelOpenMessageWhenChannelOpenInfoIsNotForwardedTcpipChannelInfo()
206184
{
@@ -215,7 +193,7 @@ public void ForwardedPortShouldIgnoreChannelOpenMessageWhenChannelOpenInfoIsNotF
215193

216194
_sessionMock.Raise(p => p.ChannelOpenReceived += null,
217195
new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(channelNumber, initialWindowSize,
218-
maximumPacketSize, new DirectTcpipChannelInfo())));
196+
maximumPacketSize, new DirectTcpipChannelInfo("HOST", 5, "ORIGIN", 4))));
219197

220198
_sessionMock.Verify(p => p.CreateChannelForwardedTcpip(channelNumber, initialWindowSize, maximumPacketSize), Times.Never);
221199

Renci.SshClient/Renci.SshNet.Tests/Classes/Messages/Authentication/RequestMessageTest.cs

Lines changed: 0 additions & 42 deletions
This file was deleted.
Lines changed: 153 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Renci.SshNet.Messages.Connection;
1+
using System.Linq;
2+
using Renci.SshNet.Common;
3+
using Renci.SshNet.Messages.Connection;
24
using Microsoft.VisualStudio.TestTools.UnitTesting;
35
using System;
46
using Renci.SshNet.Tests.Common;
@@ -9,29 +11,162 @@ namespace Renci.SshNet.Tests.Classes.Messages.Connection
911
///This is a test class for ChannelDataMessageTest and is intended
1012
///to contain all ChannelDataMessageTest Unit Tests
1113
///</summary>
12-
[TestClass()]
14+
[TestClass]
1315
public class ChannelDataMessageTest : TestBase
1416
{
15-
/// <summary>
16-
///A test for ChannelDataMessage Constructor
17-
///</summary>
18-
[TestMethod()]
19-
public void ChannelDataMessageConstructorTest()
17+
[TestMethod]
18+
public void DefaultConstructor()
2019
{
21-
ChannelDataMessage target = new ChannelDataMessage();
22-
Assert.Inconclusive("TODO: Implement code to verify target");
20+
var target = new ChannelDataMessage();
21+
22+
Assert.IsNull(target.Data);
23+
#if TUNING
24+
Assert.AreEqual(0, target.Offset);
25+
Assert.AreEqual(0, target.Size);
26+
#endif
27+
}
28+
29+
[TestMethod]
30+
public void Constructor_LocalChannelNumberAndData()
31+
{
32+
var random = new Random();
33+
34+
var localChannelNumber = (uint)random.Next(0, int.MaxValue);
35+
var data = new byte[3];
36+
37+
var target = new ChannelDataMessage(localChannelNumber, data);
38+
39+
Assert.AreSame(data, target.Data);
40+
#if TUNING
41+
Assert.AreEqual(0, target.Offset);
42+
Assert.AreEqual(data.Length, target.Size);
43+
#endif
44+
}
45+
46+
[TestMethod]
47+
public void Constructor_LocalChannelNumberAndData_ShouldThrowArgumentNullExceptionWhenDataIsNull()
48+
{
49+
var localChannelNumber = (uint) new Random().Next(0, int.MaxValue);
50+
byte[] data = null;
51+
52+
try
53+
{
54+
new ChannelDataMessage(localChannelNumber, data);
55+
Assert.Fail();
56+
}
57+
catch (ArgumentNullException ex)
58+
{
59+
Assert.IsNull(ex.InnerException);
60+
Assert.AreEqual("data", ex.ParamName);
61+
}
62+
}
63+
64+
#if TUNING
65+
[TestMethod]
66+
public void Constructor_LocalChannelNumberAndDataAndOffsetAndSize()
67+
{
68+
var localChannelNumber = (uint) new Random().Next(0, int.MaxValue);
69+
var data = new byte[4];
70+
const int offset = 2;
71+
const int size = 1;
72+
73+
var target = new ChannelDataMessage(localChannelNumber, data, offset, size);
74+
75+
Assert.AreSame(data, target.Data);
76+
Assert.AreEqual(offset, target.Offset);
77+
Assert.AreEqual(size, target.Size);
78+
}
79+
80+
[TestMethod]
81+
public void Constructor_LocalChannelNumberAndDataAndOffsetAndSize_ShouldThrowArgumentNullExceptionWhenDataIsNull()
82+
{
83+
var localChannelNumber = (uint) new Random().Next(0, int.MaxValue);
84+
byte[] data = null;
85+
const int offset = 0;
86+
const int size = 0;
87+
88+
try
89+
{
90+
new ChannelDataMessage(localChannelNumber, data, offset, size);
91+
Assert.Fail();
92+
}
93+
catch (ArgumentNullException ex)
94+
{
95+
Assert.IsNull(ex.InnerException);
96+
Assert.AreEqual("data", ex.ParamName);
97+
}
98+
}
99+
#endif
100+
101+
[TestMethod]
102+
public void GetBytes()
103+
{
104+
var random = new Random();
105+
106+
var localChannelNumber = (uint) random.Next(0, int.MaxValue);
107+
var data = new byte[random.Next(10, 20)];
108+
random.NextBytes(data);
109+
#if TUNING
110+
var offset = random.Next(2, 4);
111+
var size = random.Next(5, 9);
112+
113+
var target = new ChannelDataMessage(localChannelNumber, data, offset, size);
114+
#else
115+
var offset = 0;
116+
var size = data.Length;
117+
118+
var target = new ChannelDataMessage(localChannelNumber, data);
119+
#endif
120+
121+
var bytes = target.GetBytes();
122+
123+
var expectedBytesLength = 1; // Type
124+
expectedBytesLength += 4; // LocalChannelNumber
125+
expectedBytesLength += 4; // Data length
126+
expectedBytesLength += size; // Data
127+
128+
Assert.AreEqual(expectedBytesLength, bytes.Length);
129+
130+
var sshDataStream = new SshDataStream(bytes);
131+
132+
Assert.AreEqual(ChannelDataMessage.MessageNumber, sshDataStream.ReadByte());
133+
Assert.AreEqual(localChannelNumber, sshDataStream.ReadUInt32());
134+
Assert.AreEqual((uint) size, sshDataStream.ReadUInt32());
135+
136+
var actualData = new byte[size];
137+
sshDataStream.Read(actualData, 0, size);
138+
Assert.IsTrue(actualData.SequenceEqual(data.Take(offset, size)));
139+
140+
Assert.IsTrue(sshDataStream.IsEndOfData);
23141
}
24142

25-
/// <summary>
26-
///A test for ChannelDataMessage Constructor
27-
///</summary>
28-
[TestMethod()]
29-
public void ChannelDataMessageConstructorTest1()
143+
[TestMethod]
144+
public void Load()
30145
{
31-
uint localChannelNumber = 0; // TODO: Initialize to an appropriate value
32-
byte[] data = null; // TODO: Initialize to an appropriate value
33-
ChannelDataMessage target = new ChannelDataMessage(localChannelNumber, data);
34-
Assert.Inconclusive("TODO: Implement code to verify target");
146+
var random = new Random();
147+
148+
var localChannelNumber = (uint)random.Next(0, int.MaxValue);
149+
var data = new byte[random.Next(10, 20)];
150+
random.NextBytes(data);
151+
#if TUNING
152+
var offset = random.Next(2, 4);
153+
var size = random.Next(5, 9);
154+
var channelDataMessage = new ChannelDataMessage(localChannelNumber, data, offset, size);
155+
#else
156+
var offset = 0;
157+
var size = data.Length;
158+
var channelDataMessage = new ChannelDataMessage(localChannelNumber, data);
159+
#endif
160+
var bytes = channelDataMessage.GetBytes();
161+
var target = new ChannelDataMessage();
162+
163+
target.Load(bytes);
164+
165+
Assert.IsTrue(target.Data.SequenceEqual(data.Take(offset, size)));
166+
#if TUNING
167+
Assert.AreEqual(0, target.Offset);
168+
Assert.AreEqual(size, target.Size);
169+
#endif
35170
}
36171
}
37172
}

0 commit comments

Comments
 (0)