Skip to content

Commit 05cdb78

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/develop'
2 parents 177812f + 75d982b commit 05cdb78

Some content is hidden

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

51 files changed

+1126
-968
lines changed

build/nuget/SSH.NET.nuspec

+1-119
Original file line numberDiff line numberDiff line change
@@ -10,125 +10,7 @@
1010
<projectUrl>https://github.com/sshnet/SSH.NET/</projectUrl>
1111
<requireLicenseAcceptance>false</requireLicenseAcceptance>
1212
<description>SSH.NET is a Secure Shell (SSH) library for .NET, optimized for parallelism and with broad framework support.</description>
13-
<releaseNotes>2016.0.0-beta3
14-
==============
15-
16-
New Features:
17-
18-
* Added support for .NET Core 1.0 (.NETStandard 1.3)
19-
20-
2016.0.0-beta2
21-
==============
22-
23-
Changes:
24-
25-
* Improved performance of ScpClient (GitHub issue #21)
26-
27-
Fixes:
28-
29-
* Terminal width (pixels) is not passed in pty-req
30-
* Stopping ForwardedPortDynamic without ever having started would result in a NRE
31-
32-
2016.0.0-beta1
33-
==============
34-
35-
New Features:
36-
37-
* Added support for HMAC-SHA512 (hmac-sha2-512 and hmac-sha2-512-96)
38-
* Added support for Universal Windows Platform 10 (UAP10.0)
39-
40-
Changes:
41-
42-
* Overall performance improvements
43-
* Relicensed code under MIT license, explicitly permitting reuse within proprietary software
44-
provided all copies of the licensed software include a copy of the MIT License terms and the
45-
copyright notice
46-
* Separated our hash algorithms into SshNet.Security.Cryptography project and package
47-
* When available, prefer hash algorithms and encodings from target framework
48-
* Refactoring to prepare for upcoming .NET Core support
49-
50-
Fixes:
51-
52-
* Partial reads from stream assume end (CodePlex issue #1516)
53-
* Session.Disconnect() hangs forever (CodePlex issue #2591)
54-
* SshData.ReadInt64() is broken (CodePlex issue #2579)
55-
* Race condition when SSH_MSG_GLOBAL_REQUEST is received immediately after successful authentication (GitHub issue #8)
56-
57-
2014.4.6-beta2
58-
==============
59-
60-
New Features:
61-
62-
* Improved accuracy of IsConnected on .NET
63-
* Added support for ssh.com (SSH-2) private keys (issue #1987)
64-
* Support an acceptable group of up to 8192 bits for SHA-1 and SHA-256 Diffie-Hellman Group and Key Exchange (issues #1973 and #1777)
65-
66-
Changes:
67-
68-
* Reduced default buffer size for SftpClient from 64 KB to 32 KB as some SSH servers apply a hard limit of 64 KB at the transport level.
69-
70-
Fixes:
71-
72-
* SftpClient is throwing undocumented exceptions (issue #2148)
73-
* Client channels are no longer closed on dispose (issue #1943)
74-
* SftpClient.Exists(string) returns true for a path that does not exist (issues #1952, #1696 and #1574)
75-
* ObjectDisposedException when channel is closing (issues #1942 and #1944)
76-
* Stack overflow during authentication when server returns same allowed methods after partial success (issue #2399)
77-
* SshCommand doesn't cleanup subscribed events (issue #2295)
78-
* Lines before protocol identification string are not skipped (issue #1935 and #2223)
79-
* ShellStream.ReadLine produces incorrect output when reading multi-byte characters (issue #2190)
80-
* SftpClient constructor throws ArgumentException when host contains underscore (issue #1845)
81-
* Signing key is missing from source download (issue #2455)
82-
* Forwarded Port channels can get stuck waiting (issue #1558)
83-
* NullReferenceException when SftpFileStream is finalized after dispose of session (issue #2013)
84-
* BlockCipher.Encrypt fails if input message is not padded (issue #2547)
85-
* ScpClient: Missing files when using DirectoryUpload (issue #1382)
86-
* Dynamic port forwarding slows down to a crawl (issue #2010)
87-
* SendKeepAlive causes SocketException when connection is dropped (issue #2029)
88-
* SocketException on Dispose or Disconnect (issue #2400)
89-
* Sending EOF on wrong channel number (issue #1877)
90-
* ForwardedPortDynamic: Unhandled exception if client terminates socket (issue #1844)
91-
92-
2014.4.6-beta1
93-
==============
94-
95-
New Features:
96-
97-
* Added callbacks to UploadFile, DownloadFile and ListDirectory in SftpClient (issue #1324)
98-
* Allow a given private key file to be used concurrently
99-
* Performance improvements:
100-
- optimization of payload size for both read and write operations (SftpClient only)
101-
- increase window size from 1MB to 2MB
102-
- increase buffer size from 16KB to 64KB for SftpClient
103-
- take into account the maximum remote packet size of the channel for write operations
104-
- increase maximum size of packets that we can receive from 32 KB to 64 KB
105-
* Improve exception message for authentication failures
106-
107-
Breaking changes:
108-
109-
* Assembly name is now Renci.SshNet for all supported frameworks
110-
* The Renci.SshNet assemblies for .NET and Silverlight are now strong-named (issue #1802)
111-
112-
Fixes:
113-
114-
* Incorrect copyright in assemblies (issue #1764)
115-
* Remove linefeed from WriteLine method in Shellstream class (issue #1584)
116-
* Disable logging of messages in release builds (issue #1767)
117-
* Stuck loop on key exchange using arcfour encryption (issue #1922)
118-
* Timeout sending data to server with low window size (issue #1706)
119-
* No connection possible with the same auth method requested multiple times (issue #1930)
120-
* Unobserved exception rethrown by finalizer thread (issue #1298 and #1587)
121-
* Client cipher is used to decrypt server messages (issue #1917)
122-
* Connection dropped by server due to invalid DSA signature (issue #1918)
123-
* Correct casing of Security/Cryptography/HMAC.cs to fix build on Linux (issue #1505)
124-
* HTTP proxy hangs (issue #1890)
125-
* Wrong parameters to SetSocketOption leads to SocketException under Mono (issue #1799)
126-
* Incorrect check for timeout values (issue #1620)
127-
* Wrong PKCS7 padding in DES algorithm (issue #1580)
128-
* OverflowException on empty server response (issue #1562)
129-
* Event handle leak (issue #1761)
130-
* SftpFileStream is very slow (issue #1919)
131-
* Write access required for private key file</releaseNotes>
13+
<releaseNotes>https://github.com/sshnet/SSH.NET/releases/tag/2016.0.0-beta3</releaseNotes>
13214
<summary>A Secure Shell (SSH) library for .NET, optimized for parallelism.</summary>
13315
<copyright>2012-2016, RENCI</copyright>
13416
<language>en-US</language>

src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Close_SessionIsConnectedAndChannelIsOpen_EofReceived.cs

+22-15
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ public class ChannelTest_Close_SessionIsConnectedAndChannelIsOpen_EofReceived
2020
private uint _remoteWindowSize;
2121
private uint _remotePacketSize;
2222
private ChannelStub _channel;
23-
private Stopwatch _closeTimer;
2423
private List<ChannelEventArgs> _channelClosedRegister;
2524
private IList<ExceptionEventArgs> _channelExceptionRegister;
25+
private ManualResetEvent _channelClosedReceived;
2626

2727
[TestInitialize]
2828
public void Initialize()
@@ -31,6 +31,16 @@ public void Initialize()
3131
Act();
3232
}
3333

34+
[TestCleanup]
35+
public void TearDown()
36+
{
37+
if (_channelClosedReceived != null)
38+
{
39+
_channelClosedReceived.Dispose();
40+
_channelClosedReceived = null;
41+
}
42+
}
43+
3444
private void Arrange()
3545
{
3646
var random = new Random();
@@ -40,9 +50,9 @@ private void Arrange()
4050
_remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
4151
_remoteWindowSize = (uint)random.Next(0, int.MaxValue);
4252
_remotePacketSize = (uint)random.Next(0, int.MaxValue);
43-
_closeTimer = new Stopwatch();
4453
_channelClosedRegister = new List<ChannelEventArgs>();
4554
_channelExceptionRegister = new List<ExceptionEventArgs>();
55+
_channelClosedReceived = new ManualResetEvent(false);
4656

4757
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
4858

@@ -55,22 +65,19 @@ private void Arrange()
5565
new Thread(() =>
5666
{
5767
Thread.Sleep(100);
68+
// signal that the ChannelCloseMessage was received; we use this to verify whether we've actually
69+
// waited on the EventWaitHandle to be set
70+
_channelClosedReceived.Set();
5871
// raise ChannelCloseReceived event to set waithandle for receiving
5972
// SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
6073
// sending the SSH_MSG_CHANNEL_CLOSE message to the server
61-
_sessionMock.Raise(s => s.ChannelCloseReceived += null,
62-
new MessageEventArgs<ChannelCloseMessage>(
63-
new ChannelCloseMessage(_localChannelNumber)));
74+
//
75+
// we're mocking the wait on the ChannelCloseMessage, but we still want
76+
// to get the channel in the state that it would have after actually receiving
77+
// the ChannelCloseMessage
78+
_sessionMock.Raise(s => s.ChannelCloseReceived += null, new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
6479
}).Start();
65-
_closeTimer.Start();
66-
try
67-
{
68-
w.WaitOne();
69-
}
70-
finally
71-
{
72-
_closeTimer.Stop();
73-
}
80+
w.WaitOne();
7481
});
7582

7683
_channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
@@ -120,7 +127,7 @@ public void WaitOnHandleOnSessionShouldBeInvokedOnce()
120127
[TestMethod]
121128
public void WaitOnHandleOnSessionShouldWaitForChannelCloseMessageToBeReceived()
122129
{
123-
Assert.IsTrue(_closeTimer.ElapsedMilliseconds >= 100, "Elapsed milliseconds=" + _closeTimer.ElapsedMilliseconds);
130+
Assert.IsTrue(_channelClosedReceived.WaitOne(0));
124131
}
125132

126133
[TestMethod]

src/Renci.SshNet.Tests/Classes/ForwardedPortDynamicTest_Started_SocketSendShutdownImmediately.cs

+25-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Net;
44
using System.Net.Sockets;
55
using System.Text;
6+
using System.Threading;
67
using Microsoft.VisualStudio.TestTools.UnitTesting;
78
using Moq;
89
using Renci.SshNet.Channels;
@@ -21,6 +22,8 @@ public class ForwardedPortDynamicTest_Started_SocketSendShutdownImmediately
2122
private IList<EventArgs> _closingRegister;
2223
private IList<ExceptionEventArgs> _exceptionRegister;
2324
private TimeSpan _connectionTimeout;
25+
private ManualResetEvent _channelDisposed;
26+
private IPEndPoint _forwardedPortEndPoint;
2427

2528
[TestInitialize]
2629
public void Initialize()
@@ -38,6 +41,7 @@ public void Cleanup()
3841
_connectionInfoMock.Setup(p => p.Timeout).Returns(TimeSpan.FromSeconds(5));
3942
_forwardedPort.Stop();
4043
}
44+
4145
if (_client != null)
4246
{
4347
if (_client.Connected)
@@ -47,13 +51,28 @@ public void Cleanup()
4751
_client = null;
4852
}
4953
}
54+
55+
if (_channelDisposed != null)
56+
{
57+
_channelDisposed.Dispose();
58+
_channelDisposed = null;
59+
}
5060
}
5161

5262
private void SetupData()
5363
{
5464
_closingRegister = new List<EventArgs>();
5565
_exceptionRegister = new List<ExceptionEventArgs>();
5666
_connectionTimeout = TimeSpan.FromSeconds(5);
67+
_channelDisposed = new ManualResetEvent(false);
68+
_forwardedPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
69+
70+
_forwardedPort = new ForwardedPortDynamic((uint) _forwardedPortEndPoint.Port);
71+
_forwardedPort.Closing += (sender, args) => _closingRegister.Add(args);
72+
_forwardedPort.Exception += (sender, args) => _exceptionRegister.Add(args);
73+
_forwardedPort.Session = _sessionMock.Object;
74+
75+
_client = new Socket(_forwardedPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
5776
}
5877

5978
private void CreateMocks()
@@ -72,30 +91,26 @@ private void SetupMocks()
7291
_sessionMock.InSequence(seq).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
7392
_connectionInfoMock.InSequence(seq).Setup(p => p.Timeout).Returns(_connectionTimeout);
7493
_channelMock.InSequence(seq).Setup(p => p.Close());
75-
_channelMock.InSequence(seq).Setup(p => p.Dispose());
94+
_channelMock.InSequence(seq).Setup(p => p.Dispose()).Callback(() => _channelDisposed.Set());
7695
}
7796

7897
private void Arrange()
7998
{
80-
SetupData();
8199
CreateMocks();
100+
SetupData();
82101
SetupMocks();
83102

84-
_forwardedPort = new ForwardedPortDynamic(8122);
85-
_forwardedPort.Closing += (sender, args) => _closingRegister.Add(args);
86-
_forwardedPort.Exception += (sender, args) => _exceptionRegister.Add(args);
87-
_forwardedPort.Session = _sessionMock.Object;
88103
_forwardedPort.Start();
89104

90-
var endPoint = new IPEndPoint(IPAddress.Loopback, 8122);
91-
92-
_client = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
93-
_client.Connect(endPoint);
105+
_client.Connect(_forwardedPortEndPoint);
94106
}
95107

96108
private void Act()
97109
{
98110
_client.Shutdown(SocketShutdown.Send);
111+
112+
// wait for channel to be disposed
113+
_channelDisposed.WaitOne(TimeSpan.FromMilliseconds(200));
99114
}
100115

101116
[TestMethod]

src/Renci.SshNet.Tests/Classes/ForwardedPortRemoteTest_Start_PortStopped.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public void ForwardedPortShouldAcceptNewConnections()
121121
var originatorAddress = new Random().Next().ToString(CultureInfo.InvariantCulture);
122122
var originatorPort = (uint)new Random().Next(0, int.MaxValue);
123123
var channelMock = new Mock<IChannelForwardedTcpip>(MockBehavior.Strict);
124+
var channelDiposed = new ManualResetEvent(false);
124125

125126
_sessionMock.Setup(
126127
p =>
@@ -132,14 +133,17 @@ public void ForwardedPortShouldAcceptNewConnections()
132133
ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port),
133134
_forwardedPort));
134135
channelMock.Setup(p => p.Close());
135-
channelMock.Setup(p => p.Dispose());
136+
channelMock.Setup(p => p.Dispose()).Callback(() => channelDiposed.Set());
136137

137138
_sessionMock.Raise(p => p.ChannelOpenReceived += null,
138139
new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(channelNumber, initialWindowSize,
139140
maximumPacketSize,
140141
new ForwardedTcpipChannelInfo(_forwardedPort.BoundHost, _forwardedPort.BoundPort, originatorAddress,
141142
originatorPort))));
142143

144+
// wait for channel to be disposed
145+
channelDiposed.WaitOne(TimeSpan.FromMilliseconds(200));
146+
143147
_sessionMock.Verify(p => p.CreateChannelForwardedTcpip(channelNumber, initialWindowSize, maximumPacketSize), Times.Once);
144148
channelMock.Verify(p => p.Bind(It.Is<IPEndPoint>(ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port), _forwardedPort), Times.Once);
145149
channelMock.Verify(p => p.Close(), Times.Once);

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public void ForwardedPortShouldAcceptChannelOpenMessageForBoundAddressAndBoundPo
9999
var originatorAddress = new Random().Next().ToString(CultureInfo.InvariantCulture);
100100
var originatorPort = (uint) new Random().Next(0, int.MaxValue);
101101
var channelMock = new Mock<IChannelForwardedTcpip>(MockBehavior.Strict);
102+
var channelDisposed = new ManualResetEvent(false);
102103

103104
_sessionMock.Setup(
104105
p =>
@@ -110,14 +111,17 @@ public void ForwardedPortShouldAcceptChannelOpenMessageForBoundAddressAndBoundPo
110111
ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port),
111112
_forwardedPort));
112113
channelMock.Setup(p => p.Close());
113-
channelMock.Setup(p => p.Dispose());
114+
channelMock.Setup(p => p.Dispose()).Callback(() => channelDisposed.Set());
114115

115116
_sessionMock.Raise(p => p.ChannelOpenReceived += null,
116117
new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(channelNumber, initialWindowSize,
117118
maximumPacketSize,
118119
new ForwardedTcpipChannelInfo(_forwardedPort.BoundHost, _forwardedPort.BoundPort, originatorAddress,
119120
originatorPort))));
120121

122+
// wait for channel to be disposed
123+
channelDisposed.WaitOne(TimeSpan.FromMilliseconds(200));
124+
121125
_sessionMock.Verify(p => p.CreateChannelForwardedTcpip(channelNumber, initialWindowSize, maximumPacketSize), Times.Once);
122126
channelMock.Verify(p => p.Bind(It.Is<IPEndPoint>(ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port), _forwardedPort), Times.Once);
123127
channelMock.Verify(p => p.Close(), Times.Once);

0 commit comments

Comments
 (0)